From fb6bc855e9f9c9e5275abc20b0e93e7515ac6b8c Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Wed, 23 Mar 2016 09:30:41 +0100 Subject: [PATCH 001/134] Remove polygonItems from their Stroke when added to a StrokesGroup --- src/domain/UBGraphicsPolygonItem.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/domain/UBGraphicsPolygonItem.cpp b/src/domain/UBGraphicsPolygonItem.cpp index 3ba4861c..4effa158 100644 --- a/src/domain/UBGraphicsPolygonItem.cpp +++ b/src/domain/UBGraphicsPolygonItem.cpp @@ -114,6 +114,9 @@ UBGraphicsPolygonItem::~UBGraphicsPolygonItem() void UBGraphicsPolygonItem::setStrokesGroup(UBGraphicsStrokesGroup *group) { + if (mStroke) + mStroke->remove(this); + mpGroup = group; } From 4491341a4d324297e26ed675092b31108e6faf3f Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 1 Apr 2016 12:41:25 +0200 Subject: [PATCH 002/134] (WIP) Interpolation of strokes. Progress so far: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - UBGraphicsScene calls UBGraphicsStroke::addPoint, which returns a list of points that can be drawn. It may be none (e.g we discard very small segments), one (if we do no interpolation) or several. - Added a UBInterpolator base, abstract class. Various interpolation methods can be added easily. - Current methods: Basic spline (custom), Catmull-Rom spline (based on alglib), and Bézier - Added a setting to toggle interpolation. Added this to the UI as well --- OpenBoard.pro | 3 + resources/forms/brushProperties.ui | 415 ++++++++++++++------------- src/core/UBPreferencesController.cpp | 2 + src/core/UBSettings.cpp | 2 + src/core/UBSettings.h | 2 + src/domain/UBGraphicsScene.cpp | 88 +++++- src/domain/UBGraphicsScene.h | 1 + src/domain/UBGraphicsStroke.cpp | 171 +++++++++++ src/domain/UBGraphicsStroke.h | 11 + src/frameworks/UBInterpolator.cpp | 139 +++++++++ src/frameworks/UBInterpolator.h | 96 +++++++ src/frameworks/frameworks.pri | 6 +- 12 files changed, 732 insertions(+), 204 deletions(-) create mode 100644 src/frameworks/UBInterpolator.cpp create mode 100644 src/frameworks/UBInterpolator.h diff --git a/OpenBoard.pro b/OpenBoard.pro index 4558b666..13b005e6 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -66,6 +66,9 @@ INCLUDEPATH += src/pdf-merger include(src/pdf-merger/pdfMerger.pri) #ThirdParty +INCLUDEPATH += $$THIRD_PARTY_PATH/spline/ +INCLUDEPATH += $$THIRD_PARTY_PATH/alglib/ +include($$THIRD_PARTY_PATH/alglib/alglib.pri) DEPENDPATH += $$THIRD_PARTY_PATH/quazip/ INCLUDEPATH += $$THIRD_PARTY_PATH/quazip/ include($$THIRD_PARTY_PATH/quazip/quazip.pri) diff --git a/resources/forms/brushProperties.ui b/resources/forms/brushProperties.ui index 19883e90..eea50fba 100644 --- a/resources/forms/brushProperties.ui +++ b/resources/forms/brushProperties.ui @@ -1,7 +1,8 @@ - + + brushProperties - - + + 0 0 @@ -9,25 +10,25 @@ 808 - + - + QFrame::NoFrame - + QFrame::Plain - - - - + + + + Qt::Vertical - + QSizePolicy::Fixed - + 20 40 @@ -35,53 +36,40 @@ - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - + + + QFrame::NoFrame - + QFrame::Raised - - + + 0 - - + + QFrame::NoFrame - + QFrame::Raised - + - - + + On Light Background - - + + Qt::Horizontal - + 40 20 @@ -90,17 +78,17 @@ - - + + 32 32 - + QFrame::StyledPanel - + QFrame::Raised @@ -109,27 +97,27 @@ - - + + QFrame::NoFrame - + QFrame::Raised - + - - + + On Dark Background - - + + Qt::Horizontal - + 40 20 @@ -138,17 +126,17 @@ - - + + 32 32 - + QFrame::StyledPanel - + QFrame::Raised @@ -159,34 +147,21 @@ - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - + + + QFrame::NoFrame - + QFrame::Raised - + - - + + Qt::Horizontal - + 154 20 @@ -195,40 +170,40 @@ - - + + Opacity - - + + 20 - + 100 - + 50 - + Qt::Horizontal - + QSlider::TicksAbove - + 20 - - + + Qt::Horizontal - + 156 20 @@ -239,40 +214,27 @@ - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - + + + + 0 0 - + Line Width - - - - + + + + Qt::Horizontal - + QSizePolicy::Fixed - + 40 20 @@ -280,15 +242,15 @@ - - - + + + Qt::Horizontal - + QSizePolicy::Fixed - + 40 20 @@ -296,149 +258,149 @@ - - - + + + 5 - + 500 - + 5 - + Qt::Horizontal - + QSlider::TicksAbove - + 100 - - - + + + Medium - - - + + + 5 - + 500 - + Qt::Horizontal - + QSlider::TicksAbove - + 100 - - - + + + Strong - - - + + + 5 - + 500 - + Qt::Horizontal - + QSlider::TicksAbove - + 100 - - - - + + + + 60 60 - + 60 60 - + QFrame::StyledPanel - + QFrame::Raised - - - - + + + + 60 60 - + 60 60 - + QFrame::StyledPanel - + QFrame::Raised - - - - + + + + 60 60 - + 60 60 - + QFrame::StyledPanel - + QFrame::Raised - - - + + + Fine @@ -446,50 +408,85 @@ - - - + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + QFrame::NoFrame - + QFrame::Raised - - + + + 0 + + + 0 + + + 0 + + 0 - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - + + + 0 0 - + Pen is Pressure Sensitive - - + + Qt::Horizontal - + 198 20 @@ -500,6 +497,30 @@ + + + + + + Smooth strokes (experimental) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + diff --git a/src/core/UBPreferencesController.cpp b/src/core/UBPreferencesController.cpp index e2ec529e..56baf2b4 100644 --- a/src/core/UBPreferencesController.cpp +++ b/src/core/UBPreferencesController.cpp @@ -163,6 +163,7 @@ void UBPreferencesController::wire() connect(mPenProperties->mediumSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mPenProperties->strongSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mPenProperties->pressureSensitiveCheckBox, SIGNAL(clicked(bool)), settings, SLOT(setPenPressureSensitive(bool))); + connect(mPenProperties->interpolateStrokesCheckBox, SIGNAL(clicked(bool)), settings->boardInterpolatePenStrokes, SLOT(setBool(bool))); // marker QList markerLightBackgroundColors = settings->boardMarkerLightBackgroundColors->colors(); @@ -229,6 +230,7 @@ void UBPreferencesController::init() mPenProperties->mediumSlider->setValue(settings->boardPenMediumWidth->get().toDouble() * sSliderRatio); mPenProperties->strongSlider->setValue(settings->boardPenStrongWidth->get().toDouble() * sSliderRatio); mPenProperties->pressureSensitiveCheckBox->setChecked(settings->boardPenPressureSensitive->get().toBool()); + mPenProperties->interpolateStrokesCheckBox->setChecked(settings->boardInterpolatePenStrokes->get().toBool()); // marker tab mMarkerProperties->fineSlider->setValue(settings->boardMarkerFineWidth->get().toDouble() * sSliderRatio); diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index d0dfc237..9a32b48e 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -267,6 +267,8 @@ void UBSettings::init() boardUseHighResTabletEvent = new UBSetting(this, "Board", "UseHighResTabletEvent", true); + boardInterpolatePenStrokes = new UBSetting(this, "Board", "InterpolatePenStrokes", true); + boardKeyboardPaletteKeyBtnSize = new UBSetting(this, "Board", "KeyboardPaletteKeyBtnSize", "16x16"); ValidateKeyboardPaletteKeyBtnSize(); diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index b7e0bc08..f4210f19 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -269,6 +269,8 @@ class UBSettings : public QObject UBSetting* boardUseHighResTabletEvent; + UBSetting* boardInterpolatePenStrokes; + UBSetting* boardKeyboardPaletteKeyBtnSize; UBSetting* appStartMode; diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index f4091c21..72eae6a9 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -23,6 +23,7 @@ */ +#include #include "UBGraphicsScene.h" @@ -35,6 +36,7 @@ #include "frameworks/UBGeometryUtils.h" #include "frameworks/UBPlatformUtils.h" +#include "frameworks/UBInterpolator.h" #include "core/UBApplication.h" #include "core/UBSettings.h" @@ -430,6 +432,8 @@ bool UBGraphicsScene::inputDevicePress(const QPointF& scenePos, const qreal& pre else { moveTo(scenePos); drawLineTo(scenePos, width, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); + + mCurrentStroke->addPoint(scenePos); } accepted = true; } @@ -537,7 +541,48 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres dc->mActiveRuler->DrawLine(position, width); } else{ - drawLineTo(position, width, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); + bool showDots = false; + + if (showDots) { + UBGraphicsPolygonItem * p = lineToPolygonItem(QLineF(scenePos, scenePos), width, width); + p->setColor(Qt::red); + this->addItem(p); + } + + UBInterpolator::InterpolationMethod interpolator = UBInterpolator::NoInterpolation; + + if (currentTool == UBStylusTool::Marker) { + // The marker is already super slow due to the transparency, we can't also do interpolation + interpolator = UBInterpolator::NoInterpolation; + } + + else if (UBSettings::settings()->boardInterpolatePenStrokes->get().toBool()) { + interpolator = UBInterpolator::Bezier; + } + + QList newPoints = mCurrentStroke->addPoint(scenePos, interpolator); + int n = newPoints.length(); + int i = 1; + qreal startWidth = mPreviousWidth; + foreach(QPointF point, newPoints) { + + if (showDots) { + if (point != scenePos) { + UBGraphicsPolygonItem * p = lineToPolygonItem(QLineF(point, point), width, width); + p->setColor(Qt::yellow); + this->addItem(p); + } + } + + + // linear interpolation of the end width + qreal endWidth = mPreviousWidth + qreal(i)*(width - mPreviousWidth)/qreal(n); + i++; + + drawLineTo(point, startWidth, endWidth, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); + startWidth = endWidth; + } + //drawLineTo(scenePos, width, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); } } else if (currentTool == UBStylusTool::Eraser) @@ -606,6 +651,30 @@ bool UBGraphicsScene::inputDeviceRelease() mDrawWithCompass = false; } else if (mCurrentStroke){ + /* + // ------------------------------------------------------------------------- + // Replace the stroke by a smoother one + // ------------------------------------------------------------------------- + UBGraphicsStroke* smoothStroke = mCurrentStroke->smoothe(); + + foreach(UBGraphicsPolygonItem* poly, mCurrentStroke->polygons()){ + mPreviousPolygonItems.removeAll(poly); + removeItem(poly); + } + delete mCurrentStroke; + mCurrentStroke = smoothStroke; + + moveTo(smoothStroke->points()[0]); + for (int i(1); i < smoothStroke->points().size(); ++i) { + QPointF currentPoint = smoothStroke->points()[i]; + + drawLineTo(currentPoint, dc->currentToolWidth(), dc->currentToolWidth(), false); + moveTo(currentPoint); + } + + // ------------------------------------------------------------------------- + */ + UBGraphicsStrokesGroup* pStrokes = new UBGraphicsStrokesGroup(); // Remove the strokes that were just drawn here and replace them by a stroke item @@ -771,15 +840,24 @@ void UBGraphicsScene::moveTo(const QPointF &pPoint) mArcPolygonItem = 0; mDrawWithCompass = false; } - void UBGraphicsScene::drawLineTo(const QPointF &pEndPoint, const qreal &pWidth, bool bLineStyle) +{ + drawLineTo(pEndPoint, pWidth, pWidth, bLineStyle); + +} + +void UBGraphicsScene::drawLineTo(const QPointF &pEndPoint, const qreal &startWidth, const qreal &endWidth, bool bLineStyle) { if (mPreviousWidth == -1.0) - mPreviousWidth = pWidth; + mPreviousWidth = startWidth; + + qreal initialWidth = startWidth; + if (initialWidth == endWidth) + initialWidth = mPreviousWidth; // UBGraphicsPolygonItem *polygonItem = lineToPolygonItem(QLineF(mPreviousPoint, pEndPoint), pWidth); - UBGraphicsPolygonItem *polygonItem = lineToPolygonItem(QLineF(mPreviousPoint, pEndPoint), mPreviousWidth,pWidth); + UBGraphicsPolygonItem *polygonItem = lineToPolygonItem(QLineF(mPreviousPoint, pEndPoint), initialWidth, endWidth); if (!polygonItem->brush().isOpaque()) { @@ -822,7 +900,7 @@ void UBGraphicsScene::drawLineTo(const QPointF &pEndPoint, const qreal &pWidth, if (!bLineStyle) { mPreviousPoint = pEndPoint; - mPreviousWidth = pWidth; + mPreviousWidth = endWidth; } } diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index b040cf2e..19571d62 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -191,6 +191,7 @@ class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem void moveTo(const QPointF& pPoint); void drawLineTo(const QPointF& pEndPoint, const qreal& pWidth, bool bLineStyle); + void drawLineTo(const QPointF& pEndPoint, const qreal& pStartWidth, const qreal& endWidth, bool bLineStyle); void eraseLineTo(const QPointF& pEndPoint, const qreal& pWidth); void drawArcTo(const QPointF& pCenterPoint, qreal pSpanAngle); diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index f6954b47..9208315c 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -31,6 +31,7 @@ #include "core/memcheck.h" + UBGraphicsStroke::UBGraphicsStroke() { // NOOP @@ -61,6 +62,129 @@ QList UBGraphicsStroke::polygons() const return mPolygons; } +/** + * @brief Add a point to the curve, interpolating extra points if required + * @return The points (or point, if none were interpolated) that were added + */ +QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator::InterpolationMethod interpolationMethod) +{ + int n = mDrawnPoints.size(); + + /* + if (n > 0) { + qreal MIN_DISTANCE = 3; + QPointF lastPoint = mDrawnPoints.last(); + qreal distance = QLineF(lastPoint, point).length(); + + //qDebug() << "distance: " << distance; + + if (distance < MIN_DISTANCE) + return QList(); + } + */ + + if (interpolationMethod == UBInterpolator::NoInterpolation || n == 0) { + mDrawnPoints << point; + mAllPoints << point; + return QList() << point; + } + + else if (interpolationMethod == UBInterpolator::Bezier) { + // This is a bit special, as the curve we are interpolating is not between two drawn points; + // it is between the midway points of the second-to-last and last point, and last and current point. + qreal MIN_DISTANCE = 3; + QPointF lastPoint = mDrawnPoints.last(); + qreal distance = QLineF(lastPoint, point).length(); + + //qDebug() << "distance: " << distance; + + if (distance < MIN_DISTANCE) + return QList(); + if (n == 1) { + // We start with a straight line to the first midway point + QPointF lastPoint = mDrawnPoints[0]; + mDrawnPoints << point; + + return QList() << ((lastPoint + point)/2.0); + } + + QPointF p0 = mDrawnPoints[mDrawnPoints.size() - 2]; + QPointF p1 = mDrawnPoints[mDrawnPoints.size() - 1]; + QPointF p2 = point; + + UBQuadraticBezier bz; + + QPointF startPoint = (p1+p0)/2.0; + QPointF endPoint = (p2+p1)/2.0; + + bz.setPoints(startPoint, p1, endPoint); + + QList newPoints = bz.getPoints(7); + + foreach(QPointF p, newPoints) { + mAllPoints << p; + } + + mDrawnPoints << point; + return newPoints; + + + } + + else { + + qreal MIN_INTERPOLATION_DISTANCE = 0; + + QPointF lastPoint; + if (!mDrawnPoints.isEmpty()) + lastPoint = mDrawnPoints.last(); + + QList newPoints; + + // Interpolation + if (n > 3 && QLineF(lastPoint, point).length() > MIN_INTERPOLATION_DISTANCE) { + + /* + UBSimpleSpline sp; + sp.setPoints(mDrawnPoints[n-2], mDrawnPoints[n-1], point); + */ + + // todo: better way of avoiding problems with constant x's. in the meantime this'll do. + qreal x0 = mDrawnPoints[n-3].x(); + qreal x1 = mDrawnPoints[n-2].x(); + qreal x2 = mDrawnPoints[n-1].x(); + qreal x3 = point.x(); + if (!(x0 == x1 || x0 == x2 || x0 == x3 || x1 == x2 || x1 == x3 || x2 == x3)) { + + UBCatmullRomSpline sp; + sp.setPoints(QList() << mDrawnPoints[n-3] << mDrawnPoints[n-2] << mDrawnPoints[n-1] << point); + + // get an extra 3 values in between the current point and last one + int n_points = 3; // number of points to interpolate + double interval = (point.x() - lastPoint.x())/double(n_points+1); + + qDebug() << "Interpolating between: " << lastPoint << " and " << point; + + for (int i(1); i <= n_points; ++i) { + double x = lastPoint.x() + i*interval; + QPointF newPoint(x, sp.y(x)); + qDebug() << newPoint; + + newPoints << newPoint; + mAllPoints << newPoint; + //qDebug() << "Got new point: " << newPoint; + } + } + + } + + newPoints << point; + mAllPoints << point; + mDrawnPoints << point; + + return newPoints; + } +} bool UBGraphicsStroke::hasPressure() { @@ -105,3 +229,50 @@ void UBGraphicsStroke::clear() } } + +/** + * @brief Smoothe the curve, by interpolating extra points where needed. + * + * @return A new stroke based on the current one. + */ +UBGraphicsStroke* UBGraphicsStroke::smoothe() +{ + // Catmull-Rom spline interpolation + UBCatmullRomSpline sp; + + UBGraphicsStroke * smoothStroke = new UBGraphicsStroke(); + + smoothStroke->mAllPoints << mAllPoints[0]; + + for (int i(0); i < mAllPoints.size() - 3; ++i) { + QPointF p1, p2; + + p1 = mAllPoints[i+1]; + p2 = mAllPoints[i+2]; + + qreal x0 = mAllPoints[i].x(); + qreal x1 = p1.x(); + qreal x2 = p2.x(); + qreal x3 = mAllPoints[i+3].x(); + + if (!(x0 == x1 || x0 == x2 || x0 == x3 || x1 == x2 || x1 == x3 || x2 == x3)) { + sp.setPoints(QList() << mAllPoints[i] << mAllPoints[i+1] << mAllPoints[i+2] << mAllPoints[i+3]); + + smoothStroke->mAllPoints << mAllPoints[i+1]; + int n_points = 3; // number of points to interpolate + double interval = (p2.x() - p1.x())/double(n_points+1); + + for (int i(1); i <= n_points; ++i) { + double x = p1.x() + i*interval; + QPointF newPoint(x, sp.y(x)); + + smoothStroke->mAllPoints << newPoint; + } + } + + } + smoothStroke->mAllPoints << mAllPoints[mAllPoints.size() - 2] << mAllPoints[mAllPoints.size() - 1]; + + + return smoothStroke; +} diff --git a/src/domain/UBGraphicsStroke.h b/src/domain/UBGraphicsStroke.h index d7f8852d..2f9b2759 100644 --- a/src/domain/UBGraphicsStroke.h +++ b/src/domain/UBGraphicsStroke.h @@ -31,6 +31,8 @@ #include #include "core/UB.h" +#include "frameworks/UBInterpolator.h" + class UBGraphicsPolygonItem; @@ -55,6 +57,12 @@ class UBGraphicsStroke void clear(); + QList addPoint(const QPointF& point, UBInterpolator::InterpolationMethod interpolationMethod = UBInterpolator::NoInterpolation); + + UBGraphicsStroke* smoothe(); + + const QList& points() { return mAllPoints; } + protected: void addPolygon(UBGraphicsPolygonItem* pol); @@ -62,6 +70,9 @@ class UBGraphicsStroke QList mPolygons; + QList mDrawnPoints; + QList mAllPoints; + }; #endif /* UBGRAPHICSSTROKE_H_ */ diff --git a/src/frameworks/UBInterpolator.cpp b/src/frameworks/UBInterpolator.cpp new file mode 100644 index 00000000..bd40b038 --- /dev/null +++ b/src/frameworks/UBInterpolator.cpp @@ -0,0 +1,139 @@ +#include "UBInterpolator.h" + +UBInterpolator::UBInterpolator() +{ +} + +UBInterpolator::~UBInterpolator() +{ +} + + +UBSimpleSpline::UBSimpleSpline() +{ + +} + +void UBSimpleSpline::setPoints(QList points) +{ + setPoints(points[0], points[1], points[2]); +} + +void UBSimpleSpline::setPoints(QPointF p0, QPointF p1, QPointF p2) +{ + /* + p0 -= p0; + p1 -= p0; + p2 -= p0; + */ + long double x0, x1, x2, y0, y1, y2; + x0 = p0.x(); + x1 = p1.x(); + x2 = p2.x(); + y0 = p0.y(); + y1 = p1.y(); + y2 = p2.y(); + + long double k1 = (y2-y0)/(x2-x0); + + m_a = (y1-y2-k1*(x1-x2))/(pow(x1,3) - pow(x2,3) - 3*x2*(pow(x1,2)-pow(x2,2)) - + 3*(pow(x1,2) - 2*x1*x2)*(x1-x2)); + + m_b = -3*m_a*x2; + m_c = k1 - 3*m_a*pow(x1,2) - 2*m_b*x1; + m_d = y1 - m_a*pow(x1,3) - m_b*pow(x1,2) - m_c*x1; +} + +double UBSimpleSpline::y(double x) +{ + return m_a*pow(x, 3) + m_b*pow(x, 2) + m_c*x + m_d; +} + +UBCatmullRomSpline::UBCatmullRomSpline() +{ + mInterpolant = 0; +} + +UBCatmullRomSpline::~UBCatmullRomSpline() +{ + if (mInterpolant) + delete mInterpolant; +} + +void UBCatmullRomSpline::setPoints(QList points) +{ + // todo : basis change to avoid crashing when several X's are equal + mInterpolant = new alglib::spline1dinterpolant(); + + // alglib arrays are defined as strings + QString x = "["; + QString y = "["; + + foreach(QPointF point, points) { + x += (QString::number(point.x()) + QString(",")); + y += (QString::number(point.y()) + QString(",")); + } + + x.chop(1); + y.chop(1); + + x+="]"; + y+="]"; + + alglib::real_1d_array xArray = x.toLatin1().data(); + alglib::real_1d_array yArray = y.toLatin1().data(); + + alglib::spline1dbuildcatmullrom(xArray, yArray, *mInterpolant); + + +} + +double UBCatmullRomSpline::y(double x) +{ + return alglib::spline1dcalc(*mInterpolant, x); +} + + +UBQuadraticBezier::UBQuadraticBezier() +{ + mPath = 0; +} + +UBQuadraticBezier::~UBQuadraticBezier() +{ + if (mPath) + delete mPath; +} + +void UBQuadraticBezier::setPoints(QList points) +{ + setPoints(points[0], points[1], points[2]); + +} + +void UBQuadraticBezier::setPoints(QPointF start, QPointF control, QPointF end) +{ + mPath = new QPainterPath(start); + mPath->quadTo(control, end); +} + +/** + * @brief Return n points along the curve, including start and end points (thus n should be larger than or equal to 2). + * + * The higher n, the more accurate the result + */ +QList UBQuadraticBezier::getPoints(int n) +{ + QList points; + + if (n <= 1) + return points; + + for (int i(0); i <= n; ++i) { + qreal percent = qreal(i)/qreal(n); + + points << mPath->pointAtPercent(percent); + } + + return points; +} diff --git a/src/frameworks/UBInterpolator.h b/src/frameworks/UBInterpolator.h new file mode 100644 index 00000000..1a028523 --- /dev/null +++ b/src/frameworks/UBInterpolator.h @@ -0,0 +1,96 @@ +#ifndef UBINTERPOLATOR_H +#define UBINTERPOLATOR_H + +#include + +#include "spline.h" +#include "interpolation.h" + +class UBInterpolator +{ + /* Abstract class representing an interpolator */ + +public: + enum InterpolationMethod { + NoInterpolation, + SimpleSpline, + CatmullRom, + Bezier + }; + + UBInterpolator(); + virtual ~UBInterpolator(); + + virtual void setPoints(QList points) = 0; + virtual double y(double x) {} + +}; + + +class UBSimpleSpline : public UBInterpolator +{ + /* A basic cubic spline interpolator, that requires only three + * points to interpolate between the second and third one. + * To do so, the curvature at p2 is set to 0, so the resulting + * curve is not very smooth. + * However, it is better than linear interpolation and requires no + * "future" points, so it can be used seamlessly during drawing. + */ + +public: + UBSimpleSpline(); + virtual ~UBSimpleSpline() {} + + virtual void setPoints(QList points); + void setPoints(QPointF p0, QPointF p1, QPointF p2); + + virtual double y(double x); + +private: + long double m_a, + m_b, + m_c, + m_d; +}; + + +class UBCatmullRomSpline : public UBInterpolator +{ + /* Catmull-Rom spline, using AlgLib as backend + * + * This requires four points to interpolate between the middle two. + */ + +public: + UBCatmullRomSpline(); + virtual ~UBCatmullRomSpline(); + + virtual void setPoints(QList points); + virtual double y(double x); + +private: + alglib::spline1dinterpolant * mInterpolant; + +}; + + +class UBQuadraticBezier : public UBInterpolator +{ + +public: + UBQuadraticBezier(); + virtual ~UBQuadraticBezier(); + + virtual void setPoints(QList points); + void setPoints(QPointF start, QPointF control, QPointF end); + + //virtual double y(double x); + + QList getPoints(int n); + +private: + + QPainterPath* mPath; +}; + +#endif // UBINTERPOLATOR_H diff --git a/src/frameworks/frameworks.pri b/src/frameworks/frameworks.pri index 74d6edbb..8d6d435d 100644 --- a/src/frameworks/frameworks.pri +++ b/src/frameworks/frameworks.pri @@ -6,7 +6,8 @@ HEADERS += src/frameworks/UBGeometryUtils.h \ src/frameworks/UBVersion.h \ src/frameworks/UBCoreGraphicsScene.h \ src/frameworks/UBCryptoUtils.h \ - src/frameworks/UBBase32.h + src/frameworks/UBBase32.h \ + $$PWD/UBInterpolator.h SOURCES += src/frameworks/UBGeometryUtils.cpp \ src/frameworks/UBPlatformUtils.cpp \ @@ -15,7 +16,8 @@ SOURCES += src/frameworks/UBGeometryUtils.cpp \ src/frameworks/UBVersion.cpp \ src/frameworks/UBCoreGraphicsScene.cpp \ src/frameworks/UBCryptoUtils.cpp \ - src/frameworks/UBBase32.cpp + src/frameworks/UBBase32.cpp \ + $$PWD/UBInterpolator.cpp win32 { From 19cfe0ac1c87e8f29e8e77a7c3966779a272531a Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 4 Apr 2016 10:03:47 +0200 Subject: [PATCH 003/134] Revert "Remove polygonItems from their Stroke when added to a StrokesGroup" This reverts commit 177571ca79cbd92f6544c80ce36ded88ce64fa7a. --- src/domain/UBGraphicsPolygonItem.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/domain/UBGraphicsPolygonItem.cpp b/src/domain/UBGraphicsPolygonItem.cpp index 4effa158..3ba4861c 100644 --- a/src/domain/UBGraphicsPolygonItem.cpp +++ b/src/domain/UBGraphicsPolygonItem.cpp @@ -114,9 +114,6 @@ UBGraphicsPolygonItem::~UBGraphicsPolygonItem() void UBGraphicsPolygonItem::setStrokesGroup(UBGraphicsStrokesGroup *group) { - if (mStroke) - mStroke->remove(this); - mpGroup = group; } From 4811d3501790a63d52baa39ec20893477110fb07 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 5 Apr 2016 14:49:56 +0200 Subject: [PATCH 004/134] Improved drawing of interpolated strokes: - Added a curveToPolygon function that creates a curved polygon, eliminating the need to generate lots of small ones to make a curve look smooth. - Cleaned up the rest of the code a bit --- src/domain/UBGraphicsScene.cpp | 96 +++++++++++++------------- src/domain/UBGraphicsScene.h | 3 + src/domain/UBGraphicsStroke.cpp | 29 +++----- src/domain/UBGraphicsStroke.h | 3 + src/frameworks/UBGeometryUtils.cpp | 105 +++++++++++++++++++++++++++++ src/frameworks/UBGeometryUtils.h | 1 + 6 files changed, 167 insertions(+), 70 deletions(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 72eae6a9..d19a9457 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -537,52 +537,31 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres position = newPosition; } + if (!mCurrentStroke) + mCurrentStroke = new UBGraphicsStroke(); + if(dc->mActiveRuler){ dc->mActiveRuler->DrawLine(position, width); } else{ - bool showDots = false; - - if (showDots) { - UBGraphicsPolygonItem * p = lineToPolygonItem(QLineF(scenePos, scenePos), width, width); - p->setColor(Qt::red); - this->addItem(p); - } - UBInterpolator::InterpolationMethod interpolator = UBInterpolator::NoInterpolation; + /* if (currentTool == UBStylusTool::Marker) { // The marker is already super slow due to the transparency, we can't also do interpolation interpolator = UBInterpolator::NoInterpolation; } + */ - else if (UBSettings::settings()->boardInterpolatePenStrokes->get().toBool()) { + if (UBSettings::settings()->boardInterpolatePenStrokes->get().toBool()) { interpolator = UBInterpolator::Bezier; } QList newPoints = mCurrentStroke->addPoint(scenePos, interpolator); - int n = newPoints.length(); - int i = 1; - qreal startWidth = mPreviousWidth; - foreach(QPointF point, newPoints) { - - if (showDots) { - if (point != scenePos) { - UBGraphicsPolygonItem * p = lineToPolygonItem(QLineF(point, point), width, width); - p->setColor(Qt::yellow); - this->addItem(p); - } - } - - - // linear interpolation of the end width - qreal endWidth = mPreviousWidth + qreal(i)*(width - mPreviousWidth)/qreal(n); - i++; - - drawLineTo(point, startWidth, endWidth, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); - startWidth = endWidth; - } - //drawLineTo(scenePos, width, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); + if (newPoints.length() > 1) + drawCurve(newPoints, mPreviousWidth, width); + else + drawLineTo(scenePos, width, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); } } else if (currentTool == UBStylusTool::Eraser) @@ -855,10 +834,36 @@ void UBGraphicsScene::drawLineTo(const QPointF &pEndPoint, const qreal &startWid if (initialWidth == endWidth) initialWidth = mPreviousWidth; - // UBGraphicsPolygonItem *polygonItem = lineToPolygonItem(QLineF(mPreviousPoint, pEndPoint), pWidth); + if (bLineStyle) { + QSetIterator itItems(mAddedItems); + + while (itItems.hasNext()) { + QGraphicsItem* item = itItems.next(); + removeItem(item); + } + mAddedItems.clear(); + } UBGraphicsPolygonItem *polygonItem = lineToPolygonItem(QLineF(mPreviousPoint, pEndPoint), initialWidth, endWidth); + addPolygonItemToCurrentStroke(polygonItem); + + if (!bLineStyle) { + mPreviousPoint = pEndPoint; + mPreviousWidth = endWidth; + } +} + +void UBGraphicsScene::drawCurve(const QList& points, qreal startWidth, qreal endWidth) +{ + UBGraphicsPolygonItem* polygonItem = curveToPolygonItem(points, startWidth, endWidth); + addPolygonItemToCurrentStroke(polygonItem); + + mPreviousWidth = endWidth; + mPreviousPoint = points.last(); +} +void UBGraphicsScene::addPolygonItemToCurrentStroke(UBGraphicsPolygonItem* polygonItem) +{ if (!polygonItem->brush().isOpaque()) { // ------------------------------------------------------------------------------------- @@ -871,19 +876,6 @@ void UBGraphicsScene::drawLineTo(const QPointF &pEndPoint, const qreal &startWid } } - - if (bLineStyle) - { - QSetIterator itItems(mAddedItems); - - while (itItems.hasNext()) - { - QGraphicsItem* item = itItems.next(); - removeItem(item); - } - mAddedItems.clear(); - } - mpLastPolygon = polygonItem; mAddedItems.insert(polygonItem); @@ -896,12 +888,6 @@ void UBGraphicsScene::drawLineTo(const QPointF &pEndPoint, const qreal &startWid mPreviousPolygonItems.append(polygonItem); - - if (!bLineStyle) - { - mPreviousPoint = pEndPoint; - mPreviousWidth = endWidth; - } } void UBGraphicsScene::eraseLineTo(const QPointF &pEndPoint, const qreal &pWidth) @@ -1149,6 +1135,14 @@ UBGraphicsPolygonItem* UBGraphicsScene::arcToPolygonItem(const QLineF& pStartRad return polygonToPolygonItem(polygon); } +UBGraphicsPolygonItem* UBGraphicsScene::curveToPolygonItem(const QList& points, qreal startWidth, qreal endWidth) +{ + QPolygonF polygon = UBGeometryUtils::curveToPolygon(points, startWidth, endWidth); + + return polygonToPolygonItem(polygon); + +} + void UBGraphicsScene::clearSelectionFrame() { if (mSelectionFrame) { diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 19571d62..a62d66e7 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -194,6 +194,7 @@ class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem void drawLineTo(const QPointF& pEndPoint, const qreal& pStartWidth, const qreal& endWidth, bool bLineStyle); void eraseLineTo(const QPointF& pEndPoint, const qreal& pWidth); void drawArcTo(const QPointF& pCenterPoint, qreal pSpanAngle); + void drawCurve(const QList& points, qreal startWidth, qreal endWidth); bool isEmpty() const; @@ -357,6 +358,8 @@ public slots: UBGraphicsPolygonItem* lineToPolygonItem(const QLineF &pLine, const qreal &pStartWidth, const qreal &pEndWidth); UBGraphicsPolygonItem* arcToPolygonItem(const QLineF& pStartRadius, qreal pSpanAngle, qreal pWidth); + UBGraphicsPolygonItem* curveToPolygonItem(const QList& points, qreal startWidth, qreal endWidth); + void addPolygonItemToCurrentStroke(UBGraphicsPolygonItem* polygonItem); void initPolygonItem(UBGraphicsPolygonItem*); diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index 9208315c..90db6dde 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -70,19 +70,6 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: { int n = mDrawnPoints.size(); - /* - if (n > 0) { - qreal MIN_DISTANCE = 3; - QPointF lastPoint = mDrawnPoints.last(); - qreal distance = QLineF(lastPoint, point).length(); - - //qDebug() << "distance: " << distance; - - if (distance < MIN_DISTANCE) - return QList(); - } - */ - if (interpolationMethod == UBInterpolator::NoInterpolation || n == 0) { mDrawnPoints << point; mAllPoints << point; @@ -92,14 +79,20 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: else if (interpolationMethod == UBInterpolator::Bezier) { // This is a bit special, as the curve we are interpolating is not between two drawn points; // it is between the midway points of the second-to-last and last point, and last and current point. - qreal MIN_DISTANCE = 3; + qreal MIN_DISTANCE = 3; // TODO: make this dependant on zoom QPointF lastPoint = mDrawnPoints.last(); qreal distance = QLineF(lastPoint, point).length(); //qDebug() << "distance: " << distance; - if (distance < MIN_DISTANCE) + // We don't draw anything below the minimum distance. For performance reasons but also to make the curve + // look smoother (e.g shaking slightly won't affect the curve). + if (distance < MIN_DISTANCE) { + // we still keep track of that point to calculate the distance correctly next time around + mDrawnPoints << point; return QList(); + } + if (n == 1) { // We start with a straight line to the first midway point QPointF lastPoint = mDrawnPoints[0]; @@ -119,7 +112,7 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: bz.setPoints(startPoint, p1, endPoint); - QList newPoints = bz.getPoints(7); + QList newPoints = bz.getPoints(10); foreach(QPointF p, newPoints) { mAllPoints << p; @@ -127,8 +120,6 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: mDrawnPoints << point; return newPoints; - - } else { @@ -149,7 +140,7 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: sp.setPoints(mDrawnPoints[n-2], mDrawnPoints[n-1], point); */ - // todo: better way of avoiding problems with constant x's. in the meantime this'll do. + // todo: better way of avoiding problems with equal x's (such as PCA). in the meantime this'll do. qreal x0 = mDrawnPoints[n-3].x(); qreal x1 = mDrawnPoints[n-2].x(); qreal x2 = mDrawnPoints[n-1].x(); diff --git a/src/domain/UBGraphicsStroke.h b/src/domain/UBGraphicsStroke.h index 2f9b2759..2f9f4eae 100644 --- a/src/domain/UBGraphicsStroke.h +++ b/src/domain/UBGraphicsStroke.h @@ -70,7 +70,10 @@ class UBGraphicsStroke QList mPolygons; + /// Points that were drawn (actually received through input device) QList mDrawnPoints; + + /// All the points (including interpolated) that are used to draw the stroke QList mAllPoints; }; diff --git a/src/frameworks/UBGeometryUtils.cpp b/src/frameworks/UBGeometryUtils.cpp index ea5f22b2..fb3392e7 100644 --- a/src/frameworks/UBGeometryUtils.cpp +++ b/src/frameworks/UBGeometryUtils.cpp @@ -242,6 +242,111 @@ QPolygonF UBGeometryUtils::arcToPolygon(const QLineF& startRadius, qreal spanAng return painterPath.toFillPolygon(); } +/** + * @brief Build and return a polygon from a list of points (at least 2), and start and end widths. + * + * The resulting polygon will pass by all points in the curve; its thickness is calculated at each point + * of the curve (linearly interpolated between start and end widths) and the segments are joined by + * (approximately) curved joints. + * + * Like with lineToPolygon, the ends are semi-circular. + */ +QPolygonF UBGeometryUtils::curveToPolygon(const QList& points, qreal startWidth, qreal endWidth) +{ + typedef QPair pointPair; + + int n_points = points.size(); + + if (n_points < 2) + return QPolygonF(); + + if (n_points == 2) + return lineToPolygon(points[0], points[1], startWidth, endWidth); + + /* The vertices (x's) are calculated based on the stroke's width and angle, and the position of the + supplied points (o's): + + x----------x--------x + + o o o + + x----------x -------x + + The vertices above and below each 'o' point are temporarily stored together, + as a pair of points. + + */ + QList newPoints; + + + QLineF firstSegment = QLineF(points[0], points[1]); + QLineF normal = firstSegment.normalVector(); + normal.setLength(startWidth/2.0); + newPoints << pointPair(normal.p2(), points[0] - QPointF(normal.dx(), normal.dy())); + + /* + Calculating the vertices (d1 and d2, below) is a little less trivial for the + next points: their positions depend on the angle between one segment and the next. + + d1 + ------------x + \ + .a b . \ + \ + --------x \ + d2 \ \ + \ .c \ + + Here, points a, b and c are supplied in the `points` list. + + N.B: The drawing isn't quite accurate; we don't do a miter joint but a kind + of rounded-off joint (the distance between b and d1 is half the width of the stroke) + */ + + for (int i(1); i < n_points-1; ++i) { + qreal width = startWidth + (qreal(i)/qreal(n_points-1)) * (endWidth - startWidth); + + QLineF normal = (QLineF(points[i-1], points[i+1])).normalVector(); + normal.setLength(width/2.0); + QPointF d1 = points[i] + QPointF(normal.dx(), normal.dy()); + QPointF d2 = points[i] - QPointF(normal.dx(), normal.dy()); + + newPoints << pointPair(d1, d2); + } + + // The last point is similar to the first + QLineF lastSegment = QLineF(points[n_points-2], points[n_points-1]); + normal = lastSegment.normalVector(); + normal.setLength(endWidth/2.0); + + QPointF d1 = points.last() + QPointF(normal.dx(), normal.dy()); + QPointF d2 = points.last() - QPointF(normal.dx(), normal.dy()); + + newPoints << pointPair(d1, d2); + + QPainterPath path; + path.moveTo(newPoints[0].first); + + for (int i(1); i < n_points; ++i) { + path.lineTo(newPoints[i].first); + } + + path.arcTo(points.last().x() - endWidth/2.0, points.last().y() - endWidth/2.0, endWidth, endWidth, (90.0 + lastSegment.angle()), -180.0); + //path.lineTo(newPoints.last().second); + + for (int i(n_points-1); i >= 0; --i) { + path.lineTo(newPoints[i].second); + } + + path.arcTo(points[0].x() - startWidth/2.0, points[0].y() - startWidth/2.0, startWidth, startWidth, (firstSegment.angle() - 90.0), -180.0); + //path.lineTo(newPoints[0].second); + + + path.closeSubpath(); + + return path.toFillPolygon(); +} + QPointF UBGeometryUtils::pointConstrainedInRect(QPointF point, QRectF rect) { return QPointF(qMax(rect.x(), qMin(rect.x() + rect.width(), point.x())), qMax(rect.y(), qMin(rect.y() + rect.height(), point.y()))); diff --git a/src/frameworks/UBGeometryUtils.h b/src/frameworks/UBGeometryUtils.h index b54cfe97..fef01891 100644 --- a/src/frameworks/UBGeometryUtils.h +++ b/src/frameworks/UBGeometryUtils.h @@ -45,6 +45,7 @@ class UBGeometryUtils static QPolygonF lineToPolygon(const QPointF& pStart, const QPointF& pEnd, const qreal& pStartWidth, const qreal& pEndWidth); + static QPolygonF curveToPolygon(const QList& points, qreal startWidth, qreal endWidth); static QPointF pointConstrainedInRect(QPointF point, QRectF rect); static QPoint pointConstrainedInRect(QPoint point, QRect rect); From 1ef73a70b87edb6eb6b065014b1a68c8fde2d2e2 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 5 Apr 2016 15:27:31 +0200 Subject: [PATCH 005/134] Strokes: corrected tracking of last received point --- src/domain/UBGraphicsStroke.cpp | 7 ++++--- src/domain/UBGraphicsStroke.h | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index 90db6dde..3553a465 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -71,6 +71,7 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: int n = mDrawnPoints.size(); if (interpolationMethod == UBInterpolator::NoInterpolation || n == 0) { + mLastReceivedPoint = point; mDrawnPoints << point; mAllPoints << point; return QList() << point; @@ -80,8 +81,7 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: // This is a bit special, as the curve we are interpolating is not between two drawn points; // it is between the midway points of the second-to-last and last point, and last and current point. qreal MIN_DISTANCE = 3; // TODO: make this dependant on zoom - QPointF lastPoint = mDrawnPoints.last(); - qreal distance = QLineF(lastPoint, point).length(); + qreal distance = QLineF(mLastReceivedPoint, point).length(); //qDebug() << "distance: " << distance; @@ -89,7 +89,7 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: // look smoother (e.g shaking slightly won't affect the curve). if (distance < MIN_DISTANCE) { // we still keep track of that point to calculate the distance correctly next time around - mDrawnPoints << point; + mLastReceivedPoint = point; return QList(); } @@ -101,6 +101,7 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: return QList() << ((lastPoint + point)/2.0); } + QPointF p0 = mDrawnPoints[mDrawnPoints.size() - 2]; QPointF p1 = mDrawnPoints[mDrawnPoints.size() - 1]; QPointF p2 = point; diff --git a/src/domain/UBGraphicsStroke.h b/src/domain/UBGraphicsStroke.h index 2f9f4eae..5ef91507 100644 --- a/src/domain/UBGraphicsStroke.h +++ b/src/domain/UBGraphicsStroke.h @@ -76,6 +76,8 @@ class UBGraphicsStroke /// All the points (including interpolated) that are used to draw the stroke QList mAllPoints; + QPointF mLastReceivedPoint; + }; #endif /* UBGRAPHICSSTROKE_H_ */ From 999fcec917d5c014155f4fa358f20969ceda01bf Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 11 Apr 2016 14:13:24 +0200 Subject: [PATCH 006/134] Removed spline interpolators --- OpenBoard.pro | 3 - src/domain/UBGraphicsScene.cpp | 24 ------- src/domain/UBGraphicsStroke.cpp | 104 +----------------------------- src/domain/UBGraphicsStroke.h | 2 - src/frameworks/UBInterpolator.cpp | 86 ------------------------ src/frameworks/UBInterpolator.h | 57 +--------------- 6 files changed, 5 insertions(+), 271 deletions(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index 13b005e6..4558b666 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -66,9 +66,6 @@ INCLUDEPATH += src/pdf-merger include(src/pdf-merger/pdfMerger.pri) #ThirdParty -INCLUDEPATH += $$THIRD_PARTY_PATH/spline/ -INCLUDEPATH += $$THIRD_PARTY_PATH/alglib/ -include($$THIRD_PARTY_PATH/alglib/alglib.pri) DEPENDPATH += $$THIRD_PARTY_PATH/quazip/ INCLUDEPATH += $$THIRD_PARTY_PATH/quazip/ include($$THIRD_PARTY_PATH/quazip/quazip.pri) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index d19a9457..b9d18043 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -630,30 +630,6 @@ bool UBGraphicsScene::inputDeviceRelease() mDrawWithCompass = false; } else if (mCurrentStroke){ - /* - // ------------------------------------------------------------------------- - // Replace the stroke by a smoother one - // ------------------------------------------------------------------------- - UBGraphicsStroke* smoothStroke = mCurrentStroke->smoothe(); - - foreach(UBGraphicsPolygonItem* poly, mCurrentStroke->polygons()){ - mPreviousPolygonItems.removeAll(poly); - removeItem(poly); - } - delete mCurrentStroke; - mCurrentStroke = smoothStroke; - - moveTo(smoothStroke->points()[0]); - for (int i(1); i < smoothStroke->points().size(); ++i) { - QPointF currentPoint = smoothStroke->points()[i]; - - drawLineTo(currentPoint, dc->currentToolWidth(), dc->currentToolWidth(), false); - moveTo(currentPoint); - } - - // ------------------------------------------------------------------------- - */ - UBGraphicsStrokesGroup* pStrokes = new UBGraphicsStrokesGroup(); // Remove the strokes that were just drawn here and replace them by a stroke item diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index 3553a465..6e28e9ca 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -88,7 +88,7 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: // We don't draw anything below the minimum distance. For performance reasons but also to make the curve // look smoother (e.g shaking slightly won't affect the curve). if (distance < MIN_DISTANCE) { - // we still keep track of that point to calculate the distance correctly next time around + // but we still keep track of that point to calculate the distance correctly next time around mLastReceivedPoint = point; return QList(); } @@ -123,59 +123,7 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: return newPoints; } - else { - - qreal MIN_INTERPOLATION_DISTANCE = 0; - - QPointF lastPoint; - if (!mDrawnPoints.isEmpty()) - lastPoint = mDrawnPoints.last(); - - QList newPoints; - - // Interpolation - if (n > 3 && QLineF(lastPoint, point).length() > MIN_INTERPOLATION_DISTANCE) { - - /* - UBSimpleSpline sp; - sp.setPoints(mDrawnPoints[n-2], mDrawnPoints[n-1], point); - */ - - // todo: better way of avoiding problems with equal x's (such as PCA). in the meantime this'll do. - qreal x0 = mDrawnPoints[n-3].x(); - qreal x1 = mDrawnPoints[n-2].x(); - qreal x2 = mDrawnPoints[n-1].x(); - qreal x3 = point.x(); - if (!(x0 == x1 || x0 == x2 || x0 == x3 || x1 == x2 || x1 == x3 || x2 == x3)) { - - UBCatmullRomSpline sp; - sp.setPoints(QList() << mDrawnPoints[n-3] << mDrawnPoints[n-2] << mDrawnPoints[n-1] << point); - - // get an extra 3 values in between the current point and last one - int n_points = 3; // number of points to interpolate - double interval = (point.x() - lastPoint.x())/double(n_points+1); - - qDebug() << "Interpolating between: " << lastPoint << " and " << point; - - for (int i(1); i <= n_points; ++i) { - double x = lastPoint.x() + i*interval; - QPointF newPoint(x, sp.y(x)); - qDebug() << newPoint; - - newPoints << newPoint; - mAllPoints << newPoint; - //qDebug() << "Got new point: " << newPoint; - } - } - - } - - newPoints << point; - mAllPoints << point; - mDrawnPoints << point; - - return newPoints; - } + return QList(); } bool UBGraphicsStroke::hasPressure() @@ -220,51 +168,3 @@ void UBGraphicsStroke::clear() mPolygons.clear(); } } - - -/** - * @brief Smoothe the curve, by interpolating extra points where needed. - * - * @return A new stroke based on the current one. - */ -UBGraphicsStroke* UBGraphicsStroke::smoothe() -{ - // Catmull-Rom spline interpolation - UBCatmullRomSpline sp; - - UBGraphicsStroke * smoothStroke = new UBGraphicsStroke(); - - smoothStroke->mAllPoints << mAllPoints[0]; - - for (int i(0); i < mAllPoints.size() - 3; ++i) { - QPointF p1, p2; - - p1 = mAllPoints[i+1]; - p2 = mAllPoints[i+2]; - - qreal x0 = mAllPoints[i].x(); - qreal x1 = p1.x(); - qreal x2 = p2.x(); - qreal x3 = mAllPoints[i+3].x(); - - if (!(x0 == x1 || x0 == x2 || x0 == x3 || x1 == x2 || x1 == x3 || x2 == x3)) { - sp.setPoints(QList() << mAllPoints[i] << mAllPoints[i+1] << mAllPoints[i+2] << mAllPoints[i+3]); - - smoothStroke->mAllPoints << mAllPoints[i+1]; - int n_points = 3; // number of points to interpolate - double interval = (p2.x() - p1.x())/double(n_points+1); - - for (int i(1); i <= n_points; ++i) { - double x = p1.x() + i*interval; - QPointF newPoint(x, sp.y(x)); - - smoothStroke->mAllPoints << newPoint; - } - } - - } - smoothStroke->mAllPoints << mAllPoints[mAllPoints.size() - 2] << mAllPoints[mAllPoints.size() - 1]; - - - return smoothStroke; -} diff --git a/src/domain/UBGraphicsStroke.h b/src/domain/UBGraphicsStroke.h index 5ef91507..860ab8f1 100644 --- a/src/domain/UBGraphicsStroke.h +++ b/src/domain/UBGraphicsStroke.h @@ -59,8 +59,6 @@ class UBGraphicsStroke QList addPoint(const QPointF& point, UBInterpolator::InterpolationMethod interpolationMethod = UBInterpolator::NoInterpolation); - UBGraphicsStroke* smoothe(); - const QList& points() { return mAllPoints; } protected: diff --git a/src/frameworks/UBInterpolator.cpp b/src/frameworks/UBInterpolator.cpp index bd40b038..b5777bcd 100644 --- a/src/frameworks/UBInterpolator.cpp +++ b/src/frameworks/UBInterpolator.cpp @@ -8,92 +8,6 @@ UBInterpolator::~UBInterpolator() { } - -UBSimpleSpline::UBSimpleSpline() -{ - -} - -void UBSimpleSpline::setPoints(QList points) -{ - setPoints(points[0], points[1], points[2]); -} - -void UBSimpleSpline::setPoints(QPointF p0, QPointF p1, QPointF p2) -{ - /* - p0 -= p0; - p1 -= p0; - p2 -= p0; - */ - long double x0, x1, x2, y0, y1, y2; - x0 = p0.x(); - x1 = p1.x(); - x2 = p2.x(); - y0 = p0.y(); - y1 = p1.y(); - y2 = p2.y(); - - long double k1 = (y2-y0)/(x2-x0); - - m_a = (y1-y2-k1*(x1-x2))/(pow(x1,3) - pow(x2,3) - 3*x2*(pow(x1,2)-pow(x2,2)) - - 3*(pow(x1,2) - 2*x1*x2)*(x1-x2)); - - m_b = -3*m_a*x2; - m_c = k1 - 3*m_a*pow(x1,2) - 2*m_b*x1; - m_d = y1 - m_a*pow(x1,3) - m_b*pow(x1,2) - m_c*x1; -} - -double UBSimpleSpline::y(double x) -{ - return m_a*pow(x, 3) + m_b*pow(x, 2) + m_c*x + m_d; -} - -UBCatmullRomSpline::UBCatmullRomSpline() -{ - mInterpolant = 0; -} - -UBCatmullRomSpline::~UBCatmullRomSpline() -{ - if (mInterpolant) - delete mInterpolant; -} - -void UBCatmullRomSpline::setPoints(QList points) -{ - // todo : basis change to avoid crashing when several X's are equal - mInterpolant = new alglib::spline1dinterpolant(); - - // alglib arrays are defined as strings - QString x = "["; - QString y = "["; - - foreach(QPointF point, points) { - x += (QString::number(point.x()) + QString(",")); - y += (QString::number(point.y()) + QString(",")); - } - - x.chop(1); - y.chop(1); - - x+="]"; - y+="]"; - - alglib::real_1d_array xArray = x.toLatin1().data(); - alglib::real_1d_array yArray = y.toLatin1().data(); - - alglib::spline1dbuildcatmullrom(xArray, yArray, *mInterpolant); - - -} - -double UBCatmullRomSpline::y(double x) -{ - return alglib::spline1dcalc(*mInterpolant, x); -} - - UBQuadraticBezier::UBQuadraticBezier() { mPath = 0; diff --git a/src/frameworks/UBInterpolator.h b/src/frameworks/UBInterpolator.h index 1a028523..9a714488 100644 --- a/src/frameworks/UBInterpolator.h +++ b/src/frameworks/UBInterpolator.h @@ -3,9 +3,6 @@ #include -#include "spline.h" -#include "interpolation.h" - class UBInterpolator { /* Abstract class representing an interpolator */ @@ -13,8 +10,8 @@ class UBInterpolator public: enum InterpolationMethod { NoInterpolation, - SimpleSpline, - CatmullRom, + //SimpleSpline, + //CatmullRom, Bezier }; @@ -22,58 +19,10 @@ public: virtual ~UBInterpolator(); virtual void setPoints(QList points) = 0; - virtual double y(double x) {} - -}; - - -class UBSimpleSpline : public UBInterpolator -{ - /* A basic cubic spline interpolator, that requires only three - * points to interpolate between the second and third one. - * To do so, the curvature at p2 is set to 0, so the resulting - * curve is not very smooth. - * However, it is better than linear interpolation and requires no - * "future" points, so it can be used seamlessly during drawing. - */ - -public: - UBSimpleSpline(); - virtual ~UBSimpleSpline() {} - - virtual void setPoints(QList points); - void setPoints(QPointF p0, QPointF p1, QPointF p2); - - virtual double y(double x); - -private: - long double m_a, - m_b, - m_c, - m_d; -}; - - -class UBCatmullRomSpline : public UBInterpolator -{ - /* Catmull-Rom spline, using AlgLib as backend - * - * This requires four points to interpolate between the middle two. - */ - -public: - UBCatmullRomSpline(); - virtual ~UBCatmullRomSpline(); - - virtual void setPoints(QList points); - virtual double y(double x); - -private: - alglib::spline1dinterpolant * mInterpolant; + //virtual double y(double x) {} }; - class UBQuadraticBezier : public UBInterpolator { From f82a0a32d3f674657013ce081468bd0ceb01ba0b Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 11 Apr 2016 15:29:19 +0200 Subject: [PATCH 007/134] Fixed calculation of minimum distance for stroke polygons' drawing --- src/domain/UBGraphicsScene.cpp | 5 ++--- src/domain/UBGraphicsStroke.cpp | 21 +++++++++------------ src/domain/UBGraphicsStroke.h | 5 ++--- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index b9d18043..465b67ef 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -558,10 +558,9 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres } QList newPoints = mCurrentStroke->addPoint(scenePos, interpolator); - if (newPoints.length() > 1) + if (newPoints.length() > 1) { drawCurve(newPoints, mPreviousWidth, width); - else - drawLineTo(scenePos, width, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); + } } } else if (currentTool == UBStylusTool::Eraser) diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index 6e28e9ca..bad4272a 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -29,12 +29,14 @@ #include "UBGraphicsPolygonItem.h" +#include "board/UBBoardController.h" +#include "core/UBApplication.h" #include "core/memcheck.h" UBGraphicsStroke::UBGraphicsStroke() { - // NOOP + mAntiScaleRatio = 1./(UBApplication::boardController->systemScaleFactor() * UBApplication::boardController->currentZoom()); } @@ -71,7 +73,6 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: int n = mDrawnPoints.size(); if (interpolationMethod == UBInterpolator::NoInterpolation || n == 0) { - mLastReceivedPoint = point; mDrawnPoints << point; mAllPoints << point; return QList() << point; @@ -80,28 +81,24 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: else if (interpolationMethod == UBInterpolator::Bezier) { // This is a bit special, as the curve we are interpolating is not between two drawn points; // it is between the midway points of the second-to-last and last point, and last and current point. - qreal MIN_DISTANCE = 3; // TODO: make this dependant on zoom - qreal distance = QLineF(mLastReceivedPoint, point).length(); - //qDebug() << "distance: " << distance; + // Don't draw segments smaller than a certain length. This can help with performance + // (less polygons in a stroke) but mostly with keeping the curve smooth. + qreal MIN_DISTANCE = 3*mAntiScaleRatio; + qreal distance = QLineF(mDrawnPoints.last(), point).length(); - // We don't draw anything below the minimum distance. For performance reasons but also to make the curve - // look smoother (e.g shaking slightly won't affect the curve). if (distance < MIN_DISTANCE) { - // but we still keep track of that point to calculate the distance correctly next time around - mLastReceivedPoint = point; return QList(); } + // The first segment is just a straight line to the first midway point if (n == 1) { - // We start with a straight line to the first midway point QPointF lastPoint = mDrawnPoints[0]; mDrawnPoints << point; - return QList() << ((lastPoint + point)/2.0); + return QList() << lastPoint << ((lastPoint + point)/2.0); } - QPointF p0 = mDrawnPoints[mDrawnPoints.size() - 2]; QPointF p1 = mDrawnPoints[mDrawnPoints.size() - 1]; QPointF p2 = point; diff --git a/src/domain/UBGraphicsStroke.h b/src/domain/UBGraphicsStroke.h index 860ab8f1..5701eda2 100644 --- a/src/domain/UBGraphicsStroke.h +++ b/src/domain/UBGraphicsStroke.h @@ -68,14 +68,13 @@ class UBGraphicsStroke QList mPolygons; - /// Points that were drawn (actually received through input device) + /// Points that were drawn by the user (actually received through input device) QList mDrawnPoints; /// All the points (including interpolated) that are used to draw the stroke QList mAllPoints; - QPointF mLastReceivedPoint; - + qreal mAntiScaleRatio; }; #endif /* UBGRAPHICSSTROKE_H_ */ From b55ab7c92ceccd5fd632a229d67690f465bc6125 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 11 Apr 2016 15:39:18 +0200 Subject: [PATCH 008/134] Corrected stroke drawing when no interpolation is used (so UBGraphicsScene::drawCurve can be used either way) --- src/domain/UBGraphicsStroke.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index bad4272a..40516174 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -72,10 +72,17 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: { int n = mDrawnPoints.size(); - if (interpolationMethod == UBInterpolator::NoInterpolation || n == 0) { + if (n == 0) { mDrawnPoints << point; mAllPoints << point; - return QList() << point; + return QList(); + } + + if (interpolationMethod == UBInterpolator::NoInterpolation) { + QPointF lastPoint = mDrawnPoints.last(); + mDrawnPoints << point; + mAllPoints << point; + return QList() << lastPoint << point; } else if (interpolationMethod == UBInterpolator::Bezier) { From 43e0e414c9a21dac368905c3dcecedc8217bd992 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Tue, 12 Apr 2016 15:54:02 +0200 Subject: [PATCH 009/134] Draw last (half-) segment of stroke to make drawing feel smoother Also, clarified the difference between received and drawn points in UBGraphicsStroke --- src/domain/UBGraphicsScene.cpp | 25 +++++++++++++++++++++++++ src/domain/UBGraphicsScene.h | 1 + src/domain/UBGraphicsStroke.cpp | 31 ++++++++++++++++++------------- src/domain/UBGraphicsStroke.h | 8 ++++---- 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 465b67ef..718505d5 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -335,6 +335,7 @@ UBGraphicsScene::UBGraphicsScene(UBDocumentProxy* parent, bool enableUndoRedoSta , mZLayerController(new UBZLayerController(this)) , mpLastPolygon(NULL) , mCurrentPolygon(0) + , mTempPolygon(NULL) , mSelectionFrame(0) { UBCoreGraphicsScene::setObjectName("BoardScene"); @@ -561,6 +562,23 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres if (newPoints.length() > 1) { drawCurve(newPoints, mPreviousWidth, width); } + + if (interpolator == UBInterpolator::Bezier) { + // Bezier curves aren't drawn all the way to the scenePos (they stop halfway between the previous and + // current scenePos), so we add a line from the last drawn position in the stroke and the + // scenePos, to make the drawing feel more responsive. This line is then deleted if a new segment is + // added to the stroke. (Or it is added to the stroke when we stop drawing) + + if (mTempPolygon) { + removeItem(mTempPolygon); + mTempPolygon = NULL; + } + + QPointF lastDrawnPoint = newPoints.last(); + + mTempPolygon = lineToPolygonItem(QLineF(lastDrawnPoint, scenePos), mPreviousWidth, width); + addItem(mTempPolygon); + } } } else if (currentTool == UBStylusTool::Eraser) @@ -629,6 +647,13 @@ bool UBGraphicsScene::inputDeviceRelease() mDrawWithCompass = false; } else if (mCurrentStroke){ + if (mTempPolygon) { + UBGraphicsPolygonItem * poly = dynamic_cast(mTempPolygon->deepCopy()); + removeItem(mTempPolygon); + mTempPolygon = NULL; + addPolygonItemToCurrentStroke(poly); + } + UBGraphicsStrokesGroup* pStrokes = new UBGraphicsStrokesGroup(); // Remove the strokes that were just drawn here and replace them by a stroke item diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index a62d66e7..ea04ce9b 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -442,6 +442,7 @@ public slots: UBZLayerController *mZLayerController; UBGraphicsPolygonItem* mpLastPolygon; + UBGraphicsPolygonItem* mTempPolygon; bool mDrawWithCompass; UBGraphicsPolygonItem *mCurrentPolygon; diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index 40516174..df02796b 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -70,18 +70,18 @@ QList UBGraphicsStroke::polygons() const */ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator::InterpolationMethod interpolationMethod) { - int n = mDrawnPoints.size(); + int n = mReceivedPoints.size(); if (n == 0) { + mReceivedPoints << point; mDrawnPoints << point; - mAllPoints << point; return QList(); } if (interpolationMethod == UBInterpolator::NoInterpolation) { - QPointF lastPoint = mDrawnPoints.last(); + QPointF lastPoint = mReceivedPoints.last(); + mReceivedPoints << point; mDrawnPoints << point; - mAllPoints << point; return QList() << lastPoint << point; } @@ -91,23 +91,24 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: // Don't draw segments smaller than a certain length. This can help with performance // (less polygons in a stroke) but mostly with keeping the curve smooth. - qreal MIN_DISTANCE = 3*mAntiScaleRatio; - qreal distance = QLineF(mDrawnPoints.last(), point).length(); + qreal MIN_DISTANCE = 5*mAntiScaleRatio; + qreal distance = QLineF(mReceivedPoints.last(), point).length(); if (distance < MIN_DISTANCE) { - return QList(); + return QList() << mDrawnPoints.last(); } // The first segment is just a straight line to the first midway point if (n == 1) { - QPointF lastPoint = mDrawnPoints[0]; - mDrawnPoints << point; + QPointF lastPoint = mReceivedPoints[0]; + mReceivedPoints << point; + mDrawnPoints << QPointF((lastPoint + point)/2.0); return QList() << lastPoint << ((lastPoint + point)/2.0); } - QPointF p0 = mDrawnPoints[mDrawnPoints.size() - 2]; - QPointF p1 = mDrawnPoints[mDrawnPoints.size() - 1]; + QPointF p0 = mReceivedPoints[mReceivedPoints.size() - 2]; + QPointF p1 = mReceivedPoints[mReceivedPoints.size() - 1]; QPointF p2 = point; UBQuadraticBezier bz; @@ -119,11 +120,15 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: QList newPoints = bz.getPoints(10); + // avoid adding duplicates + if (newPoints.first() == mDrawnPoints.last()) + mDrawnPoints.removeLast(); + foreach(QPointF p, newPoints) { - mAllPoints << p; + mDrawnPoints << p; } - mDrawnPoints << point; + mReceivedPoints << point; return newPoints; } diff --git a/src/domain/UBGraphicsStroke.h b/src/domain/UBGraphicsStroke.h index 5701eda2..e5f6d38e 100644 --- a/src/domain/UBGraphicsStroke.h +++ b/src/domain/UBGraphicsStroke.h @@ -59,7 +59,7 @@ class UBGraphicsStroke QList addPoint(const QPointF& point, UBInterpolator::InterpolationMethod interpolationMethod = UBInterpolator::NoInterpolation); - const QList& points() { return mAllPoints; } + const QList& points() { return mDrawnPoints; } protected: void addPolygon(UBGraphicsPolygonItem* pol); @@ -68,11 +68,11 @@ class UBGraphicsStroke QList mPolygons; - /// Points that were drawn by the user (actually received through input device) - QList mDrawnPoints; + /// Points that were drawn by the user (i.e, actually received through input device) + QList mReceivedPoints; /// All the points (including interpolated) that are used to draw the stroke - QList mAllPoints; + QList mDrawnPoints; qreal mAntiScaleRatio; }; From a2fb735bbc4938e6f2a0a6681a987511587c57fb Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Thu, 28 Apr 2016 15:58:52 +0200 Subject: [PATCH 010/134] Podcasts on Linux: working video, no audio yet --- src/core/UBApplication.cpp | 2 - src/podcast/UBPodcastController.cpp | 4 + src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp | 396 ++++++++++++++++++++ src/podcast/ffmpeg/UBFFmpegVideoEncoder.h | 135 +++++++ src/podcast/podcast.pri | 25 ++ 5 files changed, 560 insertions(+), 2 deletions(-) create mode 100644 src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp create mode 100644 src/podcast/ffmpeg/UBFFmpegVideoEncoder.h diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index e364027d..5e205fea 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -520,10 +520,8 @@ void UBApplication::decorateActionMenu(QAction* action) menu->addSeparator(); -#ifndef Q_OS_LINUX // No Podcast on Linux yet menu->addAction(mainWindow->actionPodcast); mainWindow->actionPodcast->setText(tr("Podcast")); -#endif menu->addSeparator(); menu->addAction(mainWindow->actionQuit); diff --git a/src/podcast/UBPodcastController.cpp b/src/podcast/UBPodcastController.cpp index 598b5135..20a96300 100644 --- a/src/podcast/UBPodcastController.cpp +++ b/src/podcast/UBPodcastController.cpp @@ -64,6 +64,8 @@ #elif defined(Q_OS_OSX) #include "quicktime/UBQuickTimeVideoEncoder.h" #include "quicktime/UBAudioQueueRecorder.h" +#elif defined(Q_OS_LINUX) + #include "ffmpeg/UBFFmpegVideoEncoder.h" #endif #include "core/memcheck.h" @@ -309,6 +311,8 @@ void UBPodcastController::start() mVideoEncoder = new UBWindowsMediaVideoEncoder(this); //deleted on stop #elif defined(Q_OS_OSX) mVideoEncoder = new UBQuickTimeVideoEncoder(this); //deleted on stop +#elif defined(Q_OS_LINUX) + mVideoEncoder = new UBFFmpegVideoEncoder(this); #endif if (mVideoEncoder) diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp new file mode 100644 index 00000000..d2dd361a --- /dev/null +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp @@ -0,0 +1,396 @@ +#include "UBFFmpegVideoEncoder.h" + +// Future proofing +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1) +#define av_frame_alloc avcodec_alloc_frame +#define av_frame_free avcodec_free_frame +#endif + +QString avErrorToQString(int errnum) +{ + char error[AV_ERROR_MAX_STRING_SIZE]; + av_make_error_string(error, AV_ERROR_MAX_STRING_SIZE, errnum); + + return QString(error); +} + +/** + * @brief Constructor for the ffmpeg video encoder + * + * + * This class provides an interface between the screencast controller and the ffmpeg + * back-end. It initializes the audio and video encoders and frees them when done; + * worker threads handle the actual encoding of frames. + * + */ +UBFFmpegVideoEncoder::UBFFmpegVideoEncoder(QObject* parent) + : UBAbstractVideoEncoder(parent) + , mOutputFormatContext(NULL) + , mSwsContext(NULL) + , mFile(NULL) +{ + + mTimebase = 100 * framesPerSecond(); + qDebug() << "timebase: " << mTimebase; + + mVideoEncoderThread = new QThread; + mVideoWorker = new UBFFmpegVideoEncoderWorker(this); + mVideoWorker->moveToThread(mVideoEncoderThread); + + connect(mVideoWorker, SIGNAL(error(QString)), + this, SLOT(setLastErrorMessage(QString))); + + connect(mVideoEncoderThread, SIGNAL(started()), + mVideoWorker, SLOT(runEncoding())); + + connect(mVideoWorker, SIGNAL(encodingFinished()), + mVideoEncoderThread, SLOT(quit())); + + connect(mVideoEncoderThread, SIGNAL(finished()), + this, SLOT(finishEncoding())); +} + +UBFFmpegVideoEncoder::~UBFFmpegVideoEncoder() +{ + if (mVideoWorker) + delete mVideoWorker; + + if (mVideoEncoderThread) + delete mVideoEncoderThread; + +} + +void UBFFmpegVideoEncoder::setLastErrorMessage(const QString& pMessage) +{ + qDebug() << "FFmpeg video encoder:" << pMessage; + mLastErrorMessage = pMessage; +} + +bool UBFFmpegVideoEncoder::start() +{ + bool initialized = init(); + + if (initialized) + mVideoEncoderThread->start(); + + return initialized; +} + +bool UBFFmpegVideoEncoder::stop() +{ + qDebug() << "Video encoder: stop requested"; + + mVideoWorker->stopEncoding(); + + return true; +} + +bool UBFFmpegVideoEncoder::init() +{ + // Initialize ffmpeg lib + av_register_all(); + avcodec_register_all(); + + AVDictionary * options = NULL; + int ret; + + // Output format and context + // -------------------------------------- + + if (avformat_alloc_output_context2(&mOutputFormatContext, NULL, + "mp4", NULL) < 0) + { + setLastErrorMessage("Couldn't allocate video format context"); + return false; + } + + // The default codecs for mp4 are h264 and aac, we use those + + + // Video codec and context + // ------------------------------------- + + AVCodec * videoCodec = avcodec_find_encoder(mOutputFormatContext->oformat->video_codec); + if (!videoCodec) { + setLastErrorMessage("Video codec not found"); + return false; + } + + mVideoStream = avformat_new_stream(mOutputFormatContext, 0); + mVideoStream->time_base = {1, mTimebase}; + + avcodec_get_context_defaults3(mVideoStream->codec, videoCodec); + AVCodecContext* c = avcodec_alloc_context3(videoCodec); + + c->bit_rate = videoBitsPerSecond(); + c->width = videoSize().width(); + c->height = videoSize().height(); + c->time_base = {1, mTimebase}; + c->gop_size = 10; + c->max_b_frames = 0; + c->pix_fmt = AV_PIX_FMT_YUV420P; + + if (mOutputFormatContext->oformat->flags & AVFMT_GLOBALHEADER) + c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + + /* + * Supported pixel formats for h264 are: + * AV_PIX_FMT_YUV420P + * AV_PIX_FMT_YUV422P + * AV_PIX_FMT_YUV444P + * AV_PIX_FMT_YUVJ420P + */ + + av_dict_set(&options, "preset", "slow", 0); + av_dict_set(&options, "crf", "20", 0); + + ret = avcodec_open2(c, videoCodec, &options); + + if (ret < 0) { + setLastErrorMessage(QString("Couldn't open video codec: ") + avErrorToQString(ret)); + return false; + } + + mVideoStream->codec = c; + + // Source images are RGB32, and should be converted to YUV for h264 video + mSwsContext = sws_getCachedContext(mSwsContext, + c->width, c->height, AV_PIX_FMT_RGB32, + c->width, c->height, c->pix_fmt, + SWS_BICUBIC, 0, 0, 0); + + // Audio codec and context + // ------------------------------------- + /* + AVCodec * audioCodec = avcodec_find_encoder(mOutputFormatContext->oformat->audio_codec); + mAudioStream = avformat_new_stream(mOutputFormatContext, audioCodec); + */ + + + // Open the output file + ret = avio_open(&(mOutputFormatContext->pb), videoFileName().toStdString().c_str(), AVIO_FLAG_WRITE); + + if (ret < 0) { + setLastErrorMessage(QString("Couldn't open video file for writing: ") + avErrorToQString(ret)); + return false; + } + + // Write stream header + ret = avformat_write_header(mOutputFormatContext, NULL); + + if (ret < 0) { + setLastErrorMessage(QString("Couldn't write header to file: ") + avErrorToQString(ret)); + return false; + } + + return true; +} +void UBFFmpegVideoEncoder::newPixmap(const QImage &pImage, long timestamp) +{ + static bool isFirstFrame = true; + if (isFirstFrame) { + timestamp = 0; + isFirstFrame = false; + } + + if (!mVideoWorker->isRunning()) { + qDebug() << "Encoder worker thread not running. Queuing frame."; + mPendingFrames.enqueue({pImage, timestamp}); + } + + else { + // First send any queued frames, then the latest one + while (!mPendingFrames.isEmpty()) { + AVFrame* avFrame = convertFrame(mPendingFrames.dequeue()); + if (avFrame) + mVideoWorker->queueFrame(avFrame); + } + + // note: if converting the frame turns out to be too slow to do here, it + // can always be done from the worker thread (in thta case, + // the worker's queue would contain ImageFrames rather than AVFrames) + + AVFrame* avFrame = convertFrame({pImage, timestamp}); + if (avFrame) + mVideoWorker->queueFrame(avFrame); + + // signal the worker that frames are available + mVideoWorker->mWaitCondition.wakeAll(); + } +} + +/** Convert a frame consisting of a QImage and timestamp to an AVFrame + * with the right pixel format and PTS + */ +AVFrame* UBFFmpegVideoEncoder::convertFrame(ImageFrame frame) +{ + AVFrame* avFrame = av_frame_alloc(); + + avFrame->format = mVideoStream->codec->pix_fmt; + avFrame->width = mVideoStream->codec->width; + avFrame->height = mVideoStream->codec->height; + avFrame->pts = mTimebase * frame.timestamp / 1000; + + const uchar * rgbImage = frame.image.bits(); + + const int in_linesize[1] = { frame.image.bytesPerLine() }; + + // Allocate the output image + if (av_image_alloc(avFrame->data, avFrame->linesize, mVideoStream->codec->width, + mVideoStream->codec->height, mVideoStream->codec->pix_fmt, 32) < 0) + { + setLastErrorMessage("Couldn't allocate image"); + return NULL; + } + + sws_scale(mSwsContext, + (const uint8_t* const*)&rgbImage, + in_linesize, + 0, + mVideoStream->codec->height, + avFrame->data, + avFrame->linesize); + + return avFrame; +} + +void UBFFmpegVideoEncoder::finishEncoding() +{ + qDebug() << "VideoEncoder::finishEncoding called"; + + // Some frames may not be encoded, so we call avcodec_encode_video2 until they're all done + + int gotOutput; + do { + // TODO: get rid of duplicated code (videoWorker does almost exactly this during encoding) + + AVPacket* packet = mVideoWorker->mPacket; + + if (avcodec_encode_video2(mVideoStream->codec, packet, NULL, &gotOutput) < 0) { + setLastErrorMessage("Couldn't encode frame to video"); + continue; + } + if (gotOutput) { + AVRational codecTimebase = mVideoStream->codec->time_base; + AVRational streamTimebase = mVideoStream->time_base; + + av_packet_rescale_ts(packet, codecTimebase, streamTimebase); + packet->stream_index = mVideoStream->index; + + av_interleaved_write_frame(mOutputFormatContext, packet); + av_packet_unref(packet); + } + } while (gotOutput); + + av_write_trailer(mOutputFormatContext); + + avio_close(mOutputFormatContext->pb); + avcodec_close(mVideoStream->codec); + sws_freeContext(mSwsContext); + avformat_free_context(mOutputFormatContext); + + emit encodingFinished(true); +} + +//------------------------------------------------------------------------- +// Worker +//------------------------------------------------------------------------- + +UBFFmpegVideoEncoderWorker::UBFFmpegVideoEncoderWorker(UBFFmpegVideoEncoder* controller) + : mController(controller) +{ + mStopRequested = false; + mIsRunning = false; + mPacket = new AVPacket(); +} + +UBFFmpegVideoEncoderWorker::~UBFFmpegVideoEncoderWorker() +{} + +void UBFFmpegVideoEncoderWorker::stopEncoding() +{ + qDebug() << "Video worker: stop requested"; + mStopRequested = true; + mWaitCondition.wakeAll(); +} + +void UBFFmpegVideoEncoderWorker::queueFrame(AVFrame* frame) +{ + mFrameQueueMutex.lock(); + mFrameQueue.enqueue(frame); + mFrameQueueMutex.unlock(); +} + +/** + * The main encoding function. Takes the queued image frames and + * assembles them into the video + */ +void UBFFmpegVideoEncoderWorker::runEncoding() +{ + mIsRunning = true; + + while (!mStopRequested) { + mFrameQueueMutex.lock(); + mWaitCondition.wait(&mFrameQueueMutex); + + while (!mFrameQueue.isEmpty()) { + writeLatestVideoFrame(); + } + + /* + while (!mAudioQueue.isEmpty()) { + writeLatestAudioFrame(); + } + */ + + mFrameQueueMutex.unlock(); + } + + emit encodingFinished(); +} + +void UBFFmpegVideoEncoderWorker::writeLatestVideoFrame() +{ + AVFrame* frame = mFrameQueue.dequeue(); + + int gotOutput; + av_init_packet(mPacket); + mPacket->data = NULL; + mPacket->size = 0; + + // qDebug() << "Encoding frame to video. Pts: " << frame->pts << "/" << mController->mTimebase; + + if (avcodec_encode_video2(mController->mVideoStream->codec, mPacket, frame, &gotOutput) < 0) + emit error("Error encoding frame to video"); + + if (gotOutput) { + AVRational codecTimebase = mController->mVideoStream->codec->time_base; + AVRational streamTimebase = mController->mVideoStream->time_base; + + + // recalculate the timestamp to match the stream's timebase + av_packet_rescale_ts(mPacket, codecTimebase, streamTimebase); + mPacket->stream_index = mController->mVideoStream->index; + + // qDebug() << "Writing encoded packet to file; pts: " << mPacket->pts << "/" << streamTimebase.den; + + av_interleaved_write_frame(mController->mOutputFormatContext, mPacket); + av_packet_unref(mPacket); + } + + // Duct-tape solution. I assume there's a better way of doing this, but: + // some players like VLC show a black screen until the second frame (which + // can be several seconds after the first one). Simply duplicating the first frame + // seems to solve this problem, and also allows the thumbnail to be generated. + + static bool firstRun = true; + if (firstRun) { + firstRun = false; + frame->pts += 1; + mFrameQueue.enqueue(frame); // only works when the queue is empty at this point. todo: clean this up! + } + else + // free the frame + av_frame_free(&frame); +} + diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h new file mode 100644 index 00000000..4dacaaf6 --- /dev/null +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h @@ -0,0 +1,135 @@ +#ifndef UBFFMPEGVIDEOENCODER_H +#define UBFFMPEGVIDEOENCODER_H + +extern "C" { + #include + #include + #include + #include + #include + #include + #include + #include +} + +#include +#include + +#include +#include + +#include "podcast/UBAbstractVideoEncoder.h" + +class UBFFmpegVideoEncoderWorker; +class UBPodcastController; + +class UBFFmpegVideoEncoder : public UBAbstractVideoEncoder +{ + Q_OBJECT + + friend class UBFFmpegVideoEncoderWorker; + +public: + + UBFFmpegVideoEncoder(QObject* parent = NULL); + virtual ~UBFFmpegVideoEncoder(); + + bool start(); + bool stop(); + + void newPixmap(const QImage& pImage, long timestamp); + + QString videoFileExtension() const { return "mp4"; } + + QString lastErrorMessage() { return mLastErrorMessage; } + + void setRecordAudio(bool pRecordAudio) { mShouldRecordAudio = pRecordAudio; } + + +signals: + + void encodingFinished(bool ok); + +private slots: + + void setLastErrorMessage(const QString& pMessage); + void finishEncoding(); + +private: + + struct ImageFrame + { + QImage image; + long timestamp; // unit: ms + }; + + AVFrame* convertFrame(ImageFrame frame); + bool init(); + + // Queue for any pixmap that might be sent before the encoder is ready + QQueue mPendingFrames; + + QString mLastErrorMessage; + bool mShouldRecordAudio; + + QThread* mVideoEncoderThread; + UBFFmpegVideoEncoderWorker* mVideoWorker; + + // Muxer + AVFormatContext* mOutputFormatContext; + int mTimebase; + + // Video + AVStream* mVideoStream; + struct SwsContext * mSwsContext; + + // Audio + AVStream* mAudioStream; + + + FILE * mFile; + +}; + + +class UBFFmpegVideoEncoderWorker : public QObject +{ + Q_OBJECT + + friend class UBFFmpegVideoEncoder; + +public: + UBFFmpegVideoEncoderWorker(UBFFmpegVideoEncoder* controller); + ~UBFFmpegVideoEncoderWorker(); + + bool isRunning() { return mIsRunning; } + + void queueFrame(AVFrame* frame); + +public slots: + void runEncoding(); + void stopEncoding(); + +signals: + void encodingFinished(); + void error(QString message); + + +private: + void writeLatestVideoFrame(); + + UBFFmpegVideoEncoder* mController; + + // std::atomic is C++11. This won't work with msvc2010, so a + // newer compiler must be used if this is to be used on Windows + std::atomic mStopRequested; + std::atomic mIsRunning; + + QQueue mFrameQueue; + QMutex mFrameQueueMutex; + QWaitCondition mWaitCondition; + + AVPacket* mPacket; +}; + +#endif // UBFFMPEGVIDEOENCODER_H diff --git a/src/podcast/podcast.pri b/src/podcast/podcast.pri index af441814..0df7b13e 100644 --- a/src/podcast/podcast.pri +++ b/src/podcast/podcast.pri @@ -33,3 +33,28 @@ macx { OBJECTIVE_SOURCES += src/podcast/quicktime/UBQuickTimeFile.mm } + +linux-g++* { + HEADERS += src/podcast/ffmpeg/UBFFmpegVideoEncoder.h + + SOURCES += src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp + + + FFMPEG = /opt/ffmpeg + + INCLUDEPATH += $${FFMPEG}/include + DEPENDPATH += /usr/lib/x86_64-linux-gnu + + LIBS += -L $${FFMPEG}/lib -lavformat \ + -L $${FFMPEG}/lib -lavcodec \ + -L $${FFMPEG}/lib -lswscale \ + -L $${FFMPEG}/lib -lavutil \ + -lva-x11 \ + -lva \ + -lxcb-shm \ + -lxcb-xfixes \ + -lxcb-render -lxcb-shape -lxcb -lX11 -lasound -lSDL -lx264 -lpthread -lvpx -lvorbisenc -lvorbis -ltheoraenc -ltheoradec -logg -lopus -lmp3lame -lfreetype -lfdk-aac -lass -llzma -lbz2 -lz -ldl -lswresample -lswscale -lavutil -lm + + + QMAKE_CXXFLAGS += -std=c++11 # move this to OpenBoard.pro when we can use C++11 on all platforms +} From 11c207d7ee66e110606c28adcdd4adbe733380de Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Wed, 4 May 2016 11:48:26 +0200 Subject: [PATCH 011/134] Podcasts on Linux: added audio support --- src/podcast/UBPodcastController.cpp | 3 + src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp | 346 +++++++++++++++++--- src/podcast/ffmpeg/UBFFmpegVideoEncoder.h | 48 ++- src/podcast/ffmpeg/UBMicrophoneInput.cpp | 211 ++++++++++++ src/podcast/ffmpeg/UBMicrophoneInput.h | 57 ++++ src/podcast/podcast.pri | 6 +- 6 files changed, 608 insertions(+), 63 deletions(-) create mode 100644 src/podcast/ffmpeg/UBMicrophoneInput.cpp create mode 100644 src/podcast/ffmpeg/UBMicrophoneInput.h diff --git a/src/podcast/UBPodcastController.cpp b/src/podcast/UBPodcastController.cpp index 20a96300..efe22027 100644 --- a/src/podcast/UBPodcastController.cpp +++ b/src/podcast/UBPodcastController.cpp @@ -66,6 +66,7 @@ #include "quicktime/UBAudioQueueRecorder.h" #elif defined(Q_OS_LINUX) #include "ffmpeg/UBFFmpegVideoEncoder.h" + #include "ffmpeg/UBMicrophoneInput.h" #endif #include "core/memcheck.h" @@ -808,6 +809,8 @@ QStringList UBPodcastController::audioRecordingDevices() devices = UBWaveRecorder::waveInDevices(); #elif defined(Q_OS_OSX) devices = UBAudioQueueRecorder::waveInDevices(); +#elif defined(Q_OS_LINUX) + devices = UBMicrophoneInput::availableDevicesNames(); #endif return devices; diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp index d2dd361a..09fcb5b4 100644 --- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp @@ -20,18 +20,32 @@ QString avErrorToQString(int errnum) * * This class provides an interface between the screencast controller and the ffmpeg * back-end. It initializes the audio and video encoders and frees them when done; - * worker threads handle the actual encoding of frames. + * a worker thread handles the actual encoding and writing of frames. * */ UBFFmpegVideoEncoder::UBFFmpegVideoEncoder(QObject* parent) : UBAbstractVideoEncoder(parent) , mOutputFormatContext(NULL) , mSwsContext(NULL) - , mFile(NULL) + , mShouldRecordAudio(true) + , mAudioInput(NULL) + , mSwrContext(NULL) + , mAudioOutBuffer(NULL) + , mAudioSampleRate(44100) + , mAudioFrameCount(0) { + if (mShouldRecordAudio) { + mAudioInput = new UBMicrophoneInput(); - mTimebase = 100 * framesPerSecond(); - qDebug() << "timebase: " << mTimebase; + connect(mAudioInput, SIGNAL(audioLevelChanged(quint8)), + this, SIGNAL(audioLevelChanged(quint8))); + + connect(mAudioInput, SIGNAL(dataAvailable(QByteArray)), + this, SLOT(onAudioAvailable(QByteArray))); + } + + mVideoTimebase = 100 * framesPerSecond(); + qDebug() << "timebase: " << mVideoTimebase; mVideoEncoderThread = new QThread; mVideoWorker = new UBFFmpegVideoEncoderWorker(this); @@ -58,6 +72,8 @@ UBFFmpegVideoEncoder::~UBFFmpegVideoEncoder() if (mVideoEncoderThread) delete mVideoEncoderThread; + if (mAudioInput) + delete mAudioInput; } void UBFFmpegVideoEncoder::setLastErrorMessage(const QString& pMessage) @@ -66,12 +82,16 @@ void UBFFmpegVideoEncoder::setLastErrorMessage(const QString& pMessage) mLastErrorMessage = pMessage; } + bool UBFFmpegVideoEncoder::start() { bool initialized = init(); - if (initialized) + if (initialized) { mVideoEncoderThread->start(); + if (mShouldRecordAudio) + mAudioInput->start(); + } return initialized; } @@ -82,12 +102,14 @@ bool UBFFmpegVideoEncoder::stop() mVideoWorker->stopEncoding(); + if (mShouldRecordAudio) + mAudioInput->stop(); + return true; } bool UBFFmpegVideoEncoder::init() { - // Initialize ffmpeg lib av_register_all(); avcodec_register_all(); @@ -96,7 +118,6 @@ bool UBFFmpegVideoEncoder::init() // Output format and context // -------------------------------------- - if (avformat_alloc_output_context2(&mOutputFormatContext, NULL, "mp4", NULL) < 0) { @@ -109,6 +130,7 @@ bool UBFFmpegVideoEncoder::init() // Video codec and context // ------------------------------------- + mVideoStream = avformat_new_stream(mOutputFormatContext, 0); AVCodec * videoCodec = avcodec_find_encoder(mOutputFormatContext->oformat->video_codec); if (!videoCodec) { @@ -116,16 +138,12 @@ bool UBFFmpegVideoEncoder::init() return false; } - mVideoStream = avformat_new_stream(mOutputFormatContext, 0); - mVideoStream->time_base = {1, mTimebase}; - - avcodec_get_context_defaults3(mVideoStream->codec, videoCodec); AVCodecContext* c = avcodec_alloc_context3(videoCodec); c->bit_rate = videoBitsPerSecond(); c->width = videoSize().width(); c->height = videoSize().height(); - c->time_base = {1, mTimebase}; + c->time_base = {1, mVideoTimebase}; c->gop_size = 10; c->max_b_frames = 0; c->pix_fmt = AV_PIX_FMT_YUV420P; @@ -161,10 +179,77 @@ bool UBFFmpegVideoEncoder::init() // Audio codec and context // ------------------------------------- - /* - AVCodec * audioCodec = avcodec_find_encoder(mOutputFormatContext->oformat->audio_codec); - mAudioStream = avformat_new_stream(mOutputFormatContext, audioCodec); - */ + if (mShouldRecordAudio) { + + // Microphone input + if (!mAudioInput->init()) { + setLastErrorMessage("Couldn't initialize audio input"); + return false; + } + + + int inChannelCount = mAudioInput->channelCount(); + int inSampleRate = mAudioInput->sampleRate(); + int inSampleSize = mAudioInput->sampleSize(); + + qDebug() << "inChannelCount = " << inChannelCount; + qDebug() << "inSampleRate = " << inSampleRate; + qDebug() << "inSampleSize = " << inSampleSize; + + // Codec + AVCodec * audioCodec = avcodec_find_encoder(mOutputFormatContext->oformat->audio_codec); + + if (!audioCodec) { + setLastErrorMessage("Audio codec not found"); + return false; + } + + mAudioStream = avformat_new_stream(mOutputFormatContext, audioCodec); + mAudioStream->id = mOutputFormatContext->nb_streams-1; + + c = mAudioStream->codec; + + c->bit_rate = 96000; + c->sample_fmt = audioCodec->sample_fmts[0]; // FLTP by default for AAC + c->sample_rate = mAudioSampleRate; + c->channels = 2; + c->channel_layout = av_get_default_channel_layout(c->channels); + c->profile = FF_PROFILE_AAC_MAIN; + c->time_base = {1, mAudioSampleRate}; + + if (mOutputFormatContext->oformat->flags & AVFMT_GLOBALHEADER) + c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; + + ret = avcodec_open2(c, audioCodec, NULL); + + if (ret < 0) { + setLastErrorMessage(QString("Couldn't open audio codec: ") + avErrorToQString(ret)); + return false; + } + + // Resampling / format converting context + mSwrContext = swr_alloc(); + if (!mSwrContext) { + setLastErrorMessage("Could not allocate resampler context"); + return false; + } + + av_opt_set_int(mSwrContext, "in_channel_count", inChannelCount, 0); + av_opt_set_int(mSwrContext, "in_sample_rate", inSampleRate, 0); + av_opt_set_sample_fmt(mSwrContext, "in_sample_fmt", (AVSampleFormat)mAudioInput->sampleFormat(), 0); + av_opt_set_int(mSwrContext, "out_channel_count", c->channels, 0); + av_opt_set_int(mSwrContext, "out_sample_rate", c->sample_rate, 0); + av_opt_set_sample_fmt(mSwrContext, "out_sample_fmt", c->sample_fmt, 0); + + ret = swr_init(mSwrContext); + if (ret < 0) { + setLastErrorMessage(QString("Couldn't initialize the resampling context: ") + avErrorToQString(ret)); + return false; + } + + // Buffer for resampled/converted audio + mAudioOutBuffer = av_audio_fifo_alloc(c->sample_fmt, c->channels, c->frame_size); + } // Open the output file @@ -185,8 +270,14 @@ bool UBFFmpegVideoEncoder::init() return true; } + +/** + * This function should be called every time a new "screenshot" is ready. + * The image is converted to the right format and sent to the encoder. + */ void UBFFmpegVideoEncoder::newPixmap(const QImage &pImage, long timestamp) { + // really necessary? static bool isFirstFrame = true; if (isFirstFrame) { timestamp = 0; @@ -201,16 +292,16 @@ void UBFFmpegVideoEncoder::newPixmap(const QImage &pImage, long timestamp) else { // First send any queued frames, then the latest one while (!mPendingFrames.isEmpty()) { - AVFrame* avFrame = convertFrame(mPendingFrames.dequeue()); + AVFrame* avFrame = convertImageFrame(mPendingFrames.dequeue()); if (avFrame) mVideoWorker->queueFrame(avFrame); } // note: if converting the frame turns out to be too slow to do here, it - // can always be done from the worker thread (in thta case, + // can always be done from the worker thread (in that case, // the worker's queue would contain ImageFrames rather than AVFrames) - AVFrame* avFrame = convertFrame({pImage, timestamp}); + AVFrame* avFrame = convertImageFrame({pImage, timestamp}); if (avFrame) mVideoWorker->queueFrame(avFrame); @@ -219,17 +310,18 @@ void UBFFmpegVideoEncoder::newPixmap(const QImage &pImage, long timestamp) } } -/** Convert a frame consisting of a QImage and timestamp to an AVFrame +/** + * Convert a frame consisting of a QImage and timestamp to an AVFrame * with the right pixel format and PTS */ -AVFrame* UBFFmpegVideoEncoder::convertFrame(ImageFrame frame) +AVFrame* UBFFmpegVideoEncoder::convertImageFrame(ImageFrame frame) { AVFrame* avFrame = av_frame_alloc(); avFrame->format = mVideoStream->codec->pix_fmt; avFrame->width = mVideoStream->codec->width; avFrame->height = mVideoStream->codec->height; - avFrame->pts = mTimebase * frame.timestamp / 1000; + avFrame->pts = mVideoTimebase * frame.timestamp / 1000; const uchar * rgbImage = frame.image.bits(); @@ -254,6 +346,93 @@ AVFrame* UBFFmpegVideoEncoder::convertFrame(ImageFrame frame) return avFrame; } +void UBFFmpegVideoEncoder::onAudioAvailable(QByteArray data) +{ + if (!data.isEmpty()) + processAudio(data); +} + +/** +* Resample and convert audio to match the encoder's settings and queue the +* output. If enough output data is available, it is packaged into AVFrames and +* sent to the encoder thread. +*/ +void UBFFmpegVideoEncoder::processAudio(QByteArray &data) +{ + int ret; + AVCodecContext* codecContext = mAudioStream->codec; + + const char * inSamples = data.constData(); + + // The number of samples (per channel) in the input + int inSamplesCount = data.size() / ((mAudioInput->sampleSize() / 8) * mAudioInput->channelCount()); + + // The number of samples we will get after conversion + int outSamplesCount = swr_get_out_samples(mSwrContext, inSamplesCount); + + // Allocate output samples + uint8_t ** outSamples = NULL; + int outSamplesLineSize; + + ret = av_samples_alloc_array_and_samples(&outSamples, &outSamplesLineSize, + codecContext->channels, outSamplesCount, + codecContext->sample_fmt, 0); + if (ret < 0) { + qDebug() << "Could not allocate audio samples" << avErrorToQString(ret); + return; + } + + // Convert to destination format + ret = swr_convert(mSwrContext, + outSamples, outSamplesCount, + (const uint8_t **)&inSamples, inSamplesCount); + if (ret < 0) { + qDebug() << "Error converting audio samples: " << avErrorToQString(ret); + return; + } + + // Append the converted samples to the out buffer. + ret = av_audio_fifo_write(mAudioOutBuffer, (void**)outSamples, outSamplesCount); + if (ret < 0) { + qDebug() << "Could not write to FIFO queue: " << avErrorToQString(ret); + return; + } + + // Keep the data queued until next call if the encoder thread isn't running + if (!mVideoWorker->isRunning()) + return; + + bool framesAdded = false; + while (av_audio_fifo_size(mAudioOutBuffer) > codecContext->frame_size) { + AVFrame * avFrame = av_frame_alloc(); + avFrame->nb_samples = codecContext->frame_size; + avFrame->channel_layout = codecContext->channel_layout; + avFrame->format = codecContext->sample_fmt; + avFrame->sample_rate = codecContext->sample_rate; + avFrame->pts = mAudioFrameCount; + + ret = av_frame_get_buffer(avFrame, 0); + if (ret < 0) { + qDebug() << "Couldn't allocate frame: " << avErrorToQString(ret); + break; + } + + ret = av_audio_fifo_read(mAudioOutBuffer, (void**)avFrame->data, codecContext->frame_size); + if (ret < 0) + qDebug() << "Could not read from FIFO queue: " << avErrorToQString(ret); + + else { + mAudioFrameCount += codecContext->frame_size; + + mVideoWorker->queueAudio(avFrame); + framesAdded = true; + } + } + + if (framesAdded) + mVideoWorker->mWaitCondition.wakeAll(); +} + void UBFFmpegVideoEncoder::finishEncoding() { qDebug() << "VideoEncoder::finishEncoding called"; @@ -264,7 +443,7 @@ void UBFFmpegVideoEncoder::finishEncoding() do { // TODO: get rid of duplicated code (videoWorker does almost exactly this during encoding) - AVPacket* packet = mVideoWorker->mPacket; + AVPacket* packet = mVideoWorker->mVideoPacket; if (avcodec_encode_video2(mVideoStream->codec, packet, NULL, &gotOutput) < 0) { setLastErrorMessage("Couldn't encode frame to video"); @@ -272,9 +451,9 @@ void UBFFmpegVideoEncoder::finishEncoding() } if (gotOutput) { AVRational codecTimebase = mVideoStream->codec->time_base; - AVRational streamTimebase = mVideoStream->time_base; + AVRational streamVideoTimebase = mVideoStream->time_base; - av_packet_rescale_ts(packet, codecTimebase, streamTimebase); + av_packet_rescale_ts(packet, codecTimebase, streamVideoTimebase); packet->stream_index = mVideoStream->index; av_interleaved_write_frame(mOutputFormatContext, packet); @@ -282,16 +461,48 @@ void UBFFmpegVideoEncoder::finishEncoding() } } while (gotOutput); + if (mShouldRecordAudio) { + + int gotOutput, ret; + do { + + AVPacket* packet = mVideoWorker->mAudioPacket; + + ret = avcodec_encode_audio2(mAudioStream->codec, packet, NULL, &gotOutput); + if (ret < 0) + setLastErrorMessage("Couldn't encode frame to audio"); + + else if (gotOutput) { + AVRational codecTimebase = mAudioStream->codec->time_base; + AVRational streamVideoTimebase = mAudioStream->time_base; + + av_packet_rescale_ts(packet, codecTimebase, streamVideoTimebase); + packet->stream_index = mAudioStream->index; + + av_interleaved_write_frame(mOutputFormatContext, packet); + av_packet_unref(packet); + } + } while (gotOutput); + + } + av_write_trailer(mOutputFormatContext); avio_close(mOutputFormatContext->pb); avcodec_close(mVideoStream->codec); sws_freeContext(mSwsContext); + + if (mShouldRecordAudio) { + avcodec_close(mAudioStream->codec); + swr_free(&mSwrContext); + } + avformat_free_context(mOutputFormatContext); emit encodingFinished(true); } + //------------------------------------------------------------------------- // Worker //------------------------------------------------------------------------- @@ -301,7 +512,8 @@ UBFFmpegVideoEncoderWorker::UBFFmpegVideoEncoderWorker(UBFFmpegVideoEncoder* con { mStopRequested = false; mIsRunning = false; - mPacket = new AVPacket(); + mVideoPacket = new AVPacket(); + mAudioPacket = new AVPacket(); } UBFFmpegVideoEncoderWorker::~UBFFmpegVideoEncoderWorker() @@ -316,11 +528,23 @@ void UBFFmpegVideoEncoderWorker::stopEncoding() void UBFFmpegVideoEncoderWorker::queueFrame(AVFrame* frame) { - mFrameQueueMutex.lock(); - mFrameQueue.enqueue(frame); - mFrameQueueMutex.unlock(); + if (frame) { + mFrameQueueMutex.lock(); + mImageQueue.enqueue(frame); + mFrameQueueMutex.unlock(); + } } +void UBFFmpegVideoEncoderWorker::queueAudio(AVFrame* frame) +{ + if (frame) { + mFrameQueueMutex.lock(); + mAudioQueue.enqueue(frame); + mFrameQueueMutex.unlock(); + } +} + + /** * The main encoding function. Takes the queued image frames and * assembles them into the video @@ -333,15 +557,13 @@ void UBFFmpegVideoEncoderWorker::runEncoding() mFrameQueueMutex.lock(); mWaitCondition.wait(&mFrameQueueMutex); - while (!mFrameQueue.isEmpty()) { + while (!mImageQueue.isEmpty()) { writeLatestVideoFrame(); } - /* while (!mAudioQueue.isEmpty()) { writeLatestAudioFrame(); } - */ mFrameQueueMutex.unlock(); } @@ -351,31 +573,31 @@ void UBFFmpegVideoEncoderWorker::runEncoding() void UBFFmpegVideoEncoderWorker::writeLatestVideoFrame() { - AVFrame* frame = mFrameQueue.dequeue(); + AVFrame* frame = mImageQueue.dequeue(); int gotOutput; - av_init_packet(mPacket); - mPacket->data = NULL; - mPacket->size = 0; + av_init_packet(mVideoPacket); + mVideoPacket->data = NULL; + mVideoPacket->size = 0; - // qDebug() << "Encoding frame to video. Pts: " << frame->pts << "/" << mController->mTimebase; + // qDebug() << "Encoding frame to video. Pts: " << frame->pts << "/" << mController->mVideoTimebase; - if (avcodec_encode_video2(mController->mVideoStream->codec, mPacket, frame, &gotOutput) < 0) - emit error("Error encoding frame to video"); + if (avcodec_encode_video2(mController->mVideoStream->codec, mVideoPacket, frame, &gotOutput) < 0) + emit error("Error encoding video frame"); if (gotOutput) { AVRational codecTimebase = mController->mVideoStream->codec->time_base; - AVRational streamTimebase = mController->mVideoStream->time_base; + AVRational streamVideoTimebase = mController->mVideoStream->time_base; // recalculate the timestamp to match the stream's timebase - av_packet_rescale_ts(mPacket, codecTimebase, streamTimebase); - mPacket->stream_index = mController->mVideoStream->index; + av_packet_rescale_ts(mVideoPacket, codecTimebase, streamVideoTimebase); + mVideoPacket->stream_index = mController->mVideoStream->index; - // qDebug() << "Writing encoded packet to file; pts: " << mPacket->pts << "/" << streamTimebase.den; + // qDebug() << "Writing encoded packet to file; pts: " << mVideoPacket->pts << "/" << streamVideoTimebase.den; - av_interleaved_write_frame(mController->mOutputFormatContext, mPacket); - av_packet_unref(mPacket); + av_interleaved_write_frame(mController->mOutputFormatContext, mVideoPacket); + av_packet_unref(mVideoPacket); } // Duct-tape solution. I assume there's a better way of doing this, but: @@ -387,10 +609,42 @@ void UBFFmpegVideoEncoderWorker::writeLatestVideoFrame() if (firstRun) { firstRun = false; frame->pts += 1; - mFrameQueue.enqueue(frame); // only works when the queue is empty at this point. todo: clean this up! + mImageQueue.enqueue(frame); // only works when the queue is empty at this point. todo: clean this up! } else // free the frame av_frame_free(&frame); } +void UBFFmpegVideoEncoderWorker::writeLatestAudioFrame() +{ + AVFrame *frame = mAudioQueue.dequeue(); + + int gotOutput, ret; + + av_init_packet(mAudioPacket); + mAudioPacket->data = NULL; + mAudioPacket->size = 0; + + //qDebug() << "Encoding audio frame"; + + ret = avcodec_encode_audio2(mController->mAudioStream->codec, mAudioPacket, frame, &gotOutput); + if (ret < 0) + emit error(QString("Error encoding audio frame: ") + avErrorToQString(ret)); + + else if (gotOutput) { + //qDebug() << "Writing audio frame to stream"; + + AVRational codecTimebase = mController->mAudioStream->codec->time_base; + AVRational streamVideoTimebase = mController->mAudioStream->time_base; + + av_packet_rescale_ts(mAudioPacket, codecTimebase, streamVideoTimebase); + mAudioPacket->stream_index = mController->mAudioStream->index; + + av_interleaved_write_frame(mController->mOutputFormatContext, mAudioPacket); + av_packet_unref(mAudioPacket); + } + + av_frame_free(&frame); +} + diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h index 4dacaaf6..83f74fd7 100644 --- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h @@ -5,20 +5,23 @@ extern "C" { #include #include #include + #include #include #include #include #include + #include #include + #include } #include -#include #include #include #include "podcast/UBAbstractVideoEncoder.h" +#include "podcast/ffmpeg/UBMicrophoneInput.h" class UBFFmpegVideoEncoderWorker; class UBPodcastController; @@ -45,7 +48,6 @@ public: void setRecordAudio(bool pRecordAudio) { mShouldRecordAudio = pRecordAudio; } - signals: void encodingFinished(bool ok); @@ -53,6 +55,7 @@ signals: private slots: void setLastErrorMessage(const QString& pMessage); + void onAudioAvailable(QByteArray data); void finishEncoding(); private: @@ -63,32 +66,42 @@ private: long timestamp; // unit: ms }; - AVFrame* convertFrame(ImageFrame frame); + AVFrame* convertImageFrame(ImageFrame frame); + AVFrame* convertAudio(QByteArray data); + void processAudio(QByteArray& data); bool init(); - // Queue for any pixmap that might be sent before the encoder is ready - QQueue mPendingFrames; - QString mLastErrorMessage; - bool mShouldRecordAudio; QThread* mVideoEncoderThread; UBFFmpegVideoEncoderWorker* mVideoWorker; // Muxer + // ------------------------------------------ AVFormatContext* mOutputFormatContext; - int mTimebase; + AVStream* mVideoStream; + AVStream* mAudioStream; // Video - AVStream* mVideoStream; + // ------------------------------------------ + QQueue mPendingFrames; struct SwsContext * mSwsContext; - // Audio - AVStream* mAudioStream; + int mVideoTimebase; + // Audio + // ------------------------------------------ + bool mShouldRecordAudio; - FILE * mFile; + UBMicrophoneInput * mAudioInput; + struct SwrContext * mSwrContext; + /// Queue for audio that has been rescaled/converted but not encoded yet + AVAudioFifo *mAudioOutBuffer; + /// Sample rate for encoded audio + int mAudioSampleRate; + /// Total audio frames sent to encoder + int mAudioFrameCount; }; @@ -105,6 +118,7 @@ public: bool isRunning() { return mIsRunning; } void queueFrame(AVFrame* frame); + void queueAudio(AVFrame *frame); public slots: void runEncoding(); @@ -117,19 +131,23 @@ signals: private: void writeLatestVideoFrame(); + void writeLatestAudioFrame(); UBFFmpegVideoEncoder* mController; // std::atomic is C++11. This won't work with msvc2010, so a - // newer compiler must be used if this is to be used on Windows + // newer compiler must be used if this class is to be used on Windows std::atomic mStopRequested; std::atomic mIsRunning; - QQueue mFrameQueue; + QQueue mImageQueue; + QQueue mAudioQueue; + QMutex mFrameQueueMutex; QWaitCondition mWaitCondition; - AVPacket* mPacket; + AVPacket* mVideoPacket; + AVPacket* mAudioPacket; }; #endif // UBFFMPEGVIDEOENCODER_H diff --git a/src/podcast/ffmpeg/UBMicrophoneInput.cpp b/src/podcast/ffmpeg/UBMicrophoneInput.cpp new file mode 100644 index 00000000..b9c3cf2c --- /dev/null +++ b/src/podcast/ffmpeg/UBMicrophoneInput.cpp @@ -0,0 +1,211 @@ +#include "UBMicrophoneInput.h" + +UBMicrophoneInput::UBMicrophoneInput() + : mAudioInput(NULL) + , mIODevice(NULL) + , mSeekPos(0) +{ +} + +UBMicrophoneInput::~UBMicrophoneInput() +{ + if (mAudioInput) + delete mAudioInput; +} + +int UBMicrophoneInput::channelCount() +{ + return mAudioFormat.channelCount(); +} + +int UBMicrophoneInput::sampleRate() +{ + return mAudioFormat.sampleRate(); +} + +/* Return the sample size in bits */ +int UBMicrophoneInput::sampleSize() +{ + return mAudioFormat.sampleSize(); +} + +/** Return the sample format in FFMpeg style (AVSampleFormat enum) */ +int UBMicrophoneInput::sampleFormat() +{ + enum AVSampleFormat { + AV_SAMPLE_FMT_NONE = -1, + AV_SAMPLE_FMT_U8, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_S32, + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_DBL, + AV_SAMPLE_FMT_U8P, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NB + }; + + int sampleSize = mAudioFormat.sampleSize(); + QAudioFormat::SampleType sampleType = mAudioFormat.sampleType(); + + // qDebug() << "Input sample format: " << sampleSize << "bits " << sampleType; + + switch (sampleType) { + case QAudioFormat::Unknown: + return AV_SAMPLE_FMT_NONE; + + case QAudioFormat::SignedInt: + if (sampleSize == 16) + return AV_SAMPLE_FMT_S16; + if (sampleSize == 32) + return AV_SAMPLE_FMT_S32; + + case QAudioFormat::UnSignedInt: + if (sampleSize == 8) + return AV_SAMPLE_FMT_U8; + + case QAudioFormat::Float: + return AV_SAMPLE_FMT_FLT; + + default: + return AV_SAMPLE_FMT_NONE; + } +} + +QString UBMicrophoneInput::codec() +{ + return mAudioFormat.codec(); +} + +qint64 UBMicrophoneInput::processUSecs() const +{ + return mAudioInput->processedUSecs(); +} + +bool UBMicrophoneInput::init() +{ + if (mAudioDeviceInfo.isNull()) { + qWarning("No audio input device selected; using default"); + mAudioDeviceInfo = QAudioDeviceInfo::defaultInputDevice(); + } + + qDebug() << "Input device name: " << mAudioDeviceInfo.deviceName(); + + mAudioFormat = mAudioDeviceInfo.preferredFormat(); + + mAudioInput = new QAudioInput(mAudioDeviceInfo, mAudioFormat, NULL); + //mAudioInput->setNotifyInterval(100); + + connect(mAudioInput, SIGNAL(stateChanged(QAudio::State)), + this, SLOT(onAudioInputStateChanged(QAudio::State))); + + return true; +} + +void UBMicrophoneInput::start() +{ + qDebug() << "starting audio input"; + + mIODevice = mAudioInput->start(); + + connect(mIODevice, SIGNAL(readyRead()), + this, SLOT(onDataReady())); + + if (mAudioInput->error() == QAudio::OpenError) + qWarning() << "Error opening audio input"; +} + +void UBMicrophoneInput::stop() +{ + mAudioInput->stop(); +} + +QStringList UBMicrophoneInput::availableDevicesNames() +{ + QStringList names; + QList devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); + + foreach (QAudioDeviceInfo device, devices) { + names.push_back(device.deviceName()); + } + + return names; +} + +void UBMicrophoneInput::setInputDevice(QString name) +{ + if (name.isEmpty()) { + mAudioDeviceInfo = QAudioDeviceInfo::defaultInputDevice(); + return; + } + + QList devices = QAudioDeviceInfo::availableDevices(QAudio::AudioInput); + bool found = false; + + foreach (QAudioDeviceInfo device, devices) { + if (device.deviceName() == name) { + mAudioDeviceInfo = device; + found = true; + break; + } + } + + if (!found) { + qWarning() << "Audio input device not found; using default instead"; + mAudioDeviceInfo = QAudioDeviceInfo::defaultInputDevice(); + } + +} + +void UBMicrophoneInput::onDataReady() +{ + int numBytes = mAudioInput->bytesReady(); + + if (numBytes > 0) + emit dataAvailable(mIODevice->read(numBytes)); +} + +void UBMicrophoneInput::onAudioInputStateChanged(QAudio::State state) +{ + qDebug() << "Audio input state changed to " << state; + switch (state) { + case QAudio::StoppedState: + if (mAudioInput->error() != QAudio::NoError) { + emit error(getErrorString(mAudioInput->error())); + } + break; + + // handle other states? + + default: + break; + } +} + + +/** + * @brief Return a meaningful error string based on QAudio error codes + */ +QString UBMicrophoneInput::getErrorString(QAudio::Error errorCode) +{ + switch (errorCode) { + case QAudio::NoError : + return ""; + + case QAudio::OpenError : + return "Couldn't open the audio device"; + + case QAudio::IOError : + return "Error reading from audio device"; + + case QAudio::UnderrunError : + return "Underrun error"; + + case QAudio::FatalError : + return "Fatal error; audio device unusable"; + + } + return ""; +} diff --git a/src/podcast/ffmpeg/UBMicrophoneInput.h b/src/podcast/ffmpeg/UBMicrophoneInput.h new file mode 100644 index 00000000..8ba306d0 --- /dev/null +++ b/src/podcast/ffmpeg/UBMicrophoneInput.h @@ -0,0 +1,57 @@ +#ifndef UBMICROPHONEINPUT_H +#define UBMICROPHONEINPUT_H + +#include +#include + +/** + * @brief The UBMicrophoneInput class captures uncompressed sound from a microphone + */ +class UBMicrophoneInput : public QObject +{ + Q_OBJECT + +public: + UBMicrophoneInput(); + virtual ~UBMicrophoneInput(); + + bool init(); + void start(); + void stop(); + + static QStringList availableDevicesNames(); + void setInputDevice(QString name = ""); + + int channelCount(); + int sampleRate(); + int sampleSize(); + int sampleFormat(); + QString codec(); + + qint64 processUSecs() const; + +signals: + /// Send the new volume, between 0 and 255 + void audioLevelChanged(quint8 level); + + /// Emitted when new audio data is available + void dataAvailable(QByteArray data); + + void error(QString message); + +private slots: + void onAudioInputStateChanged(QAudio::State state); + void onDataReady(); + +private: + QString getErrorString(QAudio::Error errorCode); + + QAudioInput* mAudioInput; + QIODevice * mIODevice; + QAudioDeviceInfo mAudioDeviceInfo; + QAudioFormat mAudioFormat; + + qint64 mSeekPos; +}; + +#endif // UBMICROPHONEINPUT_H diff --git a/src/podcast/podcast.pri b/src/podcast/podcast.pri index 0df7b13e..5b10ee9b 100644 --- a/src/podcast/podcast.pri +++ b/src/podcast/podcast.pri @@ -3,13 +3,15 @@ HEADERS += src/podcast/UBPodcastController.h \ src/podcast/UBAbstractVideoEncoder.h \ src/podcast/UBPodcastRecordingPalette.h \ src/podcast/youtube/UBYouTubePublisher.h \ - src/podcast/intranet/UBIntranetPodcastPublisher.h + src/podcast/intranet/UBIntranetPodcastPublisher.h \ + $$PWD/ffmpeg/UBMicrophoneInput.h SOURCES += src/podcast/UBPodcastController.cpp \ src/podcast/UBAbstractVideoEncoder.cpp \ src/podcast/UBPodcastRecordingPalette.cpp \ src/podcast/youtube/UBYouTubePublisher.cpp \ - src/podcast/intranet/UBIntranetPodcastPublisher.cpp + src/podcast/intranet/UBIntranetPodcastPublisher.cpp \ + $$PWD/ffmpeg/UBMicrophoneInput.cpp win32 { From 518b7d26d44c3c8e914609eee70a650e533a7500 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 6 May 2016 12:59:42 +0200 Subject: [PATCH 012/134] Clean-up and removal of duplicate code --- src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp | 243 +++++++------------- src/podcast/ffmpeg/UBFFmpegVideoEncoder.h | 15 +- 2 files changed, 96 insertions(+), 162 deletions(-) diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp index 09fcb5b4..498fbae4 100644 --- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp @@ -1,10 +1,8 @@ #include "UBFFmpegVideoEncoder.h" -// Future proofing -#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1) -#define av_frame_alloc avcodec_alloc_frame -#define av_frame_free avcodec_free_frame -#endif +//------------------------------------------------------------------------- +// Utility functions +//------------------------------------------------------------------------- QString avErrorToQString(int errnum) { @@ -15,14 +13,51 @@ QString avErrorToQString(int errnum) } /** - * @brief Constructor for the ffmpeg video encoder - * - * - * This class provides an interface between the screencast controller and the ffmpeg - * back-end. It initializes the audio and video encoders and frees them when done; - * a worker thread handles the actual encoding and writing of frames. + * @brief Write a given frame to the audio stream or, if a null frame is passed, flush the stream. * + * @param frame An AVFrame to be written to the stream, or NULL to flush the stream + * @param packet A (reusable) packet, used to temporarily store frame data + * @param stream The stream to write to + * @param outputFormatContext The output format context */ +void writeFrame(AVFrame *frame, AVPacket *packet, AVStream *stream, AVFormatContext *outputFormatContext) +{ + int gotOutput, ret; + + av_init_packet(packet); + + do { + if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) + ret = avcodec_encode_audio2(stream->codec, packet, frame, &gotOutput); + else + ret = avcodec_encode_video2(stream->codec, packet, frame, &gotOutput); + + if (ret < 0) + qWarning() << "Couldn't encode audio frame: " << avErrorToQString(ret); + + else if (gotOutput) { + AVRational codecTimebase = stream->codec->time_base; + AVRational streamVideoTimebase = stream->time_base; + + av_packet_rescale_ts(packet, codecTimebase, streamVideoTimebase); + packet->stream_index = stream->index; + + av_interleaved_write_frame(outputFormatContext, packet); + av_packet_unref(packet); + } + + } while (gotOutput && !frame); +} + +void flushStream(AVPacket *packet, AVStream *stream, AVFormatContext *outputFormatContext) +{ + writeFrame(NULL, packet, stream, outputFormatContext); +} + +//------------------------------------------------------------------------- +// UBFFmpegVideoEncoder +//------------------------------------------------------------------------- + UBFFmpegVideoEncoder::UBFFmpegVideoEncoder(QObject* parent) : UBAbstractVideoEncoder(parent) , mOutputFormatContext(NULL) @@ -34,18 +69,8 @@ UBFFmpegVideoEncoder::UBFFmpegVideoEncoder(QObject* parent) , mAudioSampleRate(44100) , mAudioFrameCount(0) { - if (mShouldRecordAudio) { - mAudioInput = new UBMicrophoneInput(); - - connect(mAudioInput, SIGNAL(audioLevelChanged(quint8)), - this, SIGNAL(audioLevelChanged(quint8))); - - connect(mAudioInput, SIGNAL(dataAvailable(QByteArray)), - this, SLOT(onAudioAvailable(QByteArray))); - } mVideoTimebase = 100 * framesPerSecond(); - qDebug() << "timebase: " << mVideoTimebase; mVideoEncoderThread = new QThread; mVideoWorker = new UBFFmpegVideoEncoderWorker(this); @@ -78,7 +103,7 @@ UBFFmpegVideoEncoder::~UBFFmpegVideoEncoder() void UBFFmpegVideoEncoder::setLastErrorMessage(const QString& pMessage) { - qDebug() << "FFmpeg video encoder:" << pMessage; + qWarning() << "FFmpeg video encoder:" << pMessage; mLastErrorMessage = pMessage; } @@ -182,12 +207,20 @@ bool UBFFmpegVideoEncoder::init() if (mShouldRecordAudio) { // Microphone input + + mAudioInput = new UBMicrophoneInput(); + + connect(mAudioInput, SIGNAL(audioLevelChanged(quint8)), + this, SIGNAL(audioLevelChanged(quint8))); + + connect(mAudioInput, SIGNAL(dataAvailable(QByteArray)), + this, SLOT(onAudioAvailable(QByteArray))); + if (!mAudioInput->init()) { setLastErrorMessage("Couldn't initialize audio input"); return false; } - int inChannelCount = mAudioInput->channelCount(); int inSampleRate = mAudioInput->sampleRate(); int inSampleSize = mAudioInput->sampleSize(); @@ -197,6 +230,7 @@ bool UBFFmpegVideoEncoder::init() qDebug() << "inSampleSize = " << inSampleSize; // Codec + AVCodec * audioCodec = avcodec_find_encoder(mOutputFormatContext->oformat->audio_codec); if (!audioCodec) { @@ -227,7 +261,8 @@ bool UBFFmpegVideoEncoder::init() return false; } - // Resampling / format converting context + // The input (raw sound from the microphone) may not match the codec's sampling rate, + // sample format or number of channels; we use libswresample to convert and resample it mSwrContext = swr_alloc(); if (!mSwrContext) { setLastErrorMessage("Could not allocate resampler context"); @@ -277,13 +312,6 @@ bool UBFFmpegVideoEncoder::init() */ void UBFFmpegVideoEncoder::newPixmap(const QImage &pImage, long timestamp) { - // really necessary? - static bool isFirstFrame = true; - if (isFirstFrame) { - timestamp = 0; - isFirstFrame = false; - } - if (!mVideoWorker->isRunning()) { qDebug() << "Encoder worker thread not running. Queuing frame."; mPendingFrames.enqueue({pImage, timestamp}); @@ -294,7 +322,7 @@ void UBFFmpegVideoEncoder::newPixmap(const QImage &pImage, long timestamp) while (!mPendingFrames.isEmpty()) { AVFrame* avFrame = convertImageFrame(mPendingFrames.dequeue()); if (avFrame) - mVideoWorker->queueFrame(avFrame); + mVideoWorker->queueVideoFrame(avFrame); } // note: if converting the frame turns out to be too slow to do here, it @@ -303,7 +331,7 @@ void UBFFmpegVideoEncoder::newPixmap(const QImage &pImage, long timestamp) AVFrame* avFrame = convertImageFrame({pImage, timestamp}); if (avFrame) - mVideoWorker->queueFrame(avFrame); + mVideoWorker->queueVideoFrame(avFrame); // signal the worker that frames are available mVideoWorker->mWaitCondition.wakeAll(); @@ -331,7 +359,7 @@ AVFrame* UBFFmpegVideoEncoder::convertImageFrame(ImageFrame frame) if (av_image_alloc(avFrame->data, avFrame->linesize, mVideoStream->codec->width, mVideoStream->codec->height, mVideoStream->codec->pix_fmt, 32) < 0) { - setLastErrorMessage("Couldn't allocate image"); + qWarning() << "Couldn't allocate image"; return NULL; } @@ -378,7 +406,7 @@ void UBFFmpegVideoEncoder::processAudio(QByteArray &data) codecContext->channels, outSamplesCount, codecContext->sample_fmt, 0); if (ret < 0) { - qDebug() << "Could not allocate audio samples" << avErrorToQString(ret); + qWarning() << "Could not allocate audio samples" << avErrorToQString(ret); return; } @@ -387,14 +415,14 @@ void UBFFmpegVideoEncoder::processAudio(QByteArray &data) outSamples, outSamplesCount, (const uint8_t **)&inSamples, inSamplesCount); if (ret < 0) { - qDebug() << "Error converting audio samples: " << avErrorToQString(ret); + qWarning() << "Error converting audio samples: " << avErrorToQString(ret); return; } // Append the converted samples to the out buffer. ret = av_audio_fifo_write(mAudioOutBuffer, (void**)outSamples, outSamplesCount); if (ret < 0) { - qDebug() << "Could not write to FIFO queue: " << avErrorToQString(ret); + qWarning() << "Could not write to FIFO queue: " << avErrorToQString(ret); return; } @@ -413,18 +441,18 @@ void UBFFmpegVideoEncoder::processAudio(QByteArray &data) ret = av_frame_get_buffer(avFrame, 0); if (ret < 0) { - qDebug() << "Couldn't allocate frame: " << avErrorToQString(ret); + qWarning() << "Couldn't allocate frame: " << avErrorToQString(ret); break; } ret = av_audio_fifo_read(mAudioOutBuffer, (void**)avFrame->data, codecContext->frame_size); if (ret < 0) - qDebug() << "Could not read from FIFO queue: " << avErrorToQString(ret); + qWarning() << "Could not read from FIFO queue: " << avErrorToQString(ret); else { mAudioFrameCount += codecContext->frame_size; - mVideoWorker->queueAudio(avFrame); + mVideoWorker->queueAudioFrame(avFrame); framesAdded = true; } } @@ -437,58 +465,14 @@ void UBFFmpegVideoEncoder::finishEncoding() { qDebug() << "VideoEncoder::finishEncoding called"; - // Some frames may not be encoded, so we call avcodec_encode_video2 until they're all done - - int gotOutput; - do { - // TODO: get rid of duplicated code (videoWorker does almost exactly this during encoding) + flushStream(mVideoWorker->mVideoPacket, mVideoStream, mOutputFormatContext); - AVPacket* packet = mVideoWorker->mVideoPacket; - - if (avcodec_encode_video2(mVideoStream->codec, packet, NULL, &gotOutput) < 0) { - setLastErrorMessage("Couldn't encode frame to video"); - continue; - } - if (gotOutput) { - AVRational codecTimebase = mVideoStream->codec->time_base; - AVRational streamVideoTimebase = mVideoStream->time_base; - - av_packet_rescale_ts(packet, codecTimebase, streamVideoTimebase); - packet->stream_index = mVideoStream->index; - - av_interleaved_write_frame(mOutputFormatContext, packet); - av_packet_unref(packet); - } - } while (gotOutput); - - if (mShouldRecordAudio) { - - int gotOutput, ret; - do { - - AVPacket* packet = mVideoWorker->mAudioPacket; - - ret = avcodec_encode_audio2(mAudioStream->codec, packet, NULL, &gotOutput); - if (ret < 0) - setLastErrorMessage("Couldn't encode frame to audio"); - - else if (gotOutput) { - AVRational codecTimebase = mAudioStream->codec->time_base; - AVRational streamVideoTimebase = mAudioStream->time_base; - - av_packet_rescale_ts(packet, codecTimebase, streamVideoTimebase); - packet->stream_index = mAudioStream->index; - - av_interleaved_write_frame(mOutputFormatContext, packet); - av_packet_unref(packet); - } - } while (gotOutput); - - } + if (mShouldRecordAudio) + flushStream(mVideoWorker->mAudioPacket, mAudioStream, mOutputFormatContext); av_write_trailer(mOutputFormatContext); - avio_close(mOutputFormatContext->pb); + avcodec_close(mVideoStream->codec); sws_freeContext(mSwsContext); @@ -517,7 +501,13 @@ UBFFmpegVideoEncoderWorker::UBFFmpegVideoEncoderWorker(UBFFmpegVideoEncoder* con } UBFFmpegVideoEncoderWorker::~UBFFmpegVideoEncoderWorker() -{} +{ + if (mVideoPacket) + delete mVideoPacket; + + if (mAudioPacket) + delete mAudioPacket; +} void UBFFmpegVideoEncoderWorker::stopEncoding() { @@ -526,7 +516,7 @@ void UBFFmpegVideoEncoderWorker::stopEncoding() mWaitCondition.wakeAll(); } -void UBFFmpegVideoEncoderWorker::queueFrame(AVFrame* frame) +void UBFFmpegVideoEncoderWorker::queueVideoFrame(AVFrame* frame) { if (frame) { mFrameQueueMutex.lock(); @@ -535,7 +525,7 @@ void UBFFmpegVideoEncoderWorker::queueFrame(AVFrame* frame) } } -void UBFFmpegVideoEncoderWorker::queueAudio(AVFrame* frame) +void UBFFmpegVideoEncoderWorker::queueAudioFrame(AVFrame* frame) { if (frame) { mFrameQueueMutex.lock(); @@ -544,7 +534,6 @@ void UBFFmpegVideoEncoderWorker::queueAudio(AVFrame* frame) } } - /** * The main encoding function. Takes the queued image frames and * assembles them into the video @@ -574,77 +563,13 @@ void UBFFmpegVideoEncoderWorker::runEncoding() void UBFFmpegVideoEncoderWorker::writeLatestVideoFrame() { AVFrame* frame = mImageQueue.dequeue(); - - int gotOutput; - av_init_packet(mVideoPacket); - mVideoPacket->data = NULL; - mVideoPacket->size = 0; - - // qDebug() << "Encoding frame to video. Pts: " << frame->pts << "/" << mController->mVideoTimebase; - - if (avcodec_encode_video2(mController->mVideoStream->codec, mVideoPacket, frame, &gotOutput) < 0) - emit error("Error encoding video frame"); - - if (gotOutput) { - AVRational codecTimebase = mController->mVideoStream->codec->time_base; - AVRational streamVideoTimebase = mController->mVideoStream->time_base; - - - // recalculate the timestamp to match the stream's timebase - av_packet_rescale_ts(mVideoPacket, codecTimebase, streamVideoTimebase); - mVideoPacket->stream_index = mController->mVideoStream->index; - - // qDebug() << "Writing encoded packet to file; pts: " << mVideoPacket->pts << "/" << streamVideoTimebase.den; - - av_interleaved_write_frame(mController->mOutputFormatContext, mVideoPacket); - av_packet_unref(mVideoPacket); - } - - // Duct-tape solution. I assume there's a better way of doing this, but: - // some players like VLC show a black screen until the second frame (which - // can be several seconds after the first one). Simply duplicating the first frame - // seems to solve this problem, and also allows the thumbnail to be generated. - - static bool firstRun = true; - if (firstRun) { - firstRun = false; - frame->pts += 1; - mImageQueue.enqueue(frame); // only works when the queue is empty at this point. todo: clean this up! - } - else - // free the frame - av_frame_free(&frame); + writeFrame(frame, mVideoPacket, mController->mVideoStream, mController->mOutputFormatContext); + av_frame_free(&frame); } void UBFFmpegVideoEncoderWorker::writeLatestAudioFrame() { AVFrame *frame = mAudioQueue.dequeue(); - - int gotOutput, ret; - - av_init_packet(mAudioPacket); - mAudioPacket->data = NULL; - mAudioPacket->size = 0; - - //qDebug() << "Encoding audio frame"; - - ret = avcodec_encode_audio2(mController->mAudioStream->codec, mAudioPacket, frame, &gotOutput); - if (ret < 0) - emit error(QString("Error encoding audio frame: ") + avErrorToQString(ret)); - - else if (gotOutput) { - //qDebug() << "Writing audio frame to stream"; - - AVRational codecTimebase = mController->mAudioStream->codec->time_base; - AVRational streamVideoTimebase = mController->mAudioStream->time_base; - - av_packet_rescale_ts(mAudioPacket, codecTimebase, streamVideoTimebase); - mAudioPacket->stream_index = mController->mAudioStream->index; - - av_interleaved_write_frame(mController->mOutputFormatContext, mAudioPacket); - av_packet_unref(mAudioPacket); - } - + writeFrame(frame, mAudioPacket, mController->mAudioStream, mController->mOutputFormatContext); av_frame_free(&frame); } - diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h index 83f74fd7..9c6b6ab9 100644 --- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h @@ -26,6 +26,16 @@ extern "C" { class UBFFmpegVideoEncoderWorker; class UBPodcastController; +/** + * This class provides an interface between the podcast controller and the ffmpeg + * back-end. + * It includes all the necessary objects and methods to record video (muxer, audio and + * video streams and encoders, etc) from inputs consisting of raw PCM audio and raw RGBA + * images. + * + * A worker thread is used to encode and write the audio and video on-the-fly. + */ + class UBFFmpegVideoEncoder : public UBAbstractVideoEncoder { Q_OBJECT @@ -117,8 +127,8 @@ public: bool isRunning() { return mIsRunning; } - void queueFrame(AVFrame* frame); - void queueAudio(AVFrame *frame); + void queueVideoFrame(AVFrame* frame); + void queueAudioFrame(AVFrame* frame); public slots: void runEncoding(); @@ -128,7 +138,6 @@ signals: void encodingFinished(); void error(QString message); - private: void writeLatestVideoFrame(); void writeLatestAudioFrame(); From 1e731be171e6faaa6497329ef3379a489d269118 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Mon, 9 May 2016 13:03:54 +0200 Subject: [PATCH 013/134] Added audio level calculation for the VU meter --- src/podcast/ffmpeg/UBMicrophoneInput.cpp | 85 ++++++++++++++++++++++-- src/podcast/ffmpeg/UBMicrophoneInput.h | 3 + 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/podcast/ffmpeg/UBMicrophoneInput.cpp b/src/podcast/ffmpeg/UBMicrophoneInput.cpp index b9c3cf2c..20007409 100644 --- a/src/podcast/ffmpeg/UBMicrophoneInput.cpp +++ b/src/podcast/ffmpeg/UBMicrophoneInput.cpp @@ -50,7 +50,6 @@ int UBMicrophoneInput::sampleFormat() int sampleSize = mAudioFormat.sampleSize(); QAudioFormat::SampleType sampleType = mAudioFormat.sampleType(); - // qDebug() << "Input sample format: " << sampleSize << "bits " << sampleType; switch (sampleType) { case QAudioFormat::Unknown: @@ -61,10 +60,12 @@ int UBMicrophoneInput::sampleFormat() return AV_SAMPLE_FMT_S16; if (sampleSize == 32) return AV_SAMPLE_FMT_S32; + break; case QAudioFormat::UnSignedInt: if (sampleSize == 8) return AV_SAMPLE_FMT_U8; + break; case QAudioFormat::Float: return AV_SAMPLE_FMT_FLT; @@ -72,6 +73,8 @@ int UBMicrophoneInput::sampleFormat() default: return AV_SAMPLE_FMT_NONE; } + + return AV_SAMPLE_FMT_NONE; } QString UBMicrophoneInput::codec() @@ -96,11 +99,14 @@ bool UBMicrophoneInput::init() mAudioFormat = mAudioDeviceInfo.preferredFormat(); mAudioInput = new QAudioInput(mAudioDeviceInfo, mAudioFormat, NULL); - //mAudioInput->setNotifyInterval(100); connect(mAudioInput, SIGNAL(stateChanged(QAudio::State)), this, SLOT(onAudioInputStateChanged(QAudio::State))); + qDebug() << "Input sample format: " << mAudioFormat.sampleSize() << "bit" + << mAudioFormat.sampleType() << "at" << mAudioFormat.sampleRate() << "Hz" + << "; codec: " << mAudioFormat.codec(); + return true; } @@ -159,12 +165,26 @@ void UBMicrophoneInput::setInputDevice(QString name) } +static qint64 uSecsElapsed = 0; void UBMicrophoneInput::onDataReady() { int numBytes = mAudioInput->bytesReady(); - if (numBytes > 0) - emit dataAvailable(mIODevice->read(numBytes)); + uSecsElapsed += mAudioFormat.durationForBytes(numBytes); + + // Only emit data every 100ms + if (uSecsElapsed > 100000) { + uSecsElapsed = 0; + QByteArray data = mIODevice->read(numBytes); + + quint8 level = audioLevel(data); + if (level != mLastAudioLevel) { + mLastAudioLevel = level; + emit audioLevelChanged(level); + } + + emit dataAvailable(data); + } } void UBMicrophoneInput::onAudioInputStateChanged(QAudio::State state) @@ -184,6 +204,63 @@ void UBMicrophoneInput::onAudioInputStateChanged(QAudio::State state) } } +/** + * @brief Calculate the current audio level of an array of samples and return it + * @param data An array of audio samples + * @return A value between 0 and 255 + * + * Audio level is calculated as the RMS (root mean square) of the samples + * in the supplied array. + */ +quint8 UBMicrophoneInput::audioLevel(const QByteArray &data) +{ + int bytesPerSample = mAudioFormat.bytesPerFrame() / mAudioFormat.channelCount(); + + const char * ptr = data.constData(); + double sum = 0; + int n_samples = data.size() / bytesPerSample; + + for (int i(0); i < (data.size() - bytesPerSample); i += bytesPerSample) { + sum += pow(sampleRelativeLevel(ptr + i), 2); + } + + double rms = sqrt(sum/n_samples); + + // The vu meter looks a bit better when the RMS isn't displayed linearly, as perceived sound + // level increases logarithmically. So here RMS can be substituted by something like + // rms^(1/e) + rms = pow(rms, 1./exp(1)); + + return UINT8_MAX * rms; +} + +/** + * @brief Calculate one sample's level relative to its maximum value + * @param sample One sample, in the format specified by mAudioFormat + * @return A double between 0 and 1.0, where 1.0 is the maximum value the sample can take. + */ +double UBMicrophoneInput::sampleRelativeLevel(const char* sample) +{ + QAudioFormat::SampleType type = mAudioFormat.sampleType(); + int sampleSize = mAudioFormat.sampleSize(); + + if (sampleSize == 16 && type == QAudioFormat::SignedInt) + return double(*reinterpret_cast(sample))/INT16_MAX; + + if (sampleSize == 8 && type == QAudioFormat::SignedInt) + return double(*reinterpret_cast(sample))/INT8_MAX; + + if (sampleSize == 16 && type == QAudioFormat::UnSignedInt) + return double(*reinterpret_cast(sample))/UINT16_MAX; + + if (sampleSize == 8 && type == QAudioFormat::UnSignedInt) + return double(*reinterpret_cast(sample))/UINT8_MAX; + + if (type == QAudioFormat::Float) + return (*reinterpret_cast(sample) + 1.0)/2.; + + return -1; +} /** * @brief Return a meaningful error string based on QAudio error codes diff --git a/src/podcast/ffmpeg/UBMicrophoneInput.h b/src/podcast/ffmpeg/UBMicrophoneInput.h index 8ba306d0..cc74f82e 100644 --- a/src/podcast/ffmpeg/UBMicrophoneInput.h +++ b/src/podcast/ffmpeg/UBMicrophoneInput.h @@ -44,6 +44,8 @@ private slots: void onDataReady(); private: + double sampleRelativeLevel(const char* sample); + quint8 audioLevel(const QByteArray& data); QString getErrorString(QAudio::Error errorCode); QAudioInput* mAudioInput; @@ -52,6 +54,7 @@ private: QAudioFormat mAudioFormat; qint64 mSeekPos; + quint8 mLastAudioLevel; }; #endif // UBMICROPHONEINPUT_H From 89bd259d60f18c20d1ec990eaeca9893d88e92fd Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 13 May 2016 10:50:35 +0200 Subject: [PATCH 014/134] Clean-up; headers added --- src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp | 30 +++- src/podcast/ffmpeg/UBFFmpegVideoEncoder.h | 21 +++ src/podcast/ffmpeg/UBMicrophoneInput.cpp | 177 +++++++++++--------- src/podcast/ffmpeg/UBMicrophoneInput.h | 29 +++- 4 files changed, 163 insertions(+), 94 deletions(-) diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp index 498fbae4..fa6bc0dd 100644 --- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM) + * + * 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 "UBFFmpegVideoEncoder.h" //------------------------------------------------------------------------- @@ -223,11 +244,6 @@ bool UBFFmpegVideoEncoder::init() int inChannelCount = mAudioInput->channelCount(); int inSampleRate = mAudioInput->sampleRate(); - int inSampleSize = mAudioInput->sampleSize(); - - qDebug() << "inChannelCount = " << inChannelCount; - qDebug() << "inSampleRate = " << inSampleRate; - qDebug() << "inSampleSize = " << inSampleSize; // Codec @@ -535,8 +551,8 @@ void UBFFmpegVideoEncoderWorker::queueAudioFrame(AVFrame* frame) } /** - * The main encoding function. Takes the queued image frames and - * assembles them into the video + * The main encoding function. Takes the queued frames and + * writes them to the video and audio streams */ void UBFFmpegVideoEncoderWorker::runEncoding() { diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h index 9c6b6ab9..eed8c16b 100644 --- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM) + * + * 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 . + */ + #ifndef UBFFMPEGVIDEOENCODER_H #define UBFFMPEGVIDEOENCODER_H diff --git a/src/podcast/ffmpeg/UBMicrophoneInput.cpp b/src/podcast/ffmpeg/UBMicrophoneInput.cpp index 20007409..ad17dd49 100644 --- a/src/podcast/ffmpeg/UBMicrophoneInput.cpp +++ b/src/podcast/ffmpeg/UBMicrophoneInput.cpp @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM) + * + * 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 "UBMicrophoneInput.h" UBMicrophoneInput::UBMicrophoneInput() @@ -13,80 +34,6 @@ UBMicrophoneInput::~UBMicrophoneInput() delete mAudioInput; } -int UBMicrophoneInput::channelCount() -{ - return mAudioFormat.channelCount(); -} - -int UBMicrophoneInput::sampleRate() -{ - return mAudioFormat.sampleRate(); -} - -/* Return the sample size in bits */ -int UBMicrophoneInput::sampleSize() -{ - return mAudioFormat.sampleSize(); -} - -/** Return the sample format in FFMpeg style (AVSampleFormat enum) */ -int UBMicrophoneInput::sampleFormat() -{ - enum AVSampleFormat { - AV_SAMPLE_FMT_NONE = -1, - AV_SAMPLE_FMT_U8, - AV_SAMPLE_FMT_S16, - AV_SAMPLE_FMT_S32, - AV_SAMPLE_FMT_FLT, - AV_SAMPLE_FMT_DBL, - AV_SAMPLE_FMT_U8P, - AV_SAMPLE_FMT_S16P, - AV_SAMPLE_FMT_S32P, - AV_SAMPLE_FMT_FLTP, - AV_SAMPLE_FMT_DBLP, - AV_SAMPLE_FMT_NB - }; - - int sampleSize = mAudioFormat.sampleSize(); - QAudioFormat::SampleType sampleType = mAudioFormat.sampleType(); - - - switch (sampleType) { - case QAudioFormat::Unknown: - return AV_SAMPLE_FMT_NONE; - - case QAudioFormat::SignedInt: - if (sampleSize == 16) - return AV_SAMPLE_FMT_S16; - if (sampleSize == 32) - return AV_SAMPLE_FMT_S32; - break; - - case QAudioFormat::UnSignedInt: - if (sampleSize == 8) - return AV_SAMPLE_FMT_U8; - break; - - case QAudioFormat::Float: - return AV_SAMPLE_FMT_FLT; - - default: - return AV_SAMPLE_FMT_NONE; - } - - return AV_SAMPLE_FMT_NONE; -} - -QString UBMicrophoneInput::codec() -{ - return mAudioFormat.codec(); -} - -qint64 UBMicrophoneInput::processUSecs() const -{ - return mAudioInput->processedUSecs(); -} - bool UBMicrophoneInput::init() { if (mAudioDeviceInfo.isNull()) { @@ -94,15 +41,14 @@ bool UBMicrophoneInput::init() mAudioDeviceInfo = QAudioDeviceInfo::defaultInputDevice(); } - qDebug() << "Input device name: " << mAudioDeviceInfo.deviceName(); - mAudioFormat = mAudioDeviceInfo.preferredFormat(); - mAudioInput = new QAudioInput(mAudioDeviceInfo, mAudioFormat, NULL); connect(mAudioInput, SIGNAL(stateChanged(QAudio::State)), this, SLOT(onAudioInputStateChanged(QAudio::State))); + + qDebug() << "Input device name: " << mAudioDeviceInfo.deviceName(); qDebug() << "Input sample format: " << mAudioFormat.sampleSize() << "bit" << mAudioFormat.sampleType() << "at" << mAudioFormat.sampleRate() << "Hz" << "; codec: " << mAudioFormat.codec(); @@ -112,8 +58,6 @@ bool UBMicrophoneInput::init() void UBMicrophoneInput::start() { - qDebug() << "starting audio input"; - mIODevice = mAudioInput->start(); connect(mIODevice, SIGNAL(readyRead()), @@ -165,6 +109,74 @@ void UBMicrophoneInput::setInputDevice(QString name) } +int UBMicrophoneInput::channelCount() +{ + return mAudioFormat.channelCount(); +} + +int UBMicrophoneInput::sampleRate() +{ + return mAudioFormat.sampleRate(); +} + +/* Return the sample size in bits */ +int UBMicrophoneInput::sampleSize() +{ + return mAudioFormat.sampleSize(); +} + +/** Return the sample format in FFMpeg style (AVSampleFormat enum) */ +int UBMicrophoneInput::sampleFormat() +{ + enum AVSampleFormat { + AV_SAMPLE_FMT_NONE = -1, + AV_SAMPLE_FMT_U8, + AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_S32, + AV_SAMPLE_FMT_FLT, + AV_SAMPLE_FMT_DBL, + AV_SAMPLE_FMT_U8P, + AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_S32P, + AV_SAMPLE_FMT_FLTP, + AV_SAMPLE_FMT_DBLP, + AV_SAMPLE_FMT_NB + }; + + int sampleSize = mAudioFormat.sampleSize(); + QAudioFormat::SampleType sampleType = mAudioFormat.sampleType(); + + switch (sampleType) { + case QAudioFormat::Unknown: + return AV_SAMPLE_FMT_NONE; + + case QAudioFormat::SignedInt: + if (sampleSize == 16) + return AV_SAMPLE_FMT_S16; + if (sampleSize == 32) + return AV_SAMPLE_FMT_S32; + break; + + case QAudioFormat::UnSignedInt: + if (sampleSize == 8) + return AV_SAMPLE_FMT_U8; + break; + + case QAudioFormat::Float: + return AV_SAMPLE_FMT_FLT; + + default: + return AV_SAMPLE_FMT_NONE; + } + + return AV_SAMPLE_FMT_NONE; +} + +QString UBMicrophoneInput::codec() +{ + return mAudioFormat.codec(); +} + static qint64 uSecsElapsed = 0; void UBMicrophoneInput::onDataReady() { @@ -189,7 +201,6 @@ void UBMicrophoneInput::onDataReady() void UBMicrophoneInput::onAudioInputStateChanged(QAudio::State state) { - qDebug() << "Audio input state changed to " << state; switch (state) { case QAudio::StoppedState: if (mAudioInput->error() != QAudio::NoError) { @@ -227,8 +238,7 @@ quint8 UBMicrophoneInput::audioLevel(const QByteArray &data) double rms = sqrt(sum/n_samples); // The vu meter looks a bit better when the RMS isn't displayed linearly, as perceived sound - // level increases logarithmically. So here RMS can be substituted by something like - // rms^(1/e) + // level increases logarithmically. So here RMS is substituted by rms^(1/e) rms = pow(rms, 1./exp(1)); return UINT8_MAX * rms; @@ -237,7 +247,8 @@ quint8 UBMicrophoneInput::audioLevel(const QByteArray &data) /** * @brief Calculate one sample's level relative to its maximum value * @param sample One sample, in the format specified by mAudioFormat - * @return A double between 0 and 1.0, where 1.0 is the maximum value the sample can take. + * @return A double between 0 and 1.0, where 1.0 is the maximum value the sample can take, + * or -1 if the value couldn't be calculated. */ double UBMicrophoneInput::sampleRelativeLevel(const char* sample) { diff --git a/src/podcast/ffmpeg/UBMicrophoneInput.h b/src/podcast/ffmpeg/UBMicrophoneInput.h index cc74f82e..b82f5e70 100644 --- a/src/podcast/ffmpeg/UBMicrophoneInput.h +++ b/src/podcast/ffmpeg/UBMicrophoneInput.h @@ -1,3 +1,24 @@ +/* + * Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM) + * + * 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 . + */ + #ifndef UBMICROPHONEINPUT_H #define UBMICROPHONEINPUT_H @@ -5,7 +26,9 @@ #include /** - * @brief The UBMicrophoneInput class captures uncompressed sound from a microphone + * @brief The UBMicrophoneInput class captures uncompressed sound from a microphone. + * + * Audio samples can be read by connecting to the dataAvailable signal. */ class UBMicrophoneInput : public QObject { @@ -28,10 +51,8 @@ public: int sampleFormat(); QString codec(); - qint64 processUSecs() const; - signals: - /// Send the new volume, between 0 and 255 + /// Send the new audio level, between 0 and 255 void audioLevelChanged(quint8 level); /// Emitted when new audio data is available From 9b7993c59ed2f5623c89f7c976ad02e3f53d47dd Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 2 Sep 2016 17:43:16 -0400 Subject: [PATCH 015/134] Updated ffmpeg library path and removed twice-defined signal --- src/podcast/ffmpeg/UBFFmpegVideoEncoder.h | 4 ---- src/podcast/podcast.pri | 8 +------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h index eed8c16b..c2e19de6 100644 --- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h @@ -79,10 +79,6 @@ public: void setRecordAudio(bool pRecordAudio) { mShouldRecordAudio = pRecordAudio; } -signals: - - void encodingFinished(bool ok); - private slots: void setLastErrorMessage(const QString& pMessage); diff --git a/src/podcast/podcast.pri b/src/podcast/podcast.pri index 5b10ee9b..865060e0 100644 --- a/src/podcast/podcast.pri +++ b/src/podcast/podcast.pri @@ -42,15 +42,9 @@ linux-g++* { SOURCES += src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp - FFMPEG = /opt/ffmpeg - - INCLUDEPATH += $${FFMPEG}/include DEPENDPATH += /usr/lib/x86_64-linux-gnu - LIBS += -L $${FFMPEG}/lib -lavformat \ - -L $${FFMPEG}/lib -lavcodec \ - -L $${FFMPEG}/lib -lswscale \ - -L $${FFMPEG}/lib -lavutil \ + LIBS += -lavformat -lavcodec -lswscale -lavutil \ -lva-x11 \ -lva \ -lxcb-shm \ From 081dbee1ed153c958981ed46659665b5945cdb49 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 2 Sep 2016 17:43:35 -0400 Subject: [PATCH 016/134] User-resizable background grid: - The background selection palette now includes a slider to change the size of the background grid. Default min/max values are 16 and 64px, defined in UBSettings. Grid resizes dynamically as the slider is moved. - Measuring tools' (ruler, triangle) markers follow grid size: 1 square of the background grid corresponds to 1cm - Grid size can be different for each page of a document - Grid size is saved in the .svg - Documents with a background grid but no specified grid size follow the default size defined in UBSettings. Previously, grid size was calculated based on DPI, which can vary from one OS, computer or display to the next. This new setting allows documents to be migrated from one machine to another with no unexpected changes in grid size happening. It also makes it easy to correct any problems importing old documents (whose grid size might be smaller or larger than expected when imported on a new version of OpenBoard). --- src/adaptors/UBSvgSubsetAdaptor.cpp | 19 +++- src/board/UBBoardController.cpp | 4 - src/board/UBBoardPaletteManager.cpp | 11 +- src/board/UBBoardPaletteManager.h | 3 +- src/board/UBBoardView.cpp | 8 +- src/core/UBSettings.cpp | 4 +- src/core/UBSettings.h | 4 + src/domain/UBGraphicsScene.cpp | 23 ++++- src/domain/UBGraphicsScene.h | 8 ++ src/gui/UBActionPalette.h | 12 +-- src/gui/UBBackgroundPalette.cpp | 153 ++++++++++++++++++++++++++++ src/gui/UBBackgroundPalette.h | 46 +++++++++ src/gui/gui.pri | 6 +- src/tools/UBAbstractDrawRuler.cpp | 5 +- src/tools/UBAbstractDrawRuler.h | 2 +- src/tools/UBGraphicsCompass.cpp | 8 +- src/tools/UBGraphicsCompass.h | 1 - src/tools/UBGraphicsRuler.cpp | 57 ++++++++--- src/tools/UBGraphicsTriangle.cpp | 35 +++++-- 19 files changed, 346 insertions(+), 63 deletions(-) create mode 100644 src/gui/UBBackgroundPalette.cpp create mode 100644 src/gui/UBBackgroundPalette.h diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index e44eba15..82da8160 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -453,11 +453,22 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx QStringRef ubCrossedBackground = mXmlReader.attributes().value(mNamespaceUri, "crossed-background"); - if (!ubDarkBackground.isNull()) + if (!ubCrossedBackground.isNull()) crossedBackground = (ubCrossedBackground.toString() == xmlTrue); mScene->setBackground(darkBackground, crossedBackground); + if (crossedBackground) { + QStringRef ubGridSize = mXmlReader.attributes().value(mNamespaceUri, "grid-size"); + + if (!ubGridSize.isNull()) { + int gridSize = ubGridSize.toInt(); + + UBSettings::settings()->crossSize = gridSize; + mScene->setBackgroundGridSize(gridSize); + } + } + QStringRef pageNominalSize = mXmlReader.attributes().value(mNamespaceUri, "nominal-size"); if (!pageNominalSize.isNull()) { @@ -1068,6 +1079,12 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::writeSvgElement(UBDocumentProxy* pro mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "dark-background", mScene->isDarkBackground() ? xmlTrue : xmlFalse); mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "crossed-background", mScene->isCrossedBackground() ? xmlTrue : xmlFalse); + if (mScene->isCrossedBackground()) { + int gridSize = mScene->backgroundGridSize(); + + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "grid-size", QString::number(gridSize)); + } + QDesktopWidget* desktop = UBApplication::desktop(); if (proxy->pageDpi() == 0) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index c7e1c657..a87524d2 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -122,10 +122,6 @@ UBBoardController::UBBoardController(UBMainWindow* mainWindow) mMarkerColorOnDarkBackground = UBSettings::settings()->markerColors(true).at(markerColorIndex); mMarkerColorOnLightBackground = UBSettings::settings()->markerColors(false).at(markerColorIndex); - QDesktopWidget* desktop = UBApplication::desktop(); - int dpiCommon = (desktop->physicalDpiX() + desktop->physicalDpiY()) / 2; - int sPixelsPerMillimeter = qRound(dpiCommon / UBGeometryUtils::inchSize); - UBSettings::settings()->crossSize = 10*sPixelsPerMillimeter; } diff --git a/src/board/UBBoardPaletteManager.cpp b/src/board/UBBoardPaletteManager.cpp index bb7324d1..cbff6491 100644 --- a/src/board/UBBoardPaletteManager.cpp +++ b/src/board/UBBoardPaletteManager.cpp @@ -45,6 +45,7 @@ #include "gui/UBZoomPalette.h" #include "gui/UBWebToolsPalette.h" #include "gui/UBActionPalette.h" +#include "gui/UBBackgroundPalette.h" #include "gui/UBFavoriteToolPalette.h" #include "gui/UBStartupHintsPalette.h" @@ -253,11 +254,11 @@ void UBBoardPaletteManager::setupPalettes() backgroundsActions << UBApplication::mainWindow->actionPlainDarkBackground; backgroundsActions << UBApplication::mainWindow->actionCrossedDarkBackground; - mBackgroundsPalette = new UBActionPalette(backgroundsActions, Qt::Horizontal , mContainer); + mBackgroundsPalette = new UBBackgroundPalette(backgroundsActions, mContainer); mBackgroundsPalette->setButtonIconSize(QSize(128, 128)); mBackgroundsPalette->groupActions(); mBackgroundsPalette->setClosable(true); - mBackgroundsPalette->setAutoClose(true); + mBackgroundsPalette->setAutoClose(false); mBackgroundsPalette->adjustSizeAndPosition(); mBackgroundsPalette->hide(); @@ -532,7 +533,7 @@ void UBBoardPaletteManager::changeBackground() else UBApplication::boardController->changeBackground(false, false); - UBApplication::mainWindow->actionBackgrounds->setChecked(false); + mBackgroundsPalette->backgroundChanged(); } @@ -552,8 +553,10 @@ void UBBoardPaletteManager::activeSceneChanged() if (mZoomPalette) connect(mZoomPalette, SIGNAL(mouseEntered()), activeScene, SLOT(hideTool())); - if (mBackgroundsPalette) + if (mBackgroundsPalette) { connect(mBackgroundsPalette, SIGNAL(mouseEntered()), activeScene, SLOT(hideTool())); + mBackgroundsPalette->refresh(); + } } diff --git a/src/board/UBBoardPaletteManager.h b/src/board/UBBoardPaletteManager.h index e6b42aa1..408e895f 100644 --- a/src/board/UBBoardPaletteManager.h +++ b/src/board/UBBoardPaletteManager.h @@ -48,6 +48,7 @@ class UBClockPalette; class UBPageNumberPalette; class UBZoomPalette; class UBActionPalette; +class UBBackgroundPalette; class UBBoardController; class UBServerXMLHttpRequest; class UBKeyboardPalette; @@ -113,7 +114,7 @@ class UBBoardPaletteManager : public QObject /** The right dock palette */ UBRightPalette* mRightPalette; - UBActionPalette *mBackgroundsPalette; + UBBackgroundPalette *mBackgroundsPalette; UBActionPalette *mToolsPalette; UBActionPalette* mAddItemPalette; UBActionPalette* mErasePalette; diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 34ed6f1f..b50d0115 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -1609,16 +1609,16 @@ void UBBoardView::drawBackground (QPainter *painter, const QRectF &rect) if (scene () && scene ()->isCrossedBackground ()) { - qreal firstY = ((int) (rect.y () / UBSettings::crossSize)) * UBSettings::crossSize; + qreal firstY = ((int) (rect.y () / scene()->backgroundGridSize())) * scene()->backgroundGridSize(); - for (qreal yPos = firstY; yPos < rect.y () + rect.height (); yPos += UBSettings::crossSize) + for (qreal yPos = firstY; yPos < rect.y () + rect.height (); yPos += scene()->backgroundGridSize()) { painter->drawLine (rect.x (), yPos, rect.x () + rect.width (), yPos); } - qreal firstX = ((int) (rect.x () / UBSettings::crossSize)) * UBSettings::crossSize; + qreal firstX = ((int) (rect.x () / scene()->backgroundGridSize())) * scene()->backgroundGridSize(); - for (qreal xPos = firstX; xPos < rect.x () + rect.width (); xPos += UBSettings::crossSize) + for (qreal xPos = firstX; xPos < rect.x () + rect.width (); xPos += scene()->backgroundGridSize()) { painter->drawLine (xPos, rect.y (), xPos, rect.y () + rect.height ()); } diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index c344908a..47177e89 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -46,7 +46,9 @@ QPointer UBSettings::sSingleton = 0; int UBSettings::pointerDiameter = 40; -int UBSettings::crossSize = 32; +int UBSettings::crossSize = 24; +int UBSettings::minCrossSize = 12; +int UBSettings::maxCrossSize = 64; int UBSettings::colorPaletteSize = 5; int UBSettings::objectFrameWidth = 20; int UBSettings::boardMargin = 10; diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index 9d04f0dc..0d874471 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -182,7 +182,11 @@ class UBSettings : public QObject static QColor documentSizeMarkColorDarkBackground; static QColor documentSizeMarkColorLightBackground; + // Background grid static int crossSize; + static int minCrossSize; + static int maxCrossSize; + static int colorPaletteSize; static int objectFrameWidth; diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 5181af4a..01918dc3 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -353,6 +353,8 @@ UBGraphicsScene::UBGraphicsScene(UBDocumentProxy* parent, bool enableUndoRedoSta UBApplication::applicationController->initialVScroll())); } + mBackgroundGridSize = UBSettings::settings()->crossSize; + // Just for debug. Do not delete please // connect(this, SIGNAL(selectionChanged()), this, SLOT(selectionChangedProcessing())); connect(UBApplication::undoStack.data(), SIGNAL(indexChanged(int)), this, SLOT(updateSelectionFrameWrapper(int))); @@ -981,6 +983,18 @@ void UBGraphicsScene::setBackgroundZoomFactor(qreal zoom) mZoomFactor = zoom; } + +void UBGraphicsScene::setBackgroundGridSize(int pSize) +{ + if (pSize > 0) { + mBackgroundGridSize = pSize; + setModified(true); + + foreach(QGraphicsView* view, views()) + view->resetCachedContent(); + } +} + void UBGraphicsScene::setDrawingMode(bool bModeDesktop) { mIsDesktopMode = bModeDesktop; @@ -1158,6 +1172,7 @@ UBGraphicsScene* UBGraphicsScene::sceneDeepCopy() const UBGraphicsScene* copy = new UBGraphicsScene(this->document(), this->mUndoRedoStackEnabled); copy->setBackground(this->isDarkBackground(), this->isCrossedBackground()); + copy->setBackgroundGridSize(mBackgroundGridSize); copy->setSceneRect(this->sceneRect()); if (this->mNominalSize.isValid()) @@ -2404,16 +2419,16 @@ void UBGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect) if (isCrossedBackground()) { - qreal firstY = ((int) (rect.y () / UBSettings::crossSize)) * UBSettings::crossSize; + qreal firstY = ((int) (rect.y () / backgroundGridSize())) * backgroundGridSize(); - for (qreal yPos = firstY; yPos < rect.y () + rect.height (); yPos += UBSettings::crossSize) + for (qreal yPos = firstY; yPos < rect.y () + rect.height (); yPos += backgroundGridSize()) { painter->drawLine (rect.x (), yPos, rect.x () + rect.width (), yPos); } - qreal firstX = ((int) (rect.x () / UBSettings::crossSize)) * UBSettings::crossSize; + qreal firstX = ((int) (rect.x () / backgroundGridSize())) * backgroundGridSize(); - for (qreal xPos = firstX; xPos < rect.x () + rect.width (); xPos += UBSettings::crossSize) + for (qreal xPos = firstX; xPos < rect.x () + rect.width (); xPos += backgroundGridSize()) { painter->drawLine (xPos, rect.y (), xPos, rect.y () + rect.height ()); } diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 29966f6d..9d6d9500 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -220,6 +220,11 @@ class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem return mCrossedBackground; } + int backgroundGridSize() const + { + return mBackgroundGridSize; + } + bool hasBackground() { return (mBackgroundObject != 0); @@ -331,6 +336,7 @@ public slots: void setBackground(bool pIsDark, bool pIsCrossed); void setBackgroundZoomFactor(qreal zoom); + void setBackgroundGridSize(int pSize); void setDrawingMode(bool bModeDesktop); void deselectAllItems(); @@ -404,6 +410,8 @@ public slots: bool mDarkBackground; bool mCrossedBackground; + int mBackgroundGridSize; + bool mIsDesktopMode; qreal mZoomFactor; diff --git a/src/gui/UBActionPalette.h b/src/gui/UBActionPalette.h index 97752769..3e1e3238 100644 --- a/src/gui/UBActionPalette.h +++ b/src/gui/UBActionPalette.h @@ -55,9 +55,9 @@ class UBActionPalette : public UBFloatingPalette void setToolButtonStyle(Qt::ToolButtonStyle); QList actions(); - void setActions(QList actions); + virtual void setActions(QList actions); void groupActions(); - void addAction(QAction* action); + virtual void addAction(QAction* action); void setClosable(bool closable); void setAutoClose(bool autoClose) @@ -72,10 +72,10 @@ class UBActionPalette : public UBFloatingPalette bool m_customCloseProcessing; virtual int border(); - void clearLayout(); + virtual void clearLayout(); QSize buttonSize(); - UBActionPaletteButton* getButtonFromAction(QAction* action); + virtual UBActionPaletteButton* getButtonFromAction(QAction* action); public slots: void close(); @@ -91,7 +91,7 @@ class UBActionPalette : public UBFloatingPalette virtual void mouseReleaseEvent(QMouseEvent * event); virtual void init(Qt::Orientation orientation); - void updateLayout(); + virtual void updateLayout(); QList mButtons; QButtonGroup* mButtonGroup; @@ -105,7 +105,7 @@ class UBActionPalette : public UBFloatingPalette QPoint mMousePos; UBActionPaletteButton *createPaletteButton(QAction* action, QWidget *parent); - private slots: + protected slots: void buttonClicked(); void actionChanged(); }; diff --git a/src/gui/UBBackgroundPalette.cpp b/src/gui/UBBackgroundPalette.cpp new file mode 100644 index 00000000..d10fcc08 --- /dev/null +++ b/src/gui/UBBackgroundPalette.cpp @@ -0,0 +1,153 @@ +#include "UBBackgroundPalette.h" + +UBBackgroundPalette::UBBackgroundPalette(QList actions, QWidget * parent) + : UBActionPalette(parent) +{ + init(); + setActions(actions); +} + + +UBBackgroundPalette::UBBackgroundPalette(QWidget * parent) + : UBActionPalette(parent) +{ + init(); +} + + + +void UBBackgroundPalette::init() +{ + UBActionPalette::clearLayout(); + delete layout(); + + + m_customCloseProcessing = false; + + mButtonSize = QSize(32, 32); + mIsClosable = false; + mAutoClose = false; + mButtonGroup = 0; + mToolButtonStyle = Qt::ToolButtonIconOnly; + mButtons.clear(); + + mVLayout = new QVBoxLayout(this); + mTopLayout = new QHBoxLayout(); + mBottomLayout = new QHBoxLayout(); + + mVLayout->addLayout(mTopLayout); + mVLayout->addLayout(mBottomLayout); + + mSlider = new QSlider(Qt::Horizontal); + + mSlider->setMinimum(UBSettings::settings()->minCrossSize); + mSlider->setMaximum(UBSettings::settings()->maxCrossSize); + mSlider->setSingleStep(2); + mSlider->setTracking(true); // valueChanged() is emitted during movement and not just upon releasing the slider + + mSliderLabel = new QLabel(tr("Grid size")); + + mBottomLayout->addSpacing(16); + mBottomLayout->addWidget(mSliderLabel); + mBottomLayout->addWidget(mSlider); + mBottomLayout->addSpacing(16); + + updateLayout(); +} + +void UBBackgroundPalette::addAction(QAction* action) +{ + UBActionPaletteButton* button = createPaletteButton(action, this); + + mTopLayout->addWidget(button); + mActions << action; +} + +void UBBackgroundPalette::setActions(QList actions) +{ + mMapActionToButton.clear(); + + foreach(QAction* action, actions) + { + addAction(action); + } + + actionChanged(); +} + +void UBBackgroundPalette::updateLayout() +{ + if (mToolButtonStyle == Qt::ToolButtonIconOnly) { + mVLayout->setContentsMargins (sLayoutContentMargin / 2 + border(), sLayoutContentMargin / 2 + border() + , sLayoutContentMargin / 2 + border(), sLayoutContentMargin / 2 + border()); + } + else + { + mVLayout->setContentsMargins (sLayoutContentMargin + border(), sLayoutContentMargin + border() + , sLayoutContentMargin + border(), sLayoutContentMargin + border()); + + } + update(); +} + +void UBBackgroundPalette::clearLayout() +{ + while(!mTopLayout->isEmpty()) { + QLayoutItem* pItem = mTopLayout->itemAt(0); + QWidget* pW = pItem->widget(); + mTopLayout->removeItem(pItem); + delete pItem; + mTopLayout->removeWidget(pW); + delete pW; + } + + delete mTopLayout; + + while(!mBottomLayout->isEmpty()) { + QLayoutItem* pItem = mBottomLayout->itemAt(0); + QWidget* pW = pItem->widget(); + mBottomLayout->removeItem(pItem); + delete pItem; + mBottomLayout->removeWidget(pW); + delete pW; + } + + delete mBottomLayout; + + delete mVLayout; + + mActions.clear(); + mButtons.clear(); +} + +void UBBackgroundPalette::showEvent(QShowEvent* event) +{ + backgroundChanged(); + + mSlider->setValue(UBApplication::boardController->activeScene()->backgroundGridSize()); + connect(mSlider, SIGNAL(valueChanged(int)), + this, SLOT(sliderValueChanged(int))); + + QWidget::showEvent(event); +} + +void UBBackgroundPalette::sliderValueChanged(int value) +{ + UBApplication::boardController->activeScene()->setBackgroundGridSize(value); +} + +void UBBackgroundPalette::backgroundChanged() +{ + bool dark = UBApplication::boardController->activeScene()->isDarkBackground(); + + if (dark) + mSliderLabel->setStyleSheet("QLabel { color : white; }"); + else + mSliderLabel->setStyleSheet("QLabel { color : black; }"); +} + +void UBBackgroundPalette::refresh() +{ + backgroundChanged(); + mSlider->setValue(UBApplication::boardController->activeScene()->backgroundGridSize()); +} diff --git a/src/gui/UBBackgroundPalette.h b/src/gui/UBBackgroundPalette.h new file mode 100644 index 00000000..c9f6ffe1 --- /dev/null +++ b/src/gui/UBBackgroundPalette.h @@ -0,0 +1,46 @@ +#ifndef UBBACKGROUNDPALETTE_H +#define UBBACKGROUNDPALETTE_H + +#include "gui/UBActionPalette.h" +#include "core/UBApplication.h" +#include "board/UBBoardController.h" +#include "domain/UBGraphicsScene.h" + +class UBBackgroundPalette : public UBActionPalette +{ + Q_OBJECT + + public: + + UBBackgroundPalette(QList actions, QWidget* parent = 0); + UBBackgroundPalette(QWidget* parent = 0); + + void addAction(QAction *action); + void setActions(QList actions); + void clearLayout(); + + + public slots: + void showEvent(QShowEvent* event); + void backgroundChanged(); + void refresh(); + + protected slots: + void sliderValueChanged(int value); + + protected: + virtual void updateLayout(); + void init(); + + + QVBoxLayout* mVLayout; + QHBoxLayout* mTopLayout; + QHBoxLayout* mBottomLayout; + + QSlider* mSlider; + QLabel* mSliderLabel; + + +}; + +#endif // UBBACKGROUNDPALETTE_H diff --git a/src/gui/gui.pri b/src/gui/gui.pri index 38f5f654..a4921eff 100644 --- a/src/gui/gui.pri +++ b/src/gui/gui.pri @@ -40,7 +40,8 @@ HEADERS += src/gui/UBThumbnailView.h \ src/gui/UBFeaturesActionBar.h \ src/gui/UBMessagesDialog.h \ src/gui/UBOpenSankoreImporterWidget.h \ - src/gui/UBStartupHintsPalette.h + src/gui/UBStartupHintsPalette.h \ + src/gui/UBBackgroundPalette.h SOURCES += src/gui/UBThumbnailView.cpp \ src/gui/UBFloatingPalette.cpp \ src/gui/UBToolbarButtonGroup.cpp \ @@ -83,7 +84,8 @@ SOURCES += src/gui/UBThumbnailView.cpp \ src/gui/UBFeaturesActionBar.cpp \ src/gui/UBMessagesDialog.cpp \ src/gui/UBOpenSankoreImporterWidget.cpp \ - src/gui/UBStartupHintsPalette.cpp + src/gui/UBStartupHintsPalette.cpp \ + src/gui/UBBackgroundPalette.cpp win32:SOURCES += src/gui/UBKeyboardPalette_win.cpp macx:OBJECTIVE_SOURCES += src/gui/UBKeyboardPalette_mac.mm linux-g++:SOURCES += src/gui/UBKeyboardPalette_linux.cpp diff --git a/src/tools/UBAbstractDrawRuler.cpp b/src/tools/UBAbstractDrawRuler.cpp index 170c4b2b..70fde592 100644 --- a/src/tools/UBAbstractDrawRuler.cpp +++ b/src/tools/UBAbstractDrawRuler.cpp @@ -58,11 +58,8 @@ UBAbstractDrawRuler::UBAbstractDrawRuler() : mShowButtons(false) , mAntiScaleRatio(1.0) { - //we actually need to evaluate pixels per millimeter - QDesktopWidget* desktop = UBApplication::desktop(); - int dpiCommon = (desktop->physicalDpiX() + desktop->physicalDpiY()) / 2; - sPixelsPerMillimeter = qRound(dpiCommon / UBGeometryUtils::inchSize); + sPixelsPerCentimeter = UBApplication::boardController->activeScene()->backgroundGridSize(); } void UBAbstractDrawRuler::create(QGraphicsItem& item) diff --git a/src/tools/UBAbstractDrawRuler.h b/src/tools/UBAbstractDrawRuler.h index 60bc2e5f..73c10d05 100644 --- a/src/tools/UBAbstractDrawRuler.h +++ b/src/tools/UBAbstractDrawRuler.h @@ -92,7 +92,7 @@ protected: static const int sFillTransparency; static const int sDrawTransparency; static const int sRoundingRadius; - int sPixelsPerMillimeter; + int sPixelsPerCentimeter; }; #endif diff --git a/src/tools/UBGraphicsCompass.cpp b/src/tools/UBGraphicsCompass.cpp index 20c1c28b..d1282b1f 100644 --- a/src/tools/UBGraphicsCompass.cpp +++ b/src/tools/UBGraphicsCompass.cpp @@ -65,10 +65,6 @@ UBGraphicsCompass::UBGraphicsCompass() , mDrewCenterCross(false) { setRect(sDefaultRect); - //TODO claudio: remove code duplication - QDesktopWidget* desktop = UBApplication::desktop(); - int dpiCommon = (desktop->physicalDpiX() + desktop->physicalDpiY()) / 2; - mPixelsPerMillimeter = qRound(dpiCommon / 25.4f); setFlag(QGraphicsItem::ItemIsMovable, true); setFlag(QGraphicsItem::ItemIsSelectable, true); @@ -427,7 +423,9 @@ void UBGraphicsCompass::paintAngleDisplay(QPainter *painter) void UBGraphicsCompass::paintRadiusDisplay(QPainter *painter) { - qreal radiusInCentimeters = rect().width() / (mPixelsPerMillimeter * 10); + double pixelsPerCentimeter = UBApplication::boardController->activeScene()->backgroundGridSize(); + + qreal radiusInCentimeters = rect().width() / pixelsPerCentimeter; QString format = rect().width() >= sDisplayRadiusUnitMinLength ? "%1 cm" : "%1"; QString radiusText = QString(format).arg(radiusInCentimeters, 0, 'f', 1); diff --git a/src/tools/UBGraphicsCompass.h b/src/tools/UBGraphicsCompass.h index 485237db..5cd80530 100644 --- a/src/tools/UBGraphicsCompass.h +++ b/src/tools/UBGraphicsCompass.h @@ -123,7 +123,6 @@ class UBGraphicsCompass: public QObject, public QGraphicsRectItem, public UBItem QGraphicsSvgItem* mResizeSvgItem; qreal mAntiScaleRatio; bool mDrewCenterCross; - int mPixelsPerMillimeter; // Constants static const int sNeedleLength = 18; diff --git a/src/tools/UBGraphicsRuler.cpp b/src/tools/UBGraphicsRuler.cpp index cb95cc88..65965fcf 100644 --- a/src/tools/UBGraphicsRuler.cpp +++ b/src/tools/UBGraphicsRuler.cpp @@ -176,20 +176,44 @@ void UBGraphicsRuler::paintGraduations(QPainter *painter) painter->save(); painter->setFont(font()); QFontMetricsF fontMetrics(painter->font()); - for (int millimeters = 0; millimeters < (rect().width() - sLeftEdgeMargin - sRoundingRadius) / sPixelsPerMillimeter; millimeters++) - { - int graduationX = rotationCenter().x() + sPixelsPerMillimeter * millimeters; - int graduationHeight = (0 == millimeters % UBGeometryUtils::millimetersPerCentimeter) ? - UBGeometryUtils::centimeterGraduationHeight : - ((0 == millimeters % UBGeometryUtils::millimetersPerHalfCentimeter) ? - UBGeometryUtils::halfCentimeterGraduationHeight : UBGeometryUtils::millimeterGraduationHeight); - painter->drawLine(QLine(graduationX, rotationCenter().y(), graduationX, rotationCenter().y() + graduationHeight)); - painter->drawLine(QLine(graduationX, rotationCenter().y() + rect().height(), graduationX, rotationCenter().y() + rect().height() - graduationHeight)); - if (0 == millimeters % UBGeometryUtils::millimetersPerCentimeter) + + // Update the width of one "centimeter" to correspond to the width of the background grid (whether it is displayed or not) + sPixelsPerCentimeter = UBApplication::boardController->activeScene()->backgroundGridSize(); + + double pixelsPerMillimeter = double(sPixelsPerCentimeter)/10.0; + int rulerLengthInMillimeters = (rect().width() - sLeftEdgeMargin - sRoundingRadius)/pixelsPerMillimeter; + + // When a "centimeter" is too narrow, we only display every 5th number, and every 5th millimeter mark + double numbersWidth = fontMetrics.width("00"); + bool shouldDisplayAllNumbers = (numbersWidth <= (sPixelsPerCentimeter - 5)); + + for (int millimeters(0); millimeters < rulerLengthInMillimeters; millimeters++) { + + double graduationX = rotationCenter().x() + pixelsPerMillimeter * millimeters; + double graduationHeight = 0; + + if (millimeters % UBGeometryUtils::millimetersPerCentimeter == 0) + graduationHeight = UBGeometryUtils::centimeterGraduationHeight; + + else if (millimeters % UBGeometryUtils::millimetersPerHalfCentimeter == 0) + graduationHeight = UBGeometryUtils::halfCentimeterGraduationHeight; + + else + graduationHeight = UBGeometryUtils::millimeterGraduationHeight; + + + if (shouldDisplayAllNumbers || millimeters % UBGeometryUtils::millimetersPerHalfCentimeter == 0) { + painter->drawLine(QLineF(graduationX, rotationCenter().y(), graduationX, rotationCenter().y() + graduationHeight)); + painter->drawLine(QLineF(graduationX, rotationCenter().y() + rect().height(), graduationX, rotationCenter().y() + rect().height() - graduationHeight)); + } + + + if ((shouldDisplayAllNumbers && millimeters % UBGeometryUtils::millimetersPerCentimeter == 0) + || millimeters % (UBGeometryUtils::millimetersPerCentimeter*5) == 0) { QString text = QString("%1").arg((int)(millimeters / UBGeometryUtils::millimetersPerCentimeter)); - if (graduationX + fontMetrics.width(text) / 2 < rect().right()) - { + + if (graduationX + fontMetrics.width(text) / 2 < rect().right()) { qreal textWidth = fontMetrics.width(text); qreal textHeight = fontMetrics.tightBoundingRect(text).height() + 5; painter->drawText( @@ -201,7 +225,10 @@ void UBGraphicsRuler::paintGraduations(QPainter *painter) } } } + + painter->restore(); + } void UBGraphicsRuler::paintRotationCenter(QPainter *painter) @@ -252,7 +279,7 @@ QRectF UBGraphicsRuler::closeButtonRect() const closePixmap.height() * mAntiScaleRatio); QPointF closeRectCenter( - rect().left() + sLeftEdgeMargin + sPixelsPerMillimeter * 5, + rect().left() + sLeftEdgeMargin + sPixelsPerCentimeter/2, rect().center().y()); QPointF closeRectTopLeft( @@ -270,9 +297,9 @@ QRectF UBGraphicsRuler::rotateButtonRect() const rotatePixmap.width() * mAntiScaleRatio, rotatePixmap.height() * mAntiScaleRatio); - int centimeters = (int)(rect().width() - sLeftEdgeMargin - resizeButtonRect().width()) / (int)(10 * sPixelsPerMillimeter); + int centimeters = (int)(rect().width() - sLeftEdgeMargin - resizeButtonRect().width()) / (sPixelsPerCentimeter); QPointF rotateRectCenter( - rect().left() + sLeftEdgeMargin + (centimeters - 0.5) * 10 * sPixelsPerMillimeter, + rect().left() + sLeftEdgeMargin + (centimeters - 0.5) * sPixelsPerCentimeter, rect().center().y()); QPointF rotateRectTopLeft( diff --git a/src/tools/UBGraphicsTriangle.cpp b/src/tools/UBGraphicsTriangle.cpp index 5ba3ab91..7ee4f553 100644 --- a/src/tools/UBGraphicsTriangle.cpp +++ b/src/tools/UBGraphicsTriangle.cpp @@ -349,14 +349,27 @@ void UBGraphicsTriangle::paintGraduations(QPainter *painter) painter->setFont(font()); QFontMetricsF fontMetrics(painter->font()); - for (int millimeters = 0; millimeters < (rect().width() - sLeftEdgeMargin - sRoundingRadius) / sPixelsPerMillimeter; millimeters++) + // Update the width of one "centimeter" to correspond to the width of the background grid (whether it is displayed or not) + sPixelsPerCentimeter = UBApplication::boardController->activeScene()->backgroundGridSize(); + double pixelsPerMillimeter = double(sPixelsPerCentimeter)/10.0; + + // When a "centimeter" is too narrow, we only display every 5th number, and every 5th millimeter mark + double numbersWidth = fontMetrics.width("00"); + bool shouldDisplayAllNumbers = (numbersWidth <= (sPixelsPerCentimeter - 5)); + + for (int millimeters = 0; millimeters < (rect().width() - sLeftEdgeMargin - sRoundingRadius) / pixelsPerMillimeter; millimeters++) { - int graduationX = rotationCenter().x() + kx * sPixelsPerMillimeter * millimeters; + double graduationX = rotationCenter().x() + kx * pixelsPerMillimeter * millimeters; + double graduationHeight = 0; - int graduationHeight = (0 == millimeters % UBGeometryUtils::millimetersPerCentimeter) ? - UBGeometryUtils::centimeterGraduationHeight : - ((0 == millimeters % UBGeometryUtils::millimetersPerHalfCentimeter) ? - UBGeometryUtils::halfCentimeterGraduationHeight : UBGeometryUtils::millimeterGraduationHeight); + if (millimeters % UBGeometryUtils::millimetersPerCentimeter == 0) + graduationHeight = UBGeometryUtils::centimeterGraduationHeight; + + else if (millimeters % UBGeometryUtils::millimetersPerHalfCentimeter == 0) + graduationHeight = UBGeometryUtils::halfCentimeterGraduationHeight; + + else + graduationHeight = UBGeometryUtils::millimeterGraduationHeight; qreal requiredSpace = graduationHeight + SEPARATOR ; /* B____C @@ -387,12 +400,14 @@ void UBGraphicsTriangle::paintGraduations(QPainter *painter) qreal BC = rect().height(); qreal DE = AD * BC / AB, availableSpace = DE; - if (requiredSpace <= availableSpace) - painter->drawLine(QLine(graduationX, rotationCenter().y(), graduationX, rotationCenter().y() - ky * graduationHeight)); - else + if (availableSpace < requiredSpace) break; - if (0 == millimeters % UBGeometryUtils::millimetersPerCentimeter) + if (shouldDisplayAllNumbers || millimeters % UBGeometryUtils::millimetersPerHalfCentimeter == 0) + painter->drawLine(QLineF(graduationX, rotationCenter().y(), graduationX, rotationCenter().y() - ky * graduationHeight)); + + if ((shouldDisplayAllNumbers && millimeters % UBGeometryUtils::millimetersPerCentimeter == 0) + || millimeters % (UBGeometryUtils::millimetersPerCentimeter*5) == 0) { QString text = QString("%1").arg((int)(millimeters / UBGeometryUtils::millimetersPerCentimeter)); qreal textWidth = fontMetrics.width(text); From 38c145321d5aea50b2e1757bacc37021ee91e95c Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 2 Sep 2016 22:37:02 -0400 Subject: [PATCH 017/134] Corrected background palette icon (dark, crossed BG), that always appeared selected --- .../images/backgroundPalette/background4.svg | 206 +++++++++++------- 1 file changed, 133 insertions(+), 73 deletions(-) diff --git a/resources/images/backgroundPalette/background4.svg b/resources/images/backgroundPalette/background4.svg index 2513743c..053ebf05 100644 --- a/resources/images/backgroundPalette/background4.svg +++ b/resources/images/backgroundPalette/background4.svg @@ -1,73 +1,133 @@ - - - - - - - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + +image/svg+xml \ No newline at end of file From def5f7f7193e74ded5c6fb5741397a6d10c0f488 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Fri, 2 Sep 2016 22:44:46 -0400 Subject: [PATCH 018/134] Added ruled background --- resources/OpenBoard.qrc | 4 + resources/forms/mainWindow.ui | 38 +++++ .../images/backgroundPalette/background5.svg | 146 +++++++++++++++++ .../backgroundPalette/background5On.svg | 149 +++++++++++++++++ .../images/backgroundPalette/background6.svg | 146 +++++++++++++++++ .../backgroundPalette/background6On.svg | 150 ++++++++++++++++++ src/adaptors/UBExportFullPDF.cpp | 6 +- src/adaptors/UBExportPDF.cpp | 6 +- src/adaptors/UBSvgSubsetAdaptor.cpp | 37 ++++- src/api/UBWidgetUniboardAPI.cpp | 8 +- src/board/UBBoardController.cpp | 47 ++++-- src/board/UBBoardController.h | 4 +- src/board/UBBoardPaletteManager.cpp | 21 ++- src/board/UBBoardView.cpp | 12 +- src/core/UB.h | 7 + src/core/UBApplicationController.cpp | 2 +- src/core/UBPersistenceManager.cpp | 2 +- src/core/UBSettings.cpp | 28 +++- src/core/UBSettings.h | 4 +- src/desktop/UBDesktopAnnotationController.cpp | 4 +- src/domain/UBGraphicsScene.cpp | 22 ++- src/domain/UBGraphicsScene.h | 8 +- 22 files changed, 797 insertions(+), 54 deletions(-) create mode 100644 resources/images/backgroundPalette/background5.svg create mode 100644 resources/images/backgroundPalette/background5On.svg create mode 100644 resources/images/backgroundPalette/background6.svg create mode 100644 resources/images/backgroundPalette/background6On.svg diff --git a/resources/OpenBoard.qrc b/resources/OpenBoard.qrc index 07f0d10a..1a2f3d1e 100644 --- a/resources/OpenBoard.qrc +++ b/resources/OpenBoard.qrc @@ -159,6 +159,10 @@ images/backgroundPalette/background3On.svg images/backgroundPalette/background4.svg images/backgroundPalette/background4On.svg + images/backgroundPalette/background5.svg + images/backgroundPalette/background5On.svg + images/backgroundPalette/background6.svg + images/backgroundPalette/background6On.svg images/toolPalette/podcast.svg images/toolPalette/podcastOn.svg images/toolPalette/rulerTool.png diff --git a/resources/forms/mainWindow.ui b/resources/forms/mainWindow.ui index 287d4e0a..d1c27a4b 100644 --- a/resources/forms/mainWindow.ui +++ b/resources/forms/mainWindow.ui @@ -1004,6 +1004,25 @@ Grid Light Background + + + true + + + + :/images/backgroundPalette/background5.svg + :/images/backgroundPalette/background5On.svg:/images/backgroundPalette/background5.svg + + + Ruled Light Background + + + Light + + + Ruled Light Background + + true @@ -1042,6 +1061,25 @@ Grid Dark Background + + + true + + + + :/images/backgroundPalette/background6.svg + :/images/backgroundPalette/background6On.svg:/images/backgroundPalette/background6.svg + + + Ruled Dark Background + + + Dark + + + Ruled Dark Background + + true diff --git a/resources/images/backgroundPalette/background5.svg b/resources/images/backgroundPalette/background5.svg new file mode 100644 index 00000000..ac6e870e --- /dev/null +++ b/resources/images/backgroundPalette/background5.svg @@ -0,0 +1,146 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/resources/images/backgroundPalette/background5On.svg b/resources/images/backgroundPalette/background5On.svg new file mode 100644 index 00000000..25d0a1c3 --- /dev/null +++ b/resources/images/backgroundPalette/background5On.svg @@ -0,0 +1,149 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/resources/images/backgroundPalette/background6.svg b/resources/images/backgroundPalette/background6.svg new file mode 100644 index 00000000..1c38545b --- /dev/null +++ b/resources/images/backgroundPalette/background6.svg @@ -0,0 +1,146 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/resources/images/backgroundPalette/background6On.svg b/resources/images/backgroundPalette/background6On.svg new file mode 100644 index 00000000..1210a251 --- /dev/null +++ b/resources/images/backgroundPalette/background6On.svg @@ -0,0 +1,150 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/src/adaptors/UBExportFullPDF.cpp b/src/adaptors/UBExportFullPDF.cpp index 64b989a0..9b6684f0 100644 --- a/src/adaptors/UBExportFullPDF.cpp +++ b/src/adaptors/UBExportFullPDF.cpp @@ -97,8 +97,8 @@ void UBExportFullPDF::saveOverlayPdf(UBDocumentProxy* pDocumentProxy, const QStr UBGraphicsScene* scene = UBPersistenceManager::persistenceManager()->loadDocumentScene(pDocumentProxy, pageIndex); // set background to white, no grid for PDF output bool isDark = scene->isDarkBackground(); - bool isCrossed = scene->isCrossedBackground(); - scene->setBackground(false, false); + UBPageBackground pageBackground = scene->pageBackground(); + scene->setBackground(false, UBPageBackground::plain); // set high res rendering scene->setRenderingQuality(UBItem::RenderingQualityHigh); @@ -126,7 +126,7 @@ void UBExportFullPDF::saveOverlayPdf(UBDocumentProxy* pDocumentProxy, const QStr //restore background state scene->setDrawingMode(false); - scene->setBackground(isDark, isCrossed); + scene->setBackground(isDark, pageBackground); } if (pdfPainter) delete pdfPainter; diff --git a/src/adaptors/UBExportPDF.cpp b/src/adaptors/UBExportPDF.cpp index ad9aaa5a..9f70c57b 100644 --- a/src/adaptors/UBExportPDF.cpp +++ b/src/adaptors/UBExportPDF.cpp @@ -91,8 +91,8 @@ bool UBExportPDF::persistsDocument(UBDocumentProxy* pDocumentProxy, const QStrin UBApplication::showMessage(tr("Exporting page %1 of %2").arg(pageIndex + 1).arg(existingPageCount)); // set background to white, no crossing for PDF output bool isDark = scene->isDarkBackground(); - bool isCrossed = scene->isCrossedBackground(); - scene->setBackground(false, false); + UBPageBackground pageBackground = scene->pageBackground(); + scene->setBackground(false, UBPageBackground::plain); QSize pageSize = scene->nominalSize(); @@ -113,7 +113,7 @@ bool UBExportPDF::persistsDocument(UBDocumentProxy* pDocumentProxy, const QStrin scene->setRenderingQuality(UBItem::RenderingQualityNormal); //restore background state - scene->setBackground(isDark, isCrossed); + scene->setBackground(isDark, pageBackground); } if(!painterNeedsBegin) pdfPainter.end(); diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 82da8160..bf04c400 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -445,6 +445,7 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx bool darkBackground = false; bool crossedBackground = false; + bool ruledBackground = false; QStringRef ubDarkBackground = mXmlReader.attributes().value(mNamespaceUri, "dark-background"); @@ -456,7 +457,6 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx if (!ubCrossedBackground.isNull()) crossedBackground = (ubCrossedBackground.toString() == xmlTrue); - mScene->setBackground(darkBackground, crossedBackground); if (crossedBackground) { QStringRef ubGridSize = mXmlReader.attributes().value(mNamespaceUri, "grid-size"); @@ -469,6 +469,32 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx } } + QStringRef ubRuledBackground = mXmlReader.attributes().value(mNamespaceUri, "ruled-background"); + + if (!ubRuledBackground.isNull()) + ruledBackground = (ubRuledBackground.toString() == xmlTrue); + + if (ruledBackground && !crossedBackground) { // if for some reason both are true, the background will be a grid + QStringRef ubGridSize = mXmlReader.attributes().value(mNamespaceUri, "grid-size"); + + if (!ubGridSize.isNull()) { + int gridSize = ubGridSize.toInt(); + + UBSettings::settings()->crossSize = gridSize; + mScene->setBackgroundGridSize(gridSize); + } + } + + UBPageBackground bg; + if (crossedBackground) + bg = UBPageBackground::crossed; + else if (ruledBackground) + bg = UBPageBackground::ruled; + else + bg = UBPageBackground::plain; + + mScene->setBackground(darkBackground, bg); + QStringRef pageNominalSize = mXmlReader.attributes().value(mNamespaceUri, "nominal-size"); if (!pageNominalSize.isNull()) { @@ -1077,9 +1103,14 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::writeSvgElement(UBDocumentProxy* pro } mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "dark-background", mScene->isDarkBackground() ? xmlTrue : xmlFalse); - mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "crossed-background", mScene->isCrossedBackground() ? xmlTrue : xmlFalse); - if (mScene->isCrossedBackground()) { + bool crossedBackground = mScene->pageBackground() == UBPageBackground::crossed; + bool ruledBackground = mScene->pageBackground() == UBPageBackground::ruled; + + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "crossed-background", crossedBackground ? xmlTrue : xmlFalse); + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "ruled-background", ruledBackground ? xmlTrue : xmlFalse); + + if (crossedBackground || ruledBackground) { int gridSize = mScene->backgroundGridSize(); mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "grid-size", QString::number(gridSize)); diff --git a/src/api/UBWidgetUniboardAPI.cpp b/src/api/UBWidgetUniboardAPI.cpp index c84bb546..5645519c 100644 --- a/src/api/UBWidgetUniboardAPI.cpp +++ b/src/api/UBWidgetUniboardAPI.cpp @@ -223,8 +223,12 @@ void UBWidgetUniboardAPI::addObject(QString pUrl, int width, int height, int x, void UBWidgetUniboardAPI::setBackground(bool pIsDark, bool pIsCrossed) { - if (mScene) - mScene->setBackground(pIsDark, pIsCrossed); + if (mScene) { + if (pIsCrossed) + mScene->setBackground(pIsDark, UBPageBackground::crossed); + else + mScene->setBackground(pIsDark, UBPageBackground::plain); + } } diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index a87524d2..b1dac51f 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1527,14 +1527,14 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, adjustDisplayViews(); UBSettings::settings()->setDarkBackground(mActiveScene->isDarkBackground()); - UBSettings::settings()->setCrossedBackground(mActiveScene->isCrossedBackground()); + UBSettings::settings()->setPageBackground(mActiveScene->pageBackground()); freezeW3CWidgets(false); } selectionChanged(); - updateBackgroundActionsState(mActiveScene->isDarkBackground(), mActiveScene->isCrossedBackground()); + updateBackgroundActionsState(mActiveScene->isDarkBackground(), mActiveScene->pageBackground()); if(documentChange) UBGraphicsTextItem::lastUsedTextColor = QColor(); @@ -1650,17 +1650,17 @@ int UBBoardController::autosaveTimeoutFromSettings() return value * minute; } -void UBBoardController::changeBackground(bool isDark, bool isCrossed) +void UBBoardController::changeBackground(bool isDark, UBPageBackground pageBackground) { bool currentIsDark = mActiveScene->isDarkBackground(); - bool currentIsCrossed = mActiveScene->isCrossedBackground(); + UBPageBackground currentBackgroundType = mActiveScene->pageBackground(); - if ((isDark != currentIsDark) || (currentIsCrossed != isCrossed)) + if ((isDark != currentIsDark) || (currentBackgroundType != pageBackground)) { UBSettings::settings()->setDarkBackground(isDark); - UBSettings::settings()->setCrossedBackground(isCrossed); + UBSettings::settings()->setPageBackground(pageBackground); - mActiveScene->setBackground(isDark, isCrossed); + mActiveScene->setBackground(isDark, pageBackground); emit backgroundChanged(); } @@ -2449,16 +2449,31 @@ void UBBoardController::moveToolWidgetToScene(UBToolWidget* toolWidget) } -void UBBoardController::updateBackgroundActionsState(bool isDark, bool isCrossed) +void UBBoardController::updateBackgroundActionsState(bool isDark, UBPageBackground pageBackground) { - if (isDark && !isCrossed) - mMainWindow->actionPlainDarkBackground->setChecked(true); - else if (isDark && isCrossed) - mMainWindow->actionCrossedDarkBackground->setChecked(true); - else if (!isDark && isCrossed) - mMainWindow->actionCrossedLightBackground->setChecked(true); - else - mMainWindow->actionPlainLightBackground->setChecked(true); + switch (pageBackground) { + + case UBPageBackground::crossed: + if (isDark) + mMainWindow->actionCrossedDarkBackground->setChecked(true); + else + mMainWindow->actionCrossedLightBackground->setChecked(true); + break; + + case UBPageBackground::ruled : + if (isDark) + mMainWindow->actionRuledDarkBackground->setChecked(true); + else + mMainWindow->actionRuledLightBackground->setChecked(true); + break; + + default: + if (isDark) + mMainWindow->actionPlainDarkBackground->setChecked(true); + else + mMainWindow->actionPlainLightBackground->setChecked(true); + break; + } } diff --git a/src/board/UBBoardController.h b/src/board/UBBoardController.h index f57b21ef..5631299a 100644 --- a/src/board/UBBoardController.h +++ b/src/board/UBBoardController.h @@ -220,7 +220,7 @@ class UBBoardController : public UBDocumentContainer UBItem *downloadFinished(bool pSuccess, QUrl sourceUrl, QUrl contentUrl, QString pHeader, QByteArray pData, QPointF pPos, QSize pSize, bool isBackground = false, bool internalData = false); - void changeBackground(bool isDark, bool isCrossed); + void changeBackground(bool isDark, UBPageBackground pageBackground); void setToolCursor(int tool); void showMessage(const QString& message, bool showSpinningWheel = false); void hideMessage(); @@ -321,7 +321,7 @@ class UBBoardController : public UBDocumentContainer void stylusToolDoubleClicked(int tool); void boardViewResized(QResizeEvent* event); void documentWillBeDeleted(UBDocumentProxy* pProxy); - void updateBackgroundActionsState(bool isDark, bool isCrossed); + void updateBackgroundActionsState(bool isDark, UBPageBackground pageBackground); void colorPaletteChanged(); void libraryDialogClosed(int ret); void lastWindowClosed(); diff --git a/src/board/UBBoardPaletteManager.cpp b/src/board/UBBoardPaletteManager.cpp index cbff6491..449d0831 100644 --- a/src/board/UBBoardPaletteManager.cpp +++ b/src/board/UBBoardPaletteManager.cpp @@ -251,8 +251,10 @@ void UBBoardPaletteManager::setupPalettes() backgroundsActions << UBApplication::mainWindow->actionPlainLightBackground; backgroundsActions << UBApplication::mainWindow->actionCrossedLightBackground; + backgroundsActions << UBApplication::mainWindow->actionRuledLightBackground; backgroundsActions << UBApplication::mainWindow->actionPlainDarkBackground; backgroundsActions << UBApplication::mainWindow->actionCrossedDarkBackground; + backgroundsActions << UBApplication::mainWindow->actionRuledDarkBackground; mBackgroundsPalette = new UBBackgroundPalette(backgroundsActions, mContainer); mBackgroundsPalette->setButtonIconSize(QSize(128, 128)); @@ -434,8 +436,10 @@ void UBBoardPaletteManager::connectPalettes() connect(UBApplication::mainWindow->actionPlainLightBackground, SIGNAL(triggered()), this, SLOT(changeBackground())); connect(UBApplication::mainWindow->actionCrossedLightBackground, SIGNAL(triggered()), this, SLOT(changeBackground())); + connect(UBApplication::mainWindow->actionRuledLightBackground, SIGNAL(triggered()), this, SLOT(changeBackground())); connect(UBApplication::mainWindow->actionPlainDarkBackground, SIGNAL(triggered()), this, SLOT(changeBackground())); connect(UBApplication::mainWindow->actionCrossedDarkBackground, SIGNAL(triggered()), this, SLOT(changeBackground())); + connect(UBApplication::mainWindow->actionRuledDarkBackground, SIGNAL(triggered()), this, SLOT(changeBackground())); connect(UBApplication::mainWindow->actionPodcast, SIGNAL(triggered(bool)), this, SLOT(tooglePodcastPalette(bool))); connect(UBApplication::mainWindow->actionAddItemToCurrentPage, SIGNAL(triggered()), this, SLOT(addItemToCurrentPage())); @@ -525,13 +529,22 @@ void UBBoardPaletteManager::containerResized() void UBBoardPaletteManager::changeBackground() { if (UBApplication::mainWindow->actionCrossedLightBackground->isChecked()) - UBApplication::boardController->changeBackground(false, true); + UBApplication::boardController->changeBackground(false, UBPageBackground::crossed); + + else if (UBApplication::mainWindow->actionRuledLightBackground->isChecked()) + UBApplication::boardController->changeBackground(false, UBPageBackground::ruled); + else if (UBApplication::mainWindow->actionPlainDarkBackground->isChecked()) - UBApplication::boardController->changeBackground(true, false); + UBApplication::boardController->changeBackground(true, UBPageBackground::plain); + else if (UBApplication::mainWindow->actionCrossedDarkBackground->isChecked()) - UBApplication::boardController->changeBackground(true, true); + UBApplication::boardController->changeBackground(true, UBPageBackground::crossed); + + else if (UBApplication::mainWindow->actionRuledDarkBackground->isChecked()) + UBApplication::boardController->changeBackground(true, UBPageBackground::ruled); + else - UBApplication::boardController->changeBackground(false, false); + UBApplication::boardController->changeBackground(false, UBPageBackground::plain); mBackgroundsPalette->backgroundChanged(); } diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index b50d0115..490e3955 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -1607,7 +1607,7 @@ void UBBoardView::drawBackground (QPainter *painter, const QRectF &rect) painter->setPen (bgCrossColor); - if (scene () && scene ()->isCrossedBackground ()) + if (scene () && scene ()->pageBackground() == UBPageBackground::crossed) { qreal firstY = ((int) (rect.y () / scene()->backgroundGridSize())) * scene()->backgroundGridSize(); @@ -1623,6 +1623,16 @@ void UBBoardView::drawBackground (QPainter *painter, const QRectF &rect) painter->drawLine (xPos, rect.y (), xPos, rect.y () + rect.height ()); } } + + if (scene() && scene()->pageBackground() == UBPageBackground::ruled) + { + qreal firstY = ((int) (rect.y () / scene()->backgroundGridSize())) * scene()->backgroundGridSize(); + + for (qreal yPos = firstY; yPos < rect.y () + rect.height (); yPos += scene()->backgroundGridSize()) + { + painter->drawLine (rect.x (), yPos, rect.x () + rect.width (), yPos); + } + } } if (!mFilterZIndex && scene ()) diff --git a/src/core/UB.h b/src/core/UB.h index 651ac139..4c791615 100644 --- a/src/core/UB.h +++ b/src/core/UB.h @@ -212,4 +212,11 @@ struct UBUndoType }; }; +enum UBPageBackground +{ + plain = 0, + crossed, + ruled +}; + #endif /* UB_H_ */ diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index 48d670ad..7e45d365 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -111,7 +111,7 @@ UBApplicationController::UBApplicationController(UBBoardView *pControlView, } mBlackScene = new UBGraphicsScene(0); // deleted by UBApplicationController::destructor - mBlackScene->setBackground(true, false); + mBlackScene->setBackground(true, UBPageBackground::plain); if (mDisplayManager->numScreens() >= 2) { diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index bcef40aa..9b951b1e 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -653,7 +653,7 @@ UBGraphicsScene* UBPersistenceManager::createDocumentSceneAt(UBDocumentProxy* pr UBGraphicsScene *newScene = mSceneCache.createScene(proxy, index, useUndoRedoStack); newScene->setBackground(UBSettings::settings()->isDarkBackground(), - UBSettings::settings()->UBSettings::isCrossedBackground()); + UBSettings::settings()->UBSettings::pageBackground()); persistDocumentScene(proxy, newScene, index); diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index ad9bc861..3b1bc4f5 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -735,9 +735,16 @@ bool UBSettings::isDarkBackground() } -bool UBSettings::isCrossedBackground() +UBPageBackground UBSettings::pageBackground() { - return value("Board/CrossedBackground", 0).toBool(); + QString val = value("Board/PageBackground", 0).toString(); + + if (val == "crossed") + return UBPageBackground::crossed; + else if (val == "ruled") + return UBPageBackground::ruled; + else + return UBPageBackground::plain; } @@ -748,9 +755,18 @@ void UBSettings::setDarkBackground(bool isDarkBackground) } -void UBSettings::setCrossedBackground(bool isCrossedBackground) +void UBSettings::setPageBackground(UBPageBackground background) { - setValue("Board/CrossedBackground", isCrossedBackground); + QString val; + + if (background == UBPageBackground::crossed) + val = "crossed"; + else if (background == UBPageBackground::ruled) + val = "ruled"; + else + val = "plain"; + + setValue("Board/PageBackground", val); } @@ -1413,4 +1429,8 @@ void UBSettings::checkNewSettings() // A typo was corrected in version 1.3 removeSetting("Board/useSystemOnScreenKeybard"); + + // CrossedBackground changed in 1.4 (no longer a bool but an enum; can be crossed or ruled) + removeSetting("Board/CrossedBackground"); + } diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index b0bf73ca..6be12962 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -87,9 +87,9 @@ class UBSettings : public QObject // Background related bool isDarkBackground(); - bool isCrossedBackground(); + UBPageBackground pageBackground(); void setDarkBackground(bool isDarkBackground); - void setCrossedBackground(bool isCrossedBackground); + void setPageBackground(UBPageBackground background); // Stylus palette related bool isStylusPaletteVisible(); diff --git a/src/desktop/UBDesktopAnnotationController.cpp b/src/desktop/UBDesktopAnnotationController.cpp index 894b33bc..40188703 100644 --- a/src/desktop/UBDesktopAnnotationController.cpp +++ b/src/desktop/UBDesktopAnnotationController.cpp @@ -185,9 +185,9 @@ UBDesktopAnnotationController::~UBDesktopAnnotationController() void UBDesktopAnnotationController::updateColors(){ if(UBApplication::boardController->activeScene()->isDarkBackground()){ - mTransparentDrawingScene->setBackground(true, false); + mTransparentDrawingScene->setBackground(true, UBPageBackground::plain); }else{ - mTransparentDrawingScene->setBackground(false, false); + mTransparentDrawingScene->setBackground(false, UBPageBackground::plain); } } diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index acd54ee7..6a451a28 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -321,7 +321,7 @@ UBGraphicsScene::UBGraphicsScene(UBDocumentProxy* parent, bool enableUndoRedoSta , mMarkerCircle(0) , mDocument(parent) , mDarkBackground(false) - , mCrossedBackground(false) + , mPageBackground(UBPageBackground::plain) , mIsDesktopMode(false) , mZoomFactor(1) , mBackgroundObject(0) @@ -1010,7 +1010,7 @@ void UBGraphicsScene::drawArcTo(const QPointF& pCenterPoint, qreal pSpanAngle) setDocumentUpdated(); } -void UBGraphicsScene::setBackground(bool pIsDark, bool pIsCrossed) +void UBGraphicsScene::setBackground(bool pIsDark, UBPageBackground pBackground) { bool needRepaint = false; @@ -1026,9 +1026,9 @@ void UBGraphicsScene::setBackground(bool pIsDark, bool pIsCrossed) setModified(true); } - if (mCrossedBackground != pIsCrossed) + if (mPageBackground != pBackground) { - mCrossedBackground = pIsCrossed; + mPageBackground = pBackground; needRepaint = true; setModified(true); } @@ -1243,7 +1243,7 @@ UBGraphicsScene* UBGraphicsScene::sceneDeepCopy() const { UBGraphicsScene* copy = new UBGraphicsScene(this->document(), this->mUndoRedoStackEnabled); - copy->setBackground(this->isDarkBackground(), this->isCrossedBackground()); + copy->setBackground(this->isDarkBackground(), mPageBackground); copy->setBackgroundGridSize(mBackgroundGridSize); copy->setSceneRect(this->sceneRect()); @@ -2489,7 +2489,7 @@ void UBGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect) painter->setPen (bgCrossColor); - if (isCrossedBackground()) + if (mPageBackground == UBPageBackground::crossed) { qreal firstY = ((int) (rect.y () / backgroundGridSize())) * backgroundGridSize(); @@ -2505,6 +2505,16 @@ void UBGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect) painter->drawLine (xPos, rect.y (), xPos, rect.y () + rect.height ()); } } + + else if (mPageBackground == UBPageBackground::ruled) + { + qreal firstY = ((int) (rect.y () / backgroundGridSize())) * backgroundGridSize(); + + for (qreal yPos = firstY; yPos < rect.y () + rect.height (); yPos += backgroundGridSize()) + { + painter->drawLine (rect.x (), yPos, rect.x () + rect.width (), yPos); + } + } } } diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 05674873..37f1a470 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -217,9 +217,9 @@ class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem return !mDarkBackground; } - bool isCrossedBackground() const + UBPageBackground pageBackground() const { - return mCrossedBackground; + return mPageBackground; } int backgroundGridSize() const @@ -336,7 +336,7 @@ public slots: void initStroke(); void hideTool(); - void setBackground(bool pIsDark, bool pIsCrossed); + void setBackground(bool pIsDark, UBPageBackground pBackground); void setBackgroundZoomFactor(qreal zoom); void setBackgroundGridSize(int pSize); void setDrawingMode(bool bModeDesktop); @@ -413,7 +413,7 @@ public slots: UBDocumentProxy* mDocument; bool mDarkBackground; - bool mCrossedBackground; + UBPageBackground mPageBackground; int mBackgroundGridSize; bool mIsDesktopMode; From 145a7238c078e5cc61ce528fa1843c3648fa69e9 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 8 Oct 2016 22:30:46 -0400 Subject: [PATCH 019/134] Background grid: initialize to *approximately* 1cm upon startup --- src/board/UBBoardController.cpp | 31 +++++++++++++++++++++++++++++++ src/board/UBBoardController.h | 1 + src/board/UBBoardView.cpp | 14 ++++++++------ src/core/UBSettings.cpp | 2 +- src/tools/UBAbstractDrawRuler.h | 2 +- src/tools/UBGraphicsRuler.cpp | 2 +- src/tools/UBGraphicsTriangle.cpp | 2 +- 7 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 6ba15e3e..e61d613b 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -152,6 +152,8 @@ void UBBoardController::init() setActiveDocumentScene(doc); + initBackgroundGridSize(); + undoRedoStateChange(true); } @@ -162,6 +164,35 @@ UBBoardController::~UBBoardController() delete mDisplayView; } +/** + * @brief Set the default background grid size to appear as roughly 1cm on screen + */ +void UBBoardController::initBackgroundGridSize() +{ + // Besides adjusting for DPI, we also need to scale the grid size by the ratio of the control view size + // to document size. However the control view isn't available as soon as the boardController is created, + // so we approximate this ratio as (document resolution) / (screen resolution). + // Later on, this is calculated by `updateSystemScaleFactor` and stored in `mSystemScaleFactor`. + + QDesktopWidget* desktop = UBApplication::desktop(); + qreal dpi = (desktop->physicalDpiX() + desktop->physicalDpiY()) / 2.; + + //qDebug() << "dpi: " << dpi; + + // The display manager isn't initialized yet so we have to just assume the control view is on the main display + qreal screenY = desktop->screenGeometry(mControlView).height(); + qreal documentY = mActiveScene->nominalSize().height(); + qreal resolutionRatio = documentY / screenY; + + //qDebug() << "resolution ratio: " << resolutionRatio; + + int gridSize = (resolutionRatio * 10. * dpi) / UBGeometryUtils::inchSize; + + UBSettings::settings()->crossSize = gridSize; + mActiveScene->setBackgroundGridSize(gridSize); + + //qDebug() << "grid size: " << gridSize; +} int UBBoardController::currentPage() { diff --git a/src/board/UBBoardController.h b/src/board/UBBoardController.h index 5631299a..1b66c1e8 100644 --- a/src/board/UBBoardController.h +++ b/src/board/UBBoardController.h @@ -284,6 +284,7 @@ class UBBoardController : public UBDocumentContainer void appMainModeChanged(UBApplicationController::MainMode); private: + void initBackgroundGridSize(); void updatePageSizeState(); void saveViewState(); void adjustDisplayViews(); diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 096a4898..0926ec91 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -1607,20 +1607,22 @@ void UBBoardView::drawBackground (QPainter *painter, const QRectF &rect) bgCrossColor.setAlpha (alpha); // fade the crossing on small zooms } + qreal gridSize = scene()->backgroundGridSize(); + painter->setPen (bgCrossColor); if (scene () && scene ()->pageBackground() == UBPageBackground::crossed) { - qreal firstY = ((int) (rect.y () / scene()->backgroundGridSize())) * scene()->backgroundGridSize(); + qreal firstY = ((int) (rect.y () / gridSize)) * gridSize; - for (qreal yPos = firstY; yPos < rect.y () + rect.height (); yPos += scene()->backgroundGridSize()) + for (qreal yPos = firstY; yPos < rect.y () + rect.height (); yPos += gridSize) { painter->drawLine (rect.x (), yPos, rect.x () + rect.width (), yPos); } - qreal firstX = ((int) (rect.x () / scene()->backgroundGridSize())) * scene()->backgroundGridSize(); + qreal firstX = ((int) (rect.x () / gridSize)) * gridSize; - for (qreal xPos = firstX; xPos < rect.x () + rect.width (); xPos += scene()->backgroundGridSize()) + for (qreal xPos = firstX; xPos < rect.x () + rect.width (); xPos += gridSize) { painter->drawLine (xPos, rect.y (), xPos, rect.y () + rect.height ()); } @@ -1628,9 +1630,9 @@ void UBBoardView::drawBackground (QPainter *painter, const QRectF &rect) if (scene() && scene()->pageBackground() == UBPageBackground::ruled) { - qreal firstY = ((int) (rect.y () / scene()->backgroundGridSize())) * scene()->backgroundGridSize(); + qreal firstY = ((int) (rect.y () / gridSize)) * gridSize; - for (qreal yPos = firstY; yPos < rect.y () + rect.height (); yPos += scene()->backgroundGridSize()) + for (qreal yPos = firstY; yPos < rect.y () + rect.height (); yPos += gridSize) { painter->drawLine (rect.x (), yPos, rect.x () + rect.width (), yPos); } diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index 373a9062..fc9e2b55 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -48,7 +48,7 @@ QPointer UBSettings::sSingleton = 0; int UBSettings::pointerDiameter = 40; int UBSettings::crossSize = 24; int UBSettings::minCrossSize = 12; -int UBSettings::maxCrossSize = 64; +int UBSettings::maxCrossSize = 96; //TODO: user-settable? int UBSettings::colorPaletteSize = 5; int UBSettings::objectFrameWidth = 20; int UBSettings::boardMargin = 10; diff --git a/src/tools/UBAbstractDrawRuler.h b/src/tools/UBAbstractDrawRuler.h index 73c10d05..caf84821 100644 --- a/src/tools/UBAbstractDrawRuler.h +++ b/src/tools/UBAbstractDrawRuler.h @@ -92,7 +92,7 @@ protected: static const int sFillTransparency; static const int sDrawTransparency; static const int sRoundingRadius; - int sPixelsPerCentimeter; + qreal sPixelsPerCentimeter; }; #endif diff --git a/src/tools/UBGraphicsRuler.cpp b/src/tools/UBGraphicsRuler.cpp index 65965fcf..66f287b7 100644 --- a/src/tools/UBGraphicsRuler.cpp +++ b/src/tools/UBGraphicsRuler.cpp @@ -180,7 +180,7 @@ void UBGraphicsRuler::paintGraduations(QPainter *painter) // Update the width of one "centimeter" to correspond to the width of the background grid (whether it is displayed or not) sPixelsPerCentimeter = UBApplication::boardController->activeScene()->backgroundGridSize(); - double pixelsPerMillimeter = double(sPixelsPerCentimeter)/10.0; + qreal pixelsPerMillimeter = sPixelsPerCentimeter/10.0; int rulerLengthInMillimeters = (rect().width() - sLeftEdgeMargin - sRoundingRadius)/pixelsPerMillimeter; // When a "centimeter" is too narrow, we only display every 5th number, and every 5th millimeter mark diff --git a/src/tools/UBGraphicsTriangle.cpp b/src/tools/UBGraphicsTriangle.cpp index 7ee4f553..6d58bb3f 100644 --- a/src/tools/UBGraphicsTriangle.cpp +++ b/src/tools/UBGraphicsTriangle.cpp @@ -351,7 +351,7 @@ void UBGraphicsTriangle::paintGraduations(QPainter *painter) // Update the width of one "centimeter" to correspond to the width of the background grid (whether it is displayed or not) sPixelsPerCentimeter = UBApplication::boardController->activeScene()->backgroundGridSize(); - double pixelsPerMillimeter = double(sPixelsPerCentimeter)/10.0; + double pixelsPerMillimeter = sPixelsPerCentimeter/10.0; // When a "centimeter" is too narrow, we only display every 5th number, and every 5th millimeter mark double numbersWidth = fontMetrics.width("00"); From 02205e861b8d68ab16dbc92c26b21b4deab14ae5 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 8 Oct 2016 22:35:35 -0400 Subject: [PATCH 020/134] Removed blending of adjacent polygons in marker strokes Due to antialiasing, adjacent polygons are separated by a very fine space. The previous solution attempted to hide this by adding a border to the polygons. The border of adjacent polygons would overlap, which was visible (despite the attempted color correction) and, more importantly, caused massive lags especially on Linux. Therefore it has been removed but feel free to revert this commit some day and try to fix this more cleanly. --- src/domain/UBGraphicsPolygonItem.cpp | 33 ++-------------------------- 1 file changed, 2 insertions(+), 31 deletions(-) diff --git a/src/domain/UBGraphicsPolygonItem.cpp b/src/domain/UBGraphicsPolygonItem.cpp index d5f8d4f6..39fb5151 100644 --- a/src/domain/UBGraphicsPolygonItem.cpp +++ b/src/domain/UBGraphicsPolygonItem.cpp @@ -136,38 +136,9 @@ UBGraphicsStroke* UBGraphicsPolygonItem::stroke() const void UBGraphicsPolygonItem::setColor(const QColor& pColor) { QGraphicsPolygonItem::setBrush(QBrush(pColor)); + setPen(Qt::NoPen); - if (pColor.alphaF() >= 1.0) - { - mHasAlpha = false; - setPen(Qt::NoPen); - } - else - { - mHasAlpha = true; - - QColor penColor = pColor; - - // trick QT antialiasing - // TODO UB 4.x see if we can do better ... it does not behave well with 16 bit color depth - qreal trickAlpha = pColor.alphaF(); - - if (trickAlpha >= 0.2 && trickAlpha < 0.6) - { - trickAlpha /= 12; - } - else if (trickAlpha < 0.8) - { - trickAlpha /= 5; - } - else if (trickAlpha < 1.0) - { - trickAlpha /= 2; - } - - penColor.setAlphaF(trickAlpha); - QGraphicsPolygonItem::setPen(QPen(penColor)); - } + mHasAlpha = (pColor.alphaF() < 1.0); } From df71f158c330b2e7e1fd902b7a9bb85142fe262c Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 15 Oct 2016 15:42:38 -0400 Subject: [PATCH 021/134] Added stroke simplification algorithm If enabled in the preferences menu, pen and marker strokes will be replaced by a simplified stroke after they are drawn. The algorithm is very basic (for now): if three points are almost lined up (the threshold angle can be specified in the config file), then the middle one is removed. This is repeated over the whole stroke; new polygons are then generated based on the simplified stroke points. This typically cuts down on number of points and polygons by a factor of about 10, while having minimal visual impact. --- resources/forms/brushProperties.ui | 24 ++++ src/core/UBPreferencesController.cpp | 6 + src/core/UBSettings.cpp | 5 + src/core/UBSettings.h | 4 + src/domain/UBGraphicsPolygonItem.cpp | 8 +- src/domain/UBGraphicsScene.cpp | 77 ++++++++--- src/domain/UBGraphicsScene.h | 5 +- src/domain/UBGraphicsStroke.cpp | 195 +++++++++++++++++++++++---- src/domain/UBGraphicsStroke.h | 15 ++- src/frameworks/UBGeometryUtils.cpp | 76 ++++++++--- src/frameworks/UBGeometryUtils.h | 3 + src/frameworks/UBInterpolator.cpp | 2 +- 12 files changed, 350 insertions(+), 70 deletions(-) diff --git a/resources/forms/brushProperties.ui b/resources/forms/brushProperties.ui index eea50fba..2866714e 100644 --- a/resources/forms/brushProperties.ui +++ b/resources/forms/brushProperties.ui @@ -521,6 +521,30 @@ + + + + + + Simplify strokes after drawing (experimental) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + diff --git a/src/core/UBPreferencesController.cpp b/src/core/UBPreferencesController.cpp index 7f87cdda..df58462c 100644 --- a/src/core/UBPreferencesController.cpp +++ b/src/core/UBPreferencesController.cpp @@ -166,6 +166,7 @@ void UBPreferencesController::wire() connect(mPenProperties->strongSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mPenProperties->pressureSensitiveCheckBox, SIGNAL(clicked(bool)), settings, SLOT(setPenPressureSensitive(bool))); connect(mPenProperties->interpolateStrokesCheckBox, SIGNAL(clicked(bool)), settings->boardInterpolatePenStrokes, SLOT(setBool(bool))); + connect(mPenProperties->simplifyStrokesCheckBox, SIGNAL(clicked(bool)), settings->boardSimplifyPenStrokes, SLOT(setBool(bool))); // marker QList markerLightBackgroundColors = settings->boardMarkerLightBackgroundColors->colors(); @@ -183,6 +184,8 @@ void UBPreferencesController::wire() connect(mMarkerProperties->mediumSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mMarkerProperties->strongSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mMarkerProperties->pressureSensitiveCheckBox, SIGNAL(clicked(bool)), settings, SLOT(setMarkerPressureSensitive(bool))); + connect(mMarkerProperties->interpolateStrokesCheckBox, SIGNAL(clicked(bool)), settings->boardInterpolateMarkerStrokes, SLOT(setBool(bool))); + connect(mMarkerProperties->simplifyStrokesCheckBox, SIGNAL(clicked(bool)), settings->boardSimplifyMarkerStrokes, SLOT(setBool(bool))); connect(mMarkerProperties->opacitySlider, SIGNAL(valueChanged(int)), this, SLOT(opacitySliderChanged(int))); // about tab @@ -233,12 +236,15 @@ void UBPreferencesController::init() mPenProperties->strongSlider->setValue(settings->boardPenStrongWidth->get().toDouble() * sSliderRatio); mPenProperties->pressureSensitiveCheckBox->setChecked(settings->boardPenPressureSensitive->get().toBool()); mPenProperties->interpolateStrokesCheckBox->setChecked(settings->boardInterpolatePenStrokes->get().toBool()); + mPenProperties->simplifyStrokesCheckBox->setChecked(settings->boardSimplifyPenStrokes->get().toBool()); // marker tab mMarkerProperties->fineSlider->setValue(settings->boardMarkerFineWidth->get().toDouble() * sSliderRatio); mMarkerProperties->mediumSlider->setValue(settings->boardMarkerMediumWidth->get().toDouble() * sSliderRatio); mMarkerProperties->strongSlider->setValue(settings->boardMarkerStrongWidth->get().toDouble() * sSliderRatio); mMarkerProperties->pressureSensitiveCheckBox->setChecked(settings->boardMarkerPressureSensitive->get().toBool()); + mMarkerProperties->interpolateStrokesCheckBox->setChecked(settings->boardInterpolateMarkerStrokes->get().toBool()); + mMarkerProperties->simplifyStrokesCheckBox->setChecked(settings->boardSimplifyMarkerStrokes->get().toBool()); mMarkerProperties->opacitySlider->setValue(settings->boardMarkerAlpha->get().toDouble() * 100); diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index fc9e2b55..cfde5119 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -270,6 +270,11 @@ void UBSettings::init() boardUseHighResTabletEvent = new UBSetting(this, "Board", "UseHighResTabletEvent", true); boardInterpolatePenStrokes = new UBSetting(this, "Board", "InterpolatePenStrokes", true); + boardSimplifyPenStrokes = new UBSetting(this, "Board", "SimplifyPenStrokes", true); + boardSimplifyPenStrokesThresholdAngle = new UBSetting(this, "Board", "SimplifyPenStrokesThresholdAngle", 2); + + boardInterpolateMarkerStrokes = new UBSetting(this, "Board", "InterpolateMarkerStrokes", true); + boardSimplifyMarkerStrokes = new UBSetting(this, "Board", "SimplifyMarkerStrokes", true); boardKeyboardPaletteKeyBtnSize = new UBSetting(this, "Board", "KeyboardPaletteKeyBtnSize", "16x16"); ValidateKeyboardPaletteKeyBtnSize(); diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index 6be12962..0fb8bf68 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -274,6 +274,10 @@ class UBSettings : public QObject UBSetting* boardUseHighResTabletEvent; UBSetting* boardInterpolatePenStrokes; + UBSetting* boardSimplifyPenStrokes; + UBSetting* boardSimplifyPenStrokesThresholdAngle; + UBSetting* boardInterpolateMarkerStrokes; + UBSetting* boardSimplifyMarkerStrokes; UBSetting* boardKeyboardPaletteKeyBtnSize; diff --git a/src/domain/UBGraphicsPolygonItem.cpp b/src/domain/UBGraphicsPolygonItem.cpp index 39fb5151..320da3f3 100644 --- a/src/domain/UBGraphicsPolygonItem.cpp +++ b/src/domain/UBGraphicsPolygonItem.cpp @@ -121,10 +121,12 @@ void UBGraphicsPolygonItem::setStrokesGroup(UBGraphicsStrokesGroup *group) void UBGraphicsPolygonItem::setStroke(UBGraphicsStroke* stroke) { - clearStroke(); + if (stroke) { + clearStroke(); - mStroke = stroke; - mStroke->addPolygon(this); + mStroke = stroke; + mStroke->addPolygon(this); + } } UBGraphicsStroke* UBGraphicsPolygonItem::stroke() const diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 23db81d5..b63ee57f 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -415,7 +415,7 @@ bool UBGraphicsScene::inputDevicePress(const QPointF& scenePos, const qreal& pre // --------------------------------------------------------------- // Create a new Stroke. A Stroke is a collection of QGraphicsLines // --------------------------------------------------------------- - mCurrentStroke = new UBGraphicsStroke(); + mCurrentStroke = new UBGraphicsStroke(this); if (currentTool != UBStylusTool::Line){ // Handle the pressure @@ -438,7 +438,7 @@ bool UBGraphicsScene::inputDevicePress(const QPointF& scenePos, const qreal& pre moveTo(scenePos); drawLineTo(scenePos, width, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); - mCurrentStroke->addPoint(scenePos); + mCurrentStroke->addPoint(scenePos, width); } accepted = true; } @@ -543,7 +543,7 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres } if (!mCurrentStroke) - mCurrentStroke = new UBGraphicsStroke(); + mCurrentStroke = new UBGraphicsStroke(this); if(dc->mActiveRuler){ dc->mActiveRuler->DrawLine(position, width); @@ -551,20 +551,15 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres else{ UBInterpolator::InterpolationMethod interpolator = UBInterpolator::NoInterpolation; - /* - if (currentTool == UBStylusTool::Marker) { - // The marker is already super slow due to the transparency, we can't also do interpolation - interpolator = UBInterpolator::NoInterpolation; - } - */ - - if (UBSettings::settings()->boardInterpolatePenStrokes->get().toBool()) { + if ((currentTool == UBStylusTool::Pen && UBSettings::settings()->boardInterpolatePenStrokes->get().toBool()) + || (currentTool == UBStylusTool::Marker && UBSettings::settings()->boardInterpolateMarkerStrokes->get().toBool())) + { interpolator = UBInterpolator::Bezier; } - QList newPoints = mCurrentStroke->addPoint(scenePos, interpolator); + QList > newPoints = mCurrentStroke->addPoint(scenePos, width, interpolator); if (newPoints.length() > 1) { - drawCurve(newPoints, mPreviousWidth, width); + drawCurve(newPoints); } if (interpolator == UBInterpolator::Bezier) { @@ -578,7 +573,7 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres mTempPolygon = NULL; } - QPointF lastDrawnPoint = newPoints.last(); + QPointF lastDrawnPoint = newPoints.last().first; mTempPolygon = lineToPolygonItem(QLineF(lastDrawnPoint, scenePos), mPreviousWidth, width); addItem(mTempPolygon); @@ -658,6 +653,14 @@ bool UBGraphicsScene::inputDeviceRelease() addPolygonItemToCurrentStroke(poly); } + // replace the stroke by a simplified version of it + if ((currentTool == UBStylusTool::Pen && UBSettings::settings()->boardSimplifyPenStrokes->get().toBool()) + || (currentTool == UBStylusTool::Marker && UBSettings::settings()->boardSimplifyMarkerStrokes->get().toBool())) + { + simplifyCurrentStroke(); + } + + UBGraphicsStrokesGroup* pStrokes = new UBGraphicsStrokesGroup(); // Remove the strokes that were just drawn here and replace them by a stroke item @@ -857,6 +860,15 @@ void UBGraphicsScene::drawLineTo(const QPointF &pEndPoint, const qreal &startWid } } +void UBGraphicsScene::drawCurve(const QList >& points) +{ + UBGraphicsPolygonItem* polygonItem = curveToPolygonItem(points); + addPolygonItemToCurrentStroke(polygonItem); + + mPreviousPoint = points.last().first; + mPreviousWidth = points.last().second; +} + void UBGraphicsScene::drawCurve(const QList& points, qreal startWidth, qreal endWidth) { UBGraphicsPolygonItem* polygonItem = curveToPolygonItem(points, startWidth, endWidth); @@ -886,7 +898,7 @@ void UBGraphicsScene::addPolygonItemToCurrentStroke(UBGraphicsPolygonItem* polyg // Here we add the item to the scene addItem(polygonItem); if (!mCurrentStroke) - mCurrentStroke = new UBGraphicsStroke(); + mCurrentStroke = new UBGraphicsStroke(this); polygonItem->setStroke(mCurrentStroke); @@ -1151,12 +1163,19 @@ UBGraphicsPolygonItem* UBGraphicsScene::arcToPolygonItem(const QLineF& pStartRad return polygonToPolygonItem(polygon); } +UBGraphicsPolygonItem* UBGraphicsScene::curveToPolygonItem(const QList >& points) +{ + QPolygonF polygon = UBGeometryUtils::curveToPolygon(points, false, true); + + return polygonToPolygonItem(polygon); + +} + UBGraphicsPolygonItem* UBGraphicsScene::curveToPolygonItem(const QList& points, qreal startWidth, qreal endWidth) { QPolygonF polygon = UBGeometryUtils::curveToPolygon(points, startWidth, endWidth); return polygonToPolygonItem(polygon); - } void UBGraphicsScene::clearSelectionFrame() @@ -2625,6 +2644,30 @@ bool UBGraphicsScene::hasTextItemWithFocus(UBGraphicsGroupContainerItem *item){ return bHasFocus; } + +void UBGraphicsScene::simplifyCurrentStroke() +{ + if (!mCurrentStroke) + return; + + UBGraphicsStroke* simplerStroke = mCurrentStroke->simplify(); + if (!simplerStroke) + return; + + foreach(UBGraphicsPolygonItem* poly, mCurrentStroke->polygons()){ + mPreviousPolygonItems.removeAll(poly); + removeItem(poly); + } + + mCurrentStroke = simplerStroke; + + foreach(UBGraphicsPolygonItem* poly, mCurrentStroke->polygons()) { + addItem(poly); + mPreviousPolygonItems.append(poly); + } + +} + void UBGraphicsScene::setDocumentUpdated() { if (document()) @@ -2738,5 +2781,5 @@ void UBGraphicsScene::setToolCursor(int tool) void UBGraphicsScene::initStroke() { - mCurrentStroke = new UBGraphicsStroke(); + mCurrentStroke = new UBGraphicsStroke(this); } diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 37f1a470..74577250 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -196,6 +196,7 @@ class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem void drawLineTo(const QPointF& pEndPoint, const qreal& pStartWidth, const qreal& endWidth, bool bLineStyle); void eraseLineTo(const QPointF& pEndPoint, const qreal& pWidth); void drawArcTo(const QPointF& pCenterPoint, qreal pSpanAngle); + void drawCurve(const QList > &points); void drawCurve(const QList& points, qreal startWidth, qreal endWidth); bool isEmpty() const; @@ -368,7 +369,8 @@ public slots: UBGraphicsPolygonItem* lineToPolygonItem(const QLineF &pLine, const qreal &pStartWidth, const qreal &pEndWidth); UBGraphicsPolygonItem* arcToPolygonItem(const QLineF& pStartRadius, qreal pSpanAngle, qreal pWidth); - UBGraphicsPolygonItem* curveToPolygonItem(const QList& points, qreal startWidth, qreal endWidth); + UBGraphicsPolygonItem* curveToPolygonItem(const QList > &points); + UBGraphicsPolygonItem* curveToPolygonItem(const QList &points, qreal startWidth, qreal endWidth); void addPolygonItemToCurrentStroke(UBGraphicsPolygonItem* polygonItem); void initPolygonItem(UBGraphicsPolygonItem*); @@ -402,6 +404,7 @@ public slots: void updateEraserColor(); void updateMarkerCircleColor(); bool hasTextItemWithFocus(UBGraphicsGroupContainerItem* item); + void simplifyCurrentStroke(); QGraphicsEllipseItem* mEraser; QGraphicsEllipseItem* mPointer; // "laser" pointer diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index f20b680b..a640d0a0 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -34,9 +34,15 @@ #include "board/UBBoardController.h" #include "core/UBApplication.h" #include "core/memcheck.h" +#include "domain/UBGraphicsScene.h" +#include "frameworks/UBGeometryUtils.h" -UBGraphicsStroke::UBGraphicsStroke() + +typedef QPair strokePoint; + +UBGraphicsStroke::UBGraphicsStroke(UBGraphicsScene *scene) + :mScene(scene) { mAntiScaleRatio = 1./(UBApplication::boardController->systemScaleFactor() * UBApplication::boardController->currentZoom()); } @@ -44,7 +50,10 @@ UBGraphicsStroke::UBGraphicsStroke() UBGraphicsStroke::~UBGraphicsStroke() { - // NOOP + foreach(UBGraphicsPolygonItem* poly, mPolygons) + poly->setStroke(NULL); + + mPolygons.clear(); } @@ -70,47 +79,51 @@ QList UBGraphicsStroke::polygons() const * @brief Add a point to the curve, interpolating extra points if required * @return The points (or point, if none were interpolated) that were added */ -QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator::InterpolationMethod interpolationMethod) +QList > UBGraphicsStroke::addPoint(const QPointF& point, qreal width, UBInterpolator::InterpolationMethod interpolationMethod) { + strokePoint newPoint(point, width); + int n = mReceivedPoints.size(); if (n == 0) { - mReceivedPoints << point; - mDrawnPoints << point; - return QList(); + mReceivedPoints << newPoint; + mDrawnPoints << newPoint; + return QList(); } if (interpolationMethod == UBInterpolator::NoInterpolation) { - QPointF lastPoint = mReceivedPoints.last(); - mReceivedPoints << point; - mDrawnPoints << point; - return QList() << lastPoint << point; + strokePoint lastPoint = mReceivedPoints.last(); + mReceivedPoints << newPoint; + mDrawnPoints << newPoint; + return QList() << lastPoint << newPoint; } else if (interpolationMethod == UBInterpolator::Bezier) { - // This is a bit special, as the curve we are interpolating is not between two drawn points; + // The curve we are interpolating is not between two drawn points; // it is between the midway points of the second-to-last and last point, and last and current point. // Don't draw segments smaller than a certain length. This can help with performance - // (less polygons in a stroke) but mostly with keeping the curve smooth. - qreal MIN_DISTANCE = 5*mAntiScaleRatio; - qreal distance = QLineF(mReceivedPoints.last(), point).length(); + // (less polygons to draw) but mostly with keeping the curve smooth. + qreal MIN_DISTANCE = 3*mAntiScaleRatio; + qreal distance = QLineF(mReceivedPoints.last().first, newPoint.first).length(); if (distance < MIN_DISTANCE) { - return QList() << mDrawnPoints.last(); + return QList() << mDrawnPoints.last(); } // The first segment is just a straight line to the first midway point if (n == 1) { - QPointF lastPoint = mReceivedPoints[0]; - mReceivedPoints << point; - mDrawnPoints << QPointF((lastPoint + point)/2.0); + QPointF lastPoint = mReceivedPoints[0].first; + qreal lastWidth = mReceivedPoints[0].second; + strokePoint p(((lastPoint+point)/2.0), (lastWidth+width)/2.0); + mReceivedPoints << newPoint; + mDrawnPoints << p; - return QList() << lastPoint << ((lastPoint + point)/2.0); + return QList() << mReceivedPoints[0] << p; } - QPointF p0 = mReceivedPoints[mReceivedPoints.size() - 2]; - QPointF p1 = mReceivedPoints[mReceivedPoints.size() - 1]; + QPointF p0 = mReceivedPoints[mReceivedPoints.size() - 2].first; + QPointF p1 = mReceivedPoints[mReceivedPoints.size() - 1].first; QPointF p2 = point; UBQuadraticBezier bz; @@ -120,21 +133,28 @@ QList UBGraphicsStroke::addPoint(const QPointF& point, UBInterpolator:: bz.setPoints(startPoint, p1, endPoint); - QList newPoints = bz.getPoints(10); + QList calculated = bz.getPoints(10); + QList newPoints; + + qreal startWidth = mDrawnPoints.last().second; + + for (int i(0); i < calculated.size(); ++i) { + qreal w = startWidth + (qreal(i)/qreal(calculated.size()-1)) * (width - startWidth); + newPoints << strokePoint(calculated[i], w); + } // avoid adding duplicates - if (newPoints.first() == mDrawnPoints.last()) + if (newPoints.first().first == mDrawnPoints.last().first) mDrawnPoints.removeLast(); - foreach(QPointF p, newPoints) { + foreach(strokePoint p, newPoints) mDrawnPoints << p; - } - mReceivedPoints << point; + mReceivedPoints << strokePoint(point, width); return newPoints; } - return QList(); + return QList(); } bool UBGraphicsStroke::hasPressure() @@ -179,3 +199,124 @@ void UBGraphicsStroke::clear() mPolygons.clear(); } } + +/** + * @brief Return a simplified version of the stroke, with less points and polygons. + * + */ +UBGraphicsStroke* UBGraphicsStroke::simplify() +{ + if (mDrawnPoints.size() < 3) + return NULL; + + UBGraphicsStroke* newStroke = new UBGraphicsStroke(); + newStroke->mDrawnPoints = QList(mDrawnPoints); + + QList& points = newStroke->mDrawnPoints; + qDebug() << "Simplifying. Before: " << points.size() << " points and " << polygons().size() << " polygons"; + + /* Basic simplifying algorithm: consider A, B and C the current point and the two following ones. + * If the angle between (AB) and (BC) is lower than a certain threshold, + * the three points are considered to be aligned and the middle one (B) is removed. + * + * We then consider the two following points as the new B and C while keeping the same A, and + * test these three points. As long as they are aligned, B is erased and we start over. + * If not, the current B becomes the new A, and so on. + * + * + * TODO: more advanced algorithm that could also simplify curved sections of the stroke + */ + + // angle difference in degrees between AB and BC below which the segments are considered colinear + qreal threshold = UBSettings::settings()->boardSimplifyPenStrokesThresholdAngle->get().toReal(); + + QList::iterator it = points.begin(); + QList::iterator> toDelete; + + while (it+2 != points.end()) { + QList::iterator b_it(it+1); + + while (b_it+1 != points.end()) { + qreal angle = qFabs(QLineF(it->first, b_it->first).angle() - QLineF(b_it->first, (b_it+1)->first).angle()); + + if (angle < threshold) + b_it = points.erase(b_it); + else + break; + } + + if (b_it+1 == points.end()) + break; + else + it = b_it; + } + + // Next, we iterate over the new points to build the polygons that make up the stroke + + QList newPolygons; + QList newStrokePoints; + int i(0); + + while (i < points.size()) { + bool drawCurve = false; + + newStrokePoints << points[i]; + + // When a polygon is transparent and it overlaps with itself, it is *sometimes* filled incorrectly. + // Limiting the size of the polygons, and creating new ones when the angle between consecutive points is above a + // certain threshold helps mitigate this issue. + // TODO: fix fill issue + + if (newStrokePoints.size() > 1 && i < points.size() - 1) { + qreal angle = qFabs(UBGeometryUtils::angle(points[i-1].first, points[i].first, points[i+1].first)); + qDebug() << "Angle: " << angle; + if (angle > 40 && angle < 320) + drawCurve = true; + } + + if (newStrokePoints.size() % 20 == 0) + drawCurve = true; + + + if (drawCurve) { + UBGraphicsPolygonItem* poly = mScene->polygonToPolygonItem(UBGeometryUtils::curveToPolygon(newStrokePoints, true, true)); + //poly->setColor(QColor(rand()%256, rand()%256, rand()%256, poly->brush().color().alpha())); + + // Subtract overlapping polygons if the stroke is translucent + + if (!poly->brush().isOpaque()) { + foreach(UBGraphicsPolygonItem* prev, newPolygons) + poly->subtract(prev); + } + + newPolygons << poly; + newStrokePoints.clear(); + --i; + } + + ++i; + } + + if (newStrokePoints.size() > 0) { + UBGraphicsPolygonItem* poly = mScene->polygonToPolygonItem(UBGeometryUtils::curveToPolygon(newStrokePoints, true, true)); + + if (!poly->brush().isOpaque()) { + foreach(UBGraphicsPolygonItem* prev, newPolygons) + poly->subtract(prev); + } + + newPolygons << poly; + } + + + newStroke->mPolygons = QList(newPolygons); + + foreach(UBGraphicsPolygonItem* poly, newStroke->mPolygons) { + poly->setFillRule(Qt::WindingFill); + poly->setStroke(newStroke); + } + + qDebug() << "After: " << points.size() << " points and " << newStroke->polygons().size() << " polygons"; + + return newStroke; +} diff --git a/src/domain/UBGraphicsStroke.h b/src/domain/UBGraphicsStroke.h index 8c332498..918ec894 100644 --- a/src/domain/UBGraphicsStroke.h +++ b/src/domain/UBGraphicsStroke.h @@ -38,13 +38,14 @@ class UBGraphicsPolygonItem; +class UBGraphicsScene; class UBGraphicsStroke { friend class UBGraphicsPolygonItem; public: - UBGraphicsStroke(); + UBGraphicsStroke(UBGraphicsScene* scene = NULL); virtual ~UBGraphicsStroke(); bool hasPressure(); @@ -59,22 +60,26 @@ class UBGraphicsStroke void clear(); - QList addPoint(const QPointF& point, UBInterpolator::InterpolationMethod interpolationMethod = UBInterpolator::NoInterpolation); + QList > addPoint(const QPointF& point, qreal width, UBInterpolator::InterpolationMethod interpolationMethod = UBInterpolator::NoInterpolation); - const QList& points() { return mDrawnPoints; } + const QList >& points() { return mDrawnPoints; } + + UBGraphicsStroke* simplify(); protected: void addPolygon(UBGraphicsPolygonItem* pol); private: + UBGraphicsScene * mScene; + QList mPolygons; /// Points that were drawn by the user (i.e, actually received through input device) - QList mReceivedPoints; + QList > mReceivedPoints; /// All the points (including interpolated) that are used to draw the stroke - QList mDrawnPoints; + QList > mDrawnPoints; qreal mAntiScaleRatio; }; diff --git a/src/frameworks/UBGeometryUtils.cpp b/src/frameworks/UBGeometryUtils.cpp index f42f6684..eb36a27e 100644 --- a/src/frameworks/UBGeometryUtils.cpp +++ b/src/frameworks/UBGeometryUtils.cpp @@ -265,6 +265,36 @@ QPolygonF UBGeometryUtils::curveToPolygon(const QList& points, qreal st if (n_points == 2) return lineToPolygon(points[0], points[1], startWidth, endWidth); + QList > pointsAndWidths; + for (int i(0); i < n_points; ++i) { + qreal width = startWidth + (qreal(i)/qreal(n_points-1)) * (endWidth - startWidth); + + pointsAndWidths << QPair(points[i], width); + } + + return curveToPolygon(pointsAndWidths, true, true); +} + +/** + * @brief Build and return a polygon from a list of points and thicknesses (at least 2) + * + * The resulting polygon will pass by all points in the curve; the segments are joined by + * (approximately) curved joints. The ends of the polygon can be terminated by arcs by passing + * `true` as the `roundStart` and/or `roundEnd` parameters. + * + */ +QPolygonF UBGeometryUtils::curveToPolygon(const QList >& points, bool roundStart, bool roundEnd) +{ + int n_points = points.size(); + + if (n_points == 0) + return QPolygonF(); + if (n_points == 1) + return lineToPolygon(points.first().first, points.first().first, points.first().second, points.first().second); + + qreal startWidth = points.first().second; + qreal endWidth = points.last().second; + /* The vertices (x's) are calculated based on the stroke's width and angle, and the position of the supplied points (o's): @@ -276,15 +306,16 @@ QPolygonF UBGeometryUtils::curveToPolygon(const QList& points, qreal st The vertices above and below each 'o' point are temporarily stored together, as a pair of points. - */ + + typedef QPair pointPair; QList newPoints; - QLineF firstSegment = QLineF(points[0], points[1]); + QLineF firstSegment = QLineF(points[0].first, points[1].first); QLineF normal = firstSegment.normalVector(); normal.setLength(startWidth/2.0); - newPoints << pointPair(normal.p2(), points[0] - QPointF(normal.dx(), normal.dy())); + newPoints << pointPair(normal.p2(), points[0].first - QPointF(normal.dx(), normal.dy())); /* Calculating the vertices (d1 and d2, below) is a little less trivial for the @@ -306,45 +337,50 @@ QPolygonF UBGeometryUtils::curveToPolygon(const QList& points, qreal st */ for (int i(1); i < n_points-1; ++i) { - qreal width = startWidth + (qreal(i)/qreal(n_points-1)) * (endWidth - startWidth); + //qreal width = startWidth + (qreal(i)/qreal(n_points-1)) * (endWidth - startWidth); - QLineF normal = (QLineF(points[i-1], points[i+1])).normalVector(); - normal.setLength(width/2.0); - QPointF d1 = points[i] + QPointF(normal.dx(), normal.dy()); - QPointF d2 = points[i] - QPointF(normal.dx(), normal.dy()); + QLineF normal = (QLineF(points[i-1].first, points[i+1].first)).normalVector(); + normal.setLength(points[i].second/2.0); + QPointF d1 = points[i].first + QPointF(normal.dx(), normal.dy()); + QPointF d2 = points[i].first - QPointF(normal.dx(), normal.dy()); newPoints << pointPair(d1, d2); } // The last point is similar to the first - QLineF lastSegment = QLineF(points[n_points-2], points[n_points-1]); + QLineF lastSegment = QLineF(points[n_points-2].first, points[n_points-1].first); normal = lastSegment.normalVector(); normal.setLength(endWidth/2.0); - QPointF d1 = points.last() + QPointF(normal.dx(), normal.dy()); - QPointF d2 = points.last() - QPointF(normal.dx(), normal.dy()); + QPointF d1 = points.last().first + QPointF(normal.dx(), normal.dy()); + QPointF d2 = points.last().first - QPointF(normal.dx(), normal.dy()); newPoints << pointPair(d1, d2); QPainterPath path; + path.setFillRule(Qt::WindingFill); path.moveTo(newPoints[0].first); for (int i(1); i < n_points; ++i) { path.lineTo(newPoints[i].first); } - path.arcTo(points.last().x() - endWidth/2.0, points.last().y() - endWidth/2.0, endWidth, endWidth, (90.0 + lastSegment.angle()), -180.0); - //path.lineTo(newPoints.last().second); + if (roundEnd) + path.arcTo(points.last().first.x() - endWidth/2.0, points.last().first.y() - endWidth/2.0, endWidth, endWidth, (90.0 + lastSegment.angle()), -180.0); + else + path.lineTo(newPoints.last().second); for (int i(n_points-1); i >= 0; --i) { path.lineTo(newPoints[i].second); } - path.arcTo(points[0].x() - startWidth/2.0, points[0].y() - startWidth/2.0, startWidth, startWidth, (firstSegment.angle() - 90.0), -180.0); - //path.lineTo(newPoints[0].second); + if (roundStart) + path.arcTo(points[0].first.x() - startWidth/2.0, points[0].first.y() - startWidth/2.0, startWidth, startWidth, (firstSegment.angle() - 90.0), -180.0); + else + path.lineTo(newPoints[0].first); - path.closeSubpath(); + //path.closeSubpath(); return path.toFillPolygon(); } @@ -391,3 +427,11 @@ void UBGeometryUtils::crashPointList(QVector &points) } } } + +/** + * @brief Return the angle between three points + */ +qreal UBGeometryUtils::angle(const QPointF& a, const QPointF& b, const QPointF& c) +{ + return (QLineF(a, b).angle() - QLineF(b, c).angle()); +} diff --git a/src/frameworks/UBGeometryUtils.h b/src/frameworks/UBGeometryUtils.h index 6d0aeff1..988b4a20 100644 --- a/src/frameworks/UBGeometryUtils.h +++ b/src/frameworks/UBGeometryUtils.h @@ -48,12 +48,15 @@ class UBGeometryUtils static QPolygonF lineToPolygon(const QPointF& pStart, const QPointF& pEnd, const qreal& pStartWidth, const qreal& pEndWidth); static QPolygonF curveToPolygon(const QList& points, qreal startWidth, qreal endWidth); + static QPolygonF curveToPolygon(const QList >& points, bool roundStart, bool roundEnd); static QPointF pointConstrainedInRect(QPointF point, QRectF rect); static QPoint pointConstrainedInRect(QPoint point, QRect rect); static void crashPointList(QVector &points); + static qreal angle(const QPointF& a, const QPointF& b, const QPointF& c); + const static int centimeterGraduationHeight; const static int halfCentimeterGraduationHeight; const static int millimeterGraduationHeight; diff --git a/src/frameworks/UBInterpolator.cpp b/src/frameworks/UBInterpolator.cpp index b5777bcd..3b75da12 100644 --- a/src/frameworks/UBInterpolator.cpp +++ b/src/frameworks/UBInterpolator.cpp @@ -34,7 +34,7 @@ void UBQuadraticBezier::setPoints(QPointF start, QPointF control, QPointF end) /** * @brief Return n points along the curve, including start and end points (thus n should be larger than or equal to 2). * - * The higher n, the more accurate the result + * The higher n, the more accurate the resulting curve will be. */ QList UBQuadraticBezier::getPoints(int n) { From b850787164bb94aaf69da362dd5fb2cb08adbd4e Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 15 Oct 2016 15:46:13 -0400 Subject: [PATCH 022/134] Updated translation files; completed french translations --- resources/i18n/OpenBoard_ar.ts | 79 +- resources/i18n/OpenBoard_bg.ts | 79 +- resources/i18n/OpenBoard_ca.ts | 79 +- resources/i18n/OpenBoard_cs.ts | 79 +- resources/i18n/OpenBoard_da.ts | 79 +- resources/i18n/OpenBoard_de.ts | 79 +- resources/i18n/OpenBoard_el.ts | 79 +- resources/i18n/OpenBoard_en.ts | 75 +- resources/i18n/OpenBoard_en_UK.ts | 75 +- resources/i18n/OpenBoard_es.ts | 79 +- resources/i18n/OpenBoard_fr.ts | 67 +- resources/i18n/OpenBoard_fr_CH.ts | 67 +- resources/i18n/OpenBoard_it.ts | 79 +- resources/i18n/OpenBoard_iw.ts | 79 +- resources/i18n/OpenBoard_ja.ts | 79 +- resources/i18n/OpenBoard_ko.ts | 79 +- resources/i18n/OpenBoard_mg.ts | 79 +- resources/i18n/OpenBoard_nb.ts | 79 +- resources/i18n/OpenBoard_nl.ts | 79 +- resources/i18n/OpenBoard_pl.ts | 79 +- resources/i18n/OpenBoard_pt.ts | 67 +- resources/i18n/OpenBoard_ro.ts | 79 +- resources/i18n/OpenBoard_ru.ts | 79 +- resources/i18n/OpenBoard_sk.ts | 5313 +++++++++++++++-------------- resources/i18n/OpenBoard_sv.ts | 79 +- resources/i18n/OpenBoard_tr.ts | 79 +- resources/i18n/OpenBoard_zh.ts | 79 +- resources/i18n/OpenBoard_zh_CN.ts | 79 +- resources/i18n/OpenBoard_zh_TW.ts | 79 +- 29 files changed, 4040 insertions(+), 3441 deletions(-) diff --git a/resources/i18n/OpenBoard_ar.ts b/resources/i18n/OpenBoard_ar.ts index 5e8d5520..7190f110 100644 --- a/resources/i18n/OpenBoard_ar.ts +++ b/resources/i18n/OpenBoard_ar.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ التحيين + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1243,6 +1258,26 @@ Warnings during export was appeared ظهر تحذير أثناء التصدير + + Exporting document... + تصدير الوثيقة... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + تصدير ناجح. + UBExportCFF @@ -1279,11 +1314,11 @@ Exporting document... - تصدير الوثيقة... + تصدير الوثيقة... Export successful. - تصدير ناجح. + تصدير ناجح. Exporting %1 %2 of %3 @@ -1293,18 +1328,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1314,28 +1337,16 @@ Exporting document... - تصدير الوثيقة... + تصدير الوثيقة... Export successful. - تصدير ناجح. + تصدير ناجح. Export to PDF التصدير للـPDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1345,11 +1356,11 @@ Exporting document... - تصدير الوثيقة... + تصدير الوثيقة... Export successful. - تصدير ناجح. + تصدير ناجح. Exporting page %1 of %2 @@ -2419,6 +2430,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive القلم حساس للضغط + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_bg.ts b/resources/i18n/OpenBoard_bg.ts index 9a9988a9..5bb78838 100644 --- a/resources/i18n/OpenBoard_bg.ts +++ b/resources/i18n/OpenBoard_bg.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Обновления + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1235,6 +1250,26 @@ Warnings during export was appeared Появиха се предупреждения по време на експортирането на страницата + + Exporting document... + + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + + UBExportCFF @@ -1271,11 +1306,11 @@ Exporting document... - Експортиране на документ... + Експортиране на документ... Export successful. - Експортирането е успешно. + Експортирането е успешно. Exporting %1 %2 of %3 @@ -1285,18 +1320,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1306,28 +1329,16 @@ Exporting document... - Експортиране на документа... + Експортиране на документа... Export successful. - Експортирането е успешно. + Експортирането е успешно. Export to PDF Експортиране към PDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1337,11 +1348,11 @@ Exporting document... - Експортиране на документ... + Експортиране на документ... Export successful. - Експортирането успешно. + Експортирането успешно. Exporting page %1 of %2 @@ -2414,6 +2425,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Химикалката е чувствителна на натиск + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_ca.ts b/resources/i18n/OpenBoard_ca.ts index ef3c4db3..41a72f74 100644 --- a/resources/i18n/OpenBoard_ca.ts +++ b/resources/i18n/OpenBoard_ca.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Actualitza + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1234,6 +1249,26 @@ Warnings during export was appeared Advertiments: durant l'exportació han aparegut + + Exporting document... + S'està exportant el document... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + L'exportació ha estat correcta. + UBExportCFF @@ -1270,11 +1305,11 @@ Exporting document... - S'està exportant el document... + S'està exportant el document... Export successful. - L'exportació ha estat correcta. + L'exportació ha estat correcta. Exporting %1 %2 of %3 @@ -1284,18 +1319,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1305,7 +1328,7 @@ Exporting document... - S'està exportant el document... + S'està exportant el document... Export to PDF @@ -1313,19 +1336,7 @@ Export successful. - L'exportació ha estat correcta. - - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - + L'exportació ha estat correcta. @@ -1336,11 +1347,11 @@ Exporting document... - S'està exportant el document... + S'està exportant el document... Export successful. - L'exportació ha estat correcta. + L'exportació ha estat correcta. Exporting page %1 of %2 @@ -2407,6 +2418,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive El llapis és sensible a la pressió + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_cs.ts b/resources/i18n/OpenBoard_cs.ts index f9ea57bb..78678f0d 100644 --- a/resources/i18n/OpenBoard_cs.ts +++ b/resources/i18n/OpenBoard_cs.ts @@ -800,6 +800,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -892,6 +900,13 @@ K dispozici je aktualizace + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1237,6 +1252,26 @@ Warnings during export was appeared Během exportu se objevila varování + + Exporting document... + Exportuje se dokument... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + Export byl úspěšně dokončen. + UBExportCFF @@ -1277,28 +1312,16 @@ Exporting document... - Exportuje se dokument... + Exportuje se dokument... Export successful. - Export byl úspěšně dokončen. + Export byl úspěšně dokončen. Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1312,23 +1335,11 @@ Exporting document... - Exportuje se dokument... + Exportuje se dokument... Export successful. - Export byl úspěšně dokončen. - - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - + Export byl úspěšně dokončen. @@ -1347,11 +1358,11 @@ Exporting document... - Exportuje se dokument... + Exportuje se dokument... Export successful. - Export byl úspěšně dokončen. + Export byl úspěšně dokončen. @@ -2417,6 +2428,14 @@ p, li { white-space: pre-wrap; } On Dark Background Na tmavém pozadí + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_da.ts b/resources/i18n/OpenBoard_da.ts index ddddbbd3..53b43c09 100644 --- a/resources/i18n/OpenBoard_da.ts +++ b/resources/i18n/OpenBoard_da.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Opdatering + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1234,6 +1249,26 @@ Warnings during export was appeared Advarsler under eksportering blev vist + + Exporting document... + Eksporterer dokument... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + Eksport gennemført. + UBExportCFF @@ -1270,11 +1305,11 @@ Exporting document... - Eksporterer dokument... + Eksporterer dokument... Export successful. - Eksport gennemført. + Eksport gennemført. Exporting %1 %2 of %3 @@ -1284,18 +1319,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1305,28 +1328,16 @@ Exporting document... - Eksporterer dokument... + Eksporterer dokument... Export successful. - Eksport gennemført. + Eksport gennemført. Export to PDF Eksport til PDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1336,11 +1347,11 @@ Exporting document... - Eksporterer dokument... + Eksporterer dokument... Export successful. - Eksport gennemført. + Eksport gennemført. Exporting page %1 of %2 @@ -2410,6 +2421,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Pen er tryksensitiv + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_de.ts b/resources/i18n/OpenBoard_de.ts index 6ce93662..ee245d01 100644 --- a/resources/i18n/OpenBoard_de.ts +++ b/resources/i18n/OpenBoard_de.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Update + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1234,6 +1249,26 @@ Warnings during export was appeared Warnungen beim Exportieren aufgetreten + + Exporting document... + Dokument wird exportiert... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + Export erfolgreich. + UBExportCFF @@ -1270,11 +1305,11 @@ Exporting document... - Dokument wird exportiert... + Dokument wird exportiert... Export successful. - Export erfolgreich. + Export erfolgreich. Exporting %1 %2 of %3 @@ -1284,18 +1319,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1305,28 +1328,16 @@ Exporting document... - Dokument wird exportiert... + Dokument wird exportiert... Export successful. - Export erfolgreich. + Export erfolgreich. Export to PDF In PDF-Datei exportieren - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1336,11 +1347,11 @@ Exporting document... - Dokument wird exportiert... + Dokument wird exportiert... Export successful. - Export erfolgreich. + Export erfolgreich. Exporting page %1 of %2 @@ -2414,6 +2425,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Der Stift ist druckempfindlich + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_el.ts b/resources/i18n/OpenBoard_el.ts index 4260bfbf..dbb56d5a 100644 --- a/resources/i18n/OpenBoard_el.ts +++ b/resources/i18n/OpenBoard_el.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Ενημέρωση + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1234,6 +1249,26 @@ Warnings during export was appeared Εμφανίστηκαν προειδοποιήσεις κατά τη διάρκεια της εξαγωγής + + Exporting document... + Εξαγωγή εγγράφου... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + Επιτυχημένη εξαγωγή + UBExportCFF @@ -1270,11 +1305,11 @@ Exporting document... - Εξαγωγή εγγράφου... + Εξαγωγή εγγράφου... Export successful. - Επιτυχημένη εξαγωγή + Επιτυχημένη εξαγωγή Exporting %1 %2 of %3 @@ -1284,18 +1319,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1305,28 +1328,16 @@ Exporting document... - Εξαγωγή εγγράφου... + Εξαγωγή εγγράφου... Export successful. - Επιτυχημένη εξαγωγή + Επιτυχημένη εξαγωγή Export to PDF Εξαγωγή σε PDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1336,11 +1347,11 @@ Exporting document... - Εξαγωγή εγγράφου... + Εξαγωγή εγγράφου... Export successful. - Επιτυχημένη εξαγωγή + Επιτυχημένη εξαγωγή Exporting page %1 of %2 @@ -2414,6 +2425,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Η πένα είναι ευαίσθητη στην πίεση + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_en.ts b/resources/i18n/OpenBoard_en.ts index bf59ddce..9088ea8f 100644 --- a/resources/i18n/OpenBoard_en.ts +++ b/resources/i18n/OpenBoard_en.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -883,6 +891,13 @@ + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1224,43 +1239,43 @@ Warnings during export was appeared - - - UBExportDocument - Page + Exporting document... - Export as UBZ File + Export failed - Exporting document... + Unable to export to the selected location. You do not have the permissions necessary to save the file. - Export successful. + Export failed: location not writable - Exporting %1 %2 of %3 + Export successful. + + + UBExportDocument - Export to OpenBoard Format + Page - Export failed: location not writable + Export as UBZ File - Export failed + Exporting %1 %2 of %3 - Unable to export to the selected location. You do not have the permissions necessary to save the file. + Export to OpenBoard Format @@ -1270,30 +1285,10 @@ Export as PDF File - - Exporting document... - - Export to PDF - - Export successful. - - - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1305,14 +1300,6 @@ Exporting page %1 of %2 - - Export successful. - - - - Exporting document... - - Export to PDF @@ -2347,6 +2334,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_en_UK.ts b/resources/i18n/OpenBoard_en_UK.ts index 7080b3b6..423c1e7d 100644 --- a/resources/i18n/OpenBoard_en_UK.ts +++ b/resources/i18n/OpenBoard_en_UK.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -883,6 +891,13 @@ + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1224,43 +1239,43 @@ Warnings during export was appeared - - - UBExportDocument - Page + Exporting document... - Export as UBZ File + Export failed - Exporting document... + Unable to export to the selected location. You do not have the permissions necessary to save the file. - Export successful. + Export failed: location not writable - Exporting %1 %2 of %3 + Export successful. + + + UBExportDocument - Export to OpenBoard Format + Page - Export failed: location not writable + Export as UBZ File - Export failed + Exporting %1 %2 of %3 - Unable to export to the selected location. You do not have the permissions necessary to save the file. + Export to OpenBoard Format @@ -1270,30 +1285,10 @@ Export as PDF File - - Exporting document... - - - - Export successful. - - Export to PDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1301,14 +1296,6 @@ Export as PDF File - - Exporting document... - - - - Export successful. - - Exporting page %1 of %2 @@ -2347,6 +2334,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_es.ts b/resources/i18n/OpenBoard_es.ts index 26d94b66..0c05c8c7 100644 --- a/resources/i18n/OpenBoard_es.ts +++ b/resources/i18n/OpenBoard_es.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Actualizar + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1234,6 +1249,26 @@ Warnings during export was appeared Han aparecido advertencias durante la exportación + + Exporting document... + Exportando documento... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + Exportación satisfactoria. + UBExportCFF @@ -1270,11 +1305,11 @@ Exporting document... - Exportando documento... + Exportando documento... Export successful. - Exportación satisfactoria. + Exportación satisfactoria. Exporting %1 %2 of %3 @@ -1284,18 +1319,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1305,28 +1328,16 @@ Exporting document... - Exportando documento... + Exportando documento... Export successful. - Exportación satisfactoria. + Exportación satisfactoria. Export to PDF Exportar a PDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1336,11 +1347,11 @@ Exporting document... - Exportando documento... + Exportando documento... Export successful. - Exportación satisfactoria. + Exportación satisfactoria. Exporting page %1 of %2 @@ -2408,6 +2419,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive El bolígrafo es sensible a la presión + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_fr.ts b/resources/i18n/OpenBoard_fr.ts index d0e08a3b..dca5946a 100644 --- a/resources/i18n/OpenBoard_fr.ts +++ b/resources/i18n/OpenBoard_fr.ts @@ -800,6 +800,14 @@ Open the tutorial web page Ouvrir la page Web des tutoriels + + Ruled Light Background + Fond ligné clair + + + Ruled Dark Background + Fond ligné foncé + PasswordDialog @@ -892,6 +900,13 @@ Mettre à jour + + UBBackgroundPalette + + Grid size + Taille du quadrillage + + UBBoardController @@ -1240,6 +1255,26 @@ Warnings during export was appeared Avertissements lors de l'exportation + + Exporting document... + Export du document... + + + Export failed + Echec de l'export + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + Impossible d'exporter dans le dossier sélectionné. Vous n'avez pas les permissions nécessaires pour sauvegarder le fichier. + + + Export failed: location not writable + Impossible d'exporter: pas de droits d'écriture dans le répertoire + + + Export successful. + Export réussi. + UBExportCFF @@ -1272,7 +1307,7 @@ Export successful. - Export réussi. + Export réussi. Page @@ -1280,7 +1315,7 @@ Exporting document... - Exportation du document... + Exportation du document... Exporting %1 %2 of %3 @@ -1292,15 +1327,15 @@ Export failed: location not writable - Impossible d'exporter: pas de droits d'écriture dans le répertoire + Impossible d'exporter: pas de droits d'écriture dans le répertoire Export failed - Echec de l'export + Echec de l'export Unable to export to the selected location. You do not have the permissions necessary to save the file. - Impossible d'exporter dans le dossier sélectionné. Vous n'avez pas les permissions nécessaires pour sauvegarder le fichier. + Impossible d'exporter dans le dossier sélectionné. Vous n'avez pas les permissions nécessaires pour sauvegarder le fichier. @@ -1311,7 +1346,7 @@ Exporting document... - Exportation du document... + Exportation du document... Export to PDF @@ -1319,19 +1354,19 @@ Export successful. - Export terminé. + Export terminé. Export failed: location not writable - Impossible d'exporter: pas de droits d'écriture dans le répertoire + Impossible d'exporter: pas de droits d'écriture dans le répertoire Export failed - Echec de l'export + Echec de l'export Unable to export to the selected location. You do not have the permissions necessary to save the file. - Impossible d'exporter dans le dossier sélectionné. Vous n'avez pas les permissions nécessaires pour sauvegarder le fichier. + Impossible d'exporter dans le dossier sélectionné. Vous n'avez pas les permissions nécessaires pour sauvegarder le fichier. @@ -1346,11 +1381,11 @@ Export successful. - Export terminé. + Export terminé. Exporting document... - Exportation du document... + Exportation du document... Export to PDF @@ -2424,6 +2459,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Stylet sensible à la pression + + Smooth strokes (experimental) + Lissage des traits (expérimental) + + + Simplify strokes after drawing (experimental) + Simplification des traits post-dessin (expérimental) + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_fr_CH.ts b/resources/i18n/OpenBoard_fr_CH.ts index 6bd567b4..a60e44f9 100644 --- a/resources/i18n/OpenBoard_fr_CH.ts +++ b/resources/i18n/OpenBoard_fr_CH.ts @@ -800,6 +800,14 @@ Open the tutorial web page Ouvrir la page Web des tutoriels + + Ruled Light Background + Fond ligné clair + + + Ruled Dark Background + Fond ligné foncé + PasswordDialog @@ -892,6 +900,13 @@ Mettre à jour + + UBBackgroundPalette + + Grid size + Taille du quadrillage + + UBBoardController @@ -1240,6 +1255,26 @@ Warnings during export was appeared Avertissements lors de l'exportation + + Exporting document... + Export du document... + + + Export failed + Echec de l'export + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + Impossible d'exporter dans le dossier sélectionné. Vous n'avez pas les permissions nécessaires pour sauvegarder le fichier. + + + Export failed: location not writable + Impossible d'exporter: pas de droits d'écriture dans le répertoire + + + Export successful. + Export réussi. + UBExportCFF @@ -1272,7 +1307,7 @@ Export successful. - Export réussi. + Export réussi. Page @@ -1280,7 +1315,7 @@ Exporting document... - Exportation du document... + Exportation du document... Exporting %1 %2 of %3 @@ -1292,15 +1327,15 @@ Export failed: location not writable - Impossible d'exporter: pas de droits d'écriture dans le répertoire + Impossible d'exporter: pas de droits d'écriture dans le répertoire Export failed - Echec de l'export + Echec de l'export Unable to export to the selected location. You do not have the permissions necessary to save the file. - Impossible d'exporter dans le dossier sélectionné. Vous n'avez pas les permissions nécessaires pour sauvegarder le fichier. + Impossible d'exporter dans le dossier sélectionné. Vous n'avez pas les permissions nécessaires pour sauvegarder le fichier. @@ -1311,7 +1346,7 @@ Exporting document... - Exportation du document... + Exportation du document... Export to PDF @@ -1319,19 +1354,19 @@ Export successful. - Export terminé. + Export terminé. Export failed: location not writable - Impossible d'exporter: pas de droits d'écriture dans le répertoire + Impossible d'exporter: pas de droits d'écriture dans le répertoire Export failed - Echec de l'export + Echec de l'export Unable to export to the selected location. You do not have the permissions necessary to save the file. - Impossible d'exporter dans le dossier sélectionné. Vous n'avez pas les permissions nécessaires pour sauvegarder le fichier. + Impossible d'exporter dans le dossier sélectionné. Vous n'avez pas les permissions nécessaires pour sauvegarder le fichier. @@ -1346,11 +1381,11 @@ Export successful. - Export terminé. + Export terminé. Exporting document... - Exportation du document... + Exportation du document... Export to PDF @@ -2424,6 +2459,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Stylet sensible à la pression + + Smooth strokes (experimental) + Lissage des traits (expérimental) + + + Simplify strokes after drawing (experimental) + Simplification des traits post-dessin (expérimental) + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_it.ts b/resources/i18n/OpenBoard_it.ts index 3786d465..3f6a5947 100644 --- a/resources/i18n/OpenBoard_it.ts +++ b/resources/i18n/OpenBoard_it.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Aggiornamento + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1234,6 +1249,26 @@ Warnings during export was appeared È apparso un avviso durante l'esportazione + + Exporting document... + Esportazione documento in corso... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + + UBExportCFF @@ -1270,11 +1305,11 @@ Exporting document... - Esportazione documento in corso... + Esportazione documento in corso... Export successful. - Esportazione completata con successo. + Esportazione completata con successo. Exporting %1 %2 of %3 @@ -1284,18 +1319,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1305,28 +1328,16 @@ Exporting document... - Esportazione documento in corso... + Esportazione documento in corso... Export successful. - Esportazione completata con successo. + Esportazione completata con successo. Export to PDF Esporta in PDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1336,11 +1347,11 @@ Exporting document... - Esportazione documento in corso... + Esportazione documento in corso... Export successful. - Esportazione riuscita. + Esportazione riuscita. Exporting page %1 of %2 @@ -2414,6 +2425,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive La penna è sensibile alla pressione + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_iw.ts b/resources/i18n/OpenBoard_iw.ts index 0d98c054..e232651e 100644 --- a/resources/i18n/OpenBoard_iw.ts +++ b/resources/i18n/OpenBoard_iw.ts @@ -800,6 +800,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -892,6 +900,13 @@ עדכון + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1236,6 +1251,26 @@ I don't understand this sentence + + Exporting document... + מייצא מסמך... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + הייצוא בוצע בהצלחה. + UBExportCFF @@ -1272,11 +1307,11 @@ Exporting document... - מייצא מסמך... + מייצא מסמך... Export successful. - הייצוא בוצע בהצלחה. + הייצוא בוצע בהצלחה. Exporting %1 %2 of %3 @@ -1286,18 +1321,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1307,28 +1330,16 @@ Exporting document... - מייצא מסמך... + מייצא מסמך... Export successful. - הייצוא בוצע בהצלחה. + הייצוא בוצע בהצלחה. Export to PDF ייצא ל- PDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1338,11 +1349,11 @@ Exporting document... - מייצא מסמך... + מייצא מסמך... Export successful. - הייצוא בוצע בהצלחה. + הייצוא בוצע בהצלחה. Exporting page %1 of %2 @@ -2407,6 +2418,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive העט רגיש ללחץ + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_ja.ts b/resources/i18n/OpenBoard_ja.ts index 05290e17..977e8ae3 100644 --- a/resources/i18n/OpenBoard_ja.ts +++ b/resources/i18n/OpenBoard_ja.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -883,6 +891,13 @@ 更新 + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1224,6 +1239,26 @@ Warnings during export was appeared + + Exporting document... + ドキュメントのエクスポート中... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + + UBExportCFF @@ -1260,11 +1295,11 @@ Exporting document... - ドキュメントのエクスポート中... + ドキュメントのエクスポート中... Export successful. - エクスポートに成功 + エクスポートに成功 Exporting %1 %2 of %3 @@ -1274,18 +1309,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1295,28 +1318,16 @@ Exporting document... - ドキュメントのエクスポート中... + ドキュメントのエクスポート中... Export successful. - エクスポートに成功 + エクスポートに成功 Export to PDF PDFへエクスポート - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1326,11 +1337,11 @@ Exporting document... - ドキュメントのエクスポート中... + ドキュメントのエクスポート中... Export successful. - エクスポートに成功。 + エクスポートに成功。 Exporting page %1 of %2 @@ -2401,6 +2412,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive ペンは感圧性です。 + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_ko.ts b/resources/i18n/OpenBoard_ko.ts index 0f51affd..e8d068a9 100644 --- a/resources/i18n/OpenBoard_ko.ts +++ b/resources/i18n/OpenBoard_ko.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ 업데이트 + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1235,6 +1250,26 @@ Warnings during export was appeared 내보내는 도중 경고가 나타났습니다 + + Exporting document... + 문서를 내보내는 중... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + 내보내기 완료. + UBExportCFF @@ -1271,11 +1306,11 @@ Exporting document... - 문서를 내보내는 중... + 문서를 내보내는 중... Export successful. - 내보내기 완료. + 내보내기 완료. Exporting %1 %2 of %3 @@ -1285,18 +1320,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1306,28 +1329,16 @@ Exporting document... - 문서를 내보내는 중... + 문서를 내보내는 중... Export successful. - 내보내기 완료. + 내보내기 완료. Export to PDF PDF로 내보내기 - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1337,11 +1348,11 @@ Exporting document... - 문서를 내보내는 중... + 문서를 내보내는 중... Export successful. - 내보내기 완료. + 내보내기 완료. Exporting page %1 of %2 @@ -2415,6 +2426,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive 펜은 압력 감지식입니다 + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_mg.ts b/resources/i18n/OpenBoard_mg.ts index 8041ef07..9d2c93e1 100644 --- a/resources/i18n/OpenBoard_mg.ts +++ b/resources/i18n/OpenBoard_mg.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Avaozy + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1234,6 +1249,26 @@ Warnings during export was appeared Nisy fitandremana niseho tamin'ny fandefasana ny rakitra + + Exporting document... + + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + Fandefasana nety. + UBExportCFF @@ -1270,11 +1305,11 @@ Exporting document... - Mandefa rakitra ... + Mandefa rakitra ... Export successful. - Fandefasana nety. + Fandefasana nety. Exporting %1 %2 of %3 @@ -1284,18 +1319,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1305,7 +1328,7 @@ Exporting document... - Mandefa ny rakitra ... + Mandefa ny rakitra ... Export to PDF @@ -1313,19 +1336,7 @@ Export successful. - Fandefasana nety. - - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - + Fandefasana nety. @@ -1340,11 +1351,11 @@ Export successful. - Fandefasana nety. + Fandefasana nety. Exporting document... - Mandefa rakitra ... + Mandefa rakitra ... Export to PDF @@ -2414,6 +2425,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Ny penina dia sarotiny amin'ny fitsindrina + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_nb.ts b/resources/i18n/OpenBoard_nb.ts index b9e12e8c..e0f6296f 100644 --- a/resources/i18n/OpenBoard_nb.ts +++ b/resources/i18n/OpenBoard_nb.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Oppdatering + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1235,6 +1250,26 @@ Warnings during export was appeared Advarsler under eksport ble vist + + Exporting document... + Eksporterer dokument ... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + Eksport gjennomført. + UBExportCFF @@ -1271,11 +1306,11 @@ Exporting document... - Eksporterer dokument ... + Eksporterer dokument ... Export successful. - Eksport gjennomført. + Eksport gjennomført. Exporting %1 %2 of %3 @@ -1285,18 +1320,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1306,28 +1329,16 @@ Exporting document... - Eksporterer dokument ... + Eksporterer dokument ... Export successful. - Eksport gjennomført. + Eksport gjennomført. Export to PDF Eksporter til PDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1337,11 +1348,11 @@ Exporting document... - Eksporterer dokument ... + Eksporterer dokument ... Export successful. - Eksport gjennomført. + Eksport gjennomført. Exporting page %1 of %2 @@ -2409,6 +2420,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Pennen er trykksensitiv + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_nl.ts b/resources/i18n/OpenBoard_nl.ts index b4ba1bff..1b2211c9 100644 --- a/resources/i18n/OpenBoard_nl.ts +++ b/resources/i18n/OpenBoard_nl.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -883,6 +891,13 @@ Update + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1226,6 +1241,26 @@ Warnings during export was appeared + + Exporting document... + Document wordt geëxporteerd... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + Export gelukt. + UBExportCFF @@ -1262,11 +1297,11 @@ Exporting document... - Document wordt geëxporteerd... + Document wordt geëxporteerd... Export successful. - Export gelukt. + Export gelukt. Exporting %1 %2 of %3 @@ -1276,18 +1311,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1297,28 +1320,16 @@ Exporting document... - Document wordt geëxporteerd... + Document wordt geëxporteerd... Export successful. - Export gelukt. + Export gelukt. Export to PDF Exporteren naar PDF bestand - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1328,11 +1339,11 @@ Exporting document... - Document wordt geëxporteerd... + Document wordt geëxporteerd... Export successful. - Export gelukt. + Export gelukt. Exporting page %1 of %2 @@ -2399,6 +2410,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Pen is drukgevoelig + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_pl.ts b/resources/i18n/OpenBoard_pl.ts index 4b13cca1..c8cbd911 100644 --- a/resources/i18n/OpenBoard_pl.ts +++ b/resources/i18n/OpenBoard_pl.ts @@ -803,6 +803,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -895,6 +903,13 @@ Aktualizacja + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1241,6 +1256,26 @@ Warnings during export was appeared Podczas eksportowania pojawiły się ostrzeżenia + + Exporting document... + Eksportowanie dokumentu... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + Eksportowanie zakończone powodzeniem. + UBExportCFF @@ -1277,11 +1312,11 @@ Exporting document... - Eksportowanie dokumentu... + Eksportowanie dokumentu... Export successful. - Eksportowanie zakończone powodzeniem. + Eksportowanie zakończone powodzeniem. Exporting %1 %2 of %3 @@ -1291,18 +1326,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1312,28 +1335,16 @@ Exporting document... - Eksportowanie dokumentu... + Eksportowanie dokumentu... Export successful. - Eksportowanie zakończone powodzeniem. + Eksportowanie zakończone powodzeniem. Export to PDF Eksportowanie do PDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1343,11 +1354,11 @@ Exporting document... - Eksportowanie dokumentu... + Eksportowanie dokumentu... Export successful. - Eksportowanie zakończone powodzeniem. + Eksportowanie zakończone powodzeniem. Exporting page %1 of %2 @@ -2425,6 +2436,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Pióro jest czułe na nacisk + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_pt.ts b/resources/i18n/OpenBoard_pt.ts index e1a02ee9..153067ba 100644 --- a/resources/i18n/OpenBoard_pt.ts +++ b/resources/i18n/OpenBoard_pt.ts @@ -801,6 +801,14 @@ Open the tutorial web page Abrir a página web de tutorial + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -893,6 +901,13 @@ Atualizar + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1236,6 +1251,26 @@ Warnings during export was appeared Surgiram alertas durante a exportação + + Exporting document... + A exportar documento... + + + Export failed + Exportação falhou + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + Exportação falhou: localização não gravável + + + Export successful. + Exportação bem sucedida. + UBExportCFF @@ -1272,11 +1307,11 @@ Exporting document... - A exportar documento... + A exportar documento... Export successful. - Exportação bem sucedida. + Exportação bem sucedida. Exporting %1 %2 of %3 @@ -1288,15 +1323,15 @@ Export failed: location not writable - Exportação falhou: localização não gravável + Exportação falhou: localização não gravável Export failed - Exportação falhou + Exportação falhou Unable to export to the selected location. You do not have the permissions necessary to save the file. - Impossível exportar para a localização selcionada. Você não possui as permissões necessárias para gravar o arquivo. + Impossível exportar para a localização selcionada. Você não possui as permissões necessárias para gravar o arquivo. @@ -1307,11 +1342,11 @@ Exporting document... - A exportar documento... + A exportar documento... Export successful. - Exportação bem sucedida. + Exportação bem sucedida. Export to PDF @@ -1319,15 +1354,15 @@ Export failed: location not writable - Exportação falhou: localização não gravável + Exportação falhou: localização não gravável Export failed - Exportação falhou + Exportação falhou Unable to export to the selected location. You do not have the permissions necessary to save the file. - Impossível exportar para a localização selecionada. Você não possui as permissões necessárias para gravar o arquivo. + Impossível exportar para a localização selecionada. Você não possui as permissões necessárias para gravar o arquivo. @@ -1338,11 +1373,11 @@ Exporting document... - A exportar documento... + A exportar documento... Export successful. - Exportação bem sucedida. + Exportação bem sucedida. Exporting page %1 of %2 @@ -2412,6 +2447,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Caneta sensível à pressão + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_ro.ts b/resources/i18n/OpenBoard_ro.ts index ee3ce709..12224ea9 100644 --- a/resources/i18n/OpenBoard_ro.ts +++ b/resources/i18n/OpenBoard_ro.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Actualizare + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1234,6 +1249,26 @@ Warnings during export was appeared Au apărut atenționări în timpul exportului + + Exporting document... + + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + Exportare reuşită. + UBExportCFF @@ -1270,11 +1305,11 @@ Exporting document... - Exportare document ... + Exportare document ... Export successful. - Exportare reuşită. + Exportare reuşită. Exporting %1 %2 of %3 @@ -1284,18 +1319,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1305,28 +1328,16 @@ Exporting document... - Exoprtare document ... + Exoprtare document ... Export successful. - Exportare reuşită. + Exportare reuşită. Export to PDF Exportare în PDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1336,11 +1347,11 @@ Exporting document... - Exportare document... + Exportare document... Export successful. - Exportare reuşită. + Exportare reuşită. Exporting page %1 of %2 @@ -2414,6 +2425,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Stiloul este sensibil la apăsare + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_ru.ts b/resources/i18n/OpenBoard_ru.ts index 95b9741c..916cd852 100644 --- a/resources/i18n/OpenBoard_ru.ts +++ b/resources/i18n/OpenBoard_ru.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Обновить + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1234,6 +1249,26 @@ Warnings during export was appeared Обнаружены предупреждения во время экспорта + + Exporting document... + Экспорт документа... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + Экспорт успешно завершен. + UBExportCFF @@ -1270,11 +1305,11 @@ Exporting document... - Экспорт документа... + Экспорт документа... Export successful. - Экспорт успешно завершен. + Экспорт успешно завершен. Exporting %1 %2 of %3 @@ -1284,18 +1319,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1305,28 +1328,16 @@ Exporting document... - Экспорт документа... + Экспорт документа... Export successful. - Экспорт успешно завершен. + Экспорт успешно завершен. Export to PDF Экспорт в PDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1336,11 +1347,11 @@ Exporting document... - Экспорт документа... + Экспорт документа... Export successful. - Экспорт успешно завершен. + Экспорт успешно завершен. Exporting page %1 of %2 @@ -2414,6 +2425,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Перо чувствительно к нажиму + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_sk.ts b/resources/i18n/OpenBoard_sk.ts index 6dc3136d..143a28fa 100644 --- a/resources/i18n/OpenBoard_sk.ts +++ b/resources/i18n/OpenBoard_sk.ts @@ -1,2635 +1,2678 @@ - - - - - BlackoutWidget - - Click to Return to Application - Ak sa chcete vrátiť do aplikácie, kliknite sem - - - - DownloadDialog - - 0 Items - 0 položiek - - - Clean Up - Vymazať všetko - - - Downloads - Stiahnuté súbory - - - - DownloadItem - - Form - Formulár - - - Open - Otvoriť - - - Stop - Zastaviť - - - Filename - Názov súboru - - - Try Again - Skúsiť znova - - - - IntranetPodcastPublishingDialog - - Title - Názov - - - Author - Autor - - - Description - Popis - - - Publish Podcast to YouTube - Publikovať podcast na YouTube - - - - MainWindow - - Add - Pridať - - - Del - Vymazať - - - Cut - Vystrihnúť - - - Pen - Pero - - - Web - Web - - - Back - oproti reťazcu ďalšia strana - Predošlá - - - Copy - Kopírovať - - - Dark - Tmavá - - - Hand - Ruka - - - Home - Úvodná stránka - - - Left - Doľava - - - Line - Čiara - - - Next - strana - Ďalšia - - - PgUp - PgUp - - - Redo - Opakovať zmenu - - - Quit - Skončiť - - - Text - Text - - - Undo - Odvolať zmenu - - - Display Board - Zobraziť tabuľu - - - Board - Tabuľa - - - Color - Farba - - - Erase - Vygumovať - - - Display Tools - Zobraziť nástroje - - - Light - Svetlá - - - Embed Web Content - Vložiť obsah z webu - - - Pages - Stránky - - - Paste - Prilepiť - - - Pause - Pozastaviť - - - Right - Doprava - - - Sleep - Uspať - - - Tools - Nástroje - - - Multi Screen - Viac obrazoviek - - - Put Presentation to Sleep - Uspať prezentáciu - - - New Document - Nový dokument - - - Plain Dark Background - Úplne tmavé pozadie - - - Podcast Config - Nastavenia podcastu - - - Check Update - Vyhľadať aktualizáciu - - - Use Custom Document Size - Použiť vlastnú veľkosť dokumentu - - - Zoom In - Zväčšiť - - - Record Presentation to Video - Nahrať prezentáciu na video - - - Grid Dark Background - Mriežka s tmavým pozadím - - - Large Eraser - Veľká guma - - - Grid Light Background - Mriežka so svetlým pozadím - - - Hide OpenBoard Application - Schovať aplikáciu OpenBoard - - - Import an External Page - Nahrať externú stránku - - - Add Bookmark - Pridať záložku - - - OpenBoard - OpenBoard - - - Clear All Elements - Vyčistiť všetky objekty - - - Scroll Page - Posunúť sa po stránke - - - Small Line - Tenká čiara - - - Library - Knižnica - - - Configure Podcast Recording - Nastaviť nahrávanie podcastu - - - Open Page in Board - Otvoriť stránku na tabuli - - - Bigger - Zväčšiť - - - Ctrl++ - Ctrl++ - - - Ctrl+- - Ctrl+- - - - Ctrl+B - Ctrl+B - - - Ctrl+D - Ctrl+D - - - Ctrl+E - Ctrl+E - - - Ctrl+F - - - - Ctrl+G - - - - Ctrl+H - - - - Ctrl+I - Ctrl+I - - - Ctrl+J - - - - Ctrl+K - - - - Ctrl+L - Ctrl+L - - - Ctrl+M - - - - Ctrl+O - Ctrl+O - - - Ctrl+T - Ctrl+T - - - Ctrl+W - Ctrl+W - - - Ctrl+Y - Ctrl+Y - - - Ctrl+Z - Ctrl+Z - - - Delete - Vymazať - - - Eraser - Guma - - - Export - Exportovať - - - New Folder - Nový priečinok - - - Trap Flash Content - Označiť obsah vo Flashi - - - Import - Nahrať - - - Custom Capture - Vlastný spôsob označenia - - - Marker - Zvýrazňovač - - - PgDown - PgDown - - - Create a New Document - Vytvoriť nový dokument - - - Record - Nahrávať - - - Reload - Obnoviť - - - Rename - Premenovať - - - Stylus - Interaktívne pero - - - Quit OpenBoard - Skončiť OpenBoard - - - Custom Size - Vlastná veľkosť - - - Laser Pointer - Laserové ukazovadlo - - - Wide Size (16/9) - Na šírku (16/9) - - - Load Home Page - Nahrať úvodnú stránku - - - Duplicate Page - Duplikovať stránku - - - Duplicate Selected Content - Duplikovať vybraný obsah - - - Bookmarks - Záložky - - - Open in Board - Otvoriť na tabuli - - - Rename Content - Premenovať obsah - - - Zoom Out - Zmenšiť - - - Bookmark - Záložka - - - Add To Current Page - Pridať na aktuálnu stránku - - - Create a New Page - Vytvoriť novú stránku - - - Hide OpenBoard - Schovať OpenBoard - - - Erase All Items - Vygumovať všetky položky - - - Erase Content - Vygumovať obsah - - - Erase Items - Vygumovať položky - - - Duplicate - Duplikovať - - - Add Selected Content to Open Document - Pridať vybraný obsah do otvoreného dokumentu - - - Virtual Keyboard - Virtuálna klávesnica - - - Podcast - Podcast - - - Show Library - Zobraziť knižnicu - - - Medium Eraser - Stredne veľká guma - - - Stop Loading Web Page - Zastaviť nahrávanie webovej stránky - - - Duplicate the Current Page - Duplikovať aktuálnu stránku - - - Pause Podcast Recording - Pozastaviť nahrávanie podcastu - - - Create a New Folder - Vytvoriť nový priečinok - - - Clear Page - Vyčistiť stránku - - - Add To Library - Pridať do knižnice - - - Previous - Predošlá - - - Stop Loading - Zastaviť nahrávanie - - - Reload Current Page - Obnoviť aktuálnu stránku - - - Import Page - Nahrať stránku - - - Draw Lines - Kresliť čiary - - - Capture - Označiť - - - Show Main Screen on Display Screen - V zobrazenej časti obrazovky zobraziť hlavnú obrazovku - - - Flash Trap - Označiť Flash - - - Window Capture - Označiť okno - - - Delete Selected Content - Vymazať vybraný obsah - - - Add Item To New Page - Pridať položku na novú stránku - - - Add Content to Document - Pridať obsah do dokumentu - - - Smaller - Zmenšiť - - - Capture Embeddable Web Content - Označiť obsah z internetu, ktorý sa dá vložiť - - - Write Text - Písať text - - - Documents - Dokumenty - - - Add To New Page - Pridať na novú stránku - - - Regular Size (4/3) - Bežná veľkosť (4/3) - - - Web Trap - Označiť web - - - Display Virtual Keyboard - Zobraziť virtuálnu klávesnicu - - - Show Bookmarks - Zobraziť záložky - - - Use Document Wide Size (16/9) - Zobraziť na šírku dokumentu (16/9) - - - Show Computer Desktop - Zobraziť pracovnú plochu - - - eduMedia - eduMedia - - - Medium Line - Stredne hrubá čiara - - - Previous Page - Predchádzajúca stránka - - - Trap Web Content - Označiť obsah z webu - - - Selector - Oddeľovač - - - Erase all Annotations - Vygumovať všetky poznámky - - - Erase All Annotations - Vygumovať všetky poznámky - - - Export a Document - Exportovať dokument - - - Start Screen Recording - Spustiť nahrávanie obrazovky - - - New Page - Nová stránka - - - Import a Document - Nahrať dokument - - - Import eduMedia simulation - Nahrať simuláciu zo stránky eduMedia - - - Use Document Regular Size (4/3) - Používať bežnú veľkosť dokumentu (4/3) - - - Change Background - Zmeniť pozadie - - - Display Preferences - Zobraziť predvoľby - - - Preferences - Predvoľby - - - Capture Part of the Screen - Označiť časť obrazovky - - - Ctrl+Shift+H - Ctrl+Shift+H - - - Forward - Ďalšia - - - Manage Documents - Riadiť dokumenty - - - Large Line - Hrubá čiara - - - Erase Annotations - Vygumovať poznámky - - - Show on Display - Zobraziť pri projekcii - - - Select And Modify Objects - Vybrať a upraviť objekty - - - Capture a Window - Označiť okno - - - Virtual Laser Pointer - Virtuálne laserové ukazovadlo - - - Plain Light Background - Úplne svetlé pozadie - - - Add Item To Library - Pridať položku do knižnice - - - Web Browsing - Prehliadanie webu - - - Backgrounds - Pozadia - - - Smalle Eraser -spelling mistake in source: should be small - Malá guma - - - Add Item To Current Page - Pridať položku na aktuálnu stránku - - - Add to Working Document - Pridať do aktuálneho dokumentu - - - Highlight - Zvýrazniť - - - Show Desktop - Zobraziť pracovnú plochu - - - Next Page - Ďalšia stránka - - - Annotate Document - Pridať poznámku do dokumentu - - - Erase Annotation - Vygumovať poznámku - - - Play - Prehrať - - - Interact with items - Manipulovať s položkami - - - Erase Background - Vygumovať pozadie - - - Remove the backgound - spelling mistake: should be background - Odstrániť pozadie - - - Open Tutorial - Otvoriť príručku - - - Open the tutorial web page - Otvoriť webovú stránku príručky - - - - PasswordDialog - - Authentication Required - Vyžaduje sa prihlásenie - - - Password: - Heslo: - - - Username: - Používateľské meno: - - - - ProxyDialog - - Save username and password for future use - Používateľské meno a heslo uložiť na použitie v budúcnosti - - - Connect to Proxy - Pripojiť sa k proxy - - - Proxy Authentication - Prihlásenie na proxy - - - Password: - Heslo: - - - Username: - Používateľské meno: - - - - QObject - - Element ID = - ID prvku = - - - Content is not supported in destination format. - Obsah nie je podporovaný v cieľovom formáte. - - - Remove Page - Odstrániť stránku - - - Are you sure you want to remove 1 page from the selected document '%0'? - Určite chcete odstrániť 1 stránku z vybraného dokumentu '%0'? - - - - UBApplication - - Podcast - Podcast - - - Page Size - Veľkosť stránky - - - - UBApplicationController - - Web - Web - - - Update - Aktualizovať - - - No update available - Žiadna aktualizácia nie je k dispozícii - - - New update available, would you go to the web page ? - K dispozícii je nová aktualizácia. Chcete prejsť na webovú stránku? - - - Update available - K dispozícii je aktualizácia - - - - UBBoardController - - All Supported (%1) - Všetky podporované (%1) - - - Downloading content %1 failed - Nepodarilo sa stiahnuť %1 - - - Unknown content type %1 - Neznámy typ obsahu (%1) - - - Add Item - Pridať položku - - - Unknown tool type %1 - Neznámy typ nástroja %1 - - - Download finished - Sťahovanie bolo dokončené - - - Delete page %1 from document - Vymazať stránku %1 z dokumentu - - - Page %1 deleted - Stránka %1 bola vymazaná - - - Add file operation failed: file copying error - Nepodarilo sa pridať súbor: chyba pri kopírovaní súboru - - - Group - Zoskupiť - - - Ungroup - Oddeliť - - - Saving document... - Dokument sa ukladá... - - - Document has just been saved... - Dokument bol uložený. - - - - UBBoardPaletteManager - - Error Adding Image to Library - Chyba pri pridávaní obrázka do knižnice - - - CapturedImage - Označený obrázok - - - - UBCachePropertiesWidget - - Close - Zatvoriť - - - Size: - Veľkosť: - - - Color: - Farba: - - - Shape: - Tvar: - - - Cache Properties - Vlastnosti baterky - - - - UBDesktopPalette - - Show Desktop on Secondary Screen - Zobraziť pracovnú plochu na druhej obrazovke - - - Capture the Screen - Označiť obrazovku - - - Show the stylus palette - Zobraziť paletu pre interaktívne pero - - - Capture Part of the Screen - Označiť časť obrazovky - - - Show Board on Secondary Screen - Zobraziť tabuľu na druhej obrazovke - - - Show OpenBoard - Zobraziť OpenBoard - - - - UBDocumentController - - Empty - Vyprázdniť - - - Trash - Kôš - - - Are you sure you want to empty trash? - Určite chcete vyprázdniť kôš? - - - Are you sure you want to remove the folder '%1' and all its content? - Určite chcete odstrániť priečinok "%1" a celý jeho obsah? - - - Open Supported File - Otvoriť podporovaný súbor - - - Remove Document - Odstrániť dokument - - - All Images (%1) - Všetky obrázky (%1) - - - Selection does not contain any image files! - Vo výbere nie je žiaden súbor obrázka! - - - Open Document - Otvoriť dokument - - - Add Folder of Images - Pridať priečinok s obrázkami - - - Delete - Vymazať - - - New Folder - Nový priečinok - - - Add Images - Pridať obrázky - - - Duplicating Document %1 - Duplikuje sa dokument %1 - - - Page %1 - Stránka %1 - - - Document %1 copied - Dokument %1 bol skopírovaný - - - Importing file %1... - Nahráva sa súbor %1... - - - Failed to import file ... - Súbor sa nepodarilo nahrať... - - - Are you sure you want to remove the document '%1'? - Určite chcete odstrániť dokument "%1"? - - - Emptied trash - Kôš bol vyprázdnený - - - Empty Trash - Vyprázdniť kôš - - - Remove Folder - Odstrániť priečinok - - - Remove Page - Odstrániť stránku - - - No document selected! - Nevybrali ste žiaden dokument! - - - Import all Images from Folder - Nahrať všetky obrázky z priečinka - - - Emptying trash - Vyprázdňuje sa kôš - - - Are you sure you want to remove %n page(s) from the selected document '%1'? - - Určite chcete odstrániť %n stránku z vybraného dokumentu %1? - Určite chcete odstrániť %n stránky z vybraného dokumentu %1? - Určite chcete odstrániť %n stránok z vybraného dokumentu %1? - - - - Add all Images to Document - Pridať všetky obrázky do dokumentu - - - Add Pages from File - Pridať stránky zo súboru - - - Folder does not contain any image files - V priečinku nie sú žiadne súbory obrázkov - - - Untitled Documents - Dokumenty bez názvu - - - The document '%1' has been generated with a newer version of OpenBoard (%2). By opening it, you may lose some information. Do you want to proceed? - Dokument '%1' bol vytvorený v novšej verzii OpenBoardu (%2). Ak ho otvoríte v tejto, aktuálnej verzii, môže dôjsť k strate údajov. Chcete napriek tomu pokračovať? - - - Are you sure you want to remove all selected documents? - Určite chcete odstrániť všetky vybrané dokumenty? - - - Remove multiple documents - Odstránenie viacerých dokumentov - - - - UBDocumentManager - - All supported files (*.%1) - Všetky podporované súbory (*.%1) - - - objects - objekty - - - images - obrázky - - - videos - videá - - - widgets - widgety - - - File %1 saved - Súbor %1 bol uložený - - - Inserting page %1 of %2 - Vkladá sa stránka %1 z(o) %2 - - - Import successful. - Nahrávanie bolo úspešné. - - - Import of file %1 successful. - Nahrávanie súboru %1 bolo úspešné. - - - Importing file %1 - Nahráva sa súbor %1 - - - - UBDocumentNavigator - - Page %0 - Stránka %0 - - - - UBDocumentTreeWidget - - %1 pages copied - - %1 skopírovaná stránka - %1 skopírované stránky - %1 skopírovaných stránok - - - - %1 (copy) - %1 (kópia) - - - Copying page %1/%2 - Kopíruje sa stránka %1/%2 - - - - UBDownloadWidget - - Downloading files - Sťahujú sa súbory - - - Cancel - Zrušiť - - - - UBExportAdaptor - - Warnings during export was appeared - Počas exportu sa objavili varovania - - - - UBExportCFF - - Export to IWB - Exportovať do IWB - - - Export as IWB File - Exportovať ako súbor IWB - - - Exporting document... - Exportuje sa dokument... - - - Export successful. - Export bol úspešný. - - - Export failed. - Export sa nepodaril. - - - - UBExportDocument - - Page - Stránka - - - Export as UBZ File - Exportovať ako súbor UBZ - - - Exporting %1 %2 of %3 - Exportuje sa %1 %2 z(o) %3 - - - Exporting document... - Exportuje sa dokument... - - - Export successful. - Export bol úspešný. - - - Export to OpenBoard Format - Exportovať do formátu OpenBoard - - - Export failed: location not writable - Export sa nepodaril: do umiestnenia sa nedá zapisovať - - - Export failed - Export zlyhal - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - Do vybraného umiestnenia sa nedá exportovať. Na uloženie súboru nemáte dostatočné oprávnenia. - - - - UBExportFullPDF - - Export as PDF File - Exportovať ako súbor PDF - - - Export to PDF - Exportovať do PDF - - - Exporting document... - Exportuje sa dokument... - - - Export successful. - Export bol úspešný. - - - Export failed: location not writable - Export sa nepodaril: do umiestnenia sa nedá zapisovať - - - Export failed - Export zlyhal - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - Do vybraného umiestnenia sa nedá exportovať. Na uloženie súboru nemáte dostatočné oprávnenia. - - - - UBExportPDF - - Export as PDF File - Exportovať ako súbor PDF - - - Export to PDF - Exportovať do PDF - - - Exporting page %1 of %2 - Exportuje sa stránka %1 z(o) %2 - - - Exporting document... - Exportuje sa dokument... - - - Export successful. - Export bol úspešný. - - - - UBExportWeb - - Page - Stránka - - - Export failed. - Export zlyhal. - - - Export as Web data - Exportovať ako webové dáta - - - Exporting document... - Exportuje sa dokument... - - - Export successful. - Export bol úspešný. - - - Export to Web Browser - Exportovať do webového prehliadača - - - - UBFeatureProperties - - Add to page - Pridať na stránku - - - Set as background - Nastaviť ako pozadie - - - Add to library - Pridať do knižnice - - - Object informations - Informácie o objekte - - - - UBFeaturesActionBar - - Add to favorites - Pridať do obľúbených položiek - - - Share - Zdieľať* - - - Search - Vyhľadať - - - Delete - Vymazať - - - Back to folder - Späť do priečinka - - - Remove from favorites - Odstrániť z obľúbených položiek - - - Create new folder - Vytvoriť nový priečinok - - - Rescan file system - Znova prejsť systém súborov - - - - UBFeaturesController - - ImportedImage - NahranýObrázok - - - Audios - Zvukové nahrávky - - - Movies - Filmy - - - Pictures - Obrázky - - - Animations - Animácie - - - Interactivities - Interaktívne aktivity - - - Applications - Aplikácie - - - Shapes - Geometrické útvary - - - Favorites - Obľúbené - - - Web search - Vyhľadávanie na webe - - - Trash - Kôš - - - - UBFeaturesNewFolderDialog - - Accept - Prijať - - - Cancel - Zrušiť - - - Enter a new folder name - Zadajte názov nového priečinka - - - - UBFeaturesProgressInfo - - Loading - Nahrávanie - - - - UBGraphicsGroupContainerItemDelegate - - Locked - Zamknuté - - - Visible on Extended Screen - Zobraziť na rozšírenej obrazovke - - - - UBGraphicsItemDelegate - - Go to Content Source - Prejsť na zdroj - - - Locked - Zamknuté - - - Visible on Extended Screen - Zobraziť na rozšírenej obrazovke - - - - UBGraphicsMediaItem - - Media resource couldn't be resolved - Nepodarilo sa identifikovať nástroj na prácu s médiom - - - Unsupported media format - Nepodporovaný typ média - - - Media playback service not found - Služba na prehratie média sa nenašla - - - Media error: - Chyba média: - - - - UBGraphicsTextItem - - <Type Text Here> - <Text napíšte sem> - - - - UBGraphicsTextItemDelegate - - Text Color - Farba textu - - - Editable - Dá sa upravovať - - - - UBGraphicsW3CWidgetItem - - Web - Web - - - - UBGraphicsWidgetItem - - Loading ... - Nahráva sa... - - - - UBGraphicsWidgetItemDelegate - - Frozen - Zamrznuté - - - Transform as Tool - Zmeniť ako nástroj - - - - UBImportCFF - - Importing file %1... - Nahráva sa súbor %1... - - - Import failed. - Nahrávanie zlyhalo. - - - Import of file %1 failed. - Nepodarilo sa nahrať súbor %1. - - - Common File Format ( - Bežný formát súboru ( - - - Import successful. - Nahrávanie bolo úspešné. - - - - UBImportDocument - - Importing file %1... - Nahráva sa súbor %1... - - - Import of file %1 failed. - Nepodarilo sa nahrať súbor %1. - - - Import successful. - Nahrávanie bolo úspešné. - - - OpenBoard (*.ubz) - OpenBoard (*.ubz) - - - - UBImportImage - - Image Format ( - Súbor obrázka ( - - - - UBImportPDF - - PDF import failed. - Nahrávanie do PDF zlyhalo. - - - Importing page %1 of %2 - Nahráva sa stránka %1 z(o) %2 - - - Portable Document Format (*.pdf) - Portable Document Format (*.pdf) - - - - UBIntranetPodcastPublisher - - Publishing to Intranet in progress %1 % - Prebieha publikovanie na intranet %1 % - - - Error while publishing video to intranet (%1) - Chyba pri publikovaní videa na intranet (%1) - - - - UBIntranetPodcastPublishingDialog - - Publish - Publikovať - - - - UBKeyboardPalette - - Enter - Enter - - - - UBMainWindow - - No - Nie - - - Ok - Ok - - - Yes - Áno - - - - UBMessagesDialog - - Close - Zatvoriť - - - - UBNetworkAccessManager - - No - Nie - - - Yes - Áno - - - <qt>Enter username and password for "%1" at %2</qt> - <qt>Zadajte používateľské meno a heslo pre "%1" na %2</qt> - - - Failed to log to Proxy - Nepodarilo sa prihlásiť na proxy - - - SSL Errors: - -%1 - -%2 - -Do you want to ignore these errors for this host? - Chyby SSL: - -%1 - -%2 - -Chcete ignorovať tieto chyby na tomto serveri? - - - - UBOpenSankoreImporterWidget - - Open-Sankore Documents Detected - Našli sa dokumenty Open-Sankoré - - - Show this panel next time - Tento panel zobraziť aj nabudúce - - - You can always access the OpenBoard Document Importer through the Preferences panel in the About tab. Warning, if you have already imported your Open-Sankore datas, you might loose your current OpenBoard documents. - Nahrávanie dokumentov môžete kedykoľvek spustiť z karty O programe na paneli Predvoľby. Pozor, ak ste už nahrali dáta z Open-Sankoré, môžete ich spúšťať ako dokumenty vytvorené v OpenBoarde. - - - Cancel - Zrušiť - - - Proceed - Pokračovať - - - 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. - Vo vašom počítači sa nachádzajú dokumenty Open-Sankoré. Do OpenBoardu ich môžete nahrať stlačením tlačidla Pokračovať, ktorým sa spustí aplikácia na nahrávanie. - - - - UBPersistenceManager - - (copy) - (kópia) - - - Document Repository Loss - Strata úložiska dokumentov - - - has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. - stratil prístup k úložisku dokumentov '%1'. Aplikácia sa musí zatvoriť, aby sa predišlo poškodeniu dát. Možno nebudú uložené ani najnovšie zmeny. - - - - UBPlatformUtils - - English - Angličtina - - - Russian - Ruština - - - German - Nemčina - - - French - Francúzština - - - Swiss French - Švajčiarska francúzština - - - - UBPodcastController - - Full - Vysoké rozlíšenie - - - Small - Nízke rozlíšenie - - - Podcast recording error (%1) - Chyba pri nahrávaní podcastu (%1) - - - No Podcast encoder available ... - Žiaden kódovač podcastu nie je k dispozícii. - - - Publish to Youtube - inconsistent: elswhere written as YouTube - Publikovať na Youtube - - - Medium - Stredne vysoké rozlíšenie - - - in folder %1 - v priečinku %1 - - - Part %1 - Časť %1 - - - Podcast created %1 - Podcast vytvorený %1 - - - No Audio Recording - Žiadna zvuková nahrávka - - - Publish to Intranet - Publikovať na intranet - - - on your desktop ... - na vašu pracovnú plochu... - - - Default Audio Input - Predvolený vstup pre zvuk - - - Failed to start encoder ... - Nepodarilo sa spustiť kódovač... - - -OpenBoard Cast -Názov súboru podcastu -Film OpenBoardu - - - - UBPreferencesController - - version: - verzia: - - - Marker is pressure sensitive - Zvýrazňovač je citlivý na tlak - - - - UBProxyLoginDlg - - Password: - Heslo: - - - Proxy Login - Prihlásenie na proxy - - - Username: - Používateľské meno: - - - - UBPublicationDlg - - Description: - Popis: - - - Title: - Názov: - - - Publish - Publikovať - - - Publish document on the web - Publikovať dokument na internet - - - - UBSettings - - My Movies - Moje filmy - - - - UBStartupHintsPalette - - Visible next time - Zobraziť aj nabudúce - - - - UBTeacherBarWidget - - - - - - - UBThumbnailAdaptor - - %1 thumbnails generated ... - %1 vytvorených miniatúr... - - - Generating preview thumbnails ... - Vytvárajú sa ukážky miniatúr... - - - - UBToolsManager - - Mask - Clona - - - Cache - Baterka - - - Ruler - Pravítko - - - Triangle - Trojuholník - - - Compass - Kružidlo - - - Protractor - Uhlomer - - - Magnifier - Lupa - - - - UBTrapFlashController - - Web - Web - - - Whole page - Celá stránka - - - - UBUpdateDlg - - Document updater - Aktualizácia dokumentu - - - Please wait the import process will start soon... - Prosím, počkajte, proces nahrávania sa čoskoro začne... - - - Files update successful! -Please reboot the application to access the updated documents. - Aktualizácia bola úspešne dokončená! -Reštartujte aplikáciu, aby ste mohli pracovať s aktualizovanými dokumentmi. - - - Browse - Prehľadávať - - - Select a backup folder - Vyberte priečinok zálohy - - - files require an update. - súbory si vyžadujú aktualizáciu. - - - Update - Aktualizovať - - - An error occured during the update. The files have not been affected. - Počas aktualizácie sa vyskytla chyba. Súbory to neovplyvnilo. - - - Files update results - Výsledky aktualizácie súborov - - - Backup path: - Umiestnenie zálohy: - - - Updating file - Prebieha aktualizácia súboru - - - Remind me later - Pripomenúť mi neskôr - - - - UBWebPluginWidget - - Loading... - Nahráva sa... - - - - UBWidgetUniboardAPI - - %0 called (method=%1, status=%2) - %0 vyvolané (metóda = %1, stav = %2) - - - - UBYouTubePublisher - - YouTube authentication failed. - Nepodarilo sa prihlásiť na YouTube. - - - Error while uploading video to YouTube (%1) - Chyba pri nahrávaní videa na YouTube (%1) - - - Upload to YouTube in progress %1 % - Prebieha nahrávanie na YouTube %1 % - - - - UBYouTubePublishingDialog - - Music - Hudba - - - People & Blogs - Ľudia a blogy - - - Nonprofits & Activism - Neziskovky a aktivisti - - - Comedy - Komédia - - - Gaming - Hry - - - Sports - Šport - - - Upload - Nahrať - - - Science & Technology - Veda a technika - - - Howto & Style - Návody a štýl - - - Education - Vzdelávanie - - - Entertainment - Zábava - - - Travel & Events - Cestovanie a udalosti - - - News & Politics - Správy a politika - - - Pets & Animals - Zvieratá - - - Autos & Vehicles - Autá a dopravné prostriedky - - - - UBZoomPalette - - %1 x - %1 x - - - - WBClearButton - - Clear - Vyčistiť - - - - WBDownloadItem - - KB - kB - - - MB - MB - - - bytes - bytov - - - - %4 %5 remaining - – zostáva %4 %5 - - - minutes - minút(y) - - - Error opening saved file: %1 - Chyba pri otváraní uloženého súboru: %1 - - - seconds - sekúnd - - - Error saving: %1 - Chyba pri ukladaní súboru: %1 - - - Download canceled: %1 - Sťahovanie súboru bolo zrušené: %1 - - - %1 of %2 - Stopped - %1 z(o) %2 – zastavené - - - Save File - Uložiť súbor - - - %1 of %2 (%3/sec) %4 - %1 z(o) %2 (%3/sek) %4 - - - Network Error: %1 - Chyba siete: %1 - - - ? - unknown file size - ? - - - - WBDownloadManager - - 1 Download - 1 stiahnutý súbor - - - %1 Downloads - always >= 2 - %1 stiahnuté súbory - - - - WBHistoryModel - - Title - Názov - - - Address - Adresa - - - - WBHistoryTreeModel - - %1 items - 2,3,4 položky, 0, >=5 položiek - %1 položiek - - - Earlier Today - Dnes - - - - WBSearchLineEdit - - Search - Hľadať - - - - WBTabBar - - Reload All Tabs - Obnoviť všetky karty - - - Reload Tab - Obnoviť kartu - - - Clone Tab - Duplikovať kartu - - - &Close Tab - &Zatvoriť kartu - - - Close &Other Tabs - Zatvoriť &ostané karty - - - New &Tab - Nová &karta - - - - WBTabWidget - - (Untitled) - (Bez názvu) - - - Recently Closed Tabs - Nedávno zatvorené karty - - - - WBToolbarSearch - - Recent Searches - Nedávne vyhľadávania - - - Search - Vyhľadať - - - No Recent Searches - Žiadne nedávne vyhľadávania - - - Clear Recent Searches - Vymazať nedávne vyhľadávania - - - - WBWebPage - - PDF - PDF - - - Add to Current Document - Pridať do aktuálneho dokumentu - - - Download - Stiahnuť - - - Error loading page: %1 - Chyba pri nahrávaní stránky: %1 - - - Download PDF Document: would you prefer to download the PDF file or add it to the current OpenBoard document? - Sťahovanie dokumentu PDF: chcete súbor PDF radšej stiahnuť alebo pridať do aktuálneho dokumentu? - - - - WBWebView - - Open in New Tab - Otvoriť na novej karte - - - - YouTubePublishingDialog - - Title - Názov - - - YouTube Username - Používateľské meno na YouTube - - - YouTube Password - Heslo na YouTube - - - Category - Kategória - - - Description - Popis - - - Publish Podcast to YouTube - Publikovať podcast na YouTube - - - Keywords - Kľúčové slová - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:10pt;">By clicking 'Upload,' you certify that you own all rights to the content or that you are authorized by the owner to make the content publicly available on YouTube, and that it otherwise complies with the YouTube Terms of Service located at </span><a href="http://www.youtube.com/t/terms"><span style=" font-family:'Lucida Grande'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.youtube.com/t/terms</span></a></p></body></html> - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:10pt;">Kliknutím na "Upload" (Nahrať) potvrdzujete, že máte všetky práva k materiálu alebo že máte písomný súhlas vlastníka týchto práv na zverejnenie materiálu na sieti YouTube a že materiál je v súlade s podmienkami využívania služieb siete YouTube, ktorých aktuálne znenie sa nachádza na adrese </span><a href="http://www.youtube.com/t/terms"><span style=" font-family:'Lucida Grande'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.youtube.com/t/terms</span></a></p></body></html> - - - OpenBoard - OpenBoard - - - Restore credentials on reboot - Po reštarte obnoviť prihlasovacie údaje - - - - brushProperties - - Fine - Tenká - - - Medium - Stredne hrubá - - - Strong - Hrubá - - - Opacity - Priehľadnosť - - - Line Width - Šírka čiary - - - On Light Background - Na svetlom pozadí - - - Pen is Pressure Sensitive - Pero je citlivé na tlak - - - On Dark Background - Na tmavom pozadí - - - - capturePublishingDialog - - Title - Názov - - - E-mail - E-mail - - - Author - Autor - - - Dialog - Dialóg - - - Description - Popis - - - - documents - - OpenBoard Documents - Dokumenty OpenBoardu - - - - preferencesDialog - - Pen - Pero - - - About - O programe - - - Close - Zatvoriť - - - Horizontal - Vodorovná - - - Display Text Under Button - Pod tlačidlom zobraziť text - - - Show Page with External Browser - Stránku zobraziť v externom prehliadači - - - Default Settings - Predvolené nastavenia - - - Network - Sieť - - - Positioned at the Bottom (recommended for white boards) - Je umiestnený dole (odporúča sa pre tabule) - - - Marker - Zvýrazňovač - - - Internet - Internet - - - Positioned at the Top (recommended for tablets) - Je umiestnený navrchu (odporúča sa pre tablety) - - - Virtual Keyboard - Virtuálna klávesnica - - - Home Page: - Úvodná stránka: - - - Check software update at launch - Pri spustení programu vyhľadať aktualizáciu - - - Software Update - Aktualizácia programu - - - Keyboard button size: - Veľkosť tlačidla klávesnice: - - - Stylus Palette - Paleta pre interaktívne pero - - - Display - Zobraziť - - - Toolbar - Panel s nástrojmi - - - Vertical - Zvislá - - - Preferences - Predvoľby - - - version : … - Verzia:... - - - Licences - Licencie - - - Multi display - Viac obrazoviek - - - Show internal web page content on secondary screen or projector - Na druhej obrazovke alebo projektore zobraziť obsah internej webovej stránky - - - Swap control display and view display - Prehodiť ovládaciu obrazovku a zobrazovaciu obrazovku - - - Mode - Režim - - - Mode to start in: - Režim pri štarte: - - - Board - Tabuľa - - - Desktop - Pracovná plocha - - - Proxy User: - Použ. m. na proxy: - - - Pass: - Heslo: - - - Credits - Poďakovanie - - - Open-Sankoré Importer - Nahrávanie z Open-Sankoré - - - Check if Open-Sankoré data could be imported at launch - Zistiť, či sa pri spustení majú nahrať dáta z Open-Sankoré - - - Use system keyboard (recommended) - Používať systémovú klávesnicu (odporúča sa) - - - Built-in virtual keyboard button size: - Veľkosť tlačidla zabudovanej virtuálnej klávesnice: - - - - trapFlashDialog - - Trap flash - Označiť flash - - - Select a flash to trap - Vyberte flash, ktorý chcete označiť - - - about:blank - about:blank - - - Application name - Názov aplikácie - - - Create Application - Vytvoriť aplikáciu - - - + + + + + BlackoutWidget + + Click to Return to Application + Ak sa chcete vrátiť do aplikácie, kliknite sem + + + + DownloadDialog + + 0 Items + 0 položiek + + + Clean Up + Vymazať všetko + + + Downloads + Stiahnuté súbory + + + + DownloadItem + + Form + Formulár + + + Open + Otvoriť + + + Stop + Zastaviť + + + Filename + Názov súboru + + + Try Again + Skúsiť znova + + + + IntranetPodcastPublishingDialog + + Title + Názov + + + Author + Autor + + + Description + Popis + + + Publish Podcast to YouTube + Publikovať podcast na YouTube + + + + MainWindow + + Add + Pridať + + + Del + Vymazať + + + Cut + Vystrihnúť + + + Pen + Pero + + + Web + Web + + + Back + oproti reťazcu ďalšia strana + Predošlá + + + Copy + Kopírovať + + + Dark + Tmavá + + + Hand + Ruka + + + Home + Úvodná stránka + + + Left + Doľava + + + Line + Čiara + + + Next + strana + Ďalšia + + + PgUp + PgUp + + + Redo + Opakovať zmenu + + + Quit + Skončiť + + + Text + Text + + + Undo + Odvolať zmenu + + + Display Board + Zobraziť tabuľu + + + Board + Tabuľa + + + Color + Farba + + + Erase + Vygumovať + + + Display Tools + Zobraziť nástroje + + + Light + Svetlá + + + Embed Web Content + Vložiť obsah z webu + + + Pages + Stránky + + + Paste + Prilepiť + + + Pause + Pozastaviť + + + Right + Doprava + + + Sleep + Uspať + + + Tools + Nástroje + + + Multi Screen + Viac obrazoviek + + + Put Presentation to Sleep + Uspať prezentáciu + + + New Document + Nový dokument + + + Plain Dark Background + Úplne tmavé pozadie + + + Podcast Config + Nastavenia podcastu + + + Check Update + Vyhľadať aktualizáciu + + + Use Custom Document Size + Použiť vlastnú veľkosť dokumentu + + + Zoom In + Zväčšiť + + + Record Presentation to Video + Nahrať prezentáciu na video + + + Grid Dark Background + Mriežka s tmavým pozadím + + + Large Eraser + Veľká guma + + + Grid Light Background + Mriežka so svetlým pozadím + + + Hide OpenBoard Application + Schovať aplikáciu OpenBoard + + + Import an External Page + Nahrať externú stránku + + + Add Bookmark + Pridať záložku + + + OpenBoard + OpenBoard + + + Clear All Elements + Vyčistiť všetky objekty + + + Scroll Page + Posunúť sa po stránke + + + Small Line + Tenká čiara + + + Library + Knižnica + + + Configure Podcast Recording + Nastaviť nahrávanie podcastu + + + Open Page in Board + Otvoriť stránku na tabuli + + + Bigger + Zväčšiť + + + Ctrl++ + Ctrl++ + + + Ctrl+- + Ctrl+- + + + Ctrl+B + Ctrl+B + + + Ctrl+D + Ctrl+D + + + Ctrl+E + Ctrl+E + + + Ctrl+F + + + + Ctrl+G + + + + Ctrl+H + + + + Ctrl+I + Ctrl+I + + + Ctrl+J + + + + Ctrl+K + + + + Ctrl+L + Ctrl+L + + + Ctrl+M + + + + Ctrl+O + Ctrl+O + + + Ctrl+T + Ctrl+T + + + Ctrl+W + Ctrl+W + + + Ctrl+Y + Ctrl+Y + + + Ctrl+Z + Ctrl+Z + + + Delete + Vymazať + + + Eraser + Guma + + + Export + Exportovať + + + New Folder + Nový priečinok + + + Trap Flash Content + Označiť obsah vo Flashi + + + Import + Nahrať + + + Custom Capture + Vlastný spôsob označenia + + + Marker + Zvýrazňovač + + + PgDown + PgDown + + + Create a New Document + Vytvoriť nový dokument + + + Record + Nahrávať + + + Reload + Obnoviť + + + Rename + Premenovať + + + Stylus + Interaktívne pero + + + Quit OpenBoard + Skončiť OpenBoard + + + Custom Size + Vlastná veľkosť + + + Laser Pointer + Laserové ukazovadlo + + + Wide Size (16/9) + Na šírku (16/9) + + + Load Home Page + Nahrať úvodnú stránku + + + Duplicate Page + Duplikovať stránku + + + Duplicate Selected Content + Duplikovať vybraný obsah + + + Bookmarks + Záložky + + + Open in Board + Otvoriť na tabuli + + + Rename Content + Premenovať obsah + + + Zoom Out + Zmenšiť + + + Bookmark + Záložka + + + Add To Current Page + Pridať na aktuálnu stránku + + + Create a New Page + Vytvoriť novú stránku + + + Hide OpenBoard + Schovať OpenBoard + + + Erase All Items + Vygumovať všetky položky + + + Erase Content + Vygumovať obsah + + + Erase Items + Vygumovať položky + + + Duplicate + Duplikovať + + + Add Selected Content to Open Document + Pridať vybraný obsah do otvoreného dokumentu + + + Virtual Keyboard + Virtuálna klávesnica + + + Podcast + Podcast + + + Show Library + Zobraziť knižnicu + + + Medium Eraser + Stredne veľká guma + + + Stop Loading Web Page + Zastaviť nahrávanie webovej stránky + + + Duplicate the Current Page + Duplikovať aktuálnu stránku + + + Pause Podcast Recording + Pozastaviť nahrávanie podcastu + + + Create a New Folder + Vytvoriť nový priečinok + + + Clear Page + Vyčistiť stránku + + + Add To Library + Pridať do knižnice + + + Previous + Predošlá + + + Stop Loading + Zastaviť nahrávanie + + + Reload Current Page + Obnoviť aktuálnu stránku + + + Import Page + Nahrať stránku + + + Draw Lines + Kresliť čiary + + + Capture + Označiť + + + Show Main Screen on Display Screen + V zobrazenej časti obrazovky zobraziť hlavnú obrazovku + + + Flash Trap + Označiť Flash + + + Window Capture + Označiť okno + + + Delete Selected Content + Vymazať vybraný obsah + + + Add Item To New Page + Pridať položku na novú stránku + + + Add Content to Document + Pridať obsah do dokumentu + + + Smaller + Zmenšiť + + + Capture Embeddable Web Content + Označiť obsah z internetu, ktorý sa dá vložiť + + + Write Text + Písať text + + + Documents + Dokumenty + + + Add To New Page + Pridať na novú stránku + + + Regular Size (4/3) + Bežná veľkosť (4/3) + + + Web Trap + Označiť web + + + Display Virtual Keyboard + Zobraziť virtuálnu klávesnicu + + + Show Bookmarks + Zobraziť záložky + + + Use Document Wide Size (16/9) + Zobraziť na šírku dokumentu (16/9) + + + Show Computer Desktop + Zobraziť pracovnú plochu + + + eduMedia + eduMedia + + + Medium Line + Stredne hrubá čiara + + + Previous Page + Predchádzajúca stránka + + + Trap Web Content + Označiť obsah z webu + + + Selector + Oddeľovač + + + Erase all Annotations + Vygumovať všetky poznámky + + + Erase All Annotations + Vygumovať všetky poznámky + + + Export a Document + Exportovať dokument + + + Start Screen Recording + Spustiť nahrávanie obrazovky + + + New Page + Nová stránka + + + Import a Document + Nahrať dokument + + + Import eduMedia simulation + Nahrať simuláciu zo stránky eduMedia + + + Use Document Regular Size (4/3) + Používať bežnú veľkosť dokumentu (4/3) + + + Change Background + Zmeniť pozadie + + + Display Preferences + Zobraziť predvoľby + + + Preferences + Predvoľby + + + Capture Part of the Screen + Označiť časť obrazovky + + + Ctrl+Shift+H + Ctrl+Shift+H + + + Forward + Ďalšia + + + Manage Documents + Riadiť dokumenty + + + Large Line + Hrubá čiara + + + Erase Annotations + Vygumovať poznámky + + + Show on Display + Zobraziť pri projekcii + + + Select And Modify Objects + Vybrať a upraviť objekty + + + Capture a Window + Označiť okno + + + Virtual Laser Pointer + Virtuálne laserové ukazovadlo + + + Plain Light Background + Úplne svetlé pozadie + + + Add Item To Library + Pridať položku do knižnice + + + Web Browsing + Prehliadanie webu + + + Backgrounds + Pozadia + + + Smalle Eraser + spelling mistake in source: should be small + Malá guma + + + Add Item To Current Page + Pridať položku na aktuálnu stránku + + + Add to Working Document + Pridať do aktuálneho dokumentu + + + Highlight + Zvýrazniť + + + Show Desktop + Zobraziť pracovnú plochu + + + Next Page + Ďalšia stránka + + + Annotate Document + Pridať poznámku do dokumentu + + + Erase Annotation + Vygumovať poznámku + + + Play + Prehrať + + + Interact with items + Manipulovať s položkami + + + Erase Background + Vygumovať pozadie + + + Remove the backgound + spelling mistake: should be background + Odstrániť pozadie + + + Open Tutorial + Otvoriť príručku + + + Open the tutorial web page + Otvoriť webovú stránku príručky + + + Ruled Light Background + + + + Ruled Dark Background + + + + + PasswordDialog + + Authentication Required + Vyžaduje sa prihlásenie + + + Password: + Heslo: + + + Username: + Používateľské meno: + + + + ProxyDialog + + Save username and password for future use + Používateľské meno a heslo uložiť na použitie v budúcnosti + + + Connect to Proxy + Pripojiť sa k proxy + + + Proxy Authentication + Prihlásenie na proxy + + + Password: + Heslo: + + + Username: + Používateľské meno: + + + + QObject + + Element ID = + ID prvku = + + + Content is not supported in destination format. + Obsah nie je podporovaný v cieľovom formáte. + + + Remove Page + Odstrániť stránku + + + Are you sure you want to remove 1 page from the selected document '%0'? + Určite chcete odstrániť 1 stránku z vybraného dokumentu '%0'? + + + + UBApplication + + Podcast + Podcast + + + Page Size + Veľkosť stránky + + + + UBApplicationController + + Web + Web + + + Update + Aktualizovať + + + No update available + Žiadna aktualizácia nie je k dispozícii + + + New update available, would you go to the web page ? + K dispozícii je nová aktualizácia. Chcete prejsť na webovú stránku? + + + Update available + K dispozícii je aktualizácia + + + + UBBackgroundPalette + + Grid size + + + + + UBBoardController + + All Supported (%1) + Všetky podporované (%1) + + + Downloading content %1 failed + Nepodarilo sa stiahnuť %1 + + + Unknown content type %1 + Neznámy typ obsahu (%1) + + + Add Item + Pridať položku + + + Unknown tool type %1 + Neznámy typ nástroja %1 + + + Download finished + Sťahovanie bolo dokončené + + + Delete page %1 from document + Vymazať stránku %1 z dokumentu + + + Page %1 deleted + Stránka %1 bola vymazaná + + + Add file operation failed: file copying error + Nepodarilo sa pridať súbor: chyba pri kopírovaní súboru + + + Group + Zoskupiť + + + Ungroup + Oddeliť + + + Saving document... + Dokument sa ukladá... + + + Document has just been saved... + Dokument bol uložený. + + + + UBBoardPaletteManager + + Error Adding Image to Library + Chyba pri pridávaní obrázka do knižnice + + + CapturedImage + Označený obrázok + + + + UBCachePropertiesWidget + + Close + Zatvoriť + + + Size: + Veľkosť: + + + Color: + Farba: + + + Shape: + Tvar: + + + Cache Properties + Vlastnosti baterky + + + + UBDesktopPalette + + Show Desktop on Secondary Screen + Zobraziť pracovnú plochu na druhej obrazovke + + + Capture the Screen + Označiť obrazovku + + + Show the stylus palette + Zobraziť paletu pre interaktívne pero + + + Capture Part of the Screen + Označiť časť obrazovky + + + Show Board on Secondary Screen + Zobraziť tabuľu na druhej obrazovke + + + Show OpenBoard + Zobraziť OpenBoard + + + + UBDocumentController + + Empty + Vyprázdniť + + + Trash + Kôš + + + Are you sure you want to empty trash? + Určite chcete vyprázdniť kôš? + + + Are you sure you want to remove the folder '%1' and all its content? + Určite chcete odstrániť priečinok "%1" a celý jeho obsah? + + + Open Supported File + Otvoriť podporovaný súbor + + + Remove Document + Odstrániť dokument + + + All Images (%1) + Všetky obrázky (%1) + + + Selection does not contain any image files! + Vo výbere nie je žiaden súbor obrázka! + + + Open Document + Otvoriť dokument + + + Add Folder of Images + Pridať priečinok s obrázkami + + + Delete + Vymazať + + + New Folder + Nový priečinok + + + Add Images + Pridať obrázky + + + Duplicating Document %1 + Duplikuje sa dokument %1 + + + Page %1 + Stránka %1 + + + Document %1 copied + Dokument %1 bol skopírovaný + + + Importing file %1... + Nahráva sa súbor %1... + + + Failed to import file ... + Súbor sa nepodarilo nahrať... + + + Are you sure you want to remove the document '%1'? + Určite chcete odstrániť dokument "%1"? + + + Emptied trash + Kôš bol vyprázdnený + + + Empty Trash + Vyprázdniť kôš + + + Remove Folder + Odstrániť priečinok + + + Remove Page + Odstrániť stránku + + + No document selected! + Nevybrali ste žiaden dokument! + + + Import all Images from Folder + Nahrať všetky obrázky z priečinka + + + Emptying trash + Vyprázdňuje sa kôš + + + Are you sure you want to remove %n page(s) from the selected document '%1'? + + Určite chcete odstrániť %n stránku z vybraného dokumentu %1? + Určite chcete odstrániť %n stránky z vybraného dokumentu %1? + Určite chcete odstrániť %n stránok z vybraného dokumentu %1? + + + + Add all Images to Document + Pridať všetky obrázky do dokumentu + + + Add Pages from File + Pridať stránky zo súboru + + + Folder does not contain any image files + V priečinku nie sú žiadne súbory obrázkov + + + Untitled Documents + Dokumenty bez názvu + + + The document '%1' has been generated with a newer version of OpenBoard (%2). By opening it, you may lose some information. Do you want to proceed? + Dokument '%1' bol vytvorený v novšej verzii OpenBoardu (%2). Ak ho otvoríte v tejto, aktuálnej verzii, môže dôjsť k strate údajov. Chcete napriek tomu pokračovať? + + + Are you sure you want to remove all selected documents? + Určite chcete odstrániť všetky vybrané dokumenty? + + + Remove multiple documents + Odstránenie viacerých dokumentov + + + + UBDocumentManager + + All supported files (*.%1) + Všetky podporované súbory (*.%1) + + + objects + objekty + + + images + obrázky + + + videos + videá + + + widgets + widgety + + + File %1 saved + Súbor %1 bol uložený + + + Inserting page %1 of %2 + Vkladá sa stránka %1 z(o) %2 + + + Import successful. + Nahrávanie bolo úspešné. + + + Import of file %1 successful. + Nahrávanie súboru %1 bolo úspešné. + + + Importing file %1 + Nahráva sa súbor %1 + + + + UBDocumentNavigator + + Page %0 + Stránka %0 + + + + UBDocumentTreeWidget + + %1 pages copied + + %1 skopírovaná stránka + %1 skopírované stránky + %1 skopírovaných stránok + + + + %1 (copy) + %1 (kópia) + + + Copying page %1/%2 + Kopíruje sa stránka %1/%2 + + + + UBDownloadWidget + + Downloading files + Sťahujú sa súbory + + + Cancel + Zrušiť + + + + UBExportAdaptor + + Warnings during export was appeared + Počas exportu sa objavili varovania + + + Exporting document... + Exportuje sa dokument... + + + Export failed + Export zlyhal + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + Do vybraného umiestnenia sa nedá exportovať. Na uloženie súboru nemáte dostatočné oprávnenia. + + + Export failed: location not writable + Export sa nepodaril: do umiestnenia sa nedá zapisovať + + + Export successful. + Export bol úspešný. + + + + UBExportCFF + + Export to IWB + Exportovať do IWB + + + Export as IWB File + Exportovať ako súbor IWB + + + Exporting document... + Exportuje sa dokument... + + + Export successful. + Export bol úspešný. + + + Export failed. + Export sa nepodaril. + + + + UBExportDocument + + Page + Stránka + + + Export as UBZ File + Exportovať ako súbor UBZ + + + Exporting %1 %2 of %3 + Exportuje sa %1 %2 z(o) %3 + + + Exporting document... + Exportuje sa dokument... + + + Export successful. + Export bol úspešný. + + + Export to OpenBoard Format + Exportovať do formátu OpenBoard + + + Export failed: location not writable + Export sa nepodaril: do umiestnenia sa nedá zapisovať + + + Export failed + Export zlyhal + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + Do vybraného umiestnenia sa nedá exportovať. Na uloženie súboru nemáte dostatočné oprávnenia. + + + + UBExportFullPDF + + Export as PDF File + Exportovať ako súbor PDF + + + Export to PDF + Exportovať do PDF + + + Exporting document... + Exportuje sa dokument... + + + Export successful. + Export bol úspešný. + + + Export failed: location not writable + Export sa nepodaril: do umiestnenia sa nedá zapisovať + + + Export failed + Export zlyhal + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + Do vybraného umiestnenia sa nedá exportovať. Na uloženie súboru nemáte dostatočné oprávnenia. + + + + UBExportPDF + + Export as PDF File + Exportovať ako súbor PDF + + + Export to PDF + Exportovať do PDF + + + Exporting page %1 of %2 + Exportuje sa stránka %1 z(o) %2 + + + Exporting document... + Exportuje sa dokument... + + + Export successful. + Export bol úspešný. + + + + UBExportWeb + + Page + Stránka + + + Export failed. + Export zlyhal. + + + Export as Web data + Exportovať ako webové dáta + + + Exporting document... + Exportuje sa dokument... + + + Export successful. + Export bol úspešný. + + + Export to Web Browser + Exportovať do webového prehliadača + + + + UBFeatureProperties + + Add to page + Pridať na stránku + + + Set as background + Nastaviť ako pozadie + + + Add to library + Pridať do knižnice + + + Object informations + Informácie o objekte + + + + UBFeaturesActionBar + + Add to favorites + Pridať do obľúbených položiek + + + Share + Zdieľať* + + + Search + Vyhľadať + + + Delete + Vymazať + + + Back to folder + Späť do priečinka + + + Remove from favorites + Odstrániť z obľúbených položiek + + + Create new folder + Vytvoriť nový priečinok + + + Rescan file system + Znova prejsť systém súborov + + + + UBFeaturesController + + ImportedImage + NahranýObrázok + + + Audios + Zvukové nahrávky + + + Movies + Filmy + + + Pictures + Obrázky + + + Animations + Animácie + + + Interactivities + Interaktívne aktivity + + + Applications + Aplikácie + + + Shapes + Geometrické útvary + + + Favorites + Obľúbené + + + Web search + Vyhľadávanie na webe + + + Trash + Kôš + + + + UBFeaturesNewFolderDialog + + Accept + Prijať + + + Cancel + Zrušiť + + + Enter a new folder name + Zadajte názov nového priečinka + + + + UBFeaturesProgressInfo + + Loading + Nahrávanie + + + + UBGraphicsGroupContainerItemDelegate + + Locked + Zamknuté + + + Visible on Extended Screen + Zobraziť na rozšírenej obrazovke + + + + UBGraphicsItemDelegate + + Go to Content Source + Prejsť na zdroj + + + Locked + Zamknuté + + + Visible on Extended Screen + Zobraziť na rozšírenej obrazovke + + + + UBGraphicsMediaItem + + Media resource couldn't be resolved + Nepodarilo sa identifikovať nástroj na prácu s médiom + + + Unsupported media format + Nepodporovaný typ média + + + Media playback service not found + Služba na prehratie média sa nenašla + + + Media error: + Chyba média: + + + + UBGraphicsTextItem + + <Type Text Here> + <Text napíšte sem> + + + + UBGraphicsTextItemDelegate + + Text Color + Farba textu + + + Editable + Dá sa upravovať + + + + UBGraphicsW3CWidgetItem + + Web + Web + + + + UBGraphicsWidgetItem + + Loading ... + Nahráva sa... + + + + UBGraphicsWidgetItemDelegate + + Frozen + Zamrznuté + + + Transform as Tool + Zmeniť ako nástroj + + + + UBImportCFF + + Importing file %1... + Nahráva sa súbor %1... + + + Import failed. + Nahrávanie zlyhalo. + + + Import of file %1 failed. + Nepodarilo sa nahrať súbor %1. + + + Common File Format ( + Bežný formát súboru ( + + + Import successful. + Nahrávanie bolo úspešné. + + + + UBImportDocument + + Importing file %1... + Nahráva sa súbor %1... + + + Import of file %1 failed. + Nepodarilo sa nahrať súbor %1. + + + Import successful. + Nahrávanie bolo úspešné. + + + OpenBoard (*.ubz) + OpenBoard (*.ubz) + + + + UBImportImage + + Image Format ( + Súbor obrázka ( + + + + UBImportPDF + + PDF import failed. + Nahrávanie do PDF zlyhalo. + + + Importing page %1 of %2 + Nahráva sa stránka %1 z(o) %2 + + + Portable Document Format (*.pdf) + Portable Document Format (*.pdf) + + + + UBIntranetPodcastPublisher + + Publishing to Intranet in progress %1 % + Prebieha publikovanie na intranet %1 % + + + Error while publishing video to intranet (%1) + Chyba pri publikovaní videa na intranet (%1) + + + + UBIntranetPodcastPublishingDialog + + Publish + Publikovať + + + + UBKeyboardPalette + + Enter + Enter + + + + UBMainWindow + + No + Nie + + + Ok + Ok + + + Yes + Áno + + + + UBMessagesDialog + + Close + Zatvoriť + + + + UBNetworkAccessManager + + No + Nie + + + Yes + Áno + + + <qt>Enter username and password for "%1" at %2</qt> + <qt>Zadajte používateľské meno a heslo pre "%1" na %2</qt> + + + Failed to log to Proxy + Nepodarilo sa prihlásiť na proxy + + + SSL Errors: + +%1 + +%2 + +Do you want to ignore these errors for this host? + Chyby SSL: + +%1 + +%2 + +Chcete ignorovať tieto chyby na tomto serveri? + + + + UBOpenSankoreImporterWidget + + Open-Sankore Documents Detected + Našli sa dokumenty Open-Sankoré + + + Show this panel next time + Tento panel zobraziť aj nabudúce + + + You can always access the OpenBoard Document Importer through the Preferences panel in the About tab. Warning, if you have already imported your Open-Sankore datas, you might loose your current OpenBoard documents. + Nahrávanie dokumentov môžete kedykoľvek spustiť z karty O programe na paneli Predvoľby. Pozor, ak ste už nahrali dáta z Open-Sankoré, môžete ich spúšťať ako dokumenty vytvorené v OpenBoarde. + + + Cancel + Zrušiť + + + Proceed + Pokračovať + + + 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. + Vo vašom počítači sa nachádzajú dokumenty Open-Sankoré. Do OpenBoardu ich môžete nahrať stlačením tlačidla Pokračovať, ktorým sa spustí aplikácia na nahrávanie. + + + + UBPersistenceManager + + (copy) + (kópia) + + + Document Repository Loss + Strata úložiska dokumentov + + + has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + stratil prístup k úložisku dokumentov '%1'. Aplikácia sa musí zatvoriť, aby sa predišlo poškodeniu dát. Možno nebudú uložené ani najnovšie zmeny. + + + + UBPlatformUtils + + English + Angličtina + + + Russian + Ruština + + + German + Nemčina + + + French + Francúzština + + + Swiss French + Švajčiarska francúzština + + + + UBPodcastController + + Full + Vysoké rozlíšenie + + + Small + Nízke rozlíšenie + + + Podcast recording error (%1) + Chyba pri nahrávaní podcastu (%1) + + + No Podcast encoder available ... + Žiaden kódovač podcastu nie je k dispozícii. + + + Publish to Youtube + inconsistent: elswhere written as YouTube + Publikovať na Youtube + + + Medium + Stredne vysoké rozlíšenie + + + in folder %1 + v priečinku %1 + + + Part %1 + Časť %1 + + + Podcast created %1 + Podcast vytvorený %1 + + + No Audio Recording + Žiadna zvuková nahrávka + + + Publish to Intranet + Publikovať na intranet + + + on your desktop ... + na vašu pracovnú plochu... + + + Default Audio Input + Predvolený vstup pre zvuk + + + Failed to start encoder ... + Nepodarilo sa spustiť kódovač... + + + OpenBoard Cast + Názov súboru podcastu + Film OpenBoardu + + + + UBPreferencesController + + version: + verzia: + + + Marker is pressure sensitive + Zvýrazňovač je citlivý na tlak + + + + UBProxyLoginDlg + + Password: + Heslo: + + + Proxy Login + Prihlásenie na proxy + + + Username: + Používateľské meno: + + + + UBPublicationDlg + + Description: + Popis: + + + Title: + Názov: + + + Publish + Publikovať + + + Publish document on the web + Publikovať dokument na internet + + + + UBSettings + + My Movies + Moje filmy + + + + UBStartupHintsPalette + + Visible next time + Zobraziť aj nabudúce + + + + UBTeacherBarWidget + + + + + + + UBThumbnailAdaptor + + %1 thumbnails generated ... + %1 vytvorených miniatúr... + + + Generating preview thumbnails ... + Vytvárajú sa ukážky miniatúr... + + + + UBToolsManager + + Mask + Clona + + + Cache + Baterka + + + Ruler + Pravítko + + + Triangle + Trojuholník + + + Compass + Kružidlo + + + Protractor + Uhlomer + + + Magnifier + Lupa + + + + UBTrapFlashController + + Web + Web + + + Whole page + Celá stránka + + + + UBUpdateDlg + + Document updater + Aktualizácia dokumentu + + + Please wait the import process will start soon... + Prosím, počkajte, proces nahrávania sa čoskoro začne... + + + Files update successful! +Please reboot the application to access the updated documents. + Aktualizácia bola úspešne dokončená! +Reštartujte aplikáciu, aby ste mohli pracovať s aktualizovanými dokumentmi. + + + Browse + Prehľadávať + + + Select a backup folder + Vyberte priečinok zálohy + + + files require an update. + súbory si vyžadujú aktualizáciu. + + + Update + Aktualizovať + + + An error occured during the update. The files have not been affected. + Počas aktualizácie sa vyskytla chyba. Súbory to neovplyvnilo. + + + Files update results + Výsledky aktualizácie súborov + + + Backup path: + Umiestnenie zálohy: + + + Updating file + Prebieha aktualizácia súboru + + + Remind me later + Pripomenúť mi neskôr + + + + UBWebPluginWidget + + Loading... + Nahráva sa... + + + + UBWidgetUniboardAPI + + %0 called (method=%1, status=%2) + %0 vyvolané (metóda = %1, stav = %2) + + + + UBYouTubePublisher + + YouTube authentication failed. + Nepodarilo sa prihlásiť na YouTube. + + + Error while uploading video to YouTube (%1) + Chyba pri nahrávaní videa na YouTube (%1) + + + Upload to YouTube in progress %1 % + Prebieha nahrávanie na YouTube %1 % + + + + UBYouTubePublishingDialog + + Music + Hudba + + + People & Blogs + Ľudia a blogy + + + Nonprofits & Activism + Neziskovky a aktivisti + + + Comedy + Komédia + + + Gaming + Hry + + + Sports + Šport + + + Upload + Nahrať + + + Science & Technology + Veda a technika + + + Howto & Style + Návody a štýl + + + Education + Vzdelávanie + + + Entertainment + Zábava + + + Travel & Events + Cestovanie a udalosti + + + News & Politics + Správy a politika + + + Pets & Animals + Zvieratá + + + Autos & Vehicles + Autá a dopravné prostriedky + + + + UBZoomPalette + + %1 x + %1 x + + + + WBClearButton + + Clear + Vyčistiť + + + + WBDownloadItem + + KB + kB + + + MB + MB + + + bytes + bytov + + + - %4 %5 remaining + – zostáva %4 %5 + + + minutes + minút(y) + + + Error opening saved file: %1 + Chyba pri otváraní uloženého súboru: %1 + + + seconds + sekúnd + + + Error saving: %1 + Chyba pri ukladaní súboru: %1 + + + Download canceled: %1 + Sťahovanie súboru bolo zrušené: %1 + + + %1 of %2 - Stopped + %1 z(o) %2 – zastavené + + + Save File + Uložiť súbor + + + %1 of %2 (%3/sec) %4 + %1 z(o) %2 (%3/sek) %4 + + + Network Error: %1 + Chyba siete: %1 + + + ? + unknown file size + ? + + + + WBDownloadManager + + 1 Download + 1 stiahnutý súbor + + + %1 Downloads + always >= 2 + %1 stiahnuté súbory + + + + WBHistoryModel + + Title + Názov + + + Address + Adresa + + + + WBHistoryTreeModel + + %1 items + 2,3,4 položky, 0, >=5 položiek + %1 položiek + + + Earlier Today + Dnes + + + + WBSearchLineEdit + + Search + Hľadať + + + + WBTabBar + + Reload All Tabs + Obnoviť všetky karty + + + Reload Tab + Obnoviť kartu + + + Clone Tab + Duplikovať kartu + + + &Close Tab + &Zatvoriť kartu + + + Close &Other Tabs + Zatvoriť &ostané karty + + + New &Tab + Nová &karta + + + + WBTabWidget + + (Untitled) + (Bez názvu) + + + Recently Closed Tabs + Nedávno zatvorené karty + + + + WBToolbarSearch + + Recent Searches + Nedávne vyhľadávania + + + Search + Vyhľadať + + + No Recent Searches + Žiadne nedávne vyhľadávania + + + Clear Recent Searches + Vymazať nedávne vyhľadávania + + + + WBWebPage + + PDF + PDF + + + Add to Current Document + Pridať do aktuálneho dokumentu + + + Download + Stiahnuť + + + Error loading page: %1 + Chyba pri nahrávaní stránky: %1 + + + Download PDF Document: would you prefer to download the PDF file or add it to the current OpenBoard document? + Sťahovanie dokumentu PDF: chcete súbor PDF radšej stiahnuť alebo pridať do aktuálneho dokumentu? + + + + WBWebView + + Open in New Tab + Otvoriť na novej karte + + + + YouTubePublishingDialog + + Title + Názov + + + YouTube Username + Používateľské meno na YouTube + + + YouTube Password + Heslo na YouTube + + + Category + Kategória + + + Description + Popis + + + Publish Podcast to YouTube + Publikovať podcast na YouTube + + + Keywords + Kľúčové slová + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:10pt;">By clicking 'Upload,' you certify that you own all rights to the content or that you are authorized by the owner to make the content publicly available on YouTube, and that it otherwise complies with the YouTube Terms of Service located at </span><a href="http://www.youtube.com/t/terms"><span style=" font-family:'Lucida Grande'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.youtube.com/t/terms</span></a></p></body></html> + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Lucida Grande'; font-size:10pt;">Kliknutím na "Upload" (Nahrať) potvrdzujete, že máte všetky práva k materiálu alebo že máte písomný súhlas vlastníka týchto práv na zverejnenie materiálu na sieti YouTube a že materiál je v súlade s podmienkami využívania služieb siete YouTube, ktorých aktuálne znenie sa nachádza na adrese </span><a href="http://www.youtube.com/t/terms"><span style=" font-family:'Lucida Grande'; font-size:10pt; text-decoration: underline; color:#0000ff;">http://www.youtube.com/t/terms</span></a></p></body></html> + + + OpenBoard + OpenBoard + + + Restore credentials on reboot + Po reštarte obnoviť prihlasovacie údaje + + + + brushProperties + + Fine + Tenká + + + Medium + Stredne hrubá + + + Strong + Hrubá + + + Opacity + Priehľadnosť + + + Line Width + Šírka čiary + + + On Light Background + Na svetlom pozadí + + + Pen is Pressure Sensitive + Pero je citlivé na tlak + + + On Dark Background + Na tmavom pozadí + + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + + + + capturePublishingDialog + + Title + Názov + + + E-mail + E-mail + + + Author + Autor + + + Dialog + Dialóg + + + Description + Popis + + + + documents + + OpenBoard Documents + Dokumenty OpenBoardu + + + + preferencesDialog + + Pen + Pero + + + About + O programe + + + Close + Zatvoriť + + + Horizontal + Vodorovná + + + Display Text Under Button + Pod tlačidlom zobraziť text + + + Show Page with External Browser + Stránku zobraziť v externom prehliadači + + + Default Settings + Predvolené nastavenia + + + Network + Sieť + + + Positioned at the Bottom (recommended for white boards) + Je umiestnený dole (odporúča sa pre tabule) + + + Marker + Zvýrazňovač + + + Internet + Internet + + + Positioned at the Top (recommended for tablets) + Je umiestnený navrchu (odporúča sa pre tablety) + + + Virtual Keyboard + Virtuálna klávesnica + + + Home Page: + Úvodná stránka: + + + Check software update at launch + Pri spustení programu vyhľadať aktualizáciu + + + Software Update + Aktualizácia programu + + + Keyboard button size: + Veľkosť tlačidla klávesnice: + + + Stylus Palette + Paleta pre interaktívne pero + + + Display + Zobraziť + + + Toolbar + Panel s nástrojmi + + + Vertical + Zvislá + + + Preferences + Predvoľby + + + version : … + Verzia:... + + + Licences + Licencie + + + Multi display + Viac obrazoviek + + + Show internal web page content on secondary screen or projector + Na druhej obrazovke alebo projektore zobraziť obsah internej webovej stránky + + + Swap control display and view display + Prehodiť ovládaciu obrazovku a zobrazovaciu obrazovku + + + Mode + Režim + + + Mode to start in: + Režim pri štarte: + + + Board + Tabuľa + + + Desktop + Pracovná plocha + + + Proxy User: + Použ. m. na proxy: + + + Pass: + Heslo: + + + Credits + Poďakovanie + + + Open-Sankoré Importer + Nahrávanie z Open-Sankoré + + + Check if Open-Sankoré data could be imported at launch + Zistiť, či sa pri spustení majú nahrať dáta z Open-Sankoré + + + Use system keyboard (recommended) + Používať systémovú klávesnicu (odporúča sa) + + + Built-in virtual keyboard button size: + Veľkosť tlačidla zabudovanej virtuálnej klávesnice: + + + + trapFlashDialog + + Trap flash + Označiť flash + + + Select a flash to trap + Vyberte flash, ktorý chcete označiť + + + about:blank + about:blank + + + Application name + Názov aplikácie + + + Create Application + Vytvoriť aplikáciu + + + diff --git a/resources/i18n/OpenBoard_sv.ts b/resources/i18n/OpenBoard_sv.ts index 0a0395bc..5f736c78 100644 --- a/resources/i18n/OpenBoard_sv.ts +++ b/resources/i18n/OpenBoard_sv.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Uppdatera + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1235,6 +1250,26 @@ Warnings during export was appeared Varningar unde export dök upp + + Exporting document... + Exporterar dokument... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + Export lyckades. + UBExportCFF @@ -1271,11 +1306,11 @@ Exporting document... - Exporterar dokument... + Exporterar dokument... Export successful. - Export lyckades. + Export lyckades. Exporting %1 %2 of %3 @@ -1285,18 +1320,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1306,28 +1329,16 @@ Exporting document... - Exporterar dokument... + Exporterar dokument... Export successful. - Export lyckades. + Export lyckades. Export to PDF Exportera till PDF - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1337,11 +1348,11 @@ Exporting document... - Exporterar dokument... + Exporterar dokument... Export successful. - Export lyckades. + Export lyckades. Exporting page %1 of %2 @@ -2415,6 +2426,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Pennan är tryckkänslig + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_tr.ts b/resources/i18n/OpenBoard_tr.ts index 9b9c9c84..b3fefd7d 100644 --- a/resources/i18n/OpenBoard_tr.ts +++ b/resources/i18n/OpenBoard_tr.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ Güncelle + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1233,6 +1248,26 @@ Warnings during export was appeared Dışa aktarma sırasında bir uyarı mesajı göründü + + Exporting document... + Döküman dışa aktarılıyor... + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + + UBExportCFF @@ -1269,11 +1304,11 @@ Exporting document... - Döküman dışa aktarılıyor... + Döküman dışa aktarılıyor... Export successful. - Dışa aktarım tamamlandı. + Dışa aktarım tamamlandı. Exporting %1 %2 of %3 @@ -1283,18 +1318,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1304,28 +1327,16 @@ Exporting document... - Döküman dışa aktarılıyor... + Döküman dışa aktarılıyor... Export successful. - Dışa aktarım tamamlandı. + Dışa aktarım tamamlandı. Export to PDF PDF Olarak Aktar - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1335,11 +1346,11 @@ Exporting document... - Döküman dışa aktarılıyor... + Döküman dışa aktarılıyor... Export successful. - Dışa aktarım tamamlandı. + Dışa aktarım tamamlandı. Exporting page %1 of %2 @@ -2412,6 +2423,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive Kalem Basınca Duyarlıdır + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_zh.ts b/resources/i18n/OpenBoard_zh.ts index 90dd8f2f..af14e1f9 100644 --- a/resources/i18n/OpenBoard_zh.ts +++ b/resources/i18n/OpenBoard_zh.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ 更新 + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1232,6 +1247,26 @@ Warnings during export was appeared 导出过程中出现警告 + + Exporting document... + 文档导出中…… + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + + UBExportCFF @@ -1268,11 +1303,11 @@ Exporting document... - 文档导出中…… + 文档导出中…… Export successful. - 导出成功 + 导出成功 Exporting %1 %2 of %3 @@ -1282,18 +1317,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1303,28 +1326,16 @@ Exporting document... - 文档导出中…… + 文档导出中…… Export successful. - 导出成功 + 导出成功 Export to PDF 以PDF文件格式导出 - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1334,11 +1345,11 @@ Exporting document... - 文档导出中…… + 文档导出中…… Export successful. - 导出成功 + 导出成功 Exporting page %1 of %2 @@ -2412,6 +2423,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive 使用压感笔 + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_zh_CN.ts b/resources/i18n/OpenBoard_zh_CN.ts index 90dd8f2f..af14e1f9 100644 --- a/resources/i18n/OpenBoard_zh_CN.ts +++ b/resources/i18n/OpenBoard_zh_CN.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ 更新 + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1232,6 +1247,26 @@ Warnings during export was appeared 导出过程中出现警告 + + Exporting document... + 文档导出中…… + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + + UBExportCFF @@ -1268,11 +1303,11 @@ Exporting document... - 文档导出中…… + 文档导出中…… Export successful. - 导出成功 + 导出成功 Exporting %1 %2 of %3 @@ -1282,18 +1317,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1303,28 +1326,16 @@ Exporting document... - 文档导出中…… + 文档导出中…… Export successful. - 导出成功 + 导出成功 Export to PDF 以PDF文件格式导出 - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportPDF @@ -1334,11 +1345,11 @@ Exporting document... - 文档导出中…… + 文档导出中…… Export successful. - 导出成功 + 导出成功 Exporting page %1 of %2 @@ -2412,6 +2423,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive 使用压感笔 + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog diff --git a/resources/i18n/OpenBoard_zh_TW.ts b/resources/i18n/OpenBoard_zh_TW.ts index dcd9da75..cf800729 100644 --- a/resources/i18n/OpenBoard_zh_TW.ts +++ b/resources/i18n/OpenBoard_zh_TW.ts @@ -799,6 +799,14 @@ Open the tutorial web page + + Ruled Light Background + + + + Ruled Dark Background + + PasswordDialog @@ -891,6 +899,13 @@ 更新 + + UBBackgroundPalette + + Grid size + + + UBBoardController @@ -1232,6 +1247,26 @@ Warnings during export was appeared 匯出過程出現警告 + + Exporting document... + + + + Export failed + + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + + + + Export failed: location not writable + + + + Export successful. + + UBExportCFF @@ -1268,11 +1303,11 @@ Exporting document... - 文件匯出中... + 文件匯出中... Export successful. - 匯出成功。 + 匯出成功。 Exporting %1 %2 of %3 @@ -1282,18 +1317,6 @@ Export to OpenBoard Format - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - - UBExportFullPDF @@ -1303,7 +1326,7 @@ Exporting document... - 匯出文件中... + 匯出文件中... Export to PDF @@ -1311,19 +1334,7 @@ Export successful. - 匯出成功。 - - - Export failed: location not writable - - - - Export failed - - - - Unable to export to the selected location. You do not have the permissions necessary to save the file. - + 匯出成功。 @@ -1338,11 +1349,11 @@ Export successful. - 匯出成功。 + 匯出成功。 Exporting document... - 匯出文件中... + 匯出文件中... Export to PDF @@ -2399,6 +2410,14 @@ p, li { white-space: pre-wrap; } Pen is Pressure Sensitive 感壓筆 + + Smooth strokes (experimental) + + + + Simplify strokes after drawing (experimental) + + capturePublishingDialog From 483973e516440555ecb310ed387f69cd9b0f1de2 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 15 Oct 2016 21:31:45 -0400 Subject: [PATCH 023/134] Fixed compiling on Windows (following addition of podcast and stroke stuff) --- src/domain/UBGraphicsScene.cpp | 2 +- src/podcast/podcast.pri | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index b63ee57f..a892cef6 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -25,7 +25,7 @@ */ -#include +//#include #include "UBGraphicsScene.h" diff --git a/src/podcast/podcast.pri b/src/podcast/podcast.pri index 865060e0..56eda037 100644 --- a/src/podcast/podcast.pri +++ b/src/podcast/podcast.pri @@ -4,14 +4,12 @@ HEADERS += src/podcast/UBPodcastController.h \ src/podcast/UBPodcastRecordingPalette.h \ src/podcast/youtube/UBYouTubePublisher.h \ src/podcast/intranet/UBIntranetPodcastPublisher.h \ - $$PWD/ffmpeg/UBMicrophoneInput.h SOURCES += src/podcast/UBPodcastController.cpp \ src/podcast/UBAbstractVideoEncoder.cpp \ src/podcast/UBPodcastRecordingPalette.cpp \ src/podcast/youtube/UBYouTubePublisher.cpp \ src/podcast/intranet/UBIntranetPodcastPublisher.cpp \ - $$PWD/ffmpeg/UBMicrophoneInput.cpp win32 { @@ -37,9 +35,11 @@ macx { } linux-g++* { - HEADERS += src/podcast/ffmpeg/UBFFmpegVideoEncoder.h + HEADERS += src/podcast/ffmpeg/UBFFmpegVideoEncoder.h \ + src/podcast/ffmpeg/UBMicrophoneInput.h - SOURCES += src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp + SOURCES += src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp \ + src/podcast/ffmpeg/UBMicrophoneInput.cpp DEPENDPATH += /usr/lib/x86_64-linux-gnu From 8b57776939316cea73cedf8d134835b44144a763 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 15 Oct 2016 21:32:19 -0400 Subject: [PATCH 024/134] Fixed line tool --- src/domain/UBGraphicsScene.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index a892cef6..0e2cd0ea 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -548,6 +548,11 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres if(dc->mActiveRuler){ dc->mActiveRuler->DrawLine(position, width); } + + else if (currentTool == UBStylusTool::Line) { + drawLineTo(position, width, true); + } + else{ UBInterpolator::InterpolationMethod interpolator = UBInterpolator::NoInterpolation; @@ -1150,6 +1155,8 @@ void UBGraphicsScene::initPolygonItem(UBGraphicsPolygonItem* polygonItem) polygonItem->setColor(colorOnLightBG); } + //polygonItem->setColor(QColor(rand()%256, rand()%256, rand()%256, polygonItem->brush().color().alpha())); + polygonItem->setColorOnDarkBackground(colorOnDarkBG); polygonItem->setColorOnLightBackground(colorOnLightBG); From 1945298a1438e775440dd831e2c87fbd9458c9ef Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 15 Oct 2016 22:47:39 -0400 Subject: [PATCH 025/134] Removed unnecessary include --- src/domain/UBGraphicsScene.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 0e2cd0ea..a68af042 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -25,7 +25,6 @@ */ -//#include #include "UBGraphicsScene.h" From c84ef9d028e67ae706aad40789ceb9668aefbb8f Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 15 Oct 2016 22:48:18 -0400 Subject: [PATCH 026/134] Bumped version to 1.4.0-a.1 --- OpenBoard.pro | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index 2505bb5b..4c838820 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -9,10 +9,10 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 -VERSION_MIN = 3 -VERSION_PATCH = 4 -VERSION_TYPE = r # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_BUILD = 0 +VERSION_MIN = 4 +VERSION_PATCH = 0 +VERSION_TYPE = a # a = alpha, b = beta, rc = release candidate, r = release, other => error +VERSION_BUILD = 1 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}" From d8e78dae14b87ffa916f27cc9cf9fe07a324d9bb Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 22 Oct 2016 13:20:47 -0400 Subject: [PATCH 027/134] Linux/Podcasts: Enable use of AAC encoder --- src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp index fa6bc0dd..5783c5d4 100644 --- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp @@ -266,6 +266,7 @@ bool UBFFmpegVideoEncoder::init() c->channel_layout = av_get_default_channel_layout(c->channels); c->profile = FF_PROFILE_AAC_MAIN; c->time_base = {1, mAudioSampleRate}; + c->strict_std_compliance = -2; // Enable use of experimental codec if (mOutputFormatContext->oformat->flags & AVFMT_GLOBALHEADER) c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; From 8c9c463d3ee770a1d992c45692436101eff5c377 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 22 Oct 2016 14:23:28 -0400 Subject: [PATCH 028/134] Support libAV as available on Ubuntu 14.04 (hack; could do with cleaning up) --- src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp | 161 +++++++++++++++++++- src/podcast/ffmpeg/UBFFmpegVideoEncoder.h | 9 ++ src/podcast/podcast.pri | 6 + 3 files changed, 175 insertions(+), 1 deletion(-) diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp index 5783c5d4..320464dd 100644 --- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.cpp @@ -21,6 +21,138 @@ #include "UBFFmpegVideoEncoder.h" +// Due to the whole FFmpeg / libAV silliness, we have to support libavresample instead +// of libswresapmle on some platforms, as well as now-obsolete function names +#if LIBAVFORMAT_VERSION_MICRO < 100 + #define swr_alloc avresample_alloc_context + #define swr_init avresample_open + #define swr_get_out_samples avresample_get_out_samples + #define swr_free avresample_free + #define av_opt_set_sample_fmt av_opt_set_int + + #define av_frame_alloc avcodec_alloc_frame + #define av_frame_free avcodec_free_frame + #define av_packet_unref av_free_packet + + #define AV_ERROR_MAX_STRING_SIZE 64 + #define AV_CODEC_FLAG_GLOBAL_HEADER (1 << 22) + + uint8_t* audio_samples_buffer; // used by processAudio because av_frame_get_buffer doesn't exist in this version + + int avformat_alloc_output_context2(AVFormatContext **avctx, AVOutputFormat *oformat, + const char *format, const char *filename) + { + AVFormatContext *s = avformat_alloc_context(); + int ret = 0; + + *avctx = NULL; + if (!s) + goto nomem; + + if (!oformat) { + if (format) { + oformat = av_guess_format(format, NULL, NULL); + if (!oformat) { + av_log(s, AV_LOG_ERROR, "Requested output format '%s' is not a suitable output format\n", format); + ret = AVERROR(EINVAL); + goto error; + } + } else { + oformat = av_guess_format(NULL, filename, NULL); + if (!oformat) { + ret = AVERROR(EINVAL); + av_log(s, AV_LOG_ERROR, "Unable to find a suitable output format for '%s'\n", + filename); + goto error; + } + } + } + + s->oformat = oformat; + if (s->oformat->priv_data_size > 0) { + s->priv_data = av_mallocz(s->oformat->priv_data_size); + if (!s->priv_data) + goto nomem; + if (s->oformat->priv_class) { + *(const AVClass**)s->priv_data= s->oformat->priv_class; + av_opt_set_defaults(s->priv_data); + } + } else + s->priv_data = NULL; + + if (filename) + av_strlcpy(s->filename, filename, sizeof(s->filename)); + + *avctx = s; + return 0; + + nomem: + av_log(s, AV_LOG_ERROR, "Out of memory\n"); + ret = AVERROR(ENOMEM); + error: + avformat_free_context(s); + return ret; + } + + + int av_samples_alloc_array_and_samples(uint8_t ***audio_data, int *linesize, int nb_channels, + int nb_samples, enum AVSampleFormat sample_fmt, int align) + { + int ret, nb_planes = av_sample_fmt_is_planar(sample_fmt) ? nb_channels : 1; + + *audio_data = (uint8_t**) av_malloc(sizeof(*audio_data) * nb_planes); + if (!*audio_data) + return AVERROR(ENOMEM); + ret = av_samples_alloc(*audio_data, linesize, nb_channels, + nb_samples, sample_fmt, align); + if (ret < 0) + av_freep(audio_data); + return ret; + } + + int swr_convert(struct SwrContext *s, uint8_t **out, int out_count, const uint8_t **in, int in_count) + { + return avresample_convert(s, out, 0, out_count, const_cast(in), 0, in_count); + } + + +#endif + +#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,55,0) + void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb) + { + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts = av_rescale_q(pkt->pts, src_tb, dst_tb); + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts = av_rescale_q(pkt->dts, src_tb, dst_tb); + if (pkt->duration > 0) + pkt->duration = av_rescale_q(pkt->duration, src_tb, dst_tb); + if (pkt->convergence_duration > 0) + pkt->convergence_duration = av_rescale_q(pkt->convergence_duration, src_tb, dst_tb); + } +#endif + +#if defined(LIBAVRESAMPLE_VERSION_INT) && LIBAVRESAMPLE_VERSION_INT < AV_VERSION_INT(1,3,0) + //#include + int avresample_get_out_samples(AVAudioResampleContext *avr, int in_nb_samples) + { + int64_t samples = avresample_get_delay(avr) + (int64_t)in_nb_samples; + /* + if (avr->resample_needed) { + samples = av_rescale_rnd(samples, + avr->out_sample_rate, + avr->in_sample_rate, + AV_ROUND_UP); + } + */ + samples += avresample_available(avr); + if (samples > INT_MAX) + return AVERROR(EINVAL); + return samples; + } + +#endif + //------------------------------------------------------------------------- // Utility functions //------------------------------------------------------------------------- @@ -28,7 +160,7 @@ QString avErrorToQString(int errnum) { char error[AV_ERROR_MAX_STRING_SIZE]; - av_make_error_string(error, AV_ERROR_MAX_STRING_SIZE, errnum); + av_strerror(errnum, error, AV_ERROR_MAX_STRING_SIZE); return QString(error); } @@ -287,9 +419,11 @@ bool UBFFmpegVideoEncoder::init() } av_opt_set_int(mSwrContext, "in_channel_count", inChannelCount, 0); + av_opt_set_int(mSwrContext, "in_channel_layout", av_get_default_channel_layout(inChannelCount), 0); av_opt_set_int(mSwrContext, "in_sample_rate", inSampleRate, 0); av_opt_set_sample_fmt(mSwrContext, "in_sample_fmt", (AVSampleFormat)mAudioInput->sampleFormat(), 0); av_opt_set_int(mSwrContext, "out_channel_count", c->channels, 0); + av_opt_set_int(mSwrContext, "out_channel_layout", c->channel_layout, 0); av_opt_set_int(mSwrContext, "out_sample_rate", c->sample_rate, 0); av_opt_set_sample_fmt(mSwrContext, "out_sample_fmt", c->sample_fmt, 0); @@ -449,6 +583,7 @@ void UBFFmpegVideoEncoder::processAudio(QByteArray &data) bool framesAdded = false; while (av_audio_fifo_size(mAudioOutBuffer) > codecContext->frame_size) { + AVFrame * avFrame = av_frame_alloc(); avFrame->nb_samples = codecContext->frame_size; avFrame->channel_layout = codecContext->channel_layout; @@ -456,7 +591,24 @@ void UBFFmpegVideoEncoder::processAudio(QByteArray &data) avFrame->sample_rate = codecContext->sample_rate; avFrame->pts = mAudioFrameCount; +#if LIBAVFORMAT_VERSION_MICRO < 100 + int buffer_size = av_samples_get_buffer_size(NULL, codecContext->channels, codecContext->frame_size, codecContext->sample_fmt, 0); + audio_samples_buffer = (uint8_t*)av_malloc(buffer_size); + if (!audio_samples_buffer) { + qWarning() << "Couldn't allocate samples for audio frame: " << avErrorToQString(ret); + break; + } + + ret = avcodec_fill_audio_frame(avFrame, + codecContext->channels, + codecContext->sample_fmt, + (const uint8_t*)audio_samples_buffer, + buffer_size, + 0); + +#else ret = av_frame_get_buffer(avFrame, 0); +#endif if (ret < 0) { qWarning() << "Couldn't allocate frame: " << avErrorToQString(ret); break; @@ -589,4 +741,11 @@ void UBFFmpegVideoEncoderWorker::writeLatestAudioFrame() AVFrame *frame = mAudioQueue.dequeue(); writeFrame(frame, mAudioPacket, mController->mAudioStream, mController->mOutputFormatContext); av_frame_free(&frame); + +#if LIBAVFORMAT_VERSION_MICRO < 100 + if (audio_samples_buffer) { + av_free(audio_samples_buffer); + audio_samples_buffer = NULL; + } +#endif } diff --git a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h index c2e19de6..6068a369 100644 --- a/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h +++ b/src/podcast/ffmpeg/UBFFmpegVideoEncoder.h @@ -32,8 +32,17 @@ extern "C" { #include #include #include + #include #include + +// Due to the whole ffmpeg / libAV silliness, we have to support libavresample on some platforms +#if LIBAVFORMAT_VERSION_MICRO > 100 #include +#else + #include + #define SwrContext AVAudioResampleContext +#endif + } #include diff --git a/src/podcast/podcast.pri b/src/podcast/podcast.pri index 56eda037..91dd3f5d 100644 --- a/src/podcast/podcast.pri +++ b/src/podcast/podcast.pri @@ -51,6 +51,12 @@ linux-g++* { -lxcb-xfixes \ -lxcb-render -lxcb-shape -lxcb -lX11 -lasound -lSDL -lx264 -lpthread -lvpx -lvorbisenc -lvorbis -ltheoraenc -ltheoradec -logg -lopus -lmp3lame -lfreetype -lfdk-aac -lass -llzma -lbz2 -lz -ldl -lswresample -lswscale -lavutil -lm + UBUNTU_VERSION = $$system(lsb_release -irs) + equals(UBUNTU_VERSION, Ubuntu 14.04) { + LIBS -= -lswresample + LIBS += -lavresample + } + QMAKE_CXXFLAGS += -std=c++11 # move this to OpenBoard.pro when we can use C++11 on all platforms } From b6f41165a6ba014fc5e7cd02e5a7241ebfa00803 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 5 Nov 2016 11:52:35 -0400 Subject: [PATCH 029/134] Fix for screenshot tool not grabbing videos --- src/board/UBBoardController.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index e61d613b..109b298e 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -2104,29 +2104,28 @@ QUrl UBBoardController::expandWidgetToTempDir(const QByteArray& pZipedData, cons } +/** + * @brief Take a screenshot of part of the scene + * @param pSceneRect The area to capture, in the active scene's coordinates + */ void UBBoardController::grabScene(const QRectF& pSceneRect) { if (mActiveScene) { - QImage image(pSceneRect.width(), pSceneRect.height(), QImage::Format_ARGB32); - image.fill(Qt::transparent); - - QRectF targetRect(0, 0, pSceneRect.width(), pSceneRect.height()); - QPainter painter(&image); - painter.setRenderHint(QPainter::SmoothPixmapTransform); - painter.setRenderHint(QPainter::Antialiasing); - - mActiveScene->setRenderingContext(UBGraphicsScene::NonScreen); - mActiveScene->setRenderingQuality(UBItem::RenderingQualityHigh); + // Ideally we should render the scene directly to a QImage rather than use grabWindow; + // this was the previous solution but it couldn't grab videos (QGraphicsVideoItem), so it + // was changed to this admittedly more sketchy way of doing it. - mActiveScene->render(&painter, targetRect, pSceneRect); + UBBoardView* view = mActiveScene->controlView(); + QPoint pos = view->viewport()->mapFromGlobal(view->mapToGlobal(view->mapFromScene(pSceneRect.topLeft()))) + QPoint(1,1); - mActiveScene->setRenderingContext(UBGraphicsScene::Screen); -// mActiveScene->setRenderingQuality(UBItem::RenderingQualityNormal); - mActiveScene->setRenderingQuality(UBItem::RenderingQualityHigh); + qreal scale = systemScaleFactor(); + QScreen * screen = UBApplication::controlScreen(); + QPixmap image = screen->grabWindow(view->viewport()->winId(), + pos.x(), pos.y(), pSceneRect.width()*scale - 1, pSceneRect.height()*scale - 1); - mPaletteManager->addItem(QPixmap::fromImage(image)); + mPaletteManager->addItem(image, QPointF(0,0), 1/scale); selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); } } From 5bf52b8b3f8b77bfaf571e9786e2869e21d465ee Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 5 Nov 2016 13:17:12 -0400 Subject: [PATCH 030/134] Take into account stroke thickness when simplifying it --- src/core/UBSettings.cpp | 1 + src/core/UBSettings.h | 1 + src/domain/UBGraphicsStroke.cpp | 29 ++++++++++++++++++++--------- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index cfde5119..d759eec6 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -272,6 +272,7 @@ void UBSettings::init() boardInterpolatePenStrokes = new UBSetting(this, "Board", "InterpolatePenStrokes", true); boardSimplifyPenStrokes = new UBSetting(this, "Board", "SimplifyPenStrokes", true); boardSimplifyPenStrokesThresholdAngle = new UBSetting(this, "Board", "SimplifyPenStrokesThresholdAngle", 2); + boardSimplifyPenStrokesThresholdWidthDifference = new UBSetting(this, "Board", "SimplifyPenStrokesThresholdWidthDifference", 2.0); boardInterpolateMarkerStrokes = new UBSetting(this, "Board", "InterpolateMarkerStrokes", true); boardSimplifyMarkerStrokes = new UBSetting(this, "Board", "SimplifyMarkerStrokes", true); diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index 0fb8bf68..21e1e9c9 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -276,6 +276,7 @@ class UBSettings : public QObject UBSetting* boardInterpolatePenStrokes; UBSetting* boardSimplifyPenStrokes; UBSetting* boardSimplifyPenStrokesThresholdAngle; + UBSetting* boardSimplifyPenStrokesThresholdWidthDifference; UBSetting* boardInterpolateMarkerStrokes; UBSetting* boardSimplifyMarkerStrokes; diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index a640d0a0..7dddf6e9 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -223,23 +223,32 @@ UBGraphicsStroke* UBGraphicsStroke::simplify() * test these three points. As long as they are aligned, B is erased and we start over. * If not, the current B becomes the new A, and so on. * + * In case the stroke thickness varies a lot between A and B, then B is not removed even if it + * should be according to the previous criteria. * * TODO: more advanced algorithm that could also simplify curved sections of the stroke */ // angle difference in degrees between AB and BC below which the segments are considered colinear - qreal threshold = UBSettings::settings()->boardSimplifyPenStrokesThresholdAngle->get().toReal(); + qreal thresholdAngle = UBSettings::settings()->boardSimplifyPenStrokesThresholdAngle->get().toReal(); + + // Relative difference in thickness between two consecutive points (A and B) below which they are considered equal + qreal thresholdWidthDifference = UBSettings::settings()->boardSimplifyPenStrokesThresholdWidthDifference->get().toReal(); QList::iterator it = points.begin(); QList::iterator> toDelete; while (it+2 != points.end()) { + // it, b_it and (b_it+1) correspond to A, B and C respectively QList::iterator b_it(it+1); while (b_it+1 != points.end()) { qreal angle = qFabs(QLineF(it->first, b_it->first).angle() - QLineF(b_it->first, (b_it+1)->first).angle()); + qreal widthRatio = qMax(it->second, b_it->second)/qMin(it->second, b_it->second); + if (widthRatio > thresholdWidthDifference) + qDebug() << "Width ratio: " << widthRatio; - if (angle < threshold) + if (angle < thresholdAngle && widthRatio < thresholdWidthDifference) b_it = points.erase(b_it); else break; @@ -267,16 +276,18 @@ UBGraphicsStroke* UBGraphicsStroke::simplify() // certain threshold helps mitigate this issue. // TODO: fix fill issue - if (newStrokePoints.size() > 1 && i < points.size() - 1) { - qreal angle = qFabs(UBGeometryUtils::angle(points[i-1].first, points[i].first, points[i+1].first)); - qDebug() << "Angle: " << angle; - if (angle > 40 && angle < 320) + if (hasAlpha()) { + if (newStrokePoints.size() > 1 && i < points.size() - 1) { + qreal angle = qFabs(UBGeometryUtils::angle(points[i-1].first, points[i].first, points[i+1].first)); + qDebug() << "Angle: " << angle; + if (angle > 40 && angle < 320) + drawCurve = true; + } + + if (newStrokePoints.size() % 20 == 0) drawCurve = true; } - if (newStrokePoints.size() % 20 == 0) - drawCurve = true; - if (drawCurve) { UBGraphicsPolygonItem* poly = mScene->polygonToPolygonItem(UBGeometryUtils::curveToPolygon(newStrokePoints, true, true)); From 1070251d1ce5439b560c29338c90b326e2e4e032 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 5 Nov 2016 13:18:38 -0400 Subject: [PATCH 031/134] When drawing with pressure, set pressure to be 20% minimum --- src/domain/UBGraphicsScene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index a68af042..4fd9d8fd 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -501,7 +501,7 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres if (currentTool != UBStylusTool::Line){ // Handle the pressure - width = dc->currentToolWidth() * pressure; + width = dc->currentToolWidth() * qMax(pressure, 0.2); }else{ // Ignore pressure for line tool width = dc->currentToolWidth(); From 8365f2f7a627ebb9a6948e272adbcedbe58f9727 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 5 Nov 2016 16:38:31 -0400 Subject: [PATCH 032/134] Fix saving of polygons' fill rule Up until now, the fill rule of a polygon was always saved as even-odd, despite the fact that in most if not all cases, polygons are drawn with winding fill within OpenBoard. Saving is now fixed, but there is no way to know upon loading whether the polygon was correctly saved or whether; so for now, we just set the fill rule to Winding when loading a polygon. --- src/adaptors/UBSvgSubsetAdaptor.cpp | 23 +++++++++++++++++++++++ src/domain/UBGraphicsPolygonItem.cpp | 1 + 2 files changed, 24 insertions(+) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index e0dbb4e2..4f0a1860 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -1599,6 +1599,8 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::polygonItemToSvgPolygon(UBGraphicsPo if (polygonItem->fillRule() == Qt::OddEvenFill) mXmlWriter.writeAttribute("fill-rule", "evenodd"); + else + mXmlWriter.writeAttribute("fill-rule", "winding"); if (!groupHoldsInfo) { @@ -1720,6 +1722,27 @@ UBGraphicsPolygonItem* UBSvgSubsetAdaptor::UBSvgSubsetReader::polygonItemFromPol color.setAlphaF(opacity); polygonItem->setColorOnLightBackground(color); } + + /* + + Unfortunately the fill rule was never saved correctly until OpenBoard v1.4, + before then, it was always saved as even-odd. So we can't load it safely here. + Saving is now fixed, but any old documents would be loaded incorrectly if the code + below is used. It should be activated at some point in the future though. + + QStringRef fillRule = mXmlReader.attributes().value("fill-rule"); + + if (!fillRule.isNull()) { + QString value = fillRule.toString(); + + if (value == "evenodd") + polygonItem->setFillRule(Qt::OddEvenFill); + else + polygonItem->setFillRule(Qt::WindingFill); + } + */ + polygonItem->setFillRule(Qt::WindingFill); + return polygonItem; } diff --git a/src/domain/UBGraphicsPolygonItem.cpp b/src/domain/UBGraphicsPolygonItem.cpp index 320da3f3..4e74420a 100644 --- a/src/domain/UBGraphicsPolygonItem.cpp +++ b/src/domain/UBGraphicsPolygonItem.cpp @@ -171,6 +171,7 @@ void UBGraphicsPolygonItem::copyItemParameters(UBItem *copy) const cp->setBrush(this->brush()); cp->setPen(this->pen()); cp->mHasAlpha = this->mHasAlpha; + cp->setFillRule(this->fillRule()); cp->setColorOnDarkBackground(this->colorOnDarkBackground()); cp->setColorOnLightBackground(this->colorOnLightBackground()); From 452383b8cc41dbec95f022751afd6324eb6b3f14 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 5 Nov 2016 18:32:28 -0400 Subject: [PATCH 033/134] Save one-polygon strokes to SVG as polygons, not polylines This prevents a bug where a simplified stroke (containing only one polygon) was incorrectly saved as a polyline, which meant the stroke was lost when the document was loaded. --- src/domain/UBGraphicsStroke.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index 7dddf6e9..a2b66015 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -170,6 +170,9 @@ bool UBGraphicsStroke::hasPressure() } } + else + return true; + return false; } From a4b83e2c5611d83255be290cab4ccc3db61e49a3 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 18 Feb 2017 19:01:57 -0500 Subject: [PATCH 034/134] Better calculation of angles --- src/frameworks/UBGeometryUtils.cpp | 17 +++++++++++++---- src/frameworks/UBGeometryUtils.h | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/frameworks/UBGeometryUtils.cpp b/src/frameworks/UBGeometryUtils.cpp index eb36a27e..cd6ff7ef 100644 --- a/src/frameworks/UBGeometryUtils.cpp +++ b/src/frameworks/UBGeometryUtils.cpp @@ -255,8 +255,6 @@ QPolygonF UBGeometryUtils::arcToPolygon(const QLineF& startRadius, qreal spanAng */ QPolygonF UBGeometryUtils::curveToPolygon(const QList& points, qreal startWidth, qreal endWidth) { - typedef QPair pointPair; - int n_points = points.size(); if (n_points < 2) @@ -431,7 +429,18 @@ void UBGeometryUtils::crashPointList(QVector &points) /** * @brief Return the angle between three points */ -qreal UBGeometryUtils::angle(const QPointF& a, const QPointF& b, const QPointF& c) +qreal UBGeometryUtils::angle(const QPointF& p1, const QPointF& p2, const QPointF& p3) { - return (QLineF(a, b).angle() - QLineF(b, c).angle()); + // Angle between three points, using the law of cosines: + // The angle at B equals arccos((a^2-b^2-c^2)/(2*a*c)), where a, b and c are the sides of the triangle + // opposite A, B and C, respectively + + qreal a, b, c, beta; + a = qSqrt(qPow(p2.x() - p3.x(), 2) + qPow(p2.y() - p3.y(), 2)); + b = qSqrt(qPow(p1.x() - p3.x(), 2) + qPow(p1.y() - p3.y(), 2)); + c = qSqrt(qPow(p1.x() - p2.x(), 2) + qPow(p1.y() - p2.y(), 2)); + + beta = qAcos((a*a - b*b - c*c)/(2*a*c)); + + return 2*3.14159*beta; } diff --git a/src/frameworks/UBGeometryUtils.h b/src/frameworks/UBGeometryUtils.h index 988b4a20..f4174709 100644 --- a/src/frameworks/UBGeometryUtils.h +++ b/src/frameworks/UBGeometryUtils.h @@ -55,7 +55,7 @@ class UBGeometryUtils static void crashPointList(QVector &points); - static qreal angle(const QPointF& a, const QPointF& b, const QPointF& c); + static qreal angle(const QPointF& p1, const QPointF& p2, const QPointF& p3); const static int centimeterGraduationHeight; const static int halfCentimeterGraduationHeight; From 3d46bd0bc53bdf037c474075d388025aaccabe8b Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 4 Mar 2017 16:55:57 -0500 Subject: [PATCH 035/134] Fix/re-enable checking for updates We can (again) check for updates and, if an update is available, send the user to the site to download them. The old format (a .json specifying a version number and download URL) was kept. The address for this file is now specified in the settings. --- src/core/UBApplicationController.cpp | 140 ++++++++++++--------------- src/core/UBApplicationController.h | 15 +-- src/core/UBSettings.cpp | 1 + src/core/UBSettings.h | 1 + src/frameworks/UBVersion.cpp | 25 +++-- 5 files changed, 86 insertions(+), 96 deletions(-) diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index 36ae40ca..5ae365a2 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -90,7 +90,6 @@ UBApplicationController::UBApplicationController(UBBoardView *pControlView, , mAutomaticCheckForUpdates(false) , mCheckingForUpdates(false) , mIsShowingDesktop(false) - , mHttp(0) { mDisplayManager = new UBDisplayManager(this); @@ -121,7 +120,7 @@ UBApplicationController::UBApplicationController(UBBoardView *pControlView, connect(UBApplication::webController, SIGNAL(imageCaptured(const QPixmap &, bool, const QUrl&)) , this, SLOT(addCapturedPixmap(const QPixmap &, bool, const QUrl&))); - networkAccessManager = new QNetworkAccessManager (this); + mNetworkAccessManager = new QNetworkAccessManager (this); QTimer::singleShot (1000, this, SLOT (checkAtLaunch())); } @@ -136,8 +135,6 @@ UBApplicationController::~UBApplicationController() delete mBlackScene; delete mMirror; - if (mHttp) delete mHttp; - delete(mOpenSankoreImporter); mOpenSankoreImporter = NULL; } @@ -478,85 +475,71 @@ void UBApplicationController::showDesktop(bool dontSwitchFrontProcess) } -void UBApplicationController::checkUpdate(QString urlString) +void UBApplicationController::checkUpdate(const QUrl& url) { + QUrl jsonUrl = url; + if (url.isEmpty()) + jsonUrl = UBSettings::settings()->appSoftwareUpdateURI->get().toUrl(); + qDebug() << "Checking for update at url: " << jsonUrl.toString(); - #if defined(QT_NO_DEBUG) - /* - if(mHttp) - mHttp->deleteLater(); - QUrl url(urlString); - mHttp = new QHttpPart(url.host()); - connect(mHttp, SIGNAL(requestFinished(int,bool)), this, SLOT(updateRequestFinished(int,bool))); - connect(mHttp, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(updateHeaderReceived(QHttpResponseHeader))); - - mHttp->get(url.path()); - - */ - -#else - if(mHttpreply) - mHttpreply->deleteLater(); - QUrl url(urlString); - mHttpreply = qnam.get(QNetworkRequest(url)); - connect(mHttpreply, SIGNAL(requestFinished(int,bool)), this, SLOT(updateRequestFinished(int,bool))); - connect(mHttpreply, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(updateHeaderReceived(QHttpResponseHeader))); - // mHttpreply->setUrl(url.path()); - //mHttp->get(url.path()); + connect(mNetworkAccessManager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(updateRequestFinished(QNetworkReply*))); + + mNetworkAccessManager->get(QNetworkRequest(jsonUrl)); -#endif } -/* -void UBApplicationController::updateHeaderReceived(QHttpResponseHeader header) + + +void UBApplicationController::updateRequestFinished(QNetworkReply * reply) { - if(header.statusCode() == 302 && header.hasKey("Location")){ - mHttp->close(); - checkUpdate(header.value("Location")); + if (reply->error()) { + qWarning() << "Error downloading update file: " << reply->errorString(); + return; } -} -*/ -void UBApplicationController::updateHeaderReceived(QNetworkRequest header ) -{ - //if(header.attribute(QNetworkRequest::HttpStatusCodeAttribute) == 302 && header.header(QNetworkRequest::LocationHeader)){ - // mHttp->close(); - mHttpreply->close(); - //checkUpdate(header.value("Location")); - // } -} + // Check if we are being redirected. If so, call checkUpdate again -void UBApplicationController::updateRequestFinished(int id, bool error) -{ - if (error){ - qWarning() << "http command id" << id << "return an error"; - } - else{ - /* QString responseString = QString(mHttp->readAll()); - qDebug() << responseString; - if (!responseString.isEmpty() && responseString.contains("version") && responseString.contains("url")){ - mHttp->close(); - mHttp->deleteLater(); - mHttp = 0; - downloadJsonFinished(responseString); - } - */ - QString responseString = QString(mHttpreply->readAll()); - qDebug() << responseString; - if (!responseString.isEmpty() && responseString.contains("version") && responseString.contains("url")){ - mHttpreply->close(); - mHttpreply->deleteLater(); - mHttpreply = 0; - downloadJsonFinished(responseString); - } - } -} + QVariant redirect_target = reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (!redirect_target.isNull()) { + // The returned URL might be relative. resolved() creates an absolute url from it + QUrl redirect_url(reply->url().resolved(redirect_target.toUrl())); + checkUpdate(redirect_url); + return; + } + + // No error and no redirect => we read the whole response + + QString responseString = QString(reply->readAll()); + + if (!responseString.isEmpty() && + responseString.contains("version") && + responseString.contains("url")) { + + reply->close(); + reply->deleteLater(); + + downloadJsonFinished(responseString); + } +} void UBApplicationController::downloadJsonFinished(QString currentJson) { + /* + The .json files simply specify the latest version number available, and + the URL to send the user to, so they can download it. + + They look like: + + { + "version": "1.3.5", + "url": "http://openboard.ch" + } + */ + QScriptValue scriptValue; QScriptEngine scriptEngine; scriptValue = scriptEngine.evaluate ("(" + currentJson + ")"); @@ -564,17 +547,18 @@ void UBApplicationController::downloadJsonFinished(QString currentJson) UBVersion installedVersion (qApp->applicationVersion()); UBVersion jsonVersion (scriptValue.property("version").toString()); + qDebug() << "json version: " << jsonVersion.toUInt(); + qDebug() << "installed version: " << installedVersion.toUInt(); + if (jsonVersion > installedVersion) { - if (UBApplication::mainWindow->yesNoQuestion(tr("Update available"), tr ("New update available, would you go to the web page ?"))){ - QUrl url(scriptValue.property ("url").toString()); - QDesktopServices::openUrl (url); - } - } - else { - if (isNoUpdateDisplayed) { - mMainWindow->information(tr("Update"), tr("No update available")); + if (UBApplication::mainWindow->yesNoQuestion(tr("Update available"), tr ("New update available, would you go to the web page ?"))){ + QUrl url(scriptValue.property("url").toString()); + QDesktopServices::openUrl(url); } } + else if (isNoUpdateDisplayed) { + mMainWindow->information(tr("Update"), tr("No update available")); + } } void UBApplicationController::checkAtLaunch() @@ -583,14 +567,14 @@ void UBApplicationController::checkAtLaunch() if(UBSettings::settings()->appEnableAutomaticSoftwareUpdates->get().toBool()){ isNoUpdateDisplayed = false; - //checkUpdate (); + checkUpdate(); } } void UBApplicationController::checkUpdateRequest() { isNoUpdateDisplayed = true; - //checkUpdate (); + checkUpdate(); } void UBApplicationController::hideDesktop() diff --git a/src/core/UBApplicationController.h b/src/core/UBApplicationController.h index 03ace3a9..c3cfb40d 100644 --- a/src/core/UBApplicationController.h +++ b/src/core/UBApplicationController.h @@ -53,12 +53,8 @@ class UBVersion; class UBSoftwareUpdate; class QNetworkAccessManager; class QNetworkReply; -class QHttpPart; class UBRightPalette; class UBOpenSankoreImporter; -class QScriptValue; -class QScriptEngine; -class QNetworkReply; class UBApplicationController : public QObject { @@ -158,8 +154,8 @@ class UBApplicationController : public QObject void checkAtLaunch(); private slots: - void updateRequestFinished(int id, bool error); - void updateHeaderReceived(QNetworkRequest header ); + void updateRequestFinished(QNetworkReply * reply); + protected: @@ -193,13 +189,10 @@ class UBApplicationController : public QObject bool mIsShowingDesktop; bool isNoUpdateDisplayed; - void checkUpdate (QString urlString = "http://get.openboard.org/update.json"); - QNetworkAccessManager *networkAccessManager; + void checkUpdate(const QUrl &url = QUrl()); + QNetworkAccessManager * mNetworkAccessManager; void downloadJsonFinished(QString updateString); - QHttpPart* mHttp; - QNetworkAccessManager qnam; - QNetworkReply *mHttpreply; }; #endif /* UBAPPLICATIONCONTROLLER_H_ */ diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index cccf87b7..4b657602 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -226,6 +226,7 @@ void UBSettings::init() appToolBarDisplayText = new UBSetting(this, "App", "ToolBarDisplayText", true); appEnableAutomaticSoftwareUpdates = new UBSetting(this, "App", "EnableAutomaticSoftwareUpdates", false); appEnableSoftwareUpdates = new UBSetting(this, "App", "EnableSoftwareUpdates", true); + appSoftwareUpdateURI = new UBSetting(this, "App", "SoftwareUpdateURI", "http://www.openboard.ch/update.json"); appToolBarOrientationVertical = new UBSetting(this, "App", "ToolBarOrientationVertical", false); appPreferredLanguage = new UBSetting(this,"App","PreferredLanguage", ""); diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index 9f024d57..4e3f0ec5 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -240,6 +240,7 @@ class UBSettings : public QObject UBSetting* appToolBarDisplayText; UBSetting* appEnableAutomaticSoftwareUpdates; UBSetting* appEnableSoftwareUpdates; + UBSetting* appSoftwareUpdateURI; UBSetting* appToolBarOrientationVertical; UBSetting* appPreferredLanguage; diff --git a/src/frameworks/UBVersion.cpp b/src/frameworks/UBVersion.cpp index a08c4fc7..b8916152 100644 --- a/src/frameworks/UBVersion.cpp +++ b/src/frameworks/UBVersion.cpp @@ -42,21 +42,32 @@ UBVersion::UBVersion(const QString &string) uint UBVersion::toUInt() const { + /* Based on semantic versioning, version numbers look like: + * Major.Minor.Patch-Type.Build + * + * To compare version numbers, the string is split into each part, and they are multiplied + * to give a number where the first two digits are the Major version, the next two are the + * Minor version, and so on. + * + * i.e if Major, Minor etc. are named A, B, C, D, E, the number will look like: + * AABBCCDDEE + */ + uint result = 0; - QStringList list = mString.split("."); + QStringList list = mString.split(QRegExp("[-\\.]")); switch (list.count()) { case 2: //short version 1.0 - result = (list.at(0).toUInt() * 1000000) + (list.at(1).toUInt() * 10000) + (Release * 100); + result = (list.at(0).toUInt() * 100000000) + (list.at(1).toUInt() * 1000000) + (Release * 100); break; case 3: //release version 1.0.0 - result = (list.at(0).toUInt() * 1000000) + (list.at(1).toUInt() * 10000) + (Release * 100) + list.at(2).toUInt(); + result = (list.at(0).toUInt() * 100000000) + (list.at(1).toUInt() * 1000000) + list.at(2).toUInt()*10000 + (Release * 100); break; - case 4:{ - //standard version 1.0.a/b/r.0 - uint releaseStage = list.at(2).startsWith("a") ? Alpha :(list.at(2).startsWith("b") ? Beta : ReleaseCandidate); - result = (list.at(0).toUInt() * 1000000) + (list.at(1).toUInt() * 10000) + (releaseStage * 100) + list.at(3).toUInt(); + case 5:{ + //standard version 1.0.0.a/b/rc.0 + uint releaseStage = list.at(3).startsWith("a") ? Alpha :(list.at(3).startsWith("b") ? Beta : ReleaseCandidate); + result = (list.at(0).toUInt() * 100000000) + (list.at(1).toUInt() * 1000000) + (list.at(2).toUInt() * 10000) + (releaseStage * 100) + list.at(4).toUInt(); break; } default: From dd10e24083a1a2a6b5632ea37769972f4acb4686 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 4 Mar 2017 21:40:01 -0500 Subject: [PATCH 036/134] Fix angle calculation in geometry tools --- src/frameworks/UBGeometryUtils.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/frameworks/UBGeometryUtils.cpp b/src/frameworks/UBGeometryUtils.cpp index aa1ab020..80d5e448 100644 --- a/src/frameworks/UBGeometryUtils.cpp +++ b/src/frameworks/UBGeometryUtils.cpp @@ -427,12 +427,12 @@ void UBGeometryUtils::crashPointList(QVector &points) } /** - * @brief Return the angle between three points + * @brief Return the angle in degrees between three points */ qreal UBGeometryUtils::angle(const QPointF& p1, const QPointF& p2, const QPointF& p3) { // Angle between three points, using the law of cosines: - // The angle at B equals arccos((a^2-b^2-c^2)/(2*a*c)), where a, b and c are the sides of the triangle + // The angle at B equals arccos((a^2-b^2+c^2)/(2*a*c)), where a, b and c are the sides of the triangle // opposite A, B and C, respectively qreal a, b, c, beta; @@ -440,7 +440,10 @@ qreal UBGeometryUtils::angle(const QPointF& p1, const QPointF& p2, const QPointF b = qSqrt(qPow(p1.x() - p3.x(), 2) + qPow(p1.y() - p3.y(), 2)); c = qSqrt(qPow(p1.x() - p2.x(), 2) + qPow(p1.y() - p2.y(), 2)); - beta = qAcos((a*a - b*b - c*c)/(2*a*c)); + if (a == 0 || c == 0) + beta = 3.14159; + else + beta = qAcos((a*a - b*b + c*c)/(2*a*c)); - return 2*3.14159*beta; + return 180.* beta/3.14159; } From ee5ad4a1427ca428de56532b57b92f5963a1ba4c Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 4 Mar 2017 21:40:39 -0500 Subject: [PATCH 037/134] Better calculation of angle between stroke points --- src/domain/UBGraphicsStroke.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index a2b66015..8218624d 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -246,7 +246,7 @@ UBGraphicsStroke* UBGraphicsStroke::simplify() QList::iterator b_it(it+1); while (b_it+1 != points.end()) { - qreal angle = qFabs(QLineF(it->first, b_it->first).angle() - QLineF(b_it->first, (b_it+1)->first).angle()); + qreal angle = qFabs(180-(UBGeometryUtils::angle(it->first, b_it->first, (b_it+1)->first))); qreal widthRatio = qMax(it->second, b_it->second)/qMin(it->second, b_it->second); if (widthRatio > thresholdWidthDifference) qDebug() << "Width ratio: " << widthRatio; @@ -282,7 +282,6 @@ UBGraphicsStroke* UBGraphicsStroke::simplify() if (hasAlpha()) { if (newStrokePoints.size() > 1 && i < points.size() - 1) { qreal angle = qFabs(UBGeometryUtils::angle(points[i-1].first, points[i].first, points[i+1].first)); - qDebug() << "Angle: " << angle; if (angle > 40 && angle < 320) drawCurve = true; } From aedebaf2dbb371c68fcebc75afd92a787299e1b4 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sun, 29 Jan 2017 18:35:06 -0500 Subject: [PATCH 038/134] Add "set as background" to frame menu for images Images (UBGraphicsPixmapitem and UBGraphicsSvgItem) can be set as background via the menu on their frame. Currently, the image is first centered and un-transformed before being set as background. The option in the frame appears for any UBGraphicsItem for which `data(UBGraphicsItemData::ItemCanBeSetAsBackground)` is true. This is (currently) only enabled for image items. --- src/core/UB.h | 1 + src/domain/UBGraphicsItemDelegate.cpp | 17 +++++++++++++++++ src/domain/UBGraphicsItemDelegate.h | 2 ++ src/domain/UBGraphicsPixmapItem.cpp | 2 ++ src/domain/UBGraphicsSvgItem.cpp | 2 ++ 5 files changed, 24 insertions(+) diff --git a/src/core/UB.h b/src/core/UB.h index bb197d95..0b9e285c 100644 --- a/src/core/UB.h +++ b/src/core/UB.h @@ -137,6 +137,7 @@ struct UBGraphicsItemData //Duplicating delegate's functions to make possible working with pure QGraphicsItem , ItemFlippable // (bool) , ItemRotatable // (bool) + , ItemCanBeSetAsBackground }; }; diff --git a/src/domain/UBGraphicsItemDelegate.cpp b/src/domain/UBGraphicsItemDelegate.cpp index f7f76f5c..c21b9bd1 100644 --- a/src/domain/UBGraphicsItemDelegate.cpp +++ b/src/domain/UBGraphicsItemDelegate.cpp @@ -596,6 +596,18 @@ void UBGraphicsItemDelegate::showHide(bool show) emit showOnDisplayChanged(show); } +void UBGraphicsItemDelegate::setAsBackground() +{ + UBGraphicsScene* scene = castUBGraphicsScene(); + QGraphicsItem* item = delegated(); + + if (scene && item) { + item->resetTransform(); + item->setPos(item->sceneBoundingRect().width()/-2., item->sceneBoundingRect().height()/-2.); + + scene->setAsBackgroundObject(item); + } +} void UBGraphicsItemDelegate::gotoContentSource() { @@ -681,6 +693,11 @@ void UBGraphicsItemDelegate::decorateMenu(QMenu* menu) showIcon.addPixmap(QPixmap(":/images/eyeClosed.svg"), QIcon::Normal, QIcon::Off); mShowOnDisplayAction->setIcon(showIcon); + if (delegated()->data(UBGraphicsItemData::ItemCanBeSetAsBackground).toBool()) { + mSetAsBackgroundAction = mMenu->addAction(tr("Set as background"), this, SLOT(setAsBackground())); + mSetAsBackgroundAction->setCheckable(false); + } + if (testUBFlags(GF_SHOW_CONTENT_SOURCE)) { mGotoContentSourceAction = menu->addAction(tr("Go to Content Source"), this, SLOT(gotoContentSource())); diff --git a/src/domain/UBGraphicsItemDelegate.h b/src/domain/UBGraphicsItemDelegate.h index ef9f1e0f..ad249dc1 100644 --- a/src/domain/UBGraphicsItemDelegate.h +++ b/src/domain/UBGraphicsItemDelegate.h @@ -343,6 +343,7 @@ class UBGraphicsItemDelegate : public QObject QAction* mLockAction; QAction* mShowOnDisplayAction; + QAction* mSetAsBackgroundAction; QAction* mGotoContentSourceAction; UBGraphicsDelegateFrame* mFrame; @@ -354,6 +355,7 @@ class UBGraphicsItemDelegate : public QObject UBGraphicsToolBarItem* mToolBarItem; protected slots: + virtual void setAsBackground(); virtual void gotoContentSource(); private: diff --git a/src/domain/UBGraphicsPixmapItem.cpp b/src/domain/UBGraphicsPixmapItem.cpp index 6a5e6072..b5dacc78 100644 --- a/src/domain/UBGraphicsPixmapItem.cpp +++ b/src/domain/UBGraphicsPixmapItem.cpp @@ -61,6 +61,8 @@ UBGraphicsPixmapItem::UBGraphicsPixmapItem(QGraphicsItem* parent) setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::ObjectItem)); //Necessary to set if we want z value to be assigned correctly setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); + setData(UBGraphicsItemData::ItemCanBeSetAsBackground, true); + setUuid(QUuid::createUuid()); //more logical solution is in creating uuid for element in element's constructor } diff --git a/src/domain/UBGraphicsSvgItem.cpp b/src/domain/UBGraphicsSvgItem.cpp index 81f81333..90c188ab 100644 --- a/src/domain/UBGraphicsSvgItem.cpp +++ b/src/domain/UBGraphicsSvgItem.cpp @@ -87,6 +87,8 @@ void UBGraphicsSvgItem::init() setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::ObjectItem)); //Necessary to set if we want z value to be assigned correctly + setData(UBGraphicsItemData::ItemCanBeSetAsBackground, true); + setUuid(QUuid::createUuid()); } From 881a1d5011ed57b1564018add6fc92823456e321 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sun, 30 Apr 2017 15:55:05 -0400 Subject: [PATCH 039/134] Add ability to undo/redo setting image as background --- src/domain/UBGraphicsItemDelegate.cpp | 14 ++++++++++++++ .../UBGraphicsItemTransformUndoCommand.cpp | 19 ++++++++++++++++++- .../UBGraphicsItemTransformUndoCommand.h | 5 ++++- src/domain/UBGraphicsScene.cpp | 15 +++++++++++++++ src/domain/UBGraphicsScene.h | 1 + 5 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/domain/UBGraphicsItemDelegate.cpp b/src/domain/UBGraphicsItemDelegate.cpp index c21b9bd1..99dec7cb 100644 --- a/src/domain/UBGraphicsItemDelegate.cpp +++ b/src/domain/UBGraphicsItemDelegate.cpp @@ -596,16 +596,30 @@ void UBGraphicsItemDelegate::showHide(bool show) emit showOnDisplayChanged(show); } +/** + * @brief Set delegate as background for the scene, replacing any existing background. + */ void UBGraphicsItemDelegate::setAsBackground() { UBGraphicsScene* scene = castUBGraphicsScene(); QGraphicsItem* item = delegated(); if (scene && item) { + startUndoStep(); + item->resetTransform(); item->setPos(item->sceneBoundingRect().width()/-2., item->sceneBoundingRect().height()/-2.); scene->setAsBackgroundObject(item); + + UBGraphicsItemTransformUndoCommand *uc = + new UBGraphicsItemTransformUndoCommand(mDelegated, + mPreviousPosition, + mPreviousTransform, + mPreviousZValue, + mPreviousSize, + true); + UBApplication::undoStack->push(uc); } } diff --git a/src/domain/UBGraphicsItemTransformUndoCommand.cpp b/src/domain/UBGraphicsItemTransformUndoCommand.cpp index fad0a3af..f280fd5b 100644 --- a/src/domain/UBGraphicsItemTransformUndoCommand.cpp +++ b/src/domain/UBGraphicsItemTransformUndoCommand.cpp @@ -30,12 +30,14 @@ #include "UBGraphicsItemTransformUndoCommand.h" #include "UBResizableGraphicsItem.h" #include "domain/UBItem.h" +#include "domain/UBGraphicsScene.h" #include "core/memcheck.h" UBGraphicsItemTransformUndoCommand::UBGraphicsItemTransformUndoCommand(QGraphicsItem* pItem, const QPointF& prevPos, const QTransform& prevTransform, const qreal& prevZValue, - const QSizeF& prevSize):UBUndoCommand() + const QSizeF& prevSize, bool setToBackground) + : UBUndoCommand() { mItem = pItem; mPreviousTransform = prevTransform; @@ -52,6 +54,8 @@ UBGraphicsItemTransformUndoCommand::UBGraphicsItemTransformUndoCommand(QGraphics if (resizableItem) mCurrentSize = resizableItem->size(); + + mSetToBackground = setToBackground; } UBGraphicsItemTransformUndoCommand::~UBGraphicsItemTransformUndoCommand() @@ -61,6 +65,13 @@ UBGraphicsItemTransformUndoCommand::~UBGraphicsItemTransformUndoCommand() void UBGraphicsItemTransformUndoCommand::undo() { + if (mSetToBackground) { + UBGraphicsScene* scene = dynamic_cast(mItem->scene()); + if (scene && scene->isBackgroundObject(mItem)) { + scene->unsetBackgroundObject(); + } + } + mItem->setPos(mPreviousPosition); mItem->setTransform(mPreviousTransform); mItem->setZValue(mPreviousZValue); @@ -73,6 +84,12 @@ void UBGraphicsItemTransformUndoCommand::undo() void UBGraphicsItemTransformUndoCommand::redo() { + if (mSetToBackground) { + UBGraphicsScene* scene = dynamic_cast(mItem->scene()); + if (scene) + scene->setAsBackgroundObject(mItem); + } + mItem->setPos(mCurrentPosition); mItem->setTransform(mCurrentTransform); mItem->setZValue(mCurrentZValue); diff --git a/src/domain/UBGraphicsItemTransformUndoCommand.h b/src/domain/UBGraphicsItemTransformUndoCommand.h index da67efad..9cd6b93a 100644 --- a/src/domain/UBGraphicsItemTransformUndoCommand.h +++ b/src/domain/UBGraphicsItemTransformUndoCommand.h @@ -42,7 +42,8 @@ class UBGraphicsItemTransformUndoCommand : public UBUndoCommand const QPointF& prevPos, const QTransform& prevTransform, const qreal& prevZValue, - const QSizeF& prevSize = QSizeF()); + const QSizeF& prevSize = QSizeF(), + bool setToBackground = false); virtual ~UBGraphicsItemTransformUndoCommand(); virtual int getType() const { return UBUndoType::undotype_GRAPHICITEMTRANSFORM; } @@ -63,6 +64,8 @@ class UBGraphicsItemTransformUndoCommand : public UBUndoCommand qreal mPreviousZValue; qreal mCurrentZValue; + bool mSetToBackground; + }; #endif /* UBGRAPHICSITEMTRANSFORMUNDOCOMMAND_H_ */ diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 162eba9d..efd58c41 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -1983,6 +1983,21 @@ QGraphicsItem* UBGraphicsScene::setAsBackgroundObject(QGraphicsItem* item, bool return item; } +void UBGraphicsScene::unsetBackgroundObject() +{ + if (!mBackgroundObject) + return; + + mBackgroundObject->setFlag(QGraphicsItem::ItemIsSelectable, true); + mBackgroundObject->setFlag(QGraphicsItem::ItemIsMovable, true); + mBackgroundObject->setAcceptedMouseButtons(Qt::LeftButton); + + // Item zLayer and Layer Type should be set by the caller of this function, as + // it may depend on the object type, where it was before, etc. + + mBackgroundObject = 0; +} + QRectF UBGraphicsScene::normalizedSceneRect(qreal ratio) { diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 74577250..544aa34c 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -174,6 +174,7 @@ class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem void addGroup(UBGraphicsGroupContainerItem *groupItem); QGraphicsItem* setAsBackgroundObject(QGraphicsItem* item, bool pAdaptTransformation = false, bool expand = false); + void unsetBackgroundObject(); QGraphicsItem* backgroundObject() const { From 0d7d9b0424c230266bbad2a15e1aa0cca8fcd735 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sun, 30 Apr 2017 16:09:26 -0400 Subject: [PATCH 040/134] Don't show the properties page (in library pane) for interactivities, applications and animations --- src/gui/UBFeaturesWidget.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui/UBFeaturesWidget.cpp b/src/gui/UBFeaturesWidget.cpp index fe3520c7..b826ed02 100644 --- a/src/gui/UBFeaturesWidget.cpp +++ b/src/gui/UBFeaturesWidget.cpp @@ -174,7 +174,12 @@ void UBFeaturesWidget::currentSelected(const QModelIndex ¤t) // } else if (feature.getType() == FEATURE_SEARCH) { // centralWidget->showElement(feature, UBFeaturesCentralWidget::FeaturesWebView); - } else { + } + // Don't show the properties page for interactivities, applications and animations + else if (feature.getType() != FEATURE_INTERACTIVE + && feature.getType() != FEATURE_INTERNAL + && feature.getType() != FEATURE_FLASH) + { centralWidget->showElement(feature, UBFeaturesCentralWidget::FeaturePropertiesList); mActionBar->setCurrentState( IN_PROPERTIES ); } From 123ebf1d957e48227b0819d8236cba57aa52a0d2 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 9 Sep 2017 13:30:51 -0400 Subject: [PATCH 041/134] Improved drawing of end of current stroke Distance between the last drawn point and the current point is calculated to be able to discard very short stroke segments (i.e we only add to the current stroke if the input device has moved more than a certain distance since the last drawn point). This commit moves this code from the stroke to the scene, which allows to calculate distance more accurately: it is now calculated as the total, absolute distance traveled since the last point, rather than simply the length of a line between the last point and current one. --- src/domain/UBGraphicsScene.cpp | 21 +++++++++++++++++---- src/domain/UBGraphicsScene.h | 1 + src/domain/UBGraphicsStroke.cpp | 8 -------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 9b6a1958..4327a495 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -561,9 +561,22 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres interpolator = UBInterpolator::Bezier; } - QList > newPoints = mCurrentStroke->addPoint(scenePos, width, interpolator); - if (newPoints.length() > 1) { - drawCurve(newPoints); + + // Don't draw segments smaller than a certain length. This can help with performance + // (less polygons to draw) but mostly with making the curve look smooth. + + qreal antiScaleRatio = 1./(UBApplication::boardController->systemScaleFactor() * UBApplication::boardController->currentZoom()); + qreal MIN_DISTANCE = 10*antiScaleRatio; // arbitrary. Move to settings if relevant. + qreal distance = QLineF(mPreviousPoint, scenePos).length(); + + mDistanceFromLastStrokePoint += distance; + + if (mDistanceFromLastStrokePoint > MIN_DISTANCE) { + QList > newPoints = mCurrentStroke->addPoint(scenePos, width, interpolator); + if (newPoints.length() > 1) + drawCurve(newPoints); + + mDistanceFromLastStrokePoint = 0; } if (interpolator == UBInterpolator::Bezier) { @@ -577,7 +590,7 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres mTempPolygon = NULL; } - QPointF lastDrawnPoint = newPoints.last().first; + QPointF lastDrawnPoint = mCurrentStroke->points().last().first; mTempPolygon = lineToPolygonItem(QLineF(lastDrawnPoint, scenePos), mPreviousWidth, width); addItem(mTempPolygon); diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 18a8c05a..84d01514 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -429,6 +429,7 @@ public slots: QPointF mPreviousPoint; qreal mPreviousWidth; + qreal mDistanceFromLastStrokePoint; QList mPreviousPolygonItems; diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index 8218624d..4456b26d 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -102,14 +102,6 @@ QList > UBGraphicsStroke::addPoint(const QPointF& point, q // The curve we are interpolating is not between two drawn points; // it is between the midway points of the second-to-last and last point, and last and current point. - // Don't draw segments smaller than a certain length. This can help with performance - // (less polygons to draw) but mostly with keeping the curve smooth. - qreal MIN_DISTANCE = 3*mAntiScaleRatio; - qreal distance = QLineF(mReceivedPoints.last().first, newPoint.first).length(); - - if (distance < MIN_DISTANCE) { - return QList() << mDrawnPoints.last(); - } // The first segment is just a straight line to the first midway point if (n == 1) { From 1a075c057d891928294493b4222fc7b18afe5eac Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 9 Sep 2017 14:26:44 -0400 Subject: [PATCH 042/134] Moved bezier calculations to UBGeometryUtils -> also deleted obsolete UBInterpolator classes --- src/domain/UBGraphicsScene.cpp | 11 +++---- src/domain/UBGraphicsStroke.cpp | 24 ++++++++------ src/domain/UBGraphicsStroke.h | 3 +- src/frameworks/UBGeometryUtils.cpp | 28 ++++++++++++++++ src/frameworks/UBGeometryUtils.h | 2 ++ src/frameworks/UBInterpolator.cpp | 53 ------------------------------ src/frameworks/UBInterpolator.h | 45 ------------------------- src/frameworks/frameworks.pri | 6 ++-- 8 files changed, 52 insertions(+), 120 deletions(-) delete mode 100644 src/frameworks/UBInterpolator.cpp delete mode 100644 src/frameworks/UBInterpolator.h diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 4327a495..c64815f2 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -37,7 +37,6 @@ #include "frameworks/UBGeometryUtils.h" #include "frameworks/UBPlatformUtils.h" -#include "frameworks/UBInterpolator.h" #include "core/UBApplication.h" #include "core/UBSettings.h" @@ -552,13 +551,13 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres drawLineTo(position, width, true); } - else{ - UBInterpolator::InterpolationMethod interpolator = UBInterpolator::NoInterpolation; + else { + bool interpolate = false; if ((currentTool == UBStylusTool::Pen && UBSettings::settings()->boardInterpolatePenStrokes->get().toBool()) || (currentTool == UBStylusTool::Marker && UBSettings::settings()->boardInterpolateMarkerStrokes->get().toBool())) { - interpolator = UBInterpolator::Bezier; + interpolate = true; } @@ -572,14 +571,14 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres mDistanceFromLastStrokePoint += distance; if (mDistanceFromLastStrokePoint > MIN_DISTANCE) { - QList > newPoints = mCurrentStroke->addPoint(scenePos, width, interpolator); + QList > newPoints = mCurrentStroke->addPoint(scenePos, width, interpolate); if (newPoints.length() > 1) drawCurve(newPoints); mDistanceFromLastStrokePoint = 0; } - if (interpolator == UBInterpolator::Bezier) { + if (interpolate) { // Bezier curves aren't drawn all the way to the scenePos (they stop halfway between the previous and // current scenePos), so we add a line from the last drawn position in the stroke and the // scenePos, to make the drawing feel more responsive. This line is then deleted if a new segment is diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index 4456b26d..9122bc54 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -77,9 +77,17 @@ QList UBGraphicsStroke::polygons() const /** * @brief Add a point to the curve, interpolating extra points if required - * @return The points (or point, if none were interpolated) that were added + * @param point The position of the point to add + * @param width The width of the stroke at that point. + * @param interpolate If true, a Bézier curve will be drawn rather than a straight line + * @return A list containing the last point drawn plus the point(s) that were added + * + * This method should be called when a new point is given by the input method (mouse, pen or other), and the points that are returned + * should be used to draw the actual stroke on-screen. This is because if interpolation (bézier curves) are to be used, the points to draw + * do not correspond to the points that were given by the input method. + * */ -QList > UBGraphicsStroke::addPoint(const QPointF& point, qreal width, UBInterpolator::InterpolationMethod interpolationMethod) +QList > UBGraphicsStroke::addPoint(const QPointF& point, qreal width, bool interpolate) { strokePoint newPoint(point, width); @@ -88,17 +96,17 @@ QList > UBGraphicsStroke::addPoint(const QPointF& point, q if (n == 0) { mReceivedPoints << newPoint; mDrawnPoints << newPoint; - return QList(); + return QList() << newPoint; } - if (interpolationMethod == UBInterpolator::NoInterpolation) { + if (!interpolate) { strokePoint lastPoint = mReceivedPoints.last(); mReceivedPoints << newPoint; mDrawnPoints << newPoint; return QList() << lastPoint << newPoint; } - else if (interpolationMethod == UBInterpolator::Bezier) { + else { // The curve we are interpolating is not between two drawn points; // it is between the midway points of the second-to-last and last point, and last and current point. @@ -118,14 +126,10 @@ QList > UBGraphicsStroke::addPoint(const QPointF& point, q QPointF p1 = mReceivedPoints[mReceivedPoints.size() - 1].first; QPointF p2 = point; - UBQuadraticBezier bz; - QPointF startPoint = (p1+p0)/2.0; QPointF endPoint = (p2+p1)/2.0; - bz.setPoints(startPoint, p1, endPoint); - - QList calculated = bz.getPoints(10); + QList calculated = UBGeometryUtils::quadraticBezier(startPoint, p1, endPoint, 10); QList newPoints; qreal startWidth = mDrawnPoints.last().second; diff --git a/src/domain/UBGraphicsStroke.h b/src/domain/UBGraphicsStroke.h index 918ec894..930d9546 100644 --- a/src/domain/UBGraphicsStroke.h +++ b/src/domain/UBGraphicsStroke.h @@ -33,7 +33,6 @@ #include #include "core/UB.h" -#include "frameworks/UBInterpolator.h" @@ -60,7 +59,7 @@ class UBGraphicsStroke void clear(); - QList > addPoint(const QPointF& point, qreal width, UBInterpolator::InterpolationMethod interpolationMethod = UBInterpolator::NoInterpolation); + QList > addPoint(const QPointF& point, qreal width, bool interpolate = false); const QList >& points() { return mDrawnPoints; } diff --git a/src/frameworks/UBGeometryUtils.cpp b/src/frameworks/UBGeometryUtils.cpp index 80d5e448..7a9a4cbc 100644 --- a/src/frameworks/UBGeometryUtils.cpp +++ b/src/frameworks/UBGeometryUtils.cpp @@ -447,3 +447,31 @@ qreal UBGeometryUtils::angle(const QPointF& p1, const QPointF& p2, const QPointF return 180.* beta/3.14159; } + + + +/** + * @brief Calculate a quadratic Bézier curve and return it in the form of a list of points + * @param p0 The start point of the curve + * @param p1 The control point of the curve + * @param p2 The end point of the curve + * @param nPoints The number of points by which to approximate the curve, i.e. the length of the returned list + * @return A list of points that can be used to draw the curve. + */ +QList UBGeometryUtils::quadraticBezier(const QPointF& p0, const QPointF& p1, const QPointF& p2, unsigned int nPoints) +{ + QPainterPath path(p0); + path.quadTo(p1, p2); + + QList points; + + if (nPoints <= 1) + return points; + + for (unsigned int i(0); i <= nPoints; ++i) { + qreal percent = qreal(i)/qreal(nPoints); + points << path.pointAtPercent(percent); + } + + return points; +} diff --git a/src/frameworks/UBGeometryUtils.h b/src/frameworks/UBGeometryUtils.h index f4174709..6e2992cc 100644 --- a/src/frameworks/UBGeometryUtils.h +++ b/src/frameworks/UBGeometryUtils.h @@ -57,6 +57,8 @@ class UBGeometryUtils static qreal angle(const QPointF& p1, const QPointF& p2, const QPointF& p3); + static QList quadraticBezier(const QPointF& p0, const QPointF& p1, const QPointF& p2, unsigned int nPoints); + const static int centimeterGraduationHeight; const static int halfCentimeterGraduationHeight; const static int millimeterGraduationHeight; diff --git a/src/frameworks/UBInterpolator.cpp b/src/frameworks/UBInterpolator.cpp deleted file mode 100644 index 3b75da12..00000000 --- a/src/frameworks/UBInterpolator.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "UBInterpolator.h" - -UBInterpolator::UBInterpolator() -{ -} - -UBInterpolator::~UBInterpolator() -{ -} - -UBQuadraticBezier::UBQuadraticBezier() -{ - mPath = 0; -} - -UBQuadraticBezier::~UBQuadraticBezier() -{ - if (mPath) - delete mPath; -} - -void UBQuadraticBezier::setPoints(QList points) -{ - setPoints(points[0], points[1], points[2]); - -} - -void UBQuadraticBezier::setPoints(QPointF start, QPointF control, QPointF end) -{ - mPath = new QPainterPath(start); - mPath->quadTo(control, end); -} - -/** - * @brief Return n points along the curve, including start and end points (thus n should be larger than or equal to 2). - * - * The higher n, the more accurate the resulting curve will be. - */ -QList UBQuadraticBezier::getPoints(int n) -{ - QList points; - - if (n <= 1) - return points; - - for (int i(0); i <= n; ++i) { - qreal percent = qreal(i)/qreal(n); - - points << mPath->pointAtPercent(percent); - } - - return points; -} diff --git a/src/frameworks/UBInterpolator.h b/src/frameworks/UBInterpolator.h deleted file mode 100644 index 9a714488..00000000 --- a/src/frameworks/UBInterpolator.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef UBINTERPOLATOR_H -#define UBINTERPOLATOR_H - -#include - -class UBInterpolator -{ - /* Abstract class representing an interpolator */ - -public: - enum InterpolationMethod { - NoInterpolation, - //SimpleSpline, - //CatmullRom, - Bezier - }; - - UBInterpolator(); - virtual ~UBInterpolator(); - - virtual void setPoints(QList points) = 0; - //virtual double y(double x) {} - -}; - -class UBQuadraticBezier : public UBInterpolator -{ - -public: - UBQuadraticBezier(); - virtual ~UBQuadraticBezier(); - - virtual void setPoints(QList points); - void setPoints(QPointF start, QPointF control, QPointF end); - - //virtual double y(double x); - - QList getPoints(int n); - -private: - - QPainterPath* mPath; -}; - -#endif // UBINTERPOLATOR_H diff --git a/src/frameworks/frameworks.pri b/src/frameworks/frameworks.pri index 8d6d435d..74d6edbb 100644 --- a/src/frameworks/frameworks.pri +++ b/src/frameworks/frameworks.pri @@ -6,8 +6,7 @@ HEADERS += src/frameworks/UBGeometryUtils.h \ src/frameworks/UBVersion.h \ src/frameworks/UBCoreGraphicsScene.h \ src/frameworks/UBCryptoUtils.h \ - src/frameworks/UBBase32.h \ - $$PWD/UBInterpolator.h + src/frameworks/UBBase32.h SOURCES += src/frameworks/UBGeometryUtils.cpp \ src/frameworks/UBPlatformUtils.cpp \ @@ -16,8 +15,7 @@ SOURCES += src/frameworks/UBGeometryUtils.cpp \ src/frameworks/UBVersion.cpp \ src/frameworks/UBCoreGraphicsScene.cpp \ src/frameworks/UBCryptoUtils.cpp \ - src/frameworks/UBBase32.cpp \ - $$PWD/UBInterpolator.cpp + src/frameworks/UBBase32.cpp win32 { From 5f65292d114ce02fca6233420b4c3b347559c3c0 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 16 Sep 2017 19:01:00 -0400 Subject: [PATCH 043/134] Fix for qAcos occasionally returning nan for values of (not quite) -1 or +1 --- src/frameworks/UBGeometryUtils.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/frameworks/UBGeometryUtils.cpp b/src/frameworks/UBGeometryUtils.cpp index 7a9a4cbc..01c1fe1a 100644 --- a/src/frameworks/UBGeometryUtils.cpp +++ b/src/frameworks/UBGeometryUtils.cpp @@ -443,7 +443,8 @@ qreal UBGeometryUtils::angle(const QPointF& p1, const QPointF& p2, const QPointF if (a == 0 || c == 0) beta = 3.14159; else - beta = qAcos((a*a - b*b + c*c)/(2*a*c)); + beta = qAcos(std::max(-1.0, std::min(1.0, (a*a - b*b + c*c)/(2*a*c)))); + return 180.* beta/3.14159; } From d67046f00393955a87308279dbb453fba92feb4d Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 16 Sep 2017 19:02:03 -0400 Subject: [PATCH 044/134] Small improvements to stroke simplifying --- src/domain/UBGraphicsStroke.cpp | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index 9122bc54..49f82b2f 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -244,8 +244,6 @@ UBGraphicsStroke* UBGraphicsStroke::simplify() while (b_it+1 != points.end()) { qreal angle = qFabs(180-(UBGeometryUtils::angle(it->first, b_it->first, (b_it+1)->first))); qreal widthRatio = qMax(it->second, b_it->second)/qMin(it->second, b_it->second); - if (widthRatio > thresholdWidthDifference) - qDebug() << "Width ratio: " << widthRatio; if (angle < thresholdAngle && widthRatio < thresholdWidthDifference) b_it = points.erase(b_it); @@ -259,7 +257,8 @@ UBGraphicsStroke* UBGraphicsStroke::simplify() it = b_it; } - // Next, we iterate over the new points to build the polygons that make up the stroke + // Next, we iterate over the new points to build the polygons that make up the stroke. + // A new polygon is created every time drawCurve is true. QList newPolygons; QList newStrokePoints; @@ -270,29 +269,26 @@ UBGraphicsStroke* UBGraphicsStroke::simplify() newStrokePoints << points[i]; - // When a polygon is transparent and it overlaps with itself, it is *sometimes* filled incorrectly. - // Limiting the size of the polygons, and creating new ones when the angle between consecutive points is above a - // certain threshold helps mitigate this issue. - // TODO: fix fill issue + // Limiting the size of the polygons, and creating new ones when there is a sharp angle between + // consecutive point helps with two issues: + // 1. When a polygon is transparent and it overlaps with itself, it is *sometimes* filled incorrectly. + // 2. This way of simplifying strokes resuls in sharp, rather than rounded, corners when there is a sharp angle + // in the stroke - if (hasAlpha()) { - if (newStrokePoints.size() > 1 && i < points.size() - 1) { - qreal angle = qFabs(UBGeometryUtils::angle(points[i-1].first, points[i].first, points[i+1].first)); - if (angle > 40 && angle < 320) - drawCurve = true; - } - - if (newStrokePoints.size() % 20 == 0) + if (newStrokePoints.size() > 1 && i < points.size() - 1) { + qreal angle = qFabs(UBGeometryUtils::angle(points[i-1].first, points[i].first, points[i+1].first)); + if (angle < 150) // arbitrary threshold, change if necessary drawCurve = true; } + if (hasAlpha() && newStrokePoints.size() % 20 == 0) + drawCurve = true; if (drawCurve) { UBGraphicsPolygonItem* poly = mScene->polygonToPolygonItem(UBGeometryUtils::curveToPolygon(newStrokePoints, true, true)); - //poly->setColor(QColor(rand()%256, rand()%256, rand()%256, poly->brush().color().alpha())); + //poly->setColor(QColor(rand()%256, rand()%256, rand()%256, poly->brush().color().alpha())); // useful for debugging // Subtract overlapping polygons if the stroke is translucent - if (!poly->brush().isOpaque()) { foreach(UBGraphicsPolygonItem* prev, newPolygons) poly->subtract(prev); From 79d240319201c5c91af66b9d03f4eebd73bd65fc Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 16 Sep 2017 19:05:16 -0400 Subject: [PATCH 045/134] Removed GUI settings for stroke interpolation & simplifying --- resources/forms/brushProperties.ui | 148 +++++++++------------------ src/core/UBPreferencesController.cpp | 8 -- 2 files changed, 50 insertions(+), 106 deletions(-) diff --git a/resources/forms/brushProperties.ui b/resources/forms/brushProperties.ui index 2866714e..4f9d7268 100644 --- a/resources/forms/brushProperties.ui +++ b/resources/forms/brushProperties.ui @@ -20,6 +20,56 @@ QFrame::Plain + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Pen is Pressure Sensitive + + + + + + + Qt::Horizontal + + + + 198 + 20 + + + + + + + @@ -447,104 +497,6 @@ - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - Pen is Pressure Sensitive - - - - - - - Qt::Horizontal - - - - 198 - 20 - - - - - - - - - - - - - Smooth strokes (experimental) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Simplify strokes after drawing (experimental) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - diff --git a/src/core/UBPreferencesController.cpp b/src/core/UBPreferencesController.cpp index 4bd2bd75..8e787e56 100644 --- a/src/core/UBPreferencesController.cpp +++ b/src/core/UBPreferencesController.cpp @@ -165,8 +165,6 @@ void UBPreferencesController::wire() connect(mPenProperties->mediumSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mPenProperties->strongSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mPenProperties->pressureSensitiveCheckBox, SIGNAL(clicked(bool)), settings, SLOT(setPenPressureSensitive(bool))); - connect(mPenProperties->interpolateStrokesCheckBox, SIGNAL(clicked(bool)), settings->boardInterpolatePenStrokes, SLOT(setBool(bool))); - connect(mPenProperties->simplifyStrokesCheckBox, SIGNAL(clicked(bool)), settings->boardSimplifyPenStrokes, SLOT(setBool(bool))); // marker QList markerLightBackgroundColors = settings->boardMarkerLightBackgroundColors->colors(); @@ -184,8 +182,6 @@ void UBPreferencesController::wire() connect(mMarkerProperties->mediumSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mMarkerProperties->strongSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mMarkerProperties->pressureSensitiveCheckBox, SIGNAL(clicked(bool)), settings, SLOT(setMarkerPressureSensitive(bool))); - connect(mMarkerProperties->interpolateStrokesCheckBox, SIGNAL(clicked(bool)), settings->boardInterpolateMarkerStrokes, SLOT(setBool(bool))); - connect(mMarkerProperties->simplifyStrokesCheckBox, SIGNAL(clicked(bool)), settings->boardSimplifyMarkerStrokes, SLOT(setBool(bool))); connect(mMarkerProperties->opacitySlider, SIGNAL(valueChanged(int)), this, SLOT(opacitySliderChanged(int))); // about tab @@ -233,16 +229,12 @@ void UBPreferencesController::init() mPenProperties->mediumSlider->setValue(settings->boardPenMediumWidth->get().toDouble() * sSliderRatio); mPenProperties->strongSlider->setValue(settings->boardPenStrongWidth->get().toDouble() * sSliderRatio); mPenProperties->pressureSensitiveCheckBox->setChecked(settings->boardPenPressureSensitive->get().toBool()); - mPenProperties->interpolateStrokesCheckBox->setChecked(settings->boardInterpolatePenStrokes->get().toBool()); - mPenProperties->simplifyStrokesCheckBox->setChecked(settings->boardSimplifyPenStrokes->get().toBool()); // marker tab mMarkerProperties->fineSlider->setValue(settings->boardMarkerFineWidth->get().toDouble() * sSliderRatio); mMarkerProperties->mediumSlider->setValue(settings->boardMarkerMediumWidth->get().toDouble() * sSliderRatio); mMarkerProperties->strongSlider->setValue(settings->boardMarkerStrongWidth->get().toDouble() * sSliderRatio); mMarkerProperties->pressureSensitiveCheckBox->setChecked(settings->boardMarkerPressureSensitive->get().toBool()); - mMarkerProperties->interpolateStrokesCheckBox->setChecked(settings->boardInterpolateMarkerStrokes->get().toBool()); - mMarkerProperties->simplifyStrokesCheckBox->setChecked(settings->boardSimplifyMarkerStrokes->get().toBool()); mMarkerProperties->opacitySlider->setValue(settings->boardMarkerAlpha->get().toDouble() * 100); From 5ac37603daf6a4068edbbd3bc1e75eb69caf2423 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 16 Sep 2017 19:44:41 -0400 Subject: [PATCH 046/134] Hide library pane's detail view for local items Web results still show the details which include some metadata about the image retrieved, for example. This is now a setting so it can easily be re-enabled if desired (which could be useful especially if we decide to also display metadata of local items) --- src/core/UBSettings.cpp | 2 ++ src/core/UBSettings.h | 2 ++ src/gui/UBFeaturesWidget.cpp | 6 ++---- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index e00a9b38..1e2601be 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -409,6 +409,8 @@ void UBSettings::init() documentThumbnailWidth = new UBSetting(this, "Document", "ThumbnailWidth", UBSettings::defaultThumbnailWidth); + libraryShowDetailsForLocalItems = new UBSetting(this, "Library", "ShowDetailsForLocalItems", false); + imageThumbnailWidth = new UBSetting(this, "Library", "ImageThumbnailWidth", UBSettings::defaultImageWidth); videoThumbnailWidth = new UBSetting(this, "Library", "VideoThumbnailWidth", UBSettings::defaultVideoWidth); shapeThumbnailWidth = new UBSetting(this, "Library", "ShapeThumbnailWidth", UBSettings::defaultShapeWidth); diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index aba55749..84ae5667 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -364,6 +364,8 @@ class UBSettings : public QObject UBSetting* gipThumbnailWidth; UBSetting* soundThumbnailWidth; + UBSetting* libraryShowDetailsForLocalItems; + UBSetting* rightLibPaletteBoardModeWidth; UBSetting* rightLibPaletteBoardModeIsCollapsed; UBSetting* rightLibPaletteDesktopModeWidth; diff --git a/src/gui/UBFeaturesWidget.cpp b/src/gui/UBFeaturesWidget.cpp index b826ed02..b5ffb0a0 100644 --- a/src/gui/UBFeaturesWidget.cpp +++ b/src/gui/UBFeaturesWidget.cpp @@ -175,10 +175,8 @@ void UBFeaturesWidget::currentSelected(const QModelIndex ¤t) // centralWidget->showElement(feature, UBFeaturesCentralWidget::FeaturesWebView); } - // Don't show the properties page for interactivities, applications and animations - else if (feature.getType() != FEATURE_INTERACTIVE - && feature.getType() != FEATURE_INTERNAL - && feature.getType() != FEATURE_FLASH) + + if (UBSettings::settings()->libraryShowDetailsForLocalItems->get().toBool() == true) { centralWidget->showElement(feature, UBFeaturesCentralWidget::FeaturePropertiesList); mActionBar->setCurrentState( IN_PROPERTIES ); From e61d2955a1fc996cae8cb8e5d6d6c722c7cdee70 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 16 Sep 2017 19:46:19 -0400 Subject: [PATCH 047/134] Fix for Data.AbulEdu search results not showing details (metadata,..) --- resources/library/search/Data AbulEdu.wgs/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/library/search/Data AbulEdu.wgs/index.html b/resources/library/search/Data AbulEdu.wgs/index.html index 7f03fa99..498215b2 100644 --- a/resources/library/search/Data AbulEdu.wgs/index.html +++ b/resources/library/search/Data AbulEdu.wgs/index.html @@ -212,7 +212,7 @@ }); ( $(".imgContainer").live("click",function(){ - abuledu.sendFileMetadata(createMetaData($(this))); + sankore.sendFileMetadata(createMetaData($(this))); })); /*$(window).resize(function(){ From 6ba89a09d39f1f8cd8c0031c4694ec56e4307aaf Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 16 Sep 2017 19:53:11 -0400 Subject: [PATCH 048/134] Commented out debug messages --- src/domain/UBGraphicsStroke.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index 49f82b2f..7349e70b 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -212,7 +212,7 @@ UBGraphicsStroke* UBGraphicsStroke::simplify() newStroke->mDrawnPoints = QList(mDrawnPoints); QList& points = newStroke->mDrawnPoints; - qDebug() << "Simplifying. Before: " << points.size() << " points and " << polygons().size() << " polygons"; + //qDebug() << "Simplifying. Before: " << points.size() << " points and " << polygons().size() << " polygons"; /* Basic simplifying algorithm: consider A, B and C the current point and the two following ones. * If the angle between (AB) and (BC) is lower than a certain threshold, @@ -321,7 +321,7 @@ UBGraphicsStroke* UBGraphicsStroke::simplify() poly->setStroke(newStroke); } - qDebug() << "After: " << points.size() << " points and " << newStroke->polygons().size() << " polygons"; + //qDebug() << "After: " << points.size() << " points and " << newStroke->polygons().size() << " polygons"; return newStroke; } From bde39f95d5ff85727fb4fba1ff8659b9cd95303e Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 16 Sep 2017 20:07:37 -0400 Subject: [PATCH 049/134] Updated bundled config file with new settings --- resources/etc/OpenBoard.config | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/resources/etc/OpenBoard.config b/resources/etc/OpenBoard.config index c332d35a..2c505d04 100644 --- a/resources/etc/OpenBoard.config +++ b/resources/etc/OpenBoard.config @@ -1,6 +1,7 @@ [App] AngleTolerance=4 -EnableAutomaticSoftwareUpdates=false +EnableAutomaticSoftwareUpdates=true +EnableSoftwareUpdates=true EnableStartupHints=true FavoriteToolURIs=openboardtool://openboard/mask, openboardtool://ruler, openboardtool://compass, openboardtool://protractor, openboardtool://triangle, openboardtool://magnifier, openboardtool://cache IsInSoftwareUpdateProcess=false @@ -9,8 +10,9 @@ LastSessionPageIndex=0 LookForOpenSankoreInstall=true OnlineUserName= PageCacheSize=20 -PreferredLanguage= +PreferredLanguage=fr_CH ProductWebAddress=http://www.openboard.ch +SoftwareUpdateURL=http://www.openboard.ch/update.json StartMode= SwapControlAndDisplayScreens=false ToolBarDisplayText=true @@ -22,11 +24,14 @@ UseSystemOnScreenKeyboard=true [Board] AutoSaveIntervalInMinutes=3 -CrossedBackground=0 +CrossColorDarkBackground=#C8C0C0C0 +CrossColorLightBackground=#A5E1FF DarkBackground=0 DefaultPageSize=@Size(1280 960) EraserCircleWidthIndex=1 FeatureSliderPosition=40 +InterpolateMarkerStrokes=true +InterpolatePenStrokes=true KeyboardPaletteKeyBtnSize=16x16 LeftLibPaletteBoardModeIsCollapsed=true LeftLibPaletteBoardModeWidth=270 @@ -59,7 +64,12 @@ RightLibPaletteDesktopModeIsCollapsed=true RightLibPaletteDesktopModeWidth=270 ShowEraserPreviewCircle=true ShowMarkerPreviewCircle=true +ShowPenPreviewCircle=true ShowToolsPalette=false +SimplifyMarkerStrokes=true +SimplifyPenStrokes=true +SimplifyPenStrokesThresholdAngle=3 +SimplifyPenStrokesThresholdWidthDifference=2 StartupKeyboardLocale=0 UseHighResTabletEvent=true ZoomFactor=1.4099999999999999 @@ -89,6 +99,7 @@ InteractivitiesDirectory=./library/interactivities LibIconSize=80 ShapeDirectory=./library/shape ShapeThumbnailWidth=50 +ShowDetailsForLocalItems=false SoundThumbnailWidth=50 VideoThumbnailWidth=80 VideosDirectory=./library/videos @@ -123,7 +134,7 @@ AddBookmarkURL="http://www.myuniboard.com/bookmarks/save/?url=" BookmarksPage=http://www.myuniboard.com HistoryLimit=15 Homepage=http://www.openboard.ch -ShowAddBookmarkButton=false +ShowAddBookmarkButton=true ShowPageImediatelyOnMirroredScreen=false UseExternalBrowser=false From 86ced718d94dc04edf166fe5d0c825dd02b8e95f Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 16 Sep 2017 21:12:08 -0400 Subject: [PATCH 050/134] Fix for detail view of library pane appearing also for folders (fixes commit 5ac37603) --- src/gui/UBFeaturesWidget.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/gui/UBFeaturesWidget.cpp b/src/gui/UBFeaturesWidget.cpp index b5ffb0a0..5667024d 100644 --- a/src/gui/UBFeaturesWidget.cpp +++ b/src/gui/UBFeaturesWidget.cpp @@ -176,8 +176,7 @@ void UBFeaturesWidget::currentSelected(const QModelIndex ¤t) } - if (UBSettings::settings()->libraryShowDetailsForLocalItems->get().toBool() == true) - { + else if (UBSettings::settings()->libraryShowDetailsForLocalItems->get().toBool() == true) { centralWidget->showElement(feature, UBFeaturesCentralWidget::FeaturePropertiesList); mActionBar->setCurrentState( IN_PROPERTIES ); } From bf0d6fe1e5e0e13ac2ca7599bb4b657ec8a9db40 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 16 Sep 2017 21:13:13 -0400 Subject: [PATCH 051/134] Removed 'Set as background' button for images, since that feature is now accessible from the image menu on the board --- src/gui/UBFeaturesWidget.cpp | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/gui/UBFeaturesWidget.cpp b/src/gui/UBFeaturesWidget.cpp index 5667024d..444eacff 100644 --- a/src/gui/UBFeaturesWidget.cpp +++ b/src/gui/UBFeaturesWidget.cpp @@ -867,7 +867,6 @@ UBFeatureProperties::UBFeatureProperties( QWidget *parent, const char *name ) : , mpButtonLayout(NULL) , mpAddPageButton(NULL) , mpAddToLibButton(NULL) - , mpSetAsBackgroundButton(NULL) , mpObjInfoLabel(NULL) , mpObjInfos(NULL) , mpThumbnail(NULL) @@ -899,10 +898,6 @@ UBFeatureProperties::UBFeatureProperties( QWidget *parent, const char *name ) : mpAddPageButton->setText(tr("Add to page")); mpButtonLayout->addWidget(mpAddPageButton); - mpSetAsBackgroundButton = new UBFeatureItemButton(); - mpSetAsBackgroundButton->setText(tr("Set as background")); - mpButtonLayout->addWidget(mpSetAsBackgroundButton); - mpAddToLibButton = new UBFeatureItemButton(); mpAddToLibButton->setText(tr("Add to library")); mpButtonLayout->addWidget(mpAddToLibButton); @@ -924,7 +919,6 @@ UBFeatureProperties::UBFeatureProperties( QWidget *parent, const char *name ) : mpLayout->setMargin(0); connect( mpAddPageButton, SIGNAL(clicked()), this, SLOT(onAddToPage()) ); - connect( mpSetAsBackgroundButton, SIGNAL( clicked() ), this, SLOT( onSetAsBackground() ) ); connect( mpAddToLibButton, SIGNAL( clicked() ), this, SLOT(onAddToLib() ) ); } @@ -955,11 +949,6 @@ UBFeatureProperties::~UBFeatureProperties() delete mpAddPageButton; mpAddPageButton = NULL; } - if ( mpSetAsBackgroundButton ) - { - delete mpSetAsBackgroundButton; - mpSetAsBackgroundButton = NULL; - } if ( mpAddToLibButton ) { delete mpAddToLibButton; @@ -1047,26 +1036,10 @@ void UBFeatureProperties::showElement(const UBFeature &elem) if ( UBApplication::isFromWeb( elem.getFullPath().toString() ) ) { mpAddToLibButton->show(); - if( elem.getMetadata()["Type"].toLower().contains("image") ) - { - mpSetAsBackgroundButton->show(); - } - else - { - mpSetAsBackgroundButton->hide(); - } } else { mpAddToLibButton->hide(); - if (UBFileSystemUtils::mimeTypeFromFileName( elem.getFullPath().toLocalFile() ).contains("image")) - { - mpSetAsBackgroundButton->show(); - } - else - { - mpSetAsBackgroundButton->hide(); - } } } From f1f96fd3acdbf380fefe5de1d191bdd77017bb06 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sat, 23 Sep 2017 15:11:49 -0400 Subject: [PATCH 052/134] Fix for crash when erasing center cross of compass arc Erasing part of (but not the entire) center cross of an arc drawn with the compass caused a crash. --- src/domain/UBGraphicsScene.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index c64815f2..147e2d70 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -651,7 +651,9 @@ bool UBGraphicsScene::inputDeviceRelease() mAddedItems.remove(item); removeItem(item); UBCoreGraphicsScene::removeItemFromDeletion(item); - mArcPolygonItem->setStrokesGroup(pStrokes); + UBGraphicsPolygonItem* pi = qgraphicsitem_cast(item); + if (pi) + pi->setStrokesGroup(pStrokes); pStrokes->addToGroup(item); } From 7b1f64eabf0147f3fa2551f2c25673dd64157bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Sun, 24 Sep 2017 21:25:12 +0200 Subject: [PATCH 053/134] merge 1.4-dev + thumbnail views & fixes --- OpenBoard.pro | 7 +- resources/OpenBoard.qrc | 2 + resources/etc/OpenBoard.config | 5 +- resources/forms/brushProperties.ui | 75 +++- resources/images/moveDown.svg | 8 + resources/images/moveDownDisabled.svg | 64 ++++ resources/style.qss | 2 +- src/board/UBBoardController.cpp | 34 +- src/board/UBBoardPaletteManager.cpp | 2 - src/board/UBBoardView.cpp | 7 +- src/core/UBApplication.cpp | 3 + src/core/UBPersistenceManager.cpp | 1 - src/core/UBPreferencesController.cpp | 12 + src/core/UBPreferencesController.h | 1 + src/core/UBSettings.cpp | 17 + src/core/UBSettings.h | 10 + src/document/UBDocumentContainer.cpp | 20 +- src/document/UBDocumentContainer.h | 7 + src/document/UBDocumentController.cpp | 29 +- src/domain/UBDragableThumbnail.cpp | 128 +++++++ src/domain/UBDragableThumbnail.h | 31 ++ src/domain/UBGraphicsPolygonItem.cpp | 2 +- src/domain/UBGraphicsPolygonItem.h | 2 + src/domain/UBGraphicsScene.cpp | 87 +++++ src/domain/UBGraphicsScene.h | 5 + src/domain/UBGraphicsStroke.cpp | 4 +- src/domain/UBGraphicsTextItem.cpp | 5 + src/domain/UBGraphicsTextItem.h | 2 + src/domain/UBGraphicsTextItemDelegate.cpp | 10 +- src/gui/UBBoardThumbnailsView.cpp | 301 +++++++++++++++ ...entNavigator.h => UBBoardThumbnailsView.h} | 72 ++-- src/gui/UBDocumentNavigator.cpp | 311 --------------- src/gui/UBDocumentThumbnailWidget.cpp | 16 +- src/gui/UBDocumentThumbnailWidget.h | 2 +- src/gui/UBPageNavigationWidget.cpp | 2 +- src/gui/UBPageNavigationWidget.h | 4 +- src/gui/UBThumbnailView.cpp | 41 +- src/gui/UBThumbnailView.h | 17 +- src/gui/UBThumbnailWidget.cpp | 283 ++++++++------ src/gui/UBThumbnailWidget.h | 354 ++++++++++++------ src/gui/gui.pri | 8 +- src/tools/UBGraphicsCompass.cpp | 1 + 42 files changed, 1331 insertions(+), 663 deletions(-) create mode 100644 resources/images/moveDown.svg create mode 100644 resources/images/moveDownDisabled.svg create mode 100644 src/domain/UBDragableThumbnail.cpp create mode 100644 src/domain/UBDragableThumbnail.h create mode 100644 src/gui/UBBoardThumbnailsView.cpp rename src/gui/{UBDocumentNavigator.h => UBBoardThumbnailsView.h} (52%) delete mode 100644 src/gui/UBDocumentNavigator.cpp diff --git a/OpenBoard.pro b/OpenBoard.pro index 4c838820..6559b873 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -11,9 +11,10 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 VERSION_MIN = 4 VERSION_PATCH = 0 -VERSION_TYPE = a # a = alpha, b = beta, rc = release candidate, r = release, other => error +VERSION_TYPE = b # a = alpha, b = beta, rc = release candidate, r = release, other => error VERSION_BUILD = 1 + VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}" equals(VERSION_TYPE, r) { @@ -454,3 +455,7 @@ INSTALLS = UB_ETC \ UB_LIBRARY \ UB_THIRDPARTY_INTERACTIVE +DISTFILES += \ + resources/images/moveDown.svg \ + resources/images/moveDownDisabled.svg + diff --git a/resources/OpenBoard.qrc b/resources/OpenBoard.qrc index 1a2f3d1e..df2116b3 100644 --- a/resources/OpenBoard.qrc +++ b/resources/OpenBoard.qrc @@ -339,6 +339,8 @@ images/left_arrow.png images/right_arrow.png images/moveUp.svg + images/moveDown.svg + images/moveDownDisabled.svg images/closeDisabled.svg images/menuDisabled.svg images/moveUpDisabled.svg diff --git a/resources/etc/OpenBoard.config b/resources/etc/OpenBoard.config index 2c505d04..c8762800 100644 --- a/resources/etc/OpenBoard.config +++ b/resources/etc/OpenBoard.config @@ -65,9 +65,10 @@ RightLibPaletteDesktopModeWidth=270 ShowEraserPreviewCircle=true ShowMarkerPreviewCircle=true ShowPenPreviewCircle=true +PenPreviewFromSize=5 ShowToolsPalette=false -SimplifyMarkerStrokes=true -SimplifyPenStrokes=true +SimplifyMarkerStrokes=false +SimplifyPenStrokes=false SimplifyPenStrokesThresholdAngle=3 SimplifyPenStrokesThresholdWidthDifference=2 StartupKeyboardLocale=0 diff --git a/resources/forms/brushProperties.ui b/resources/forms/brushProperties.ui index 4f9d7268..f149562f 100644 --- a/resources/forms/brushProperties.ui +++ b/resources/forms/brushProperties.ui @@ -497,7 +497,80 @@ - + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Show preview circle from + + + + + + + + + + px + + + + + + + Qt::Horizontal + + + + 198 + 20 + + + + + + + + diff --git a/resources/images/moveDown.svg b/resources/images/moveDown.svg new file mode 100644 index 00000000..16b78e93 --- /dev/null +++ b/resources/images/moveDown.svg @@ -0,0 +1,8 @@ + + + + + + + diff --git a/resources/images/moveDownDisabled.svg b/resources/images/moveDownDisabled.svg new file mode 100644 index 00000000..4894f3ae --- /dev/null +++ b/resources/images/moveDownDisabled.svg @@ -0,0 +1,64 @@ + + + +image/svg+xml + + + + \ No newline at end of file diff --git a/resources/style.qss b/resources/style.qss index e53e0ee6..92bd8d6b 100644 --- a/resources/style.qss +++ b/resources/style.qss @@ -1,5 +1,5 @@ QWidget#DockPaletteWidgetBox, -QWidget#documentNavigator, +QWidget#UBBoardThumbnailsView, QWidget#UBLibPathViewer, QWidget#UBLibNavigatorWidget, QWidget#UBLibItemProperties, diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 414d146e..ea9f195a 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -583,6 +583,7 @@ void UBBoardController::duplicateScene(int nIndex) duplicatePages(scIndexes); insertThumbPage(nIndex); emit documentThumbnailsUpdated(this); + emit addThumbnailRequired(this, nIndex + 1); selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); setActiveDocumentScene(nIndex + 1); @@ -1399,7 +1400,6 @@ UBItem *UBBoardController::downloadFinished(bool pSuccess, QUrl sourceUrl, QUrl if (result){ selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); - reloadThumbnails(); } } else if (UBMimeType::OpenboardTool == itemMimeType) @@ -1542,11 +1542,11 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, mActiveSceneIndex = index; setDocument(pDocumentProxy, forceReload); + emit initThumbnailsRequired(this); updateSystemScaleFactor(); mControlView->setScene(mActiveScene); - disconnect(mControlView, SIGNAL(mouseReleased()), mActiveScene, SLOT(updateSelectionFrame())); - connect(mControlView, SIGNAL(mouseReleased()), mActiveScene, SLOT(updateSelectionFrame())); + mDisplayView->setScene(mActiveScene); mActiveScene->setBackgroundZoomFactor(mControlView->transform().m11()); pDocumentProxy->setDefaultDocumentSize(mActiveScene->nominalSize()); @@ -1584,9 +1584,11 @@ void UBBoardController::moveSceneToIndex(int source, int target) selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); UBPersistenceManager::persistenceManager()->persistDocumentMetadata(selectedDocument()); mMovingSceneIndex = source; + mActiveSceneIndex = target; setActiveDocumentScene(target); mMovingSceneIndex = -1; + emit activeSceneChanged(); } } @@ -1636,6 +1638,23 @@ void UBBoardController::ClearUndoStack() findUniquesItems(UBApplication::undoStack->command(i), uniqueItems); } + // Get items from clipboard in order not to delete an item that was cut + // (using source URL of graphics items as a surrogate for equality testing) + // This ensures that we can cut and paste a media item, widget, etc. from one page to the next. + QClipboard *clipboard = QApplication::clipboard(); + const QMimeData* data = clipboard->mimeData(); + QList sourceURLs; + + if (data && data->hasFormat(UBApplication::mimeTypeUniboardPageItem)) { + const UBMimeDataGraphicsItem* mimeDataGI = qobject_cast (data); + + if (mimeDataGI) { + foreach (UBItem* sourceItem, mimeDataGI->items()) { + sourceURLs << sourceItem->sourceUrl(); + } + } + } + // go through all unique items, and check, if they are on scene, or not. // if not on scene, than item can be deleted QSetIterator itUniq(uniqueItems); @@ -1647,7 +1666,12 @@ void UBBoardController::ClearUndoStack() scene = dynamic_cast(item->scene()); } - if(!scene) + bool inClipboard = false; + UBItem* ubi = dynamic_cast(item); + if (ubi && sourceURLs.contains(ubi->sourceUrl())) + inClipboard = true; + + if(!scene && !inClipboard) { if (!mActiveScene->deleteItem(item)){ delete item; @@ -1798,6 +1822,7 @@ void UBBoardController::documentSceneChanged(UBDocumentProxy* pDocumentProxy, in if(selectedDocument() == pDocumentProxy) { setActiveDocumentScene(mActiveSceneIndex); + updatePage(pIndex); } } @@ -1941,7 +1966,6 @@ void UBBoardController::persistCurrentScene(bool isAnAutomaticBackup, bool force && (mActiveScene->isModified())) { UBPersistenceManager::persistenceManager()->persistDocumentScene(selectedDocument(), mActiveScene, mActiveSceneIndex, isAnAutomaticBackup,forceImmediateSave); - updatePage(mActiveSceneIndex); } } diff --git a/src/board/UBBoardPaletteManager.cpp b/src/board/UBBoardPaletteManager.cpp index 06cec6ed..581eb6b1 100644 --- a/src/board/UBBoardPaletteManager.cpp +++ b/src/board/UBBoardPaletteManager.cpp @@ -135,7 +135,6 @@ void UBBoardPaletteManager::setupDockPaletteWidgets() //------------------------------------------------// // Create the widgets for the dock palettes - mpPageNavigWidget = new UBPageNavigationWidget(); mpCachePropWidget = new UBCachePropertiesWidget(); @@ -146,7 +145,6 @@ void UBBoardPaletteManager::setupDockPaletteWidgets() mLeftPalette = new UBLeftPalette(mContainer); // LEFT palette widgets - mpPageNavigWidget = new UBPageNavigationWidget(); mLeftPalette->registerWidget(mpPageNavigWidget); mLeftPalette->addTab(mpPageNavigWidget); diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 768f90a2..97e8233c 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -1719,7 +1719,12 @@ void UBBoardView::setToolCursor (int tool) switch (tool) { case UBStylusTool::Pen: - controlViewport->setCursor (UBResources::resources ()->penCursor); + if (UBSettings::settings()->showPenPreviewCircle->get().toBool() && + UBSettings::settings()->currentPenWidth() >= UBSettings::settings()->penPreviewFromSize->get().toInt()) { + controlViewport->setCursor (QCursor (Qt::BlankCursor)); + } else { + controlViewport->setCursor (UBResources::resources ()->penCursor); + } break; case UBStylusTool::Eraser: controlViewport->setCursor (UBResources::resources ()->eraserCursor); diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index 9f4a8301..b6c771c9 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -58,6 +58,7 @@ #include "gui/UBMainWindow.h" #include "gui/UBResources.h" +#include "gui/UBThumbnailWidget.h" #include "adaptors/publishing/UBSvgSubsetRasterizer.h" @@ -286,6 +287,8 @@ int UBApplication::exec(const QString& pFileToImport) mainWindow->actionPaste->setShortcuts(QKeySequence::Paste); mainWindow->actionCut->setShortcuts(QKeySequence::Cut); + UBThumbnailUI::_private::initCatalog(); + connect(mainWindow->actionBoard, SIGNAL(triggered()), this, SLOT(showBoard())); connect(mainWindow->actionWeb, SIGNAL(triggered()), this, SLOT(showInternet())); connect(mainWindow->actionWeb, SIGNAL(triggered()), this, SLOT(stopScript())); diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index 41a45bba..e2dc31ea 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -744,7 +744,6 @@ UBGraphicsScene* UBPersistenceManager::loadDocumentScene(UBDocumentProxy* proxy, if (scene) mSceneCache.insert(proxy, sceneIndex, scene); } - if (cacheNeighboringScenes) { if(sceneIndex + 1 < proxy->pageCount() && !mSceneCache.contains(proxy, sceneIndex + 1)) mWorker->readScene(proxy,sceneIndex+1); diff --git a/src/core/UBPreferencesController.cpp b/src/core/UBPreferencesController.cpp index 8e787e56..4c87c6ac 100644 --- a/src/core/UBPreferencesController.cpp +++ b/src/core/UBPreferencesController.cpp @@ -165,6 +165,8 @@ void UBPreferencesController::wire() connect(mPenProperties->mediumSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mPenProperties->strongSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mPenProperties->pressureSensitiveCheckBox, SIGNAL(clicked(bool)), settings, SLOT(setPenPressureSensitive(bool))); + connect(mPenProperties->circleCheckBox, SIGNAL(clicked(bool)), settings, SLOT(setPenPreviewCircle(bool))); + connect(mPenProperties->circleSpinBox, SIGNAL(valueChanged(int)), this, SLOT(penPreviewFromSizeChanged(int))); // marker QList markerLightBackgroundColors = settings->boardMarkerLightBackgroundColors->colors(); @@ -178,6 +180,8 @@ void UBPreferencesController::wire() mMarkerProperties->pressureSensitiveCheckBox->setText(tr("Marker is pressure sensitive")); + mMarkerProperties->circleFrame->hide(); + connect(mMarkerProperties->fineSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mMarkerProperties->mediumSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); connect(mMarkerProperties->strongSlider, SIGNAL(valueChanged(int)), this, SLOT(widthSliderChanged(int))); @@ -229,6 +233,8 @@ void UBPreferencesController::init() mPenProperties->mediumSlider->setValue(settings->boardPenMediumWidth->get().toDouble() * sSliderRatio); mPenProperties->strongSlider->setValue(settings->boardPenStrongWidth->get().toDouble() * sSliderRatio); mPenProperties->pressureSensitiveCheckBox->setChecked(settings->boardPenPressureSensitive->get().toBool()); + mPenProperties->circleCheckBox->setChecked(settings->showPenPreviewCircle->get().toBool()); + mPenProperties->circleSpinBox->setValue(settings->penPreviewFromSize->get().toInt()); // marker tab mMarkerProperties->fineSlider->setValue(settings->boardMarkerFineWidth->get().toDouble() * sSliderRatio); @@ -278,6 +284,8 @@ void UBPreferencesController::defaultSettings() mPenProperties->mediumSlider->setValue(settings->boardPenMediumWidth->reset().toDouble() * sSliderRatio); mPenProperties->strongSlider->setValue(settings->boardPenStrongWidth->reset().toDouble() * sSliderRatio); mPenProperties->pressureSensitiveCheckBox->setChecked(settings->boardPenPressureSensitive->reset().toBool()); + mPenProperties->circleCheckBox->setChecked(settings->showPenPreviewCircle->reset().toBool()); + mPenProperties->circleSpinBox->setValue(settings->penPreviewFromSize->reset().toInt()); settings->boardPenLightBackgroundSelectedColors->reset(); QList lightBackgroundSelectedColors = settings->boardPenLightBackgroundSelectedColors->colors(); @@ -332,6 +340,10 @@ void UBPreferencesController::defaultSettings() } +void UBPreferencesController::penPreviewFromSizeChanged(int value) +{ + UBSettings::settings()->setPenPreviewFromSize(value); +} void UBPreferencesController::widthSliderChanged(int value) { diff --git a/src/core/UBPreferencesController.h b/src/core/UBPreferencesController.h index 3c129d03..ea4d8b32 100644 --- a/src/core/UBPreferencesController.h +++ b/src/core/UBPreferencesController.h @@ -89,6 +89,7 @@ class UBPreferencesController : public QObject void close(); void defaultSettings(); + void penPreviewFromSizeChanged(int value); void widthSliderChanged(int value); void opacitySliderChanged(int value); void colorSelected(const QColor&); diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index 1e2601be..68b29e6e 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -85,6 +85,12 @@ QColor UBSettings::markerCircleBrushColorLightBackground = QColor(255, 255, 255, QColor UBSettings::markerCirclePenColorDarkBackground = QColor(255, 255, 255, 127); QColor UBSettings::markerCirclePenColorLightBackground = QColor(0, 0, 0, 127); +QColor UBSettings::penCircleBrushColorDarkBackground = QColor(127, 127, 127, 80); +QColor UBSettings::penCircleBrushColorLightBackground = QColor(255, 255, 255, 30); + +QColor UBSettings::penCirclePenColorDarkBackground = QColor(255, 255, 255, 127); +QColor UBSettings::penCirclePenColorLightBackground = QColor(0, 0, 0, 127); + QColor UBSettings::documentSizeMarkColorDarkBackground = QColor(44, 44, 44, 200); QColor UBSettings::documentSizeMarkColorLightBackground = QColor(241, 241, 241); @@ -323,6 +329,8 @@ void UBSettings::init() showEraserPreviewCircle = new UBSetting(this, "Board", "ShowEraserPreviewCircle", true); showMarkerPreviewCircle = new UBSetting(this, "Board", "ShowMarkerPreviewCircle", true); + showPenPreviewCircle = new UBSetting(this, "Board", "ShowPenPreviewCircle", true); + penPreviewFromSize = new UBSetting(this, "Board", "PenPreviewFromSize", 5); webUseExternalBrowser = new UBSetting(this, "Web", "UseExternalBrowser", false); @@ -784,6 +792,15 @@ void UBSettings::setPenPressureSensitive(bool sensitive) boardPenPressureSensitive->set(sensitive); } +void UBSettings::setPenPreviewCircle(bool circle) +{ + showPenPreviewCircle->set(circle); +} + +void UBSettings::setPenPreviewFromSize(int size) +{ + penPreviewFromSize->set(size); +} void UBSettings::setMarkerPressureSensitive(bool sensitive) { diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index 84ae5667..7aa121d8 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -177,6 +177,12 @@ class UBSettings : public QObject static QColor markerCirclePenColorDarkBackground; static QColor markerCirclePenColorLightBackground; + static QColor penCircleBrushColorDarkBackground; + static QColor penCircleBrushColorLightBackground; + + static QColor penCirclePenColorDarkBackground; + static QColor penCirclePenColorLightBackground; + static QColor documentSizeMarkColorDarkBackground; static QColor documentSizeMarkColorLightBackground; @@ -303,6 +309,8 @@ class UBSettings : public QObject UBSetting* showEraserPreviewCircle; UBSetting* showMarkerPreviewCircle; + UBSetting* showPenPreviewCircle; + UBSetting* penPreviewFromSize; UBSetting* webUseExternalBrowser; UBSetting* webShowPageImmediatelyOnMirroredScreen; @@ -410,6 +418,8 @@ class UBSettings : public QObject void setStylusPaletteVisible(bool visible); void setPenPressureSensitive(bool sensitive); + void setPenPreviewCircle(bool sensitive); + void setPenPreviewFromSize(int size); void setMarkerPressureSensitive(bool sensitive); QVariant value ( const QString & key, const QVariant & defaultValue = QVariant() ); diff --git a/src/document/UBDocumentContainer.cpp b/src/document/UBDocumentContainer.cpp index e6f30d03..b63ee837 100644 --- a/src/document/UBDocumentContainer.cpp +++ b/src/document/UBDocumentContainer.cpp @@ -51,8 +51,9 @@ void UBDocumentContainer::setDocument(UBDocumentProxy* document, bool forceReloa if (mCurrentDocument != document || forceReload) { mCurrentDocument = document; - reloadThumbnails(); + emit documentSet(mCurrentDocument); + reloadThumbnails(); } } @@ -68,10 +69,14 @@ void UBDocumentContainer::duplicatePages(QList& pageIndexes) bool UBDocumentContainer::movePageToIndex(int source, int target) { + //on document view UBPersistenceManager::persistenceManager()->moveSceneToIndex(mCurrentDocument, source, target); deleteThumbPage(source); insertThumbPage(target); emit documentThumbnailsUpdated(this); + + //on board thumbnails view + emit moveThumbnailRequired(source, target); return true; } @@ -82,16 +87,26 @@ void UBDocumentContainer::deletePages(QList& pageIndexes) foreach(int index, pageIndexes) { deleteThumbPage(index - offset); + emit removeThumbnailRequired(index - offset); offset++; + } - emit documentThumbnailsUpdated(this); + } void UBDocumentContainer::addPage(int index) { UBPersistenceManager::persistenceManager()->createDocumentSceneAt(mCurrentDocument, index); insertThumbPage(index); + emit documentThumbnailsUpdated(this); + emit addThumbnailRequired(this, index); +} + +void UBDocumentContainer::initThumbPage() +{ + for (int i=0; i < selectedDocument()->pageCount(); i++) + insertThumbPage(i); } void UBDocumentContainer::updatePage(int index) @@ -108,7 +123,6 @@ void UBDocumentContainer::deleteThumbPage(int index) void UBDocumentContainer::updateThumbPage(int index) { mDocumentThumbs[index] = UBThumbnailAdaptor::get(mCurrentDocument, index); - emit documentPageUpdated(index); } void UBDocumentContainer::insertThumbPage(int index) diff --git a/src/document/UBDocumentContainer.h b/src/document/UBDocumentContainer.h index 4fc35b96..c378ddd5 100644 --- a/src/document/UBDocumentContainer.h +++ b/src/document/UBDocumentContainer.h @@ -53,6 +53,7 @@ class UBDocumentContainer : public QObject void duplicatePages(QList& pageIndexes); bool movePageToIndex(int source, int target); void deletePages(QList& pageIndexes); + void initThumbPage(); void addPage(int index); void updatePage(int index); void addEmptyThumbPage(); @@ -73,6 +74,12 @@ class UBDocumentContainer : public QObject signals: void documentSet(UBDocumentProxy* document); void documentPageUpdated(int index); + + void initThumbnailsRequired(UBDocumentContainer* source); + void addThumbnailRequired(UBDocumentContainer* source, int index); + void removeThumbnailRequired(int index); + void moveThumbnailRequired(int from, int to); + void documentThumbnailsUpdated(UBDocumentContainer* source); }; diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index 088544f8..7d3f776b 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -467,15 +467,16 @@ void UBDocumentController::openSelectedItem() if (selectedItems.count() > 0) { - UBSceneThumbnailPixmap* thumb = dynamic_cast (selectedItems.last()); + UBThumbnailPixmap* thumb = dynamic_cast (selectedItems.last()); if (thumb) { - UBDocumentProxy* proxy = thumb->proxy(); + UBDocumentProxy* proxy = thumb->documentProxy(); if (proxy && isOKToOpenDocument(proxy)) { UBApplication::applicationController->showBoard(); + UBApplication::applicationController->showBoard(); } } } @@ -504,10 +505,10 @@ void UBDocumentController::duplicateSelectedItem() QList selectedSceneIndexes; foreach (QGraphicsItem *item, selectedItems) { - UBSceneThumbnailPixmap *thumb = dynamic_cast(item); + UBThumbnailPixmap *thumb = dynamic_cast(item); if (thumb) { - UBDocumentProxy *proxy = thumb->proxy(); + UBDocumentProxy *proxy = thumb->documentProxy(); if (proxy) { @@ -1365,7 +1366,7 @@ void UBDocumentController::selectionChanged() mMainWindow->actionDuplicate->setEnabled(!trashSelected); else{ for(int i = 0; i < selection.count() && !firstSceneSelected; i += 1){ - if(dynamic_cast(selection.at(i))->sceneIndex() == 0){ + if(dynamic_cast(selection.at(i))->sceneIndex() == 0){ mMainWindow->actionDuplicate->setEnabled(!trashSelected); firstSceneSelected = true; } @@ -1515,11 +1516,11 @@ void UBDocumentController::addToDocument() foreach (QGraphicsItem* item, selectedItems) { - UBSceneThumbnailPixmap* thumb = dynamic_cast (item); + UBThumbnailPixmap* thumb = dynamic_cast (item); - if (thumb && thumb->proxy()) + if (thumb && thumb->documentProxy()) { - QPair pageInfo(thumb->proxy(), thumb->sceneIndex()); + QPair pageInfo(thumb->documentProxy(), thumb->sceneIndex()); pageInfoList << pageInfo; } } @@ -1808,11 +1809,11 @@ void UBDocumentController::deletePages(QList itemsToDelete) foreach (QGraphicsItem* item, itemsToDelete) { - UBSceneThumbnailPixmap* thumb = dynamic_cast (item); + UBThumbnailPixmap* thumb = dynamic_cast (item); if (thumb) { - proxy = thumb->proxy(); + proxy = thumb->documentProxy(); if (proxy) { sceneIndexes.append(thumb->sceneIndex()); @@ -1842,7 +1843,7 @@ int UBDocumentController::getSelectedItemIndex() if (selectedItems.count() > 0) { - UBSceneThumbnailPixmap* thumb = dynamic_cast (selectedItems.last()); + UBThumbnailPixmap* thumb = dynamic_cast (selectedItems.last()); return thumb->sceneIndex(); } else return -1; @@ -1867,11 +1868,11 @@ void UBDocumentController::refreshDocumentThumbnailsView(UBDocumentContainer*) if (proxy) { setDocument(proxy); - + initThumbPage(); for (int i = 0; i < selectedDocument()->pageCount(); i++) { const QPixmap* pix = pageAt(i); - QGraphicsPixmapItem *pixmapItem = new UBSceneThumbnailPixmap(*pix, proxy, i); // deleted by the tree widget + QGraphicsPixmapItem *pixmapItem = new UBThumbnailPixmap(*pix, proxy, i); // deleted by the tree widget if (proxy == mBoardController->selectedDocument() && mBoardController->activeSceneIndex() == i) { @@ -1898,7 +1899,7 @@ void UBDocumentController::refreshDocumentThumbnailsView(UBDocumentContainer*) if (selection) { disconnect(mDocumentUI->thumbnailWidget->scene(), SIGNAL(selectionChanged()), this, SLOT(pageSelectionChanged())); - UBSceneThumbnailPixmap *currentScene = dynamic_cast(selection); + UBThumbnailPixmap *currentScene = dynamic_cast(selection); if (currentScene) mDocumentUI->thumbnailWidget->hightlightItem(currentScene->sceneIndex()); connect(mDocumentUI->thumbnailWidget->scene(), SIGNAL(selectionChanged()), this, SLOT(pageSelectionChanged())); diff --git a/src/domain/UBDragableThumbnail.cpp b/src/domain/UBDragableThumbnail.cpp new file mode 100644 index 00000000..a8e05ec8 --- /dev/null +++ b/src/domain/UBDragableThumbnail.cpp @@ -0,0 +1,128 @@ +#include "UBDragableThumbnail.h" + +#include +#include +#include + +UBDraggableThumbnail::UBDraggableThumbnail(QWidget* parent, const QPixmap& pixmap) : + QFrame(parent) + , mThumbnail(new QLabel(this)) + , mHBoxLayout(new QHBoxLayout(this)) +{ + setFrameStyle(QFrame::Sunken | QFrame::StyledPanel); + setAcceptDrops(true); + + //set stylesheet + setObjectName("DockPaletteWidgetBox"); + setStyleSheet("background:white"); + + mHBoxLayout->setAlignment(Qt::AlignHCenter); + + setThumbnail(pixmap); + + setLayout(mHBoxLayout); +} + +void UBDraggableThumbnail::setThumbnail(const QPixmap& pixmap) +{ + mThumbnail->setAttribute(Qt::WA_DeleteOnClose); + setPixmap(pixmap); + + mHBoxLayout->addWidget(mThumbnail); +} + +void UBDraggableThumbnail::setPixmap(const QPixmap& pixmap) +{ + mThumbnail->setPixmap(pixmap); +} + +void UBDraggableThumbnail::dragEnterEvent(QDragEnterEvent *event) +{ + if (event->mimeData()->hasFormat("application/x-dnditemdata")) { + if (event->source() == this) { + event->setDropAction(Qt::MoveAction); + event->accept(); + } else { + event->acceptProposedAction(); + } + } else { + event->ignore(); + } + } + + void UBDraggableThumbnail::dragMoveEvent(QDragMoveEvent *event) + { + if (event->mimeData()->hasFormat("application/x-dnditemdata")) { + if (event->source() == this) { + event->setDropAction(Qt::MoveAction); + event->accept(); + } else { + event->acceptProposedAction(); + } + } else { + event->ignore(); + } +} + +void UBDraggableThumbnail::dropEvent(QDropEvent *event) +{ + if (event->mimeData()->hasFormat("application/x-dnditemdata")) { + QByteArray itemData = event->mimeData()->data("application/x-dnditemdata"); + QDataStream dataStream(&itemData, QIODevice::ReadOnly); + + QPixmap pixmap; + QPoint offset; + dataStream >> pixmap >> offset; + + //don't have to delete previous Thumbnail (Drag'n'Drop behavior with WA_DeleteOnClose attribute will do it) + mThumbnail = new QLabel(this); + setThumbnail(pixmap); + + if (event->source() == this) { + event->setDropAction(Qt::MoveAction); + event->accept(); + } else { + event->acceptProposedAction(); + } + } else { + event->ignore(); + } +} + + +void UBDraggableThumbnail::mousePressEvent(QMouseEvent *event) +{ + QLabel *child = static_cast(childAt(event->pos())); + if (!child) + return; + + QPixmap pixmap = *child->pixmap(); + + QByteArray itemData; + QDataStream dataStream(&itemData, QIODevice::WriteOnly); + dataStream << pixmap << QPoint(event->pos() - child->pos()); + + QMimeData *mimeData = new QMimeData; + mimeData->setData("application/x-dnditemdata", itemData); + + QDrag *drag = new QDrag(this); + drag->setMimeData(mimeData); + drag->setPixmap(pixmap); + drag->setHotSpot(event->pos() - child->pos()); + + QPixmap tempPixmap = pixmap; + QPainter painter; + painter.begin(&tempPixmap); + painter.fillRect(pixmap.rect(), QColor(127, 127, 127, 127)); + painter.end(); + + child->setPixmap(tempPixmap); + + if (drag->exec(Qt::CopyAction | Qt::MoveAction, Qt::CopyAction) == Qt::MoveAction) + child->close(); + else { + child->show(); + child->setPixmap(pixmap); + } +} + diff --git a/src/domain/UBDragableThumbnail.h b/src/domain/UBDragableThumbnail.h new file mode 100644 index 00000000..fe25c2c5 --- /dev/null +++ b/src/domain/UBDragableThumbnail.h @@ -0,0 +1,31 @@ +#ifndef UBDRAGABLELABEL_H +#define UBDRAGABLELABEL_H + +#include +#include +#include +#include +#include +#include +#include + +class UBDraggableThumbnail : public QFrame +{ + public: + UBDraggableThumbnail(QWidget* parent =0, const QPixmap& pixmap = QPixmap(":images/libpalette/notFound.png")); + + void setThumbnail(const QPixmap &pixmap); + void setPixmap(const QPixmap & pixmap); + + protected: + void dragEnterEvent(QDragEnterEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dropEvent(QDropEvent *event); + void mousePressEvent(QMouseEvent *event); + + private: + QLabel* mThumbnail; + QHBoxLayout* mHBoxLayout; +}; + +#endif // UBDRAGABLELABEL_H diff --git a/src/domain/UBGraphicsPolygonItem.cpp b/src/domain/UBGraphicsPolygonItem.cpp index 4e74420a..ad1cdb9c 100644 --- a/src/domain/UBGraphicsPolygonItem.cpp +++ b/src/domain/UBGraphicsPolygonItem.cpp @@ -184,7 +184,7 @@ void UBGraphicsPolygonItem::copyItemParameters(UBItem *copy) const void UBGraphicsPolygonItem::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) { if(mHasAlpha && scene() && scene()->isLightBackground()) - painter->setCompositionMode(QPainter::CompositionMode_SourceOver); + painter->setCompositionMode(QPainter::CompositionMode_Darken); painter->setRenderHints(QPainter::Antialiasing); diff --git a/src/domain/UBGraphicsPolygonItem.h b/src/domain/UBGraphicsPolygonItem.h index eb5eb815..8dcc26b1 100644 --- a/src/domain/UBGraphicsPolygonItem.h +++ b/src/domain/UBGraphicsPolygonItem.h @@ -109,6 +109,8 @@ class UBGraphicsPolygonItem : public QGraphicsPolygonItem, public UBItem qreal originalWidth() { return mOriginalWidth;} bool isNominalLine() {return mIsNominalLine;} + void setNominalLine(bool isNominalLine) { mIsNominalLine = isNominalLine; } + QColor colorOnDarkBackground() const { return mColorOnDarkBackground; diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 147e2d70..14f1c5e3 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -48,6 +48,7 @@ #include "gui/UBMagnifer.h" #include "gui/UBMainWindow.h" #include "gui/UBToolWidget.h" +#include "gui/UBResources.h" #include "tools/UBGraphicsRuler.h" #include "tools/UBGraphicsProtractor.h" @@ -317,6 +318,7 @@ UBGraphicsScene::UBGraphicsScene(UBDocumentProxy* parent, bool enableUndoRedoSta , mEraser(0) , mPointer(0) , mMarkerCircle(0) + , mPenCircle(0) , mDocument(parent) , mDarkBackground(false) , mPageBackground(UBPageBackground::plain) @@ -346,6 +348,7 @@ UBGraphicsScene::UBGraphicsScene(UBDocumentProxy* parent, bool enableUndoRedoSta createEraiser(); createPointer(); createMarkerCircle(); + createPenCircle(); if (UBApplication::applicationController) { @@ -410,6 +413,10 @@ bool UBGraphicsScene::inputDevicePress(const QPointF& scenePos, const qreal& pre if (currentTool == UBStylusTool::Marker) hideMarkerCircle(); + // hide the pen preview circle + if (currentTool == UBStylusTool::Pen) + hidePenCircle(); + // --------------------------------------------------------------- // Create a new Stroke. A Stroke is a collection of QGraphicsLines // --------------------------------------------------------------- @@ -492,6 +499,15 @@ bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pres } } + else if (currentTool == UBStylusTool::Pen) { + if (mInputDeviceIsPressed) + hidePenCircle(); + else { + drawPenCircle(position); + accepted = true; + } + } + if (mInputDeviceIsPressed) { if (dc->isDrawingTool()) @@ -799,6 +815,28 @@ void UBGraphicsScene::drawMarkerCircle(const QPointF &pPoint) } +void UBGraphicsScene::drawPenCircle(const QPointF &pPoint) +{ + if (mPenCircle && UBSettings::settings()->showPenPreviewCircle->get().toBool() && + UBSettings::settings()->currentPenWidth() >= UBSettings::settings()->penPreviewFromSize->get().toInt()) { + qreal penDiameter = UBSettings::settings()->currentPenWidth(); + penDiameter /= UBApplication::boardController->systemScaleFactor(); + penDiameter /= UBApplication::boardController->currentZoom(); + qreal penRadius = penDiameter/2; + + mPenCircle->setRect(QRectF(pPoint.x() - penRadius, pPoint.y() - penRadius, + penDiameter, penDiameter)); + + controlView()->viewport()->setCursor(QCursor (Qt::BlankCursor)); + mPenCircle->show(); + } + else + { + controlView()->viewport()->setCursor(UBResources::resources()->penCursor); + } + +} + void UBGraphicsScene::hideMarkerCircle() { if (mMarkerCircle) { @@ -806,6 +844,12 @@ void UBGraphicsScene::hideMarkerCircle() } } +void UBGraphicsScene::hidePenCircle() +{ + if (mPenCircle) + mPenCircle->hide(); +} + // call this function when user release mouse button in Magnifier mode void UBGraphicsScene::DisposeMagnifierQWidgets() { @@ -989,6 +1033,7 @@ void UBGraphicsScene::eraseLineTo(const QPointF &pEndPoint, const qreal &pWidth) UBGraphicsPolygonItem* polygonItem = new UBGraphicsPolygonItem(intersectedPolygons[i][j], intersectedPolygonItem->parentItem()); intersectedPolygonItem->copyItemParameters(polygonItem); + polygonItem->setNominalLine(false); polygonItem->setStroke(intersectedPolygonItem->stroke()); polygonItem->setStrokesGroup(intersectedPolygonItem->strokesGroup()); intersectedPolygonItem->strokesGroup()->addToGroup(polygonItem); @@ -1050,6 +1095,7 @@ void UBGraphicsScene::setBackground(bool pIsDark, UBPageBackground pBackground) updateEraserColor(); updateMarkerCircleColor(); + updatePenCircleColor(); recolorAllItems(); needRepaint = true; @@ -1270,6 +1316,7 @@ void UBGraphicsScene::hideTool() { hideEraser(); hideMarkerCircle(); + hidePenCircle(); } void UBGraphicsScene::leaveEvent(QEvent * event) @@ -2791,6 +2838,25 @@ void UBGraphicsScene::createMarkerCircle() } } +void UBGraphicsScene::createPenCircle() +{ + if (UBSettings::settings()->showPenPreviewCircle->get().toBool()) { + mPenCircle = new QGraphicsEllipseItem(); + + mPenCircle->setRect(QRect(0, 0, 0, 0)); + mPenCircle->setVisible(false); + + mPenCircle->setPen(Qt::DotLine); + updatePenCircleColor(); + + mPenCircle->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); + mPenCircle->setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::Eraiser)); + + mTools << mPenCircle; + addItem(mPenCircle); + } +} + void UBGraphicsScene::updateEraserColor() { if (!mEraser) @@ -2828,6 +2894,27 @@ void UBGraphicsScene::updateMarkerCircleColor() mMarkerCircle->setPen(mcPen); } +void UBGraphicsScene::updatePenCircleColor() +{ + if (!mPenCircle) + return; + + QPen mcPen = mPenCircle->pen(); + + if (mDarkBackground) { + mcPen.setColor(UBSettings::penCirclePenColorDarkBackground); + mPenCircle->setBrush(UBSettings::penCircleBrushColorDarkBackground); + } + + else { + mcPen.setColor(UBSettings::penCirclePenColorLightBackground); + mPenCircle->setBrush(UBSettings::penCircleBrushColorLightBackground); + } + + mcPen.setStyle(Qt::DotLine); + mPenCircle->setPen(mcPen); +} + void UBGraphicsScene::setToolCursor(int tool) { if (tool == (int)UBStylusTool::Selector || diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 84d01514..1f1b2a1e 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -383,7 +383,9 @@ public slots: void hideEraser(); void drawPointer(const QPointF& pEndPoint, bool isFirstDraw = false); void drawMarkerCircle(const QPointF& pEndPoint); + void drawPenCircle(const QPointF& pEndPoint); void hideMarkerCircle(); + void hidePenCircle(); void DisposeMagnifierQWidgets(); @@ -404,14 +406,17 @@ public slots: void createEraiser(); void createPointer(); void createMarkerCircle(); + void createPenCircle(); void updateEraserColor(); void updateMarkerCircleColor(); + void updatePenCircleColor(); bool hasTextItemWithFocus(UBGraphicsGroupContainerItem* item); void simplifyCurrentStroke(); QGraphicsEllipseItem* mEraser; QGraphicsEllipseItem* mPointer; // "laser" pointer QGraphicsEllipseItem* mMarkerCircle; // dotted circle around marker + QGraphicsEllipseItem* mPenCircle; // dotted circle around pen QSet mAddedItems; QSet mRemovedItems; diff --git a/src/domain/UBGraphicsStroke.cpp b/src/domain/UBGraphicsStroke.cpp index 7349e70b..3cf10a65 100644 --- a/src/domain/UBGraphicsStroke.cpp +++ b/src/domain/UBGraphicsStroke.cpp @@ -164,12 +164,10 @@ bool UBGraphicsStroke::hasPressure() if (!pol->isNominalLine() || pol->originalWidth() != nominalWidth) return true; } + return false; } - else return true; - - return false; } diff --git a/src/domain/UBGraphicsTextItem.cpp b/src/domain/UBGraphicsTextItem.cpp index f2326bb9..1f29eeee 100644 --- a/src/domain/UBGraphicsTextItem.cpp +++ b/src/domain/UBGraphicsTextItem.cpp @@ -188,6 +188,11 @@ void UBGraphicsTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) } } +void UBGraphicsTextItem::dragMoveEvent(QGraphicsSceneDragDropEvent *event) +{ + +} + void UBGraphicsTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { // scene()->itemAt(pos) returns 0 if pos is not over text, but over text item, but mouse press comes. diff --git a/src/domain/UBGraphicsTextItem.h b/src/domain/UBGraphicsTextItem.h index bb031f71..e3a3688b 100644 --- a/src/domain/UBGraphicsTextItem.h +++ b/src/domain/UBGraphicsTextItem.h @@ -118,6 +118,8 @@ class UBGraphicsTextItem : public QGraphicsTextItem, public UBItem, public UBRes virtual void keyPressEvent(QKeyEvent *event); virtual void keyReleaseEvent(QKeyEvent *event); + virtual void dragMoveEvent(QGraphicsSceneDragDropEvent *event); + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); diff --git a/src/domain/UBGraphicsTextItemDelegate.cpp b/src/domain/UBGraphicsTextItemDelegate.cpp index 34b866e6..1c817860 100644 --- a/src/domain/UBGraphicsTextItemDelegate.cpp +++ b/src/domain/UBGraphicsTextItemDelegate.cpp @@ -339,7 +339,10 @@ void UBGraphicsTextItemDelegate::pickFont() curCursor.mergeCharFormat(format); delegated()->setTextCursor(curCursor); - delegated()->setFont(selectedFont); + + if (curCursor.selectedText().length() == 0) + delegated()->setFont(selectedFont); + delegated()->setSelected(true); delegated()->document()->adjustSize(); delegated()->contentsChanged(); @@ -751,10 +754,5 @@ QVariant UBGraphicsTextItemDelegate::itemChange(QGraphicsItem::GraphicsItemChang } } - if (value.toBool() == false && delegated()->document()->toPlainText().isEmpty()) { - int wdth = QFontMetrics(delegated()->font()).width(delegated()->mTypeTextHereLabel); - delegated()->setTextWidth(qMax(wdth, (int)(delegated()->textWidth()))); - } - return UBGraphicsItemDelegate::itemChange(change, value); } diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp new file mode 100644 index 00000000..8840e45f --- /dev/null +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM) + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "core/UBApplication.h" +#include "UBBoardThumbnailsView.h" +#include "board/UBBoardController.h" +#include "adaptors/UBThumbnailAdaptor.h" +#include "adaptors/UBSvgSubsetAdaptor.h" +#include "document/UBDocumentController.h" +#include "domain/UBGraphicsScene.h" +#include "board/UBBoardPaletteManager.h" +#include "core/UBApplicationController.h" +#include "core/UBPersistenceManager.h" +#include "UBThumbnailView.h" + +UBBoardThumbnailsView::UBBoardThumbnailsView(QWidget *parent, const char *name) + : QGraphicsView(parent) + , mThumbnailWidth(0) + , mThumbnailMinWidth(100) + , mMargin(20) + , mDropSource(NULL) + , mDropTarget(NULL) + , mDropBar(new QGraphicsRectItem(0)) + , mLongPressInterval(150) +{ + setScene(new QGraphicsScene(this)); + + mDropBar->setPen(QPen(Qt::darkGray)); + mDropBar->setBrush(QBrush(Qt::lightGray)); + scene()->addItem(mDropBar); + mDropBar->hide(); + + setObjectName(name); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setFrameShadow(QFrame::Plain); + + mThumbnailWidth = width() - 2*mMargin; + + mLongPressTimer.setInterval(mLongPressInterval); + mLongPressTimer.setSingleShot(true); + + connect(UBApplication::boardController, SIGNAL(initThumbnailsRequired(UBDocumentContainer*)), this, SLOT(initThumbnails(UBDocumentContainer*)), Qt::UniqueConnection); + connect(UBApplication::boardController, SIGNAL(addThumbnailRequired(UBDocumentContainer*, int)), this, SLOT(addThumbnail(UBDocumentContainer*, int)), Qt::UniqueConnection); + connect(UBApplication::boardController, SIGNAL(moveThumbnailRequired(int, int)), this, SLOT(moveThumbnail(int, int)), Qt::UniqueConnection); + connect(this, SIGNAL(moveThumbnailRequired(int, int)), this, SLOT(moveThumbnail(int, int)), Qt::UniqueConnection); + connect(UBApplication::boardController, SIGNAL(removeThumbnailRequired(int)), this, SLOT(removeThumbnail(int)), Qt::UniqueConnection); + + connect(&mLongPressTimer, SIGNAL(timeout()), this, SLOT(longPressTimeout()), Qt::UniqueConnection); + + connect(this, SIGNAL(mousePressAndHoldEventRequired(QPoint)), this, SLOT(mousePressAndHoldEvent(QPoint)), Qt::UniqueConnection); + + connect(UBApplication::boardController, SIGNAL(pageSelectionChanged(int)), this, SLOT(scrollToSelectedPage(int)), Qt::UniqueConnection); +} + +void UBBoardThumbnailsView::moveThumbnail(int from, int to) +{ + mThumbnails.move(from, to); + + updateThumbnailsPos(); +} + +void UBBoardThumbnailsView::removeThumbnail(int i) +{ + UBDraggableThumbnailView* item = mThumbnails.at(i); + + scene()->removeItem(item->pageNumber()); + scene()->removeItem(item); + + mThumbnails.removeAt(i); + + updateThumbnailsPos(); +} + +UBDraggableThumbnailView* UBBoardThumbnailsView::createThumbnail(UBDocumentContainer* source, int i) +{ + UBGraphicsScene* pageScene = UBPersistenceManager::persistenceManager()->loadDocumentScene(source->selectedDocument(), i); + UBThumbnailView* pageView = new UBThumbnailView(pageScene); + + return new UBDraggableThumbnailView(pageView, source->selectedDocument(), i); +} + +void UBBoardThumbnailsView::addThumbnail(UBDocumentContainer* source, int i) +{ + UBDraggableThumbnailView* item = createThumbnail(source, i); + mThumbnails.insert(i, item); + + scene()->addItem(item); + scene()->addItem(item->pageNumber()); + + updateThumbnailsPos(); +} + +void UBBoardThumbnailsView::clearThumbnails() +{ + qDeleteAll(mThumbnails); + mThumbnails.clear(); +} + +void UBBoardThumbnailsView::initThumbnails(UBDocumentContainer* source) +{ + clearThumbnails(); + + for(int i = 0; i < source->selectedDocument()->pageCount(); i++) + { + mThumbnails.append(createThumbnail(source, i)); + + scene()->addItem(mThumbnails.last()); + scene()->addItem(mThumbnails.last()->pageNumber()); + } + + updateThumbnailsPos(); +} + +void UBBoardThumbnailsView::scrollToSelectedPage(int index) +{ + centerOn(mThumbnails.at(index)); +} + +void UBBoardThumbnailsView::updateThumbnailsPos() +{ + qreal thumbnailHeight = mThumbnailWidth / UBSettings::minScreenRatio; + + for (int i=0; i < mThumbnails.length(); i++) + { + mThumbnails.at(i)->setSceneIndex(i); + mThumbnails.at(i)->setPageNumber(i); + mThumbnails.at(i)->updatePos(mThumbnailWidth, thumbnailHeight); + } + + scene()->setSceneRect(scene()->itemsBoundingRect()); +} + +void UBBoardThumbnailsView::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + // Update the thumbnails width + mThumbnailWidth = (width() > mThumbnailMinWidth) ? width() - 2*mMargin : mThumbnailMinWidth; + + // Refresh the scene + updateThumbnailsPos(); +} + +void UBBoardThumbnailsView::mousePressEvent(QMouseEvent *event) +{ + mLongPressTimer.start(); + mLastPressedMousePos = event->pos(); + QGraphicsView::mousePressEvent(event); +} + +void UBBoardThumbnailsView::mouseMoveEvent(QMouseEvent *event) +{ + mLastPressedMousePos = event->pos(); + QGraphicsView::mouseMoveEvent(event); +} + +void UBBoardThumbnailsView::longPressTimeout() +{ + emit mousePressAndHoldEventRequired(mLastPressedMousePos); + mLongPressTimer.stop(); +} + +void UBBoardThumbnailsView::mousePressAndHoldEvent(QPoint pos) +{ + UBDraggableThumbnailView* item = dynamic_cast(itemAt(pos)); + if (item) + { + mDropSource = item; + mDropTarget = item; + + QPixmap pixmap = item->widget()->grab().scaledToWidth(UBSettings::defaultThumbnailWidth); + + QDrag *drag = new QDrag(this); + drag->setMimeData(new QMimeData()); + drag->setPixmap(pixmap); + drag->setHotSpot(QPoint(pixmap.width()/2, pixmap.height()/2)); + + drag->exec(); + } +} + +void UBBoardThumbnailsView::mouseReleaseEvent(QMouseEvent *event) +{ + mLongPressTimer.stop(); + + UBDraggableThumbnailView* item = dynamic_cast(itemAt(event->pos())); + + if (item) + UBApplication::boardController->setActiveDocumentScene(item->sceneIndex()); + + QGraphicsView::mouseReleaseEvent(event); +} + +void UBBoardThumbnailsView::dragEnterEvent(QDragEnterEvent *event) +{ + mDropBar->show(); + + if (event->source() == this) + { + event->setDropAction(Qt::MoveAction); + event->accept(); + } + else + { + event->acceptProposedAction(); + } +} + +void UBBoardThumbnailsView::dragMoveEvent(QDragMoveEvent *event) +{ + QPointF position = event->pos(); + + //autoscroll during drag'n'drop + QPointF scenePos = mapToScene(position.toPoint()); + int thumbnailHeight = mThumbnailWidth / UBSettings::minScreenRatio; + QRectF thumbnailArea(0, scenePos.y() - thumbnailHeight/2, mThumbnailWidth, thumbnailHeight); + + ensureVisible(thumbnailArea); + + UBDraggableThumbnailView* item = dynamic_cast(itemAt(position.toPoint())); + if (item) + { + if (item != mDropTarget) + mDropTarget = item; + + qreal scale = item->transform().m11(); + + QPointF itemCenter(item->pos().x() + item->boundingRect().width() * scale / 2, + item->pos().y() + item->boundingRect().height() * scale / 2); + + bool dropAbove = mapToScene(position.toPoint()).y() < itemCenter.y(); + bool movingUp = mDropSource->sceneIndex() > item->sceneIndex(); + qreal y = 0; + + if (movingUp) + { + if (dropAbove) + { + y = item->pos().y() - UBSettings::thumbnailSpacing / 2; + if (mDropBar->y() != y) + mDropBar->setRect(QRectF(item->pos().x(), y, item->boundingRect().width() * scale, 3)); + } + } + else + { + if (!dropAbove) + { + y = item->pos().y() + item->boundingRect().height() * scale + UBSettings::thumbnailSpacing / 2; + if (mDropBar->y() != y) + mDropBar->setRect(QRectF(item->pos().x(), y, item->boundingRect().width() * scale, 3)); + } + } + } + event->acceptProposedAction(); +} + +void UBBoardThumbnailsView::dropEvent(QDropEvent *event) +{ + Q_UNUSED(event); + + UBApplication::boardController->moveSceneToIndex(mDropSource->sceneIndex(), mDropTarget->sceneIndex()); + + mDropSource = NULL; + mDropTarget = NULL; + mDropBar->hide(); +} diff --git a/src/gui/UBDocumentNavigator.h b/src/gui/UBBoardThumbnailsView.h similarity index 52% rename from src/gui/UBDocumentNavigator.h rename to src/gui/UBBoardThumbnailsView.h index aebcce18..77a3b0ba 100644 --- a/src/gui/UBDocumentNavigator.h +++ b/src/gui/UBBoardThumbnailsView.h @@ -27,63 +27,67 @@ -#ifndef UBDOCUMENTNAVIGATOR_H -#define UBDOCUMENTNAVIGATOR_H +#ifndef UBBOARDTHUMBNAILSVIEW_H +#define UBBOARDTHUMBNAILSVIEW_H #include #include #include #include -#include -#include "document/UBDocumentProxy.h" #include "document/UBDocumentContainer.h" #include "UBThumbnailWidget.h" -#define NO_PAGESELECTED -1 - -class UBDocumentNavigator : public QGraphicsView +class UBBoardThumbnailsView : public QGraphicsView { Q_OBJECT public: - UBDocumentNavigator(QWidget* parent=0, const char* name="documentNavigator"); - ~UBDocumentNavigator(); - - void setNbColumns(int nbColumns); - int nbColumns(); - void setThumbnailMinWidth(int width); - int thumbnailMinWidth(); + UBBoardThumbnailsView(QWidget* parent=0, const char* name="UBBoardThumbnailsView"); public slots: - void onScrollToSelectedPage(int index);// { if (mCrntItem) centerOn(mCrntItem); } - void generateThumbnails(UBDocumentContainer* source); - void updateSpecificThumbnail(int iPage); + void scrollToSelectedPage(int index); + + void clearThumbnails(); + void initThumbnails(UBDocumentContainer* source); + void addThumbnail(UBDocumentContainer* source, int i); + void moveThumbnail(int from, int to); + void removeThumbnail(int i); + + void longPressTimeout(); + void mousePressAndHoldEvent(QPoint pos); protected: virtual void resizeEvent(QResizeEvent *event); + + virtual void dragEnterEvent(QDragEnterEvent* event); + virtual void dragMoveEvent(QDragMoveEvent* event); + virtual void dropEvent(QDropEvent* event); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseMoveEvent(QMouseEvent *event); virtual void mouseReleaseEvent(QMouseEvent *event); -private: +signals: + void mousePressAndHoldEventRequired(QPoint pos); + void moveThumbnailRequired(int from, int to); - void refreshScene(); - int border(); +private: + UBDraggableThumbnailView* createThumbnail(UBDocumentContainer* source, int i); + void updateThumbnailsPos(); + QList mThumbnails; - /** The scene */ - QGraphicsScene* mScene; - /** The current selected item */ - //UBSceneThumbnailNavigPixmap* mCrntItem; - /** The list of current thumbnails with labels*/ - QList mThumbsWithLabels; - /** The current number of columns */ - int mNbColumns; - /** The current thumbnails width */ int mThumbnailWidth; - /** The current thumbnails minimum width */ - int mThumbnailMinWidth; - /** The selected thumbnail */ - UBSceneThumbnailNavigPixmap* mSelectedThumbnail; + const int mThumbnailMinWidth; + const int mMargin; + + UBDraggableThumbnailView* mDropSource; + UBDraggableThumbnailView* mDropTarget; + QGraphicsRectItem *mDropBar; + + int mLongPressInterval; + QTimer mLongPressTimer; + QPoint mLastPressedMousePos; }; -#endif // UBDOCUMENTNAVIGATOR_H +#endif // UBBOARDTHUMBNAILSVIEW_H diff --git a/src/gui/UBDocumentNavigator.cpp b/src/gui/UBDocumentNavigator.cpp deleted file mode 100644 index db8c19ce..00000000 --- a/src/gui/UBDocumentNavigator.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM) - * - * 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 -#include -#include -#include -#include -#include -#include -#include - -#include "core/UBApplication.h" -#include "UBDocumentNavigator.h" -#include "board/UBBoardController.h" -#include "adaptors/UBThumbnailAdaptor.h" -#include "adaptors/UBSvgSubsetAdaptor.h" -#include "document/UBDocumentController.h" -#include "domain/UBGraphicsScene.h" -#include "board/UBBoardPaletteManager.h" -#include "core/UBApplicationController.h" - -#include "core/memcheck.h" - -/** - * \brief Constructor - * @param parent as the parent widget - * @param name as the object name - */ -UBDocumentNavigator::UBDocumentNavigator(QWidget *parent, const char *name):QGraphicsView(parent) - , mScene(NULL) - , mNbColumns(1) - , mThumbnailWidth(0) - , mThumbnailMinWidth(100) - , mSelectedThumbnail(NULL) -{ - setObjectName(name); - mScene = new QGraphicsScene(this); - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setScene(mScene); - mThumbnailWidth = width() - 2*border(); - - setFrameShadow(QFrame::Plain); - - connect(UBApplication::boardController, SIGNAL(documentThumbnailsUpdated(UBDocumentContainer*)), this, SLOT(generateThumbnails(UBDocumentContainer*))); - connect(UBApplication::boardController, SIGNAL(documentPageUpdated(int)), this, SLOT(updateSpecificThumbnail(int))); - connect(UBApplication::boardController, SIGNAL(pageSelectionChanged(int)), this, SLOT(onScrollToSelectedPage(int))); -} - -/** - * \brief Destructor - */ -UBDocumentNavigator::~UBDocumentNavigator() -{ - if(NULL != mScene) - { - delete mScene; - mScene = NULL; - } -} - -/** - * \brief Generate the thumbnails - */ -void UBDocumentNavigator::generateThumbnails(UBDocumentContainer* source) -{ - mThumbsWithLabels.clear(); - int selectedIndex = -1; - QList graphicsItemList = mScene->items(); - for(int i = 0; i < graphicsItemList.size(); i+=1) - { - QGraphicsItem* item = graphicsItemList.at(i); - if(item->isSelected()) - selectedIndex = i; - mScene->removeItem(item); - delete item; - item = NULL; - } - - for(int i = 0; i < source->selectedDocument()->pageCount(); i++) - { - //claudio This is a very bad hack and shows a architectural problem - // source->selectedDocument()->pageCount() != source->pageCount() - if(i>=source->pageCount() || source->pageAt(i)->isNull()) - source->insertThumbPage(i); - - const QPixmap* pix = source->pageAt(i); - Q_ASSERT(!pix->isNull()); - int pageIndex = UBDocumentContainer::pageFromSceneIndex(i); - - UBSceneThumbnailNavigPixmap* pixmapItem = new UBSceneThumbnailNavigPixmap(*pix, source->selectedDocument(), i); - - QString label = tr("Page %0").arg(pageIndex); - UBThumbnailTextItem *labelItem = new UBThumbnailTextItem(label); - - UBImgTextThumbnailElement thumbWithText(pixmapItem, labelItem); - thumbWithText.setBorder(border()); - mThumbsWithLabels.append(thumbWithText); - - mScene->addItem(pixmapItem); - mScene->addItem(labelItem); - } - - if (selectedIndex >= 0 && selectedIndex < mThumbsWithLabels.count()) - mSelectedThumbnail = mThumbsWithLabels.at(selectedIndex).getThumbnail(); - else - mSelectedThumbnail = NULL; - - // Draw the items - refreshScene(); -} - -void UBDocumentNavigator::onScrollToSelectedPage(int index) -{ - int c = 0; - foreach(UBImgTextThumbnailElement el, mThumbsWithLabels) - { - if (c==index) - { - el.getThumbnail()->setSelected(true); - mSelectedThumbnail = el.getThumbnail(); - } - else - { - el.getThumbnail()->setSelected(false); - } - c++; - } - if(NULL != mSelectedThumbnail) - centerOn(mSelectedThumbnail); -} - -/** - * \brief Refresh the given thumbnail - * @param iPage as the given page related thumbnail - */ -void UBDocumentNavigator::updateSpecificThumbnail(int iPage) -{ - const QPixmap* pix = UBApplication::boardController->pageAt(iPage); - UBSceneThumbnailNavigPixmap* newItem = new UBSceneThumbnailNavigPixmap(*pix, UBApplication::boardController->selectedDocument(), iPage); - - // Get the old thumbnail - UBSceneThumbnailNavigPixmap* oldItem = mThumbsWithLabels.at(iPage).getThumbnail(); - if(NULL != oldItem) - { - mScene->removeItem(oldItem); - mScene->addItem(newItem); - mThumbsWithLabels[iPage].setThumbnail(newItem); - delete oldItem; - oldItem = NULL; - } - -} - -/** - * \brief Put the element in the right place in the scene. - */ -void UBDocumentNavigator::refreshScene() -{ - qreal thumbnailHeight = mThumbnailWidth / UBSettings::minScreenRatio; - - for(int i = 0; i < mThumbsWithLabels.size(); i++) - { - // Get the item - UBImgTextThumbnailElement& item = mThumbsWithLabels[i]; - int columnIndex = i % mNbColumns; - int rowIndex = i / mNbColumns; - item.Place(rowIndex, columnIndex, mThumbnailWidth, thumbnailHeight); - } - scene()->setSceneRect(scene()->itemsBoundingRect()); -} - -/** - * \brief Set the number of thumbnails columns - * @param nbColumns as the number of columns - */ -void UBDocumentNavigator::setNbColumns(int nbColumns) -{ - mNbColumns = nbColumns; -} - -/** - * \brief Get the number of columns - * @return the number of thumbnails columns - */ -int UBDocumentNavigator::nbColumns() -{ - return mNbColumns; -} - -/** - * \brief Set the thumbnails minimum width - * @param width as the minimum width - */ -void UBDocumentNavigator::setThumbnailMinWidth(int width) -{ - mThumbnailMinWidth = width; -} - -/** - * \brief Get the thumbnails minimum width - * @return the minimum thumbnails width - */ -int UBDocumentNavigator::thumbnailMinWidth() -{ - return mThumbnailMinWidth; -} - -/** - * \brief Get the border size - * @return the border size in pixels - */ -int UBDocumentNavigator::border() -{ - return 20; -} - -/** - * \brief Handle the resize event - * @param event as the resize event - */ -void UBDocumentNavigator::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - - // Update the thumbnails width - mThumbnailWidth = (width() > mThumbnailMinWidth) ? width() - 2*border() : mThumbnailMinWidth; - - if(mSelectedThumbnail) - centerOn(mSelectedThumbnail); - - // Refresh the scene - refreshScene(); -} - -/** - * \brief Handle the mouse press event - * @param event as the mouse event - */ -void UBDocumentNavigator::mousePressEvent(QMouseEvent *event) -{ - QGraphicsItem* pClickedItem = itemAt(event->pos()); - if(NULL != pClickedItem) - { - - // First, select the clicked item - UBSceneThumbnailNavigPixmap* pCrntItem = dynamic_cast(pClickedItem); - - if(NULL == pCrntItem) - { - // If we fall here we may have clicked on the label instead of the thumbnail - UBThumbnailTextItem* pTextItem = dynamic_cast(pClickedItem); - if(NULL != pTextItem) - { - for(int i = 0; i < mThumbsWithLabels.size(); i++) - { - const UBImgTextThumbnailElement& el = mThumbsWithLabels.at(i); - if(el.getCaption() == pTextItem) - { - pCrntItem = el.getThumbnail(); - break; - } - } - } - } - - int index = 0; - for(int i = 0; i < mThumbsWithLabels.size(); i++) - { - if (mThumbsWithLabels.at(i).getThumbnail() == pCrntItem) - { - mSelectedThumbnail = pCrntItem; - index = i; - break; - } - } - UBApplication::boardController->setActiveDocumentScene(index); - } - QGraphicsView::mousePressEvent(event); -} - -void UBDocumentNavigator::mouseReleaseEvent(QMouseEvent *event) -{ - event->accept(); -} diff --git a/src/gui/UBDocumentThumbnailWidget.cpp b/src/gui/UBDocumentThumbnailWidget.cpp index 19ad39b1..b70f3926 100644 --- a/src/gui/UBDocumentThumbnailWidget.cpp +++ b/src/gui/UBDocumentThumbnailWidget.cpp @@ -75,17 +75,17 @@ void UBDocumentThumbnailWidget::mouseMoveEvent(QMouseEvent *event) QList graphicsItems = items(mMousePressPos); - UBSceneThumbnailPixmap* sceneItem = 0; + UBThumbnailPixmap* sceneItem = 0; while (!graphicsItems.isEmpty() && !sceneItem) - sceneItem = dynamic_cast(graphicsItems.takeFirst()); + sceneItem = dynamic_cast(graphicsItems.takeFirst()); if (sceneItem) { QDrag *drag = new QDrag(this); QList mimeDataItems; foreach (QGraphicsItem *item, selectedItems()) - mimeDataItems.append(UBMimeDataItem(sceneItem->proxy(), mGraphicItems.indexOf(item))); + mimeDataItems.append(UBMimeDataItem(sceneItem->documentProxy(), mGraphicItems.indexOf(item))); UBMimeData *mime = new UBMimeData(mimeDataItems); drag->setMimeData(mime); @@ -150,21 +150,21 @@ void UBDocumentThumbnailWidget::dragMoveEvent(QDragMoveEvent *event) mScrollTimer->stop(); } - QList pixmapItems; + QList pixmapItems; foreach (QGraphicsItem *item, scene()->items(mapToScene(boundingFrame))) { - UBSceneThumbnailPixmap* sceneItem = dynamic_cast(item); + UBThumbnailPixmap* sceneItem = dynamic_cast(item); if (sceneItem) pixmapItems.append(sceneItem); } int minDistance = 0; QGraphicsItem *underlyingItem = itemAt(event->pos()); - mClosestDropItem = dynamic_cast(underlyingItem); + mClosestDropItem = dynamic_cast(underlyingItem); if (!mClosestDropItem) { - foreach (UBSceneThumbnailPixmap *item, pixmapItems) + foreach (UBThumbnailPixmap *item, pixmapItems) { qreal scale = item->transform().m11(); QPointF itemCenter( @@ -305,7 +305,7 @@ void UBDocumentThumbnailWidget::hightlightItem(int index) } if (0 <= index && index < mGraphicItems.length()) { - UBSceneThumbnailPixmap *thumbnail = dynamic_cast(mGraphicItems.at(index)); + UBThumbnailPixmap *thumbnail = dynamic_cast(mGraphicItems.at(index)); if (thumbnail) thumbnail->highlight(); } diff --git a/src/gui/UBDocumentThumbnailWidget.h b/src/gui/UBDocumentThumbnailWidget.h index 617cee13..ba99acdf 100644 --- a/src/gui/UBDocumentThumbnailWidget.h +++ b/src/gui/UBDocumentThumbnailWidget.h @@ -71,7 +71,7 @@ class UBDocumentThumbnailWidget: public UBThumbnailWidget void deleteDropCaret(); QGraphicsRectItem *mDropCaretRectItem; - UBSceneThumbnailPixmap *mClosestDropItem; + UBThumbnailPixmap *mClosestDropItem; bool mDropIsRight; bool mDragEnabled; QTimer* mScrollTimer; diff --git a/src/gui/UBPageNavigationWidget.cpp b/src/gui/UBPageNavigationWidget.cpp index a6564573..eba9e401 100644 --- a/src/gui/UBPageNavigationWidget.cpp +++ b/src/gui/UBPageNavigationWidget.cpp @@ -60,7 +60,7 @@ UBPageNavigationWidget::UBPageNavigationWidget(QWidget *parent, const char *name mLayout = new QVBoxLayout(this); setLayout(mLayout); - mNavigator = new UBDocumentNavigator(this); + mNavigator = new UBBoardThumbnailsView(this); mLayout->addWidget(mNavigator, 1); mHLayout = new QHBoxLayout(); diff --git a/src/gui/UBPageNavigationWidget.h b/src/gui/UBPageNavigationWidget.h index 9fe7a388..bba9cc86 100644 --- a/src/gui/UBPageNavigationWidget.h +++ b/src/gui/UBPageNavigationWidget.h @@ -38,7 +38,7 @@ #include #include -#include "UBDocumentNavigator.h" +#include "UBBoardThumbnailsView.h" #include "UBDockPaletteWidget.h" #include "document/UBDocumentProxy.h" @@ -70,7 +70,7 @@ private: int border(); /** The thumbnails navigator widget */ - UBDocumentNavigator* mNavigator; + UBBoardThumbnailsView* mNavigator; /** The layout */ QVBoxLayout* mLayout; QHBoxLayout* mHLayout; diff --git a/src/gui/UBThumbnailView.cpp b/src/gui/UBThumbnailView.cpp index c6fc2713..f5f6f3ed 100644 --- a/src/gui/UBThumbnailView.cpp +++ b/src/gui/UBThumbnailView.cpp @@ -34,34 +34,29 @@ #include "core/memcheck.h" -UBThumbnailView::UBThumbnailView() +UBThumbnailView::UBThumbnailView(UBGraphicsScene *scene, QWidget* parent) + : QGraphicsView(scene, parent) + , mHBoxLayout(new QHBoxLayout(this)) { + setAcceptDrops(true); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing); -} -UBThumbnailView::~UBThumbnailView() -{ - // NOOP -} + int nominalWidth = scene->nominalSize().width(); + int nominalHeight = scene->nominalSize().height(); + QRectF nominalSceneRect(-nominalWidth/2, -nominalHeight/2, nominalWidth, nominalHeight); + fitInView(nominalSceneRect, Qt::KeepAspectRatio); + setSceneRect(nominalSceneRect); -void UBThumbnailView::drawBackground(QPainter *painter, const QRectF &rect) -{ - // Do not draw crossed background in thumbnails - if (qobject_cast(scene())->isDarkBackground()) - { - painter->fillRect(rect, QBrush(QColor(Qt::black))); - } - else - { - painter->fillRect(rect, QBrush(QColor(Qt::white))); - } -} + setStyleSheet( "QGraphicsView { border-style: none; }" ); -void UBThumbnailView::mouseDoubleClickEvent ( QMouseEvent * event ) -{ - Q_UNUSED(event); - emit doubleClicked(); -} + setFrameStyle(QFrame::Sunken | QFrame::StyledPanel); + //set stylesheet + setObjectName("DockPaletteWidgetBox"); + setStyleSheet("background:white"); + + mHBoxLayout->setAlignment(Qt::AlignHCenter); + setLayout(mHBoxLayout); +} diff --git a/src/gui/UBThumbnailView.h b/src/gui/UBThumbnailView.h index c2f00fb0..3a043c41 100644 --- a/src/gui/UBThumbnailView.h +++ b/src/gui/UBThumbnailView.h @@ -31,6 +31,9 @@ #define UBTHUMBNAILVIEW_H_ #include +#include +#include +#include class UBGraphicsScene; @@ -39,15 +42,15 @@ class UBThumbnailView : public QGraphicsView Q_OBJECT public: - UBThumbnailView(); - virtual ~UBThumbnailView(); - signals: - void doubleClicked(); + UBThumbnailView(UBGraphicsScene *scene, QWidget* parent =0); + virtual ~UBThumbnailView() + { - protected: - virtual void drawBackground(QPainter *painter, const QRectF &rect); - virtual void mouseDoubleClickEvent ( QMouseEvent * event ); + } + + private: + QHBoxLayout* mHBoxLayout; }; diff --git a/src/gui/UBThumbnailWidget.cpp b/src/gui/UBThumbnailWidget.cpp index 95d2b4cf..748c15c0 100644 --- a/src/gui/UBThumbnailWidget.cpp +++ b/src/gui/UBThumbnailWidget.cpp @@ -34,6 +34,8 @@ #include "UBRubberBand.h" #include "UBMainWindow.h" +#include + #include "board/UBBoardController.h" #include "core/UBSettings.h" @@ -42,6 +44,8 @@ #include "document/UBDocumentProxy.h" #include "document/UBDocumentController.h" +#include "board/UBBoardPaletteManager.h" + #include "core/memcheck.h" UBThumbnailWidget::UBThumbnailWidget(QWidget* parent) @@ -225,7 +229,7 @@ void UBThumbnailWidget::mousePressEvent(QMouseEvent *event) mClickTime = QTime::currentTime(); mMousePressPos = event->pos(); - UBSceneThumbnailPixmap* sceneItem = dynamic_cast(itemAt(mMousePressPos)); + UBThumbnailPixmap* sceneItem = dynamic_cast(itemAt(mMousePressPos)); if(sceneItem==NULL) { event->ignore(); @@ -359,7 +363,7 @@ void UBThumbnailWidget::mouseMoveEvent(QMouseEvent *event) { if (lassoSelectedItem) { - UBSceneThumbnailPixmap *thumbnailItem = dynamic_cast(lassoSelectedItem); + UBThumbnailPixmap *thumbnailItem = dynamic_cast(lassoSelectedItem); if (thumbnailItem) lassoSelectedThumbnailItems += lassoSelectedItem; } @@ -385,7 +389,7 @@ void UBThumbnailWidget::mouseMoveEvent(QMouseEvent *event) { if (lassoSelectedItem) { - UBSceneThumbnailPixmap *thumbnailItem = dynamic_cast(lassoSelectedItem); + UBThumbnailPixmap *thumbnailItem = dynamic_cast(lassoSelectedItem); if (thumbnailItem) lassoSelectedThumbnailItems += lassoSelectedItem; @@ -767,163 +771,226 @@ UBThumbnail::~UBThumbnail() delete mSelectionItem; } - -UBSceneThumbnailNavigPixmap::UBSceneThumbnailNavigPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) - : UBSceneThumbnailPixmap(pix, proxy, pSceneIndex) - , bButtonsVisible(false) - , bCanDelete(false) - , bCanMoveUp(false) - , bCanMoveDown(false) +void UBWidgetTextThumbnailElement::Place(int row, int col, qreal width, qreal height) { - if(0 <= UBDocumentContainer::pageFromSceneIndex(pSceneIndex)){ - setAcceptHoverEvents(true); - setFlag(QGraphicsItem::ItemIsSelectable, true); + int labelSpacing = 0; + if(this->caption) + { + QFontMetrics fm(this->caption->font()); + labelSpacing = UBSettings::thumbnailSpacing + fm.height(); } -} + if(this->thumbnail) + { + int w = this->thumbnail->boundingRect().width(); + int h = this->thumbnail->boundingRect().height(); -UBSceneThumbnailNavigPixmap::~UBSceneThumbnailNavigPixmap() -{ + qreal scaleWidth = width / w; + qreal scaleHeight = height / h; + qreal scaleFactor = qMin(scaleWidth, scaleHeight); + UBThumbnail* pix = dynamic_cast(this->thumbnail); -} + QTransform transform; + transform.scale(scaleFactor, scaleFactor); -void UBSceneThumbnailNavigPixmap::hoverEnterEvent(QGraphicsSceneHoverEvent *event) -{ - event->accept(); - bButtonsVisible = true; - bCanDelete = true; - bCanMoveDown = false; - bCanMoveUp = false; - if(sceneIndex() < proxy()->pageCount() - 1) - bCanMoveDown = true; - if(sceneIndex() > 0) - bCanMoveUp = true; - if(proxy()->pageCount() == 1) - bCanDelete = false; - update(); -} + // Apply the scaling + this->thumbnail->setTransform(transform); + this->thumbnail->setFlag(QGraphicsItem::ItemIsSelectable, true); -void UBSceneThumbnailNavigPixmap::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) -{ - event->accept(); - bButtonsVisible = false; - update(); + if(pix) + { + pix->setColumn(col); + pix->setRow(row); + } + + QPointF pos(border + (width - w * scaleFactor) / 2 + col * (width + border), + border + row * (height + border + labelSpacing) + (height - h * scaleFactor) / 2); + + this->thumbnail->setPos(pos); + + if(this->caption) + { + QFontMetrics fm(this->caption->font()); + QString elidedText = fm.elidedText(this->caption->toPlainText(), Qt::ElideRight, width); + + this->caption->setPlainText(elidedText); + this->caption->setWidth(fm.width(elidedText) + 2 * this->caption->document()->documentMargin()); + pos.setY(pos.y() + (height + h * scaleFactor) / 2 + 5); // What is this 5 ?? + qreal labelWidth = fm.width(elidedText); + pos.setX(border + (width - labelWidth) / 2 + col * (width + border)); + this->caption->setPos(pos); + } + } } -void UBSceneThumbnailNavigPixmap::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +void UBDraggableThumbnail::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - Q_UNUSED(option); - Q_UNUSED(widget); + QGraphicsProxyWidget::paint(painter, option, widget); + using namespace UBThumbnailUI; - UBSceneThumbnailPixmap::paint(painter, option, widget); - if(bButtonsVisible) - { - if(bCanDelete) - painter->drawPixmap(0, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/close.svg")); + if (editable()) + { + if(deletable()) + draw(painter, *getIcon("close")); else - painter->drawPixmap(0, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/closeDisabled.svg")); + draw(painter, *getIcon("closeDisabled")); - painter->drawPixmap(BUTTONSIZE + BUTTONSPACING, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/duplicate.svg")); + draw(painter, *getIcon("duplicate")); - if(bCanMoveUp) - painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUp.svg")); + if(movableUp()) + draw(painter, *getIcon("moveUp")); else - painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUpDisabled.svg")); - if(bCanMoveDown) - painter->drawPixmap(3*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menu.svg")); + draw(painter, *getIcon("moveUpDisabled")); + + if(movableDown()) + draw(painter, *getIcon("moveDown")); else - painter->drawPixmap(3*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menuDisabled.svg")); + draw(painter, *getIcon("moveDownDisabled")); + } } -void UBSceneThumbnailNavigPixmap::mousePressEvent(QGraphicsSceneMouseEvent *event) +void UBDraggableThumbnail::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { - QPointF p = event->pos(); - - // Here we check the position of the click and verify if it has to trig an action or not. - if(bCanDelete && p.x() >= 0 && p.x() <= BUTTONSIZE && p.y() >= 0 && p.y() <= BUTTONSIZE) - deletePage(); - if(p.x() >= BUTTONSIZE + BUTTONSPACING && p.x() <= 2*BUTTONSIZE + BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) - duplicatePage(); - - if(bCanMoveUp && p.x() >= 2*(BUTTONSIZE + BUTTONSPACING) && p.x() <= 3*BUTTONSIZE + 2*BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) - moveUpPage(); - if(bCanMoveDown && p.x() >= 3*(BUTTONSIZE + BUTTONSPACING) && p.x() <= 4*BUTTONSIZE + 3*BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) - moveDownPage(); + event->accept(); + showUI(); + update(); +} +void UBDraggableThumbnail::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ event->accept(); + hideUI(); + update(); } -void UBSceneThumbnailNavigPixmap::deletePage() +void UBDraggableThumbnail::deletePage() { if(UBApplication::mainWindow->yesNoQuestion(QObject::tr("Remove Page"), QObject::tr("Are you sure you want to remove 1 page from the selected document '%0'?").arg(UBApplication::documentController->selectedDocument()->metaData(UBSettings::documentName).toString()))){ UBApplication::boardController->deleteScene(sceneIndex()); } } -void UBSceneThumbnailNavigPixmap::duplicatePage() +void UBDraggableThumbnail::duplicatePage() { UBApplication::boardController->duplicateScene(sceneIndex()); } -void UBSceneThumbnailNavigPixmap::moveUpPage() +void UBDraggableThumbnail::moveUpPage() { if (sceneIndex()!=0) UBApplication::boardController->moveSceneToIndex(sceneIndex(), sceneIndex() - 1); } -void UBSceneThumbnailNavigPixmap::moveDownPage() +void UBDraggableThumbnail::moveDownPage() { if (sceneIndex() < UBApplication::boardController->selectedDocument()->pageCount()-1) UBApplication::boardController->moveSceneToIndex(sceneIndex(), sceneIndex() + 1); } -void UBImgTextThumbnailElement::Place(int row, int col, qreal width, qreal height) +void UBDraggableThumbnail::mousePressEvent(QGraphicsSceneMouseEvent *event) { - int labelSpacing = 0; - if(this->caption) + event->accept(); +} + +void UBDraggableThumbnail::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + QPointF p = event->pos(); + + using namespace UBThumbnailUI; + + if (triggered(p.y())) { - QFontMetrics fm(this->caption->font()); - labelSpacing = UBSettings::thumbnailSpacing + fm.height(); + if(deletable() && getIcon("close")->triggered(p.x())) + deletePage(); + else if(getIcon("duplicate")->triggered(p.x())) + duplicatePage(); + else if(movableUp() && getIcon("moveUp")->triggered(p.x())) + moveUpPage(); + else if (movableDown() && getIcon("moveDown")->triggered(p.x())) + moveDownPage(); } - if(this->thumbnail) - { - int w = this->thumbnail->boundingRect().width(); - int h = this->thumbnail->boundingRect().height(); - qreal scaleWidth = width / w; - qreal scaleHeight = height / h; - qreal scaleFactor = qMin(scaleWidth, scaleHeight); - UBThumbnail* pix = dynamic_cast(this->thumbnail); + event->accept(); +} - QTransform transform; - transform.scale(scaleFactor, scaleFactor); - // Apply the scaling - this->thumbnail->setTransform(transform); - this->thumbnail->setFlag(QGraphicsItem::ItemIsSelectable, true); +void UBDraggableThumbnailView::updatePos(qreal width, qreal height) +{ + QFontMetrics fm(mPageNumber->font()); + int labelSpacing = UBSettings::thumbnailSpacing + fm.height(); - if(pix) - { - pix->setColumn(col); - pix->setRow(row); - } + int w = boundingRect().width(); + int h = boundingRect().height(); - QPointF pos(border + (width - w * scaleFactor) / 2 + col * (width + border), - border + row * (height + border + labelSpacing) + (height - h * scaleFactor) / 2); + qreal scaledWidth = width / w; + qreal scaledHeight = height / h; + qreal scaledFactor = qMin(scaledWidth, scaledHeight); - this->thumbnail->setPos(pos); + QTransform transform; + transform.scale(scaledFactor, scaledFactor); - if(this->caption) - { - QFontMetrics fm(this->caption->font()); - QString elidedText = fm.elidedText(this->caption->toPlainText(), Qt::ElideRight, width); + // Apply the scaling + setTransform(transform); + setFlag(QGraphicsItem::ItemIsSelectable, true); - this->caption->setPlainText(elidedText); - this->caption->setWidth(fm.width(elidedText) + 2 * this->caption->document()->documentMargin()); - pos.setY(pos.y() + (height + h * scaleFactor) / 2 + 5); // What is this 5 ?? - qreal labelWidth = fm.width(elidedText); - pos.setX(border + (width - labelWidth) / 2 + col * (width + border)); - this->caption->setPos(pos); - } - } + QPointF position((width - w * scaledFactor) / 2, + sceneIndex() * (height + labelSpacing) + (height - h * scaledFactor) / 2); + + setPos(position); + + position.setY(position.y() + (height + h * scaledFactor) / 2); + position.setX(position.x() + (w * scaledFactor - fm.width(mPageNumber->toPlainText())) / 2); + + mPageNumber->setPos(position); +} + +UBThumbnailUI::UBThumbnailUIIcon* UBThumbnailUI::addIcon(const QString& thumbnailIcon, int pos) +{ + QString thumbnailIconPath = ":images/" + thumbnailIcon + ".svg"; + UBThumbnailUIIcon* newIcon = new UBThumbnailUIIcon(thumbnailIconPath, pos); + + using namespace UBThumbnailUI::_private; + if (!newIcon) + qDebug() << "cannot add Icon : check path : " + thumbnailIconPath; + else + catalog.insert(thumbnailIcon, newIcon); + + return newIcon; +} + +UBThumbnailUI::UBThumbnailUIIcon* UBThumbnailUI::getIcon(const QString& thumbnailIcon) +{ + using namespace UBThumbnailUI::_private; + if (!catalog.contains(thumbnailIcon)) + qDebug() << "cannot get Icon: check path ':images/" + thumbnailIcon + ".svg'"; + + return catalog.value(thumbnailIcon, NULL); +} + +void UBThumbnailUI::draw(QPainter *painter, const UBThumbnailUIIcon &thumbnailIcon) +{ + using namespace UBThumbnailUI; + painter->drawPixmap(thumbnailIcon.pos() * (ICONSIZE + ICONSPACING), 0, ICONSIZE, ICONSIZE, thumbnailIcon); +} + +void UBThumbnailUI::_private::initCatalog() +{ + using namespace UBThumbnailUI; + using namespace UBThumbnailUI::_private; + + addIcon("close", 0); + addIcon("closeDisabled", 0); + + addIcon("duplicate", 1); + + addIcon("moveUp", 2); + addIcon("moveUpDisabled", 2); + + addIcon("moveDown", 3); + addIcon("moveDownDisabled", 3); +} + +bool UBThumbnailUI::triggered(qreal y) +{ + return (y >= 0 && y <= UBThumbnailUI::ICONSIZE); } diff --git a/src/gui/UBThumbnailWidget.h b/src/gui/UBThumbnailWidget.h index 8d9770ab..81d05885 100644 --- a/src/gui/UBThumbnailWidget.h +++ b/src/gui/UBThumbnailWidget.h @@ -38,10 +38,14 @@ #include "frameworks/UBCoreGraphicsScene.h" #include "core/UBSettings.h" #include "domain/UBItem.h" +#include "gui/UBThumbnailView.h" +#include "document/UBDocumentProxy.h" + +#include +#include + #define STARTDRAGTIME 1000000 -#define BUTTONSIZE 48 -#define BUTTONSPACING 5 class UBDocumentProxy; class UBThumbnailTextItem; @@ -135,7 +139,6 @@ class UBThumbnailWidget : public QGraphicsView QTime mClickTime; }; - class UBThumbnail { public: @@ -190,6 +193,8 @@ class UBThumbnail void setColumn(int column) { mColumn = column; } int row() { return mRow; } void setRow(int row) { mRow = row; } + UBThumbnailTextItem *label(){return mLabel;} + void setLabel(UBThumbnailTextItem *label){mLabel = label;} protected: QGraphicsRectItem *mSelectionItem; @@ -198,41 +203,112 @@ class UBThumbnail int mColumn; int mRow; + UBThumbnailTextItem *mLabel; }; - -class UBThumbnailSvg : public QGraphicsSvgItem, public UBThumbnail +class UBThumbnailTextItem : public QGraphicsTextItem { public: - UBThumbnailSvg(const QString& path) - : QGraphicsSvgItem(path) + UBThumbnailTextItem(int index) + : QGraphicsTextItem(tr("Page %0").arg(index+1)) + , mWidth(0) + , mUnelidedText(toPlainText()) + , mIsHighlighted(false) + { + + } + + UBThumbnailTextItem(const QString& text) + : QGraphicsTextItem(text) + , mWidth(0) + , mUnelidedText(text) + , mIsHighlighted(false) { setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); } - virtual ~UBThumbnailSvg() + QRectF boundingRect() const { return QRectF(QPointF(0.0, 0.0), QSize(mWidth, QFontMetricsF(font()).height() + 5));} + + void setWidth(qreal pWidth) { - // NOOP + if (mWidth != pWidth) + { + prepareGeometryChange(); + mWidth = pWidth; + computeText(); + } } - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) + qreal width() {return mWidth;} + + void highlight() { - QStyleOptionGraphicsItem styleOption = UBThumbnail::muteStyleOption(option); - QGraphicsSvgItem::paint(painter, &styleOption, widget); + if (!mIsHighlighted) + { + mIsHighlighted = true; + computeText(); + } } - virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value) + void computeText() { - UBThumbnail::itemChange(this, change, value); - return QGraphicsSvgItem::itemChange(change, value); + QFontMetricsF fm(font()); + QString elidedText = fm.elidedText(mUnelidedText, Qt::ElideRight, mWidth); + + if (mIsHighlighted) + { + setHtml("" + elidedText + ""); + } + else + { + setPlainText(elidedText); + } } + private: + qreal mWidth; + QString mUnelidedText; + bool mIsHighlighted; }; +class UBWidgetTextThumbnailElement +{ +protected: + QGraphicsItem* thumbnail; + UBThumbnailTextItem* caption; + int border; + +public: + UBWidgetTextThumbnailElement(QGraphicsProxyWidget* proxyWidget, UBThumbnailTextItem* text) + : thumbnail(proxyWidget) + , caption(text) + , border(0) + { + } + + QGraphicsItem* getThumbnail() const { return this->thumbnail; } + void setThumbnail(QGraphicsItem* newGItem) { this->thumbnail = newGItem; } + + UBThumbnailTextItem* getCaption() const { return this->caption; } + void setCaption(UBThumbnailTextItem* newcaption) { this->caption = newcaption; } + + void Place(int row, int col, qreal width, qreal height); + + int getBorder() const { return this->border; } + void setBorder(int newBorder) { this->border = newBorder; } +}; class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail { public: + UBThumbnailPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) + : QGraphicsPixmapItem(pix) + , mDocumentProxy(proxy) + , mSceneIndex(pSceneIndex) + { + + } + UBThumbnailPixmap(const QPixmap& pix) : QGraphicsPixmapItem(pix) { @@ -241,11 +317,6 @@ class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); } - virtual ~UBThumbnailPixmap() - { - // NOOP - } - virtual QPainterPath shape () const { QPainterPath path; @@ -253,7 +324,6 @@ class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail return path; } - virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QStyleOptionGraphicsItem styleOption = UBThumbnail::muteStyleOption(option); @@ -265,28 +335,44 @@ class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail UBThumbnail::itemChange(this, change, value); return QGraphicsPixmapItem::itemChange(change, value); } -}; + void highlight() + { -class UBSceneThumbnailPixmap : public UBThumbnailPixmap + } + + UBDocumentProxy* documentProxy() + { + return mDocumentProxy; + } + + int sceneIndex() + { + return mSceneIndex; + } + protected: + UBDocumentProxy* mDocumentProxy; + int mSceneIndex; +}; + +class UBThumbnailProxyWidget : public QGraphicsProxyWidget { public: - UBSceneThumbnailPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) - : UBThumbnailPixmap(pix) - , mProxy(proxy) - , mSceneIndex(pSceneIndex) + UBThumbnailProxyWidget(UBDocumentProxy* proxy, int index) + : mDocumentProxy(proxy) + , mSceneIndex(index) { - // NOOP + } - virtual ~UBSceneThumbnailPixmap() + UBDocumentProxy* documentProxy() { - // NOOP + return mDocumentProxy; } - UBDocumentProxy* proxy() + void setSceneIndex(int i) { - return mProxy; + mSceneIndex = i; } int sceneIndex() @@ -294,27 +380,62 @@ class UBSceneThumbnailPixmap : public UBThumbnailPixmap return mSceneIndex; } - void highlight() - { - //NOOP - } - - private: - UBDocumentProxy* mProxy; +private: + UBDocumentProxy* mDocumentProxy; int mSceneIndex; }; -class UBSceneThumbnailNavigPixmap : public UBSceneThumbnailPixmap +class UBDraggableThumbnail : public UBThumbnailProxyWidget { public: - UBSceneThumbnailNavigPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex); - ~UBSceneThumbnailNavigPixmap(); + UBDraggableThumbnail(UBDocumentProxy* documentProxy, int index) + : UBThumbnailProxyWidget(documentProxy, index) + , mEditable(false) + { + + } + + bool editable() + { + return mEditable; + } + + bool deletable() + { + return documentProxy()->pageCount() > 1; + } + + bool movableUp() + { + return sceneIndex() > 0; + } + + bool movableDown() + { + return sceneIndex() < (documentProxy()->pageCount() -1); + } + + void showUI() + { + setEditable(true); + } + + void hideUI() + { + setEditable(false); + } + + void setEditable(bool editable) + { + mEditable = editable; + } protected: void hoverEnterEvent(QGraphicsSceneHoverEvent *event); void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); private: void deletePage(); @@ -322,117 +443,104 @@ class UBSceneThumbnailNavigPixmap : public UBSceneThumbnailPixmap void moveUpPage(); void moveDownPage(); - bool bButtonsVisible; - bool bCanDelete; - bool bCanMoveUp; - bool bCanMoveDown; + bool mEditable; }; -class UBThumbnailVideo : public UBThumbnailPixmap +class UBDraggableThumbnailPixmap : public UBDraggableThumbnail { public: - UBThumbnailVideo(const QUrl &path) - : UBThumbnailPixmap(QPixmap(":/images/movie.svg")) - , mPath(path) - { - // NOOP - } - - virtual ~UBThumbnailVideo() - { - // NOOP - } - - QUrl path() - { - return mPath; - } - - private: - - QUrl mPath; + UBDraggableThumbnailPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex); + ~UBDraggableThumbnailPixmap(); }; -class UBThumbnailTextItem : public QGraphicsTextItem +class UBDraggableThumbnailView : public UBDraggableThumbnail { public: - UBThumbnailTextItem(const QString& text) - : QGraphicsTextItem(text) - , mUnelidedText(text) - , mIsHighlighted(false) + UBDraggableThumbnailView(UBThumbnailView* thumbnailView, UBDocumentProxy* documentProxy, int index) + : UBDraggableThumbnail(documentProxy, index) + , mThumbnailView(thumbnailView) + , mPageNumber(new UBThumbnailTextItem(index)) { - setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); + setFlag(QGraphicsItem::ItemIsSelectable, true); + setWidget(mThumbnailView); + setAcceptDrops(true); } - QRectF boundingRect() const { return QRectF(QPointF(0.0, 0.0), QSize(mWidth, QFontMetricsF(font()).height() + 5));} - - void setWidth(qreal pWidth) + ~UBDraggableThumbnailView() { - if (mWidth != pWidth) - { - prepareGeometryChange(); - mWidth = pWidth; - computeText(); - } - }; + delete mPageNumber; // not a child of "this" QObject so it has to be deleted manually + } - qreal width() {return mWidth;} + void updatePos(qreal w, qreal h); - void highlight() + UBThumbnailView* thumbnailView() { - if (!mIsHighlighted) - { - mIsHighlighted = true; - computeText(); - } + return mThumbnailView; } - void computeText() + UBThumbnailTextItem* pageNumber() { - QFontMetricsF fm(font()); - QString elidedText = fm.elidedText(mUnelidedText, Qt::ElideRight, mWidth); + return mPageNumber; + } - if (mIsHighlighted) - { - setHtml("" + elidedText + ""); - } - else - { - setPlainText(elidedText); - } + void setPageNumber(int i) + { + mPageNumber->setPlainText(tr("Page %0").arg(i+1)); } - private: - qreal mWidth; - QString mUnelidedText; - bool mIsHighlighted; + private: + UBThumbnailView* mThumbnailView; + UBThumbnailTextItem* mPageNumber; + }; -class UBImgTextThumbnailElement +namespace UBThumbnailUI { -private: - UBSceneThumbnailNavigPixmap* thumbnail; - UBThumbnailTextItem* caption; - int border; + const int ICONSIZE = 96; + const int ICONSPACING = 10; -public: - UBImgTextThumbnailElement(UBSceneThumbnailNavigPixmap* thumb, UBThumbnailTextItem* text): border(0) + class UBThumbnailUIIcon : public QPixmap { - this->thumbnail = thumb; - this->caption = text; - } + public: - UBSceneThumbnailNavigPixmap* getThumbnail() const { return this->thumbnail; } - void setThumbnail(UBSceneThumbnailNavigPixmap* newGItem) { this->thumbnail = newGItem; } + UBThumbnailUIIcon(const QString& filename, int pos) + : QPixmap(QSize(ICONSIZE, ICONSIZE)) + , mPos(pos) + { + QSvgRenderer svgRenderer(filename); + QPainter painter; + fill(Qt::transparent); + painter.begin(this); + svgRenderer.render(&painter); + painter.end(); + } - UBThumbnailTextItem* getCaption() const { return this->caption; } - void setCaption(UBThumbnailTextItem* newcaption) { this->caption = newcaption; } + int pos() const + { + return mPos; + } - void Place(int row, int col, qreal width, qreal height); + bool triggered(qreal x) const + { + using namespace UBThumbnailUI; + return (x >= pos()*(ICONSIZE + ICONSPACING) && x <= (pos()+1)*ICONSIZE + pos()*ICONSPACING); + } - int getBorder() const { return this->border; } - void setBorder(int newBorder) { this->border = newBorder; } -}; + private: + int mPos; + }; + + namespace _private + { + //do not use this directly + static QMap catalog; + void initCatalog(); + } + UBThumbnailUIIcon* addIcon(const QString& thumbnailIcon, int pos); + UBThumbnailUIIcon* getIcon(const QString& thumbnailIcon); + void draw(QPainter* painter, const UBThumbnailUIIcon& thumbnailIcon); + bool triggered(qreal y); +} #endif /* UBTHUMBNAILWIDGET_H_ */ diff --git a/src/gui/gui.pri b/src/gui/gui.pri index a4921eff..8f9dea58 100644 --- a/src/gui/gui.pri +++ b/src/gui/gui.pri @@ -24,7 +24,6 @@ HEADERS += src/gui/UBThumbnailView.h \ src/gui/UBActionPalette.h \ src/gui/UBFavoriteToolPalette.h \ src/gui/UBKeyboardPalette.h \ - src/gui/UBDocumentNavigator.h \ src/gui/UBDockPalette.h \ src/gui/UBPropertyPalette.h \ src/gui/UBUpdateDlg.h \ @@ -41,7 +40,8 @@ HEADERS += src/gui/UBThumbnailView.h \ src/gui/UBMessagesDialog.h \ src/gui/UBOpenSankoreImporterWidget.h \ src/gui/UBStartupHintsPalette.h \ - src/gui/UBBackgroundPalette.h + src/gui/UBBackgroundPalette.h \ + src/gui/UBBoardThumbnailsView.h SOURCES += src/gui/UBThumbnailView.cpp \ src/gui/UBFloatingPalette.cpp \ src/gui/UBToolbarButtonGroup.cpp \ @@ -68,7 +68,6 @@ SOURCES += src/gui/UBThumbnailView.cpp \ src/gui/UBActionPalette.cpp \ src/gui/UBFavoriteToolPalette.cpp \ src/gui/UBKeyboardPalette.cpp \ - src/gui/UBDocumentNavigator.cpp \ src/gui/UBDockPalette.cpp \ src/gui/UBPropertyPalette.cpp \ src/gui/UBUpdateDlg.cpp \ @@ -85,7 +84,8 @@ SOURCES += src/gui/UBThumbnailView.cpp \ src/gui/UBMessagesDialog.cpp \ src/gui/UBOpenSankoreImporterWidget.cpp \ src/gui/UBStartupHintsPalette.cpp \ - src/gui/UBBackgroundPalette.cpp + src/gui/UBBackgroundPalette.cpp \ + src/gui/UBBoardThumbnailsView.cpp win32:SOURCES += src/gui/UBKeyboardPalette_win.cpp macx:OBJECTIVE_SOURCES += src/gui/UBKeyboardPalette_mac.mm linux-g++:SOURCES += src/gui/UBKeyboardPalette_linux.cpp diff --git a/src/tools/UBGraphicsCompass.cpp b/src/tools/UBGraphicsCompass.cpp index d1282b1f..1172ee36 100644 --- a/src/tools/UBGraphicsCompass.cpp +++ b/src/tools/UBGraphicsCompass.cpp @@ -304,6 +304,7 @@ void UBGraphicsCompass::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { updateResizeCursor(); updateDrawCursor(); + mDrewCenterCross = false; event->accept(); } else if (closeButtonRect().contains(event->pos())) From 79544999501c8227c570ec834dadec71483a0003 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sun, 24 Sep 2017 18:33:26 -0400 Subject: [PATCH 054/134] Initialize forgotten member variable This ensures distance from previous point is calculated correctly --- src/domain/UBGraphicsScene.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 14f1c5e3..793cf2ce 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -326,6 +326,7 @@ UBGraphicsScene::UBGraphicsScene(UBDocumentProxy* parent, bool enableUndoRedoSta , mZoomFactor(1) , mBackgroundObject(0) , mPreviousWidth(0) + , mDistanceFromLastStrokePoint(0) , mInputDeviceIsPressed(false) , mArcPolygonItem(0) , mRenderingContext(Screen) From 08e7ae84619901f7109e8cadec46174e429be642 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 25 Sep 2017 17:31:14 +0200 Subject: [PATCH 055/134] revert previous fix + code cleaning --- src/board/UBBoardController.cpp | 1 - src/document/UBDocumentContainer.cpp | 9 +++++++++ src/document/UBDocumentContainer.h | 1 + src/document/UBDocumentController.cpp | 1 - 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index ea9f195a..68598c85 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1542,7 +1542,6 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, mActiveSceneIndex = index; setDocument(pDocumentProxy, forceReload); - emit initThumbnailsRequired(this); updateSystemScaleFactor(); mControlView->setScene(mActiveScene); diff --git a/src/document/UBDocumentContainer.cpp b/src/document/UBDocumentContainer.cpp index b63ee837..f6551cc0 100644 --- a/src/document/UBDocumentContainer.cpp +++ b/src/document/UBDocumentContainer.cpp @@ -52,6 +52,7 @@ void UBDocumentContainer::setDocument(UBDocumentProxy* document, bool forceReloa { mCurrentDocument = document; + emit initThumbnailsRequired(this); emit documentSet(mCurrentDocument); reloadThumbnails(); } @@ -103,8 +104,16 @@ void UBDocumentContainer::addPage(int index) emit addThumbnailRequired(this, index); } +void UBDocumentContainer::clearThumbPage() +{ + qDeleteAll(mDocumentThumbs); + mDocumentThumbs.clear(); +} + void UBDocumentContainer::initThumbPage() { + clearThumbPage(); + for (int i=0; i < selectedDocument()->pageCount(); i++) insertThumbPage(i); } diff --git a/src/document/UBDocumentContainer.h b/src/document/UBDocumentContainer.h index c378ddd5..a15d455f 100644 --- a/src/document/UBDocumentContainer.h +++ b/src/document/UBDocumentContainer.h @@ -53,6 +53,7 @@ class UBDocumentContainer : public QObject void duplicatePages(QList& pageIndexes); bool movePageToIndex(int source, int target); void deletePages(QList& pageIndexes); + void clearThumbPage(); void initThumbPage(); void addPage(int index); void updatePage(int index); diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index 7d3f776b..04d53136 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -476,7 +476,6 @@ void UBDocumentController::openSelectedItem() if (proxy && isOKToOpenDocument(proxy)) { UBApplication::applicationController->showBoard(); - UBApplication::applicationController->showBoard(); } } } From ccb1d8b8af72713bcdd34dc6d146ffe33894ab54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 26 Sep 2017 17:30:33 +0200 Subject: [PATCH 056/134] reverter revert workaround --- src/board/UBBoardController.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 68598c85..3e5258f6 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1545,6 +1545,8 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, updateSystemScaleFactor(); mControlView->setScene(mActiveScene); + disconnect(mControlView, SIGNAL(mouseReleased()), mActiveScene, SLOT(updateSelectionFrame())); + connect(mControlView, SIGNAL(mouseReleased()), mActiveScene, SLOT(updateSelectionFrame())); mDisplayView->setScene(mActiveScene); mActiveScene->setBackgroundZoomFactor(mControlView->transform().m11()); From 0bbc5ec812ab2ca05c90efde4cdcc13050893e71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Wed, 27 Sep 2017 09:02:01 +0200 Subject: [PATCH 057/134] changed release name to 1.4b.2 --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index 6559b873..a8dda57a 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -12,7 +12,7 @@ VERSION_MAJ = 1 VERSION_MIN = 4 VERSION_PATCH = 0 VERSION_TYPE = b # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_BUILD = 1 +VERSION_BUILD = 2 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}" From 8429a9706c233c4e76e04573d5f2cc238076b53e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 10 Oct 2017 10:42:23 +0200 Subject: [PATCH 058/134] fixed a bug where where the active scene was overwritten by the last one --- src/board/UBBoardController.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 3e5258f6..493a1a08 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1534,12 +1534,13 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, { freezeW3CWidgets(true); - persistCurrentScene(); - ClearUndoStack(); mActiveScene = targetScene; mActiveSceneIndex = index; + + persistCurrentScene(); + setDocument(pDocumentProxy, forceReload); updateSystemScaleFactor(); From 8a9edb36cc3390e23f04c9cad86b6ac930b75eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 10 Oct 2017 12:12:03 +0200 Subject: [PATCH 059/134] fixed a crash on desktop mode --- src/domain/UBGraphicsScene.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 793cf2ce..e8bdff4b 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -828,12 +828,17 @@ void UBGraphicsScene::drawPenCircle(const QPointF &pPoint) mPenCircle->setRect(QRectF(pPoint.x() - penRadius, pPoint.y() - penRadius, penDiameter, penDiameter)); - controlView()->viewport()->setCursor(QCursor (Qt::BlankCursor)); + if (controlView()) + if (controlView()->viewport()) + controlView()->viewport()->setCursor(QCursor (Qt::BlankCursor)); + mPenCircle->show(); } else { - controlView()->viewport()->setCursor(UBResources::resources()->penCursor); + if (controlView()) + if (controlView()->viewport()) + controlView()->viewport()->setCursor(UBResources::resources()->penCursor); } } From 698193a85f7db36412cf5cd65f608feb959d10e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 10 Oct 2017 12:34:56 +0200 Subject: [PATCH 060/134] Revert "Fix for screenshot tool not grabbing videos" This reverts commit b6f41165a6ba014fc5e7cd02e5a7241ebfa00803. --- src/board/UBBoardController.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 493a1a08..1a5cc5a9 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -2127,28 +2127,29 @@ QUrl UBBoardController::expandWidgetToTempDir(const QByteArray& pZipedData, cons } -/** - * @brief Take a screenshot of part of the scene - * @param pSceneRect The area to capture, in the active scene's coordinates - */ void UBBoardController::grabScene(const QRectF& pSceneRect) { if (mActiveScene) { - // Ideally we should render the scene directly to a QImage rather than use grabWindow; - // this was the previous solution but it couldn't grab videos (QGraphicsVideoItem), so it - // was changed to this admittedly more sketchy way of doing it. + QImage image(pSceneRect.width(), pSceneRect.height(), QImage::Format_ARGB32); + image.fill(Qt::transparent); + + QRectF targetRect(0, 0, pSceneRect.width(), pSceneRect.height()); + QPainter painter(&image); + painter.setRenderHint(QPainter::SmoothPixmapTransform); + painter.setRenderHint(QPainter::Antialiasing); + + mActiveScene->setRenderingContext(UBGraphicsScene::NonScreen); + mActiveScene->setRenderingQuality(UBItem::RenderingQualityHigh); - UBBoardView* view = mActiveScene->controlView(); - QPoint pos = view->viewport()->mapFromGlobal(view->mapToGlobal(view->mapFromScene(pSceneRect.topLeft()))) + QPoint(1,1); + mActiveScene->render(&painter, targetRect, pSceneRect); - qreal scale = systemScaleFactor(); - QScreen * screen = UBApplication::controlScreen(); + mActiveScene->setRenderingContext(UBGraphicsScene::Screen); +// mActiveScene->setRenderingQuality(UBItem::RenderingQualityNormal); + mActiveScene->setRenderingQuality(UBItem::RenderingQualityHigh); - QPixmap image = screen->grabWindow(view->viewport()->winId(), - pos.x(), pos.y(), pSceneRect.width()*scale - 1, pSceneRect.height()*scale - 1); - mPaletteManager->addItem(image, QPointF(0,0), 1/scale); + mPaletteManager->addItem(QPixmap::fromImage(image)); selectedDocument()->setMetaData(UBSettings::documentUpdatedAt, UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); } } From d532097e51b1e2986c4c9fc519671156a990d445 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 10 Oct 2017 14:10:40 +0200 Subject: [PATCH 061/134] fixed release build script on APT-based distros --- release_scripts/linux/package.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release_scripts/linux/package.sh b/release_scripts/linux/package.sh index f64ddec3..e600a5e6 100755 --- a/release_scripts/linux/package.sh +++ b/release_scripts/linux/package.sh @@ -348,7 +348,7 @@ for ((i=0;i<${#tab[@]};i++)); do echo -n ", " >> "$CONTROL_FILE" 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" + echo -n "${tab[$i]} (>= "`apt-cache show ${tab[$i]} | grep "Version: " | head -1 | awk '{ print $2 }' | sed -e 's/\([:. 0-9?]*\).*/\1/g' | sed -e 's/\.$//'`") " >> "$CONTROL_FILE" done echo -n ", onboard" >> "$CONTROL_FILE" From f76de41c64d7aba4241131bbf3b31bbfdeaedf2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 10 Oct 2017 16:59:27 +0200 Subject: [PATCH 062/134] fix an error where color/font pickers were attached to the wrong view --- src/domain/UBGraphicsTextItemDelegate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/UBGraphicsTextItemDelegate.cpp b/src/domain/UBGraphicsTextItemDelegate.cpp index 1c817860..06e77d36 100644 --- a/src/domain/UBGraphicsTextItemDelegate.cpp +++ b/src/domain/UBGraphicsTextItemDelegate.cpp @@ -354,7 +354,7 @@ void UBGraphicsTextItemDelegate::pickColor() { if (mDelegated && mDelegated->scene() && mDelegated->scene()->views().size() > 0) { - QColorDialog colorDialog(delegated()->defaultTextColor(), mDelegated->scene()->views().at(0)); + QColorDialog colorDialog(delegated()->defaultTextColor(), static_cast(UBApplication::boardController->controlView())); colorDialog.setWindowTitle(tr("Text Color")); if (UBSettings::settings()->isDarkBackground()) { From f2b72c44cbeacca06c0af006dd7d1994e6d2df54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 10 Oct 2017 17:26:35 +0200 Subject: [PATCH 063/134] missing include --- src/domain/UBGraphicsTextItemDelegate.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/domain/UBGraphicsTextItemDelegate.cpp b/src/domain/UBGraphicsTextItemDelegate.cpp index 06e77d36..eb117079 100644 --- a/src/domain/UBGraphicsTextItemDelegate.cpp +++ b/src/domain/UBGraphicsTextItemDelegate.cpp @@ -41,6 +41,7 @@ #include "core/UBSettings.h" #include "board/UBBoardController.h" +#include "board/UBBoardView.h" #include "core/memcheck.h" From 68521209c3964dfa5eb5d0aa1a322b2648e6beb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 10 Oct 2017 17:53:20 +0200 Subject: [PATCH 064/134] missing fix on pickFont + DontUseNativeDialog on pickColor --- src/domain/UBGraphicsTextItemDelegate.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/domain/UBGraphicsTextItemDelegate.cpp b/src/domain/UBGraphicsTextItemDelegate.cpp index eb117079..b90a9062 100644 --- a/src/domain/UBGraphicsTextItemDelegate.cpp +++ b/src/domain/UBGraphicsTextItemDelegate.cpp @@ -322,7 +322,7 @@ void UBGraphicsTextItemDelegate::pickFont() { if (mDelegated && mDelegated->scene() && mDelegated->scene()->views().size() > 0) { - QFontDialog fontDialog(delegated()->textCursor().charFormat().font(), mDelegated->scene()->views().at(0)); + QFontDialog fontDialog(delegated()->textCursor().charFormat().font(), static_cast(UBApplication::boardController->controlView())); customize(fontDialog); if (fontDialog.exec()) @@ -357,6 +357,7 @@ void UBGraphicsTextItemDelegate::pickColor() { QColorDialog colorDialog(delegated()->defaultTextColor(), static_cast(UBApplication::boardController->controlView())); colorDialog.setWindowTitle(tr("Text Color")); + colorDialog.setOption(QColorDialog::DontUseNativeDialog); if (UBSettings::settings()->isDarkBackground()) { colorDialog.setStyleSheet("background-color: white;"); From 0fd15f62a472caec0025dd42424024a70f85f5bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Thu, 12 Oct 2017 14:36:07 +0200 Subject: [PATCH 065/134] workaround to adress badly attached thumbnail views (no more time to investigate on it...) + prevent overwriting scenes --- src/board/UBBoardController.cpp | 14 ++++++++++++-- src/document/UBDocumentContainer.cpp | 2 +- src/document/UBDocumentContainer.h | 1 + src/gui/UBBoardThumbnailsView.cpp | 17 +++++++++++++++-- src/gui/UBBoardThumbnailsView.h | 1 + 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 1a5cc5a9..db428252 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1536,11 +1536,11 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, ClearUndoStack(); + persistCurrentScene(); //previous scene + mActiveScene = targetScene; mActiveSceneIndex = index; - persistCurrentScene(); - setDocument(pDocumentProxy, forceReload); updateSystemScaleFactor(); @@ -1556,6 +1556,8 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, adjustDisplayViews(); + persistCurrentScene(); //new scene + UBSettings::settings()->setDarkBackground(mActiveScene->isDarkBackground()); UBSettings::settings()->setPageBackground(mActiveScene->pageBackground()); @@ -1567,10 +1569,18 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, updateBackgroundActionsState(mActiveScene->isDarkBackground(), mActiveScene->pageBackground()); if(documentChange) + { UBGraphicsTextItem::lastUsedTextColor = QColor(); + emit initThumbnailRequired(this); + } if (sceneChange) + { emit activeSceneChanged(); + //should not be necessary, but if not called, sometimes, some views are not "connected" the first time the document is loaded + //this is a workaround to adress unexpectedly badly attached thumbnail views (no more time to investigate on it...) + emit reloadThumbnailRequired(this, mActiveSceneIndex); + } } diff --git a/src/document/UBDocumentContainer.cpp b/src/document/UBDocumentContainer.cpp index f6551cc0..3584edbb 100644 --- a/src/document/UBDocumentContainer.cpp +++ b/src/document/UBDocumentContainer.cpp @@ -92,7 +92,7 @@ void UBDocumentContainer::deletePages(QList& pageIndexes) offset++; } - + emit documentThumbnailsUpdated(this); } void UBDocumentContainer::addPage(int index) diff --git a/src/document/UBDocumentContainer.h b/src/document/UBDocumentContainer.h index a15d455f..49262cd6 100644 --- a/src/document/UBDocumentContainer.h +++ b/src/document/UBDocumentContainer.h @@ -80,6 +80,7 @@ class UBDocumentContainer : public QObject void addThumbnailRequired(UBDocumentContainer* source, int index); void removeThumbnailRequired(int index); void moveThumbnailRequired(int from, int to); + void reloadThumbnailRequired(UBDocumentContainer* source, int index); void documentThumbnailsUpdated(UBDocumentContainer* source); }; diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index 8840e45f..06e8093b 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -78,6 +78,7 @@ UBBoardThumbnailsView::UBBoardThumbnailsView(QWidget *parent, const char *name) connect(UBApplication::boardController, SIGNAL(addThumbnailRequired(UBDocumentContainer*, int)), this, SLOT(addThumbnail(UBDocumentContainer*, int)), Qt::UniqueConnection); connect(UBApplication::boardController, SIGNAL(moveThumbnailRequired(int, int)), this, SLOT(moveThumbnail(int, int)), Qt::UniqueConnection); connect(this, SIGNAL(moveThumbnailRequired(int, int)), this, SLOT(moveThumbnail(int, int)), Qt::UniqueConnection); + connect(UBApplication::boardController, SIGNAL(reloadThumbnailRequired(UBDocumentContainer*, int)), this, SLOT(reloadThumbnail(UBDocumentContainer*, int)), Qt::UniqueConnection); connect(UBApplication::boardController, SIGNAL(removeThumbnailRequired(int)), this, SLOT(removeThumbnail(int)), Qt::UniqueConnection); connect(&mLongPressTimer, SIGNAL(timeout()), this, SLOT(longPressTimeout()), Qt::UniqueConnection); @@ -94,6 +95,13 @@ void UBBoardThumbnailsView::moveThumbnail(int from, int to) updateThumbnailsPos(); } +void UBBoardThumbnailsView::reloadThumbnail(UBDocumentContainer* source, int index) +{ + removeThumbnail(index); + + addThumbnail(source, index); +} + void UBBoardThumbnailsView::removeThumbnail(int i) { UBDraggableThumbnailView* item = mThumbnails.at(i); @@ -127,7 +135,12 @@ void UBBoardThumbnailsView::addThumbnail(UBDocumentContainer* source, int i) void UBBoardThumbnailsView::clearThumbnails() { - qDeleteAll(mThumbnails); + for(int i = 0; i < mThumbnails.size(); i++) + { + scene()->removeItem(mThumbnails.at(i)->pageNumber()); + scene()->removeItem(mThumbnails.at(i)); + mThumbnails.at(i)->deleteLater(); + } mThumbnails.clear(); } @@ -211,7 +224,7 @@ void UBBoardThumbnailsView::mousePressAndHoldEvent(QPoint pos) drag->setHotSpot(QPoint(pixmap.width()/2, pixmap.height()/2)); drag->exec(); - } + } } void UBBoardThumbnailsView::mouseReleaseEvent(QMouseEvent *event) diff --git a/src/gui/UBBoardThumbnailsView.h b/src/gui/UBBoardThumbnailsView.h index 77a3b0ba..3820e4d5 100644 --- a/src/gui/UBBoardThumbnailsView.h +++ b/src/gui/UBBoardThumbnailsView.h @@ -50,6 +50,7 @@ public slots: void clearThumbnails(); void initThumbnails(UBDocumentContainer* source); void addThumbnail(UBDocumentContainer* source, int i); + void reloadThumbnail(UBDocumentContainer* source, int i); void moveThumbnail(int from, int to); void removeThumbnail(int i); From 407e4548976b5dbedb2cb181a557c1b11fdd0122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Thu, 12 Oct 2017 14:51:29 +0200 Subject: [PATCH 066/134] incresead long press interval --- src/board/UBBoardController.cpp | 2 +- src/gui/UBBoardThumbnailsView.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index db428252..a243791e 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1571,7 +1571,7 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, if(documentChange) { UBGraphicsTextItem::lastUsedTextColor = QColor(); - emit initThumbnailRequired(this); + emit initThumbnailsRequired(this); } if (sceneChange) diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index 06e8093b..22f3c90b 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -56,7 +56,7 @@ UBBoardThumbnailsView::UBBoardThumbnailsView(QWidget *parent, const char *name) , mDropSource(NULL) , mDropTarget(NULL) , mDropBar(new QGraphicsRectItem(0)) - , mLongPressInterval(150) + , mLongPressInterval(350) { setScene(new QGraphicsScene(this)); From ce2f4259c570eed2f01c2c41cbcbaf2f367ec63e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Thu, 12 Oct 2017 15:36:35 +0200 Subject: [PATCH 067/134] Revert "workaround to adress badly attached thumbnail views (no more time to investigate on it...) + prevent overwriting scenes" This reverts commit 0fd15f62a472caec0025dd42424024a70f85f5bf. --- src/board/UBBoardController.cpp | 14 ++------------ src/document/UBDocumentContainer.cpp | 2 +- src/document/UBDocumentContainer.h | 1 - src/gui/UBBoardThumbnailsView.cpp | 17 ++--------------- src/gui/UBBoardThumbnailsView.h | 1 - 5 files changed, 5 insertions(+), 30 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index a243791e..1a5cc5a9 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1536,11 +1536,11 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, ClearUndoStack(); - persistCurrentScene(); //previous scene - mActiveScene = targetScene; mActiveSceneIndex = index; + persistCurrentScene(); + setDocument(pDocumentProxy, forceReload); updateSystemScaleFactor(); @@ -1556,8 +1556,6 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, adjustDisplayViews(); - persistCurrentScene(); //new scene - UBSettings::settings()->setDarkBackground(mActiveScene->isDarkBackground()); UBSettings::settings()->setPageBackground(mActiveScene->pageBackground()); @@ -1569,18 +1567,10 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, updateBackgroundActionsState(mActiveScene->isDarkBackground(), mActiveScene->pageBackground()); if(documentChange) - { UBGraphicsTextItem::lastUsedTextColor = QColor(); - emit initThumbnailsRequired(this); - } if (sceneChange) - { emit activeSceneChanged(); - //should not be necessary, but if not called, sometimes, some views are not "connected" the first time the document is loaded - //this is a workaround to adress unexpectedly badly attached thumbnail views (no more time to investigate on it...) - emit reloadThumbnailRequired(this, mActiveSceneIndex); - } } diff --git a/src/document/UBDocumentContainer.cpp b/src/document/UBDocumentContainer.cpp index 3584edbb..f6551cc0 100644 --- a/src/document/UBDocumentContainer.cpp +++ b/src/document/UBDocumentContainer.cpp @@ -92,7 +92,7 @@ void UBDocumentContainer::deletePages(QList& pageIndexes) offset++; } - emit documentThumbnailsUpdated(this); + } void UBDocumentContainer::addPage(int index) diff --git a/src/document/UBDocumentContainer.h b/src/document/UBDocumentContainer.h index 49262cd6..a15d455f 100644 --- a/src/document/UBDocumentContainer.h +++ b/src/document/UBDocumentContainer.h @@ -80,7 +80,6 @@ class UBDocumentContainer : public QObject void addThumbnailRequired(UBDocumentContainer* source, int index); void removeThumbnailRequired(int index); void moveThumbnailRequired(int from, int to); - void reloadThumbnailRequired(UBDocumentContainer* source, int index); void documentThumbnailsUpdated(UBDocumentContainer* source); }; diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index 22f3c90b..9c4cdb05 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -78,7 +78,6 @@ UBBoardThumbnailsView::UBBoardThumbnailsView(QWidget *parent, const char *name) connect(UBApplication::boardController, SIGNAL(addThumbnailRequired(UBDocumentContainer*, int)), this, SLOT(addThumbnail(UBDocumentContainer*, int)), Qt::UniqueConnection); connect(UBApplication::boardController, SIGNAL(moveThumbnailRequired(int, int)), this, SLOT(moveThumbnail(int, int)), Qt::UniqueConnection); connect(this, SIGNAL(moveThumbnailRequired(int, int)), this, SLOT(moveThumbnail(int, int)), Qt::UniqueConnection); - connect(UBApplication::boardController, SIGNAL(reloadThumbnailRequired(UBDocumentContainer*, int)), this, SLOT(reloadThumbnail(UBDocumentContainer*, int)), Qt::UniqueConnection); connect(UBApplication::boardController, SIGNAL(removeThumbnailRequired(int)), this, SLOT(removeThumbnail(int)), Qt::UniqueConnection); connect(&mLongPressTimer, SIGNAL(timeout()), this, SLOT(longPressTimeout()), Qt::UniqueConnection); @@ -95,13 +94,6 @@ void UBBoardThumbnailsView::moveThumbnail(int from, int to) updateThumbnailsPos(); } -void UBBoardThumbnailsView::reloadThumbnail(UBDocumentContainer* source, int index) -{ - removeThumbnail(index); - - addThumbnail(source, index); -} - void UBBoardThumbnailsView::removeThumbnail(int i) { UBDraggableThumbnailView* item = mThumbnails.at(i); @@ -135,12 +127,7 @@ void UBBoardThumbnailsView::addThumbnail(UBDocumentContainer* source, int i) void UBBoardThumbnailsView::clearThumbnails() { - for(int i = 0; i < mThumbnails.size(); i++) - { - scene()->removeItem(mThumbnails.at(i)->pageNumber()); - scene()->removeItem(mThumbnails.at(i)); - mThumbnails.at(i)->deleteLater(); - } + qDeleteAll(mThumbnails); mThumbnails.clear(); } @@ -224,7 +211,7 @@ void UBBoardThumbnailsView::mousePressAndHoldEvent(QPoint pos) drag->setHotSpot(QPoint(pixmap.width()/2, pixmap.height()/2)); drag->exec(); - } + } } void UBBoardThumbnailsView::mouseReleaseEvent(QMouseEvent *event) diff --git a/src/gui/UBBoardThumbnailsView.h b/src/gui/UBBoardThumbnailsView.h index 3820e4d5..77a3b0ba 100644 --- a/src/gui/UBBoardThumbnailsView.h +++ b/src/gui/UBBoardThumbnailsView.h @@ -50,7 +50,6 @@ public slots: void clearThumbnails(); void initThumbnails(UBDocumentContainer* source); void addThumbnail(UBDocumentContainer* source, int i); - void reloadThumbnail(UBDocumentContainer* source, int i); void moveThumbnail(int from, int to); void removeThumbnail(int i); From 5343f6b9baff3698a5841ee19fcea261fa7b50b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Thu, 12 Oct 2017 16:06:15 +0200 Subject: [PATCH 068/134] new workaround for disconnected thumbnail views... to change ASAP --- src/board/UBBoardController.cpp | 8 ++++++++ src/gui/UBBoardThumbnailsView.cpp | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 1a5cc5a9..ddee19ab 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1567,10 +1567,18 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, updateBackgroundActionsState(mActiveScene->isDarkBackground(), mActiveScene->pageBackground()); if(documentChange) + { UBGraphicsTextItem::lastUsedTextColor = QColor(); + } if (sceneChange) + { + //should not be necessary, but no more time to investigate on it for the moment : + //for some reason, certain thumbnail views are not updating except if we load the document twice.... + //the only workaroud I found for the moment.. + emit initThumbnailsRequired(this); emit activeSceneChanged(); + } } diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index 9c4cdb05..cbafef4e 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -127,7 +127,13 @@ void UBBoardThumbnailsView::addThumbnail(UBDocumentContainer* source, int i) void UBBoardThumbnailsView::clearThumbnails() { - qDeleteAll(mThumbnails); + for(int i = 0; i < mThumbnails.size(); i++) + { + scene()->removeItem(mThumbnails.at(i)->pageNumber()); + scene()->removeItem(mThumbnails.at(i)); + mThumbnails.at(i)->deleteLater(); + } + mThumbnails.clear(); } From 858c100c819f6f27a0e04508c8e3aea23c1e3907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Thu, 12 Oct 2017 19:39:09 +0200 Subject: [PATCH 069/134] changed build version to 1.4.b3 --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index a8dda57a..358f63c7 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -12,7 +12,7 @@ VERSION_MAJ = 1 VERSION_MIN = 4 VERSION_PATCH = 0 VERSION_TYPE = b # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_BUILD = 2 +VERSION_BUILD = 3 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}" From cb2c435a61d2fa44453f1afd0a1ccf74150204d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Fri, 13 Oct 2017 10:14:00 +0200 Subject: [PATCH 070/134] thumb pages were not updated correctly --- src/document/UBDocumentContainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/document/UBDocumentContainer.cpp b/src/document/UBDocumentContainer.cpp index f6551cc0..3584edbb 100644 --- a/src/document/UBDocumentContainer.cpp +++ b/src/document/UBDocumentContainer.cpp @@ -92,7 +92,7 @@ void UBDocumentContainer::deletePages(QList& pageIndexes) offset++; } - + emit documentThumbnailsUpdated(this); } void UBDocumentContainer::addPage(int index) From 746382ef79ddf1b0cfdc6de9838e1100172dc34f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 23 Oct 2017 12:01:19 +0200 Subject: [PATCH 071/134] fixed some bad behaviors on thumbnail views + deactivated moveDown and moveUp icons --- src/gui/UBBoardThumbnailsView.cpp | 7 ++++++- src/gui/UBThumbnailWidget.cpp | 12 +++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index cbafef4e..651fe29f 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -186,12 +186,17 @@ void UBBoardThumbnailsView::mousePressEvent(QMouseEvent *event) { mLongPressTimer.start(); mLastPressedMousePos = event->pos(); + + UBDraggableThumbnailView* item = dynamic_cast(itemAt(event->pos())); + + if (item) + UBApplication::boardController->setActiveDocumentScene(item->sceneIndex()); + QGraphicsView::mousePressEvent(event); } void UBBoardThumbnailsView::mouseMoveEvent(QMouseEvent *event) { - mLastPressedMousePos = event->pos(); QGraphicsView::mouseMoveEvent(event); } diff --git a/src/gui/UBThumbnailWidget.cpp b/src/gui/UBThumbnailWidget.cpp index 748c15c0..07612144 100644 --- a/src/gui/UBThumbnailWidget.cpp +++ b/src/gui/UBThumbnailWidget.cpp @@ -836,6 +836,7 @@ void UBDraggableThumbnail::paint(QPainter *painter, const QStyleOptionGraphicsIt draw(painter, *getIcon("duplicate")); + /* if(movableUp()) draw(painter, *getIcon("moveUp")); else @@ -845,6 +846,7 @@ void UBDraggableThumbnail::paint(QPainter *painter, const QStyleOptionGraphicsIt draw(painter, *getIcon("moveDown")); else draw(painter, *getIcon("moveDownDisabled")); + */ } } @@ -888,11 +890,6 @@ void UBDraggableThumbnail::moveDownPage() } void UBDraggableThumbnail::mousePressEvent(QGraphicsSceneMouseEvent *event) -{ - event->accept(); -} - -void UBDraggableThumbnail::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { QPointF p = event->pos(); @@ -913,6 +910,11 @@ void UBDraggableThumbnail::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) event->accept(); } +void UBDraggableThumbnail::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + event->accept(); +} + void UBDraggableThumbnailView::updatePos(qreal width, qreal height) { From 7a9b89694ba23fc4bf97610d25c38a6bb0ac3ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Thu, 2 Nov 2017 15:42:10 +0100 Subject: [PATCH 072/134] fixed some bad behaviors around thumbnail views and document persistence --- src/board/UBBoardController.cpp | 4 ++-- src/gui/UBBoardThumbnailsView.cpp | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index ddee19ab..d813b05e 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1539,10 +1539,10 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, mActiveScene = targetScene; mActiveSceneIndex = index; - persistCurrentScene(); - setDocument(pDocumentProxy, forceReload); + persistCurrentScene(); + updateSystemScaleFactor(); mControlView->setScene(mActiveScene); diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index 651fe29f..358529da 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -183,14 +183,17 @@ void UBBoardThumbnailsView::resizeEvent(QResizeEvent *event) } void UBBoardThumbnailsView::mousePressEvent(QMouseEvent *event) -{ +{ mLongPressTimer.start(); mLastPressedMousePos = event->pos(); UBDraggableThumbnailView* item = dynamic_cast(itemAt(event->pos())); if (item) + { + UBApplication::boardController->persistCurrentScene(); UBApplication::boardController->setActiveDocumentScene(item->sceneIndex()); + } QGraphicsView::mousePressEvent(event); } @@ -202,7 +205,9 @@ void UBBoardThumbnailsView::mouseMoveEvent(QMouseEvent *event) void UBBoardThumbnailsView::longPressTimeout() { - emit mousePressAndHoldEventRequired(mLastPressedMousePos); + if (QApplication::mouseButtons() != Qt::NoButton) + emit mousePressAndHoldEventRequired(mLastPressedMousePos); + mLongPressTimer.stop(); } From 3c6b06e3328b08b35fa1057c58d8b786d946b301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Fri, 3 Nov 2017 10:22:18 +0100 Subject: [PATCH 073/134] fixed a bug where preview circles were not removed when changing stylus tool --- src/domain/UBGraphicsScene.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index e8bdff4b..43d35cda 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -2927,6 +2927,8 @@ void UBGraphicsScene::setToolCursor(int tool) tool == (int)UBStylusTool::Text || tool == (int)UBStylusTool::Play) { deselectAllItems(); + hideMarkerCircle(); + hidePenCircle(); } if (mCurrentStroke && mCurrentStroke->polygons().empty()){ From 8645c28471dcf5329c4317fdb7fd179f1bc1a26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Fri, 3 Nov 2017 10:23:39 +0100 Subject: [PATCH 074/134] highlight active thumbnail view --- src/board/UBBoardController.cpp | 3 +++ src/document/UBDocumentContainer.cpp | 2 -- src/gui/UBThumbnailWidget.h | 7 ++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index d813b05e..a4d7e249 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1598,6 +1598,9 @@ void UBBoardController::moveSceneToIndex(int source, int target) setActiveDocumentScene(target); mMovingSceneIndex = -1; + //on board thumbnails view + emit moveThumbnailRequired(source, target); + emit activeSceneChanged(); } } diff --git a/src/document/UBDocumentContainer.cpp b/src/document/UBDocumentContainer.cpp index 3584edbb..75fcc979 100644 --- a/src/document/UBDocumentContainer.cpp +++ b/src/document/UBDocumentContainer.cpp @@ -76,8 +76,6 @@ bool UBDocumentContainer::movePageToIndex(int source, int target) insertThumbPage(target); emit documentThumbnailsUpdated(this); - //on board thumbnails view - emit moveThumbnailRequired(source, target); return true; } diff --git a/src/gui/UBThumbnailWidget.h b/src/gui/UBThumbnailWidget.h index 81d05885..c0a93737 100644 --- a/src/gui/UBThumbnailWidget.h +++ b/src/gui/UBThumbnailWidget.h @@ -35,6 +35,8 @@ #include #include +#include "core/UBApplication.h" +#include "board/UBBoardController.h" #include "frameworks/UBCoreGraphicsScene.h" #include "core/UBSettings.h" #include "domain/UBItem.h" @@ -486,12 +488,15 @@ class UBDraggableThumbnailView : public UBDraggableThumbnail void setPageNumber(int i) { mPageNumber->setPlainText(tr("Page %0").arg(i+1)); + if (UBApplication::boardController->activeSceneIndex() == i) + mPageNumber->setDefaultTextColor(QColor("#6682b5")); + else + mPageNumber->setDefaultTextColor(QColor("#000000")); } private: UBThumbnailView* mThumbnailView; UBThumbnailTextItem* mPageNumber; - }; namespace UBThumbnailUI From 3822e1f360938fe70a10d38f19790e8a2ee0d631 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Fri, 3 Nov 2017 11:40:14 +0100 Subject: [PATCH 075/134] fixed a bug where thumbnail view was not centering on the active thumbnail view, when clicking on the Next Icon (main bar) --- src/gui/UBDockPalette.cpp | 2 ++ src/gui/UBDockPalette.h | 1 + 2 files changed, 3 insertions(+) diff --git a/src/gui/UBDockPalette.cpp b/src/gui/UBDockPalette.cpp index 7dda5258..0bdad23f 100644 --- a/src/gui/UBDockPalette.cpp +++ b/src/gui/UBDockPalette.cpp @@ -100,6 +100,7 @@ UBDockPalette::UBDockPalette(eUBDockPaletteType paletteType, QWidget *parent, co connect(UBDownloadManager::downloadManager(), SIGNAL(allDownloadsFinished()), this, SLOT(onAllDownloadsFinished())); connect(UBApplication::boardController,SIGNAL(documentSet(UBDocumentProxy*)),this,SLOT(onDocumentSet(UBDocumentProxy*))); + connect(this,SIGNAL(pageSelectionChangedRequired()),UBApplication::boardController,SLOT(selectionChanged())); } /** @@ -315,6 +316,7 @@ void UBDockPalette::tabClicked(int tabIndex) toggleCollapseExpand(); } mTabPalette->update(); + emit pageSelectionChangedRequired(); } /** diff --git a/src/gui/UBDockPalette.h b/src/gui/UBDockPalette.h index d13b36bf..641ded2e 100644 --- a/src/gui/UBDockPalette.h +++ b/src/gui/UBDockPalette.h @@ -152,6 +152,7 @@ public slots: signals: void mouseEntered(); + void pageSelectionChangedRequired(); protected: virtual int border(); From ae559ac3d494f7968301caf1350b0b139b7846c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Fri, 3 Nov 2017 12:15:49 +0100 Subject: [PATCH 076/134] fixed a bug where clicking on/moving a textbox by its rubberband whith stylus tool on text caused a crash (more frequent after zoom out) --- src/board/UBBoardView.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 97e8233c..6bf80853 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -1310,10 +1310,6 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event) } else if (currentTool == UBStylusTool::Text) { - UBGraphicsItem *graphicsItem = dynamic_cast(movingItem); - if (graphicsItem) - graphicsItem->Delegate()->commitUndoStep(); - bool bReleaseIsNeed = true; if (movingItem != determineItemToPress(scene()->itemAt(this->mapToScene(event->localPos().toPoint()), QTransform()))) { @@ -1321,6 +1317,10 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event) bReleaseIsNeed = false; } + UBGraphicsItem *graphicsItem = dynamic_cast(movingItem); + if (graphicsItem) + graphicsItem->Delegate()->commitUndoStep(); + if (mWidgetMoved) { mWidgetMoved = false; From 3c5d10e04ebeb80b1d1b7a3d25e89b8e5223dc86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Fri, 3 Nov 2017 14:17:18 +0100 Subject: [PATCH 077/134] disable movePage icons + drag and drop thumbnail sized correctly --- src/gui/UBBoardThumbnailsView.cpp | 2 +- src/gui/UBThumbnailWidget.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index 358529da..d37fdc02 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -219,7 +219,7 @@ void UBBoardThumbnailsView::mousePressAndHoldEvent(QPoint pos) mDropSource = item; mDropTarget = item; - QPixmap pixmap = item->widget()->grab().scaledToWidth(UBSettings::defaultThumbnailWidth); + QPixmap pixmap = item->widget()->grab().scaledToWidth(mThumbnailWidth/2); QDrag *drag = new QDrag(this); drag->setMimeData(new QMimeData()); diff --git a/src/gui/UBThumbnailWidget.cpp b/src/gui/UBThumbnailWidget.cpp index 07612144..788c7f6d 100644 --- a/src/gui/UBThumbnailWidget.cpp +++ b/src/gui/UBThumbnailWidget.cpp @@ -901,10 +901,11 @@ void UBDraggableThumbnail::mousePressEvent(QGraphicsSceneMouseEvent *event) deletePage(); else if(getIcon("duplicate")->triggered(p.x())) duplicatePage(); + /* else if(movableUp() && getIcon("moveUp")->triggered(p.x())) moveUpPage(); else if (movableDown() && getIcon("moveDown")->triggered(p.x())) - moveDownPage(); + moveDownPage();*/ } event->accept(); From a252b90828a93620c21c7076d3a1dc6f88f7ed41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Fri, 3 Nov 2017 15:33:57 +0100 Subject: [PATCH 078/134] setActiveDocumentScene on mousePressEvent, not on mouseReleaseEvent --- src/gui/UBBoardThumbnailsView.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index d37fdc02..1fec923e 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -234,11 +234,6 @@ void UBBoardThumbnailsView::mouseReleaseEvent(QMouseEvent *event) { mLongPressTimer.stop(); - UBDraggableThumbnailView* item = dynamic_cast(itemAt(event->pos())); - - if (item) - UBApplication::boardController->setActiveDocumentScene(item->sceneIndex()); - QGraphicsView::mouseReleaseEvent(event); } From 859b52b7a4eb2079d8fa81b4b25f116df6fec19d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Fri, 3 Nov 2017 16:59:55 +0100 Subject: [PATCH 079/134] fixed a bug where thumbnail views where not correctly updated/highlighted after a drag and drop --- src/board/UBBoardController.cpp | 5 +---- src/document/UBDocumentContainer.cpp | 3 ++- src/document/UBDocumentContainer.h | 1 + src/gui/UBBoardThumbnailsView.cpp | 6 ++++++ src/gui/UBBoardThumbnailsView.h | 1 + 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index a4d7e249..49f0eef8 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1586,7 +1586,6 @@ void UBBoardController::moveSceneToIndex(int source, int target) { if (selectedDocument()) { - persistCurrentScene(false,true); UBDocumentContainer::movePageToIndex(source, target); @@ -1598,10 +1597,8 @@ void UBBoardController::moveSceneToIndex(int source, int target) setActiveDocumentScene(target); mMovingSceneIndex = -1; - //on board thumbnails view - emit moveThumbnailRequired(source, target); - emit activeSceneChanged(); + emit updateThumbnailsRequired(); } } diff --git a/src/document/UBDocumentContainer.cpp b/src/document/UBDocumentContainer.cpp index 75fcc979..9bc9601c 100644 --- a/src/document/UBDocumentContainer.cpp +++ b/src/document/UBDocumentContainer.cpp @@ -75,7 +75,8 @@ bool UBDocumentContainer::movePageToIndex(int source, int target) deleteThumbPage(source); insertThumbPage(target); emit documentThumbnailsUpdated(this); - + //on board thumbnails view + emit moveThumbnailRequired(source, target); return true; } diff --git a/src/document/UBDocumentContainer.h b/src/document/UBDocumentContainer.h index a15d455f..8ee9b5c0 100644 --- a/src/document/UBDocumentContainer.h +++ b/src/document/UBDocumentContainer.h @@ -80,6 +80,7 @@ class UBDocumentContainer : public QObject void addThumbnailRequired(UBDocumentContainer* source, int index); void removeThumbnailRequired(int index); void moveThumbnailRequired(int from, int to); + void updateThumbnailsRequired(); void documentThumbnailsUpdated(UBDocumentContainer* source); }; diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index 1fec923e..74a314c6 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -78,6 +78,7 @@ UBBoardThumbnailsView::UBBoardThumbnailsView(QWidget *parent, const char *name) connect(UBApplication::boardController, SIGNAL(addThumbnailRequired(UBDocumentContainer*, int)), this, SLOT(addThumbnail(UBDocumentContainer*, int)), Qt::UniqueConnection); connect(UBApplication::boardController, SIGNAL(moveThumbnailRequired(int, int)), this, SLOT(moveThumbnail(int, int)), Qt::UniqueConnection); connect(this, SIGNAL(moveThumbnailRequired(int, int)), this, SLOT(moveThumbnail(int, int)), Qt::UniqueConnection); + connect(UBApplication::boardController, SIGNAL(updateThumbnailsRequired()), this, SLOT(updateThumbnails()), Qt::UniqueConnection); connect(UBApplication::boardController, SIGNAL(removeThumbnailRequired(int)), this, SLOT(removeThumbnail(int)), Qt::UniqueConnection); connect(&mLongPressTimer, SIGNAL(timeout()), this, SLOT(longPressTimeout()), Qt::UniqueConnection); @@ -94,6 +95,11 @@ void UBBoardThumbnailsView::moveThumbnail(int from, int to) updateThumbnailsPos(); } +void UBBoardThumbnailsView::updateThumbnails() +{ + updateThumbnailsPos(); +} + void UBBoardThumbnailsView::removeThumbnail(int i) { UBDraggableThumbnailView* item = mThumbnails.at(i); diff --git a/src/gui/UBBoardThumbnailsView.h b/src/gui/UBBoardThumbnailsView.h index 77a3b0ba..5dff6a59 100644 --- a/src/gui/UBBoardThumbnailsView.h +++ b/src/gui/UBBoardThumbnailsView.h @@ -52,6 +52,7 @@ public slots: void addThumbnail(UBDocumentContainer* source, int i); void moveThumbnail(int from, int to); void removeThumbnail(int i); + void updateThumbnails(); void longPressTimeout(); void mousePressAndHoldEvent(QPoint pos); From 9e42b0698ed1f084a99a3e60be136fe82f974e26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 6 Nov 2017 12:09:37 +0100 Subject: [PATCH 080/134] added an option in configuration file to hide/show the 'check update' action --- resources/etc/OpenBoard.config | 1 + src/core/UBApplication.cpp | 3 ++- src/core/UBSettings.cpp | 1 + src/core/UBSettings.h | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/resources/etc/OpenBoard.config b/resources/etc/OpenBoard.config index c8762800..d016619f 100644 --- a/resources/etc/OpenBoard.config +++ b/resources/etc/OpenBoard.config @@ -1,5 +1,6 @@ [App] AngleTolerance=4 +HideCheckForSoftwareUpdate=false EnableAutomaticSoftwareUpdates=true EnableSoftwareUpdates=true EnableStartupHints=true diff --git a/src/core/UBApplication.cpp b/src/core/UBApplication.cpp index b6c771c9..d26da5df 100644 --- a/src/core/UBApplication.cpp +++ b/src/core/UBApplication.cpp @@ -514,7 +514,8 @@ void UBApplication::decorateActionMenu(QAction* action) menu->addSeparator(); menu->addAction(mainWindow->actionPreferences); menu->addAction(mainWindow->actionMultiScreen); - menu->addAction(mainWindow->actionCheckUpdate); + if (!UBSettings::settings()->appHideCheckForSoftwareUpdate->get().toBool()) + menu->addAction(mainWindow->actionCheckUpdate); menu->addSeparator(); menu->addAction(mainWindow->actionPodcast); diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index 68b29e6e..2b51e724 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -234,6 +234,7 @@ void UBSettings::init() appToolBarDisplayText = new UBSetting(this, "App", "ToolBarDisplayText", true); appEnableAutomaticSoftwareUpdates = new UBSetting(this, "App", "EnableAutomaticSoftwareUpdates", false); appSoftwareUpdateURL = new UBSetting(this, "App", "SoftwareUpdateURL", "http://www.openboard.ch/update.json"); + appHideCheckForSoftwareUpdate = new UBSetting(this, "App", "HideCheckForSoftwareUpdate", false); appToolBarOrientationVertical = new UBSetting(this, "App", "ToolBarOrientationVertical", false); appPreferredLanguage = new UBSetting(this,"App","PreferredLanguage", ""); diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index 7aa121d8..e00c8e9c 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -250,6 +250,7 @@ class UBSettings : public QObject UBSetting* appToolBarDisplayText; UBSetting* appEnableAutomaticSoftwareUpdates; UBSetting* appSoftwareUpdateURL; + UBSetting* appHideCheckForSoftwareUpdate; UBSetting* appToolBarOrientationVertical; UBSetting* appPreferredLanguage; From 120ec4c37f660c0db81eb9164356c54526dbcbdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 13 Nov 2017 11:44:26 +0100 Subject: [PATCH 081/134] added an icon for 'set as background' action --- resources/OpenBoard.qrc | 1 + resources/images/setAsBackground.svg | 87 +++++++++++++++++++++++++++ src/domain/UBGraphicsItemDelegate.cpp | 4 ++ 3 files changed, 92 insertions(+) create mode 100644 resources/images/setAsBackground.svg diff --git a/resources/OpenBoard.qrc b/resources/OpenBoard.qrc index df2116b3..4f7d7765 100644 --- a/resources/OpenBoard.qrc +++ b/resources/OpenBoard.qrc @@ -358,5 +358,6 @@ images/notAligned.svg images/groupItems.svg images/ungroupItems.svg + images/setAsBackground.svg diff --git a/resources/images/setAsBackground.svg b/resources/images/setAsBackground.svg new file mode 100644 index 00000000..080542cc --- /dev/null +++ b/resources/images/setAsBackground.svg @@ -0,0 +1,87 @@ + + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/domain/UBGraphicsItemDelegate.cpp b/src/domain/UBGraphicsItemDelegate.cpp index 99dec7cb..336e7b50 100644 --- a/src/domain/UBGraphicsItemDelegate.cpp +++ b/src/domain/UBGraphicsItemDelegate.cpp @@ -710,6 +710,10 @@ void UBGraphicsItemDelegate::decorateMenu(QMenu* menu) if (delegated()->data(UBGraphicsItemData::ItemCanBeSetAsBackground).toBool()) { mSetAsBackgroundAction = mMenu->addAction(tr("Set as background"), this, SLOT(setAsBackground())); mSetAsBackgroundAction->setCheckable(false); + + QIcon backgroundIcon; + backgroundIcon.addPixmap(QPixmap(":/images/setAsBackground.svg"), QIcon::Normal, QIcon::On); + mSetAsBackgroundAction->setIcon(backgroundIcon); } if (testUBFlags(GF_SHOW_CONTENT_SOURCE)) From 021d1e08078f058bbf862b4f202ba1934758a1a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 13 Nov 2017 11:46:16 +0100 Subject: [PATCH 082/134] added missing translations --- resources/i18n/OpenBoard_ar.ts | 26 +++++++++-- resources/i18n/OpenBoard_bg.ts | 26 +++++++++-- resources/i18n/OpenBoard_ca.ts | 26 +++++++++-- resources/i18n/OpenBoard_cs.ts | 26 +++++++++-- resources/i18n/OpenBoard_da.ts | 26 +++++++++-- resources/i18n/OpenBoard_de.ts | 74 +++++++++++++++++++++++-------- resources/i18n/OpenBoard_el.ts | 26 +++++++++-- resources/i18n/OpenBoard_en.ts | 33 ++++++++------ resources/i18n/OpenBoard_en_UK.ts | 33 ++++++++------ resources/i18n/OpenBoard_es.ts | 26 +++++++++-- resources/i18n/OpenBoard_fr.ts | 34 ++++++++++++-- resources/i18n/OpenBoard_fr_CH.ts | 34 ++++++++++++-- resources/i18n/OpenBoard_iw.ts | 26 +++++++++-- resources/i18n/OpenBoard_ja.ts | 26 +++++++++-- resources/i18n/OpenBoard_ko.ts | 26 +++++++++-- resources/i18n/OpenBoard_mg.ts | 26 +++++++++-- resources/i18n/OpenBoard_nb.ts | 26 +++++++++-- resources/i18n/OpenBoard_nl.ts | 26 +++++++++-- resources/i18n/OpenBoard_pl.ts | 26 +++++++++-- resources/i18n/OpenBoard_pt.ts | 26 +++++++++-- resources/i18n/OpenBoard_ro.ts | 26 +++++++++-- resources/i18n/OpenBoard_ru.ts | 26 +++++++++-- resources/i18n/OpenBoard_sk.ts | 26 +++++++++-- resources/i18n/OpenBoard_sv.ts | 26 +++++++++-- resources/i18n/OpenBoard_tr.ts | 26 +++++++++-- resources/i18n/OpenBoard_zh.ts | 26 +++++++++-- resources/i18n/OpenBoard_zh_CN.ts | 26 +++++++++-- resources/i18n/OpenBoard_zh_TW.ts | 26 +++++++++-- 28 files changed, 662 insertions(+), 144 deletions(-) diff --git a/resources/i18n/OpenBoard_ar.ts b/resources/i18n/OpenBoard_ar.ts index 7190f110..1a16c385 100644 --- a/resources/i18n/OpenBoard_ar.ts +++ b/resources/i18n/OpenBoard_ar.ts @@ -1216,7 +1216,7 @@ UBDocumentNavigator Page %0 - صفحة %0 + صفحة %0 @@ -1252,6 +1252,13 @@ إلغاء + + UBDraggableThumbnailView + + Page %0 + صفحة %0 + + UBExportAdaptor @@ -1406,7 +1413,7 @@ Set as background - تعيين كخلفية + تعيين كخلفية Add to library @@ -1546,6 +1553,10 @@ Go to Content Source الذهاب الى مصدر المحتوى + + Set as background + تعيين كخلفية + UBGraphicsMediaItem @@ -1954,6 +1965,13 @@ Do you want to ignore these errors for this host? 1 % صور مصغرة مولّدة + + UBThumbnailTextItem + + Page %0 + صفحة %0 + + UBToolsManager @@ -2431,11 +2449,11 @@ p, li { white-space: pre-wrap; } القلم حساس للضغط - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_bg.ts b/resources/i18n/OpenBoard_bg.ts index 5bb78838..8d3c40a3 100644 --- a/resources/i18n/OpenBoard_bg.ts +++ b/resources/i18n/OpenBoard_bg.ts @@ -1212,7 +1212,7 @@ UBDocumentNavigator Page %0 - Страница %0 + Страница %0 @@ -1244,6 +1244,13 @@ Отмени + + UBDraggableThumbnailView + + Page %0 + Страница %0 + + UBExportAdaptor @@ -1398,7 +1405,7 @@ Set as background - Задай като фон + Задай като фон Add to library @@ -1538,6 +1545,10 @@ Go to Content Source Отиди към източника на съдържанието + + Set as background + Задай като фон + UBGraphicsMediaItem @@ -1952,6 +1963,13 @@ Do you want to ignore these errors for this host? %1 икони са създадени ... + + UBThumbnailTextItem + + Page %0 + Страница %0 + + UBToolsManager @@ -2426,11 +2444,11 @@ p, li { white-space: pre-wrap; } Химикалката е чувствителна на натиск - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_ca.ts b/resources/i18n/OpenBoard_ca.ts index 41a72f74..51443cf1 100644 --- a/resources/i18n/OpenBoard_ca.ts +++ b/resources/i18n/OpenBoard_ca.ts @@ -1211,7 +1211,7 @@ UBDocumentNavigator Page %0 - Pàgina %0 + Pàgina %0 @@ -1243,6 +1243,13 @@ Cancel·la + + UBDraggableThumbnailView + + Page %0 + Pàgina %0 + + UBExportAdaptor @@ -1397,7 +1404,7 @@ Set as background - Estableix com a fons + Estableix com a fons Add to library @@ -1537,6 +1544,10 @@ Go to Content Source Ves a la font de contingut + + Set as background + Estableix com a fons + UBGraphicsMediaItem @@ -1944,6 +1955,13 @@ Voleu ignorar aquests errors per a aquest amfitrió? S'han generat %1 miniatures... + + UBThumbnailTextItem + + Page %0 + Pàgina %0 + + UBToolsManager @@ -2419,11 +2437,11 @@ p, li { white-space: pre-wrap; } El llapis és sensible a la pressió - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_cs.ts b/resources/i18n/OpenBoard_cs.ts index 78678f0d..b429c870 100644 --- a/resources/i18n/OpenBoard_cs.ts +++ b/resources/i18n/OpenBoard_cs.ts @@ -1213,7 +1213,7 @@ UBDocumentNavigator Page %0 - Stránka %0 + Stránka %0 @@ -1246,6 +1246,13 @@ Zrušit + + UBDraggableThumbnailView + + Page %0 + Stránka %0 + + UBExportAdaptor @@ -1400,7 +1407,7 @@ Set as background - Nastavit jako pozadí + Nastavit jako pozadí Add to library @@ -1540,6 +1547,10 @@ Visible on Extended Screen Viditelné na rozšířené obrazovce + + Set as background + Nastavit jako pozadí + UBGraphicsMediaItem @@ -1954,6 +1965,13 @@ Chcete ignorovat tyto chyby na tomto serveru? Vytváří se miniatury obrázků ... + + UBThumbnailTextItem + + Page %0 + Stránka %0 + + UBToolsManager @@ -2429,11 +2447,11 @@ p, li { white-space: pre-wrap; } Na tmavém pozadí - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_da.ts b/resources/i18n/OpenBoard_da.ts index 53b43c09..0ee8a7c5 100644 --- a/resources/i18n/OpenBoard_da.ts +++ b/resources/i18n/OpenBoard_da.ts @@ -1211,7 +1211,7 @@ UBDocumentNavigator Page %0 - Side %0 + Side %0 @@ -1243,6 +1243,13 @@ Annuller + + UBDraggableThumbnailView + + Page %0 + Side %0 + + UBExportAdaptor @@ -1397,7 +1404,7 @@ Set as background - Brug som baggrund + Brug som baggrund Add to library @@ -1537,6 +1544,10 @@ Go to Content Source Gå til indholdskilde + + Set as background + Brug som baggrund + UBGraphicsMediaItem @@ -1951,6 +1962,13 @@ Do you want to ignore these errors for this host? %1 miniaturebilleder genereret... + + UBThumbnailTextItem + + Page %0 + Side %0 + + UBToolsManager @@ -2422,11 +2440,11 @@ p, li { white-space: pre-wrap; } Pen er tryksensitiv - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_de.ts b/resources/i18n/OpenBoard_de.ts index 3df220a5..ddc0b4c1 100644 --- a/resources/i18n/OpenBoard_de.ts +++ b/resources/i18n/OpenBoard_de.ts @@ -1211,7 +1211,7 @@ UBDocumentNavigator Page %0 - Seite %0 + Seite %0 @@ -1243,12 +1243,39 @@ Abbrechen + + UBDraggableThumbnailView + + Page %0 + Seite %0 + + UBExportAdaptor Warnings during export was appeared Warnungen beim Exportieren aufgetreten + + Exporting document... + Dokument wird exportiert... + + + Export failed + Export fehlgeschlagen + + + Unable to export to the selected location. You do not have the permissions necessary to save the file. + Export im ausgewählten Zielpfad nicht möglich. Sie haben nicht die erforderliche Berechtigung um die Datei zu speichern. + + + Export failed: location not writable + + + + Export successful. + Export erfolgreich. + UBExportCFF @@ -1285,11 +1312,11 @@ Exporting document... - Dokument wird exportiert... + Dokument wird exportiert... Export successful. - Export erfolgreich. + Export erfolgreich. Exporting %1 %2 of %3 @@ -1301,15 +1328,15 @@ Export failed: location not writable - Export fehlgeschlagen: Zielpfad nicht beschreibbar + Export fehlgeschlagen: Zielpfad nicht beschreibbar Export failed - Export fehlgeschlagen + Export fehlgeschlagen Unable to export to the selected location. You do not have the permissions necessary to save the file. - Export im ausgewählten Zielpfad nicht möglich. Sie haben nicht die erforderliche Berechtigung um die Datei zu speichern. + Export im ausgewählten Zielpfad nicht möglich. Sie haben nicht die erforderliche Berechtigung um die Datei zu speichern. @@ -1320,11 +1347,11 @@ Exporting document... - Dokument wird exportiert... + Dokument wird exportiert... Export successful. - Export erfolgreich. + Export erfolgreich. Export to PDF @@ -1332,15 +1359,15 @@ Export failed: location not writable - Export fehlgeschlagen: Zielpfad nicht beschreibbar. + Export fehlgeschlagen: Zielpfad nicht beschreibbar. Export failed - Export fehlgeschlagen + Export fehlgeschlagen Unable to export to the selected location. You do not have the permissions necessary to save the file. - Export im ausgewählten Zielpfad nicht möglich. Sie haben nicht die erforderliche Berechtigung um die Datei zu speichern. + Export im ausgewählten Zielpfad nicht möglich. Sie haben nicht die erforderliche Berechtigung um die Datei zu speichern. @@ -1351,11 +1378,11 @@ Exporting document... - Dokument wird exportiert... + Dokument wird exportiert... Export successful. - Export erfolgreich. + Export erfolgreich. Exporting page %1 of %2 @@ -1401,7 +1428,7 @@ Set as background - Als Hintergrund festlegen + Als Hintergrund festlegen Add to library @@ -1541,6 +1568,10 @@ Go to Content Source Gehen Sie zum ursprünglichen Inhalt + + Set as background + Als Hintergrund festlegen + UBGraphicsMediaItem @@ -1762,7 +1793,7 @@ Möchten Sie diese Fehler für diesen Computer ignorieren? You can always access the OpenBoard Document Importer through the Preferences panel in the About tab. Warning, if you have already imported your Open-Sankore datas, you might loose your current OpenBoard documents. - Sie können jederzeit im Einstellungsdialog im Menü "Über" auf den OpenBoard Document Importer zugreifen. Warnung, falls sie bereits Ihre Open-Sankore Daten importiert haben, können Sie Ihre aktuellen OpenBoard Dokumente verlieren. + Sie können jederzeit im Einstellungsdialog im Menü "Über" auf den OpenBoard Document Importer zugreifen. Warnung, falls sie bereits Ihre Open-Sankore Daten importiert haben, können Sie Ihre aktuellen OpenBoard Dokumente verlieren. Cancel @@ -1774,7 +1805,7 @@ Möchten Sie diese Fehler für diesen Computer ignorieren? 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. - Auf Ihrem Computer befinden sich Open-Sankoré Dokumente. Um diese in OpenBoard zu importieren drücken Sie den "Fortfahren" Knopf um die Importanwendung zu starten. + Auf Ihrem Computer befinden sich Open-Sankoré Dokumente. Um diese in OpenBoard zu importieren drücken Sie den "Fortfahren" Knopf um die Importanwendung zu starten. @@ -1955,6 +1986,13 @@ Möchten Sie diese Fehler für diesen Computer ignorieren? Miniaturansicht %1 wird erstellt... + + UBThumbnailTextItem + + Page %0 + Seite %0 + + UBToolsManager @@ -2430,11 +2468,11 @@ p, li { white-space: pre-wrap; } Der Stift ist druckempfindlich - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_el.ts b/resources/i18n/OpenBoard_el.ts index dbb56d5a..c5bd61f6 100644 --- a/resources/i18n/OpenBoard_el.ts +++ b/resources/i18n/OpenBoard_el.ts @@ -1211,7 +1211,7 @@ UBDocumentNavigator Page %0 - Σελίδα %0 + Σελίδα %0 @@ -1243,6 +1243,13 @@ Άκυρο + + UBDraggableThumbnailView + + Page %0 + Σελίδα %0 + + UBExportAdaptor @@ -1397,7 +1404,7 @@ Set as background - Ορισμός ως παρασκήνιο + Ορισμός ως παρασκήνιο Add to library @@ -1537,6 +1544,10 @@ Go to Content Source Μετάβαση στην Πηγή Περιεχομένου + + Set as background + Ορισμός ως παρασκήνιο + UBGraphicsMediaItem @@ -1951,6 +1962,13 @@ Do you want to ignore these errors for this host? %1 μικρογραφίες δημιουργήθηκαν... + + UBThumbnailTextItem + + Page %0 + Σελίδα %0 + + UBToolsManager @@ -2426,11 +2444,11 @@ p, li { white-space: pre-wrap; } Η πένα είναι ευαίσθητη στην πίεση - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_en.ts b/resources/i18n/OpenBoard_en.ts index 9088ea8f..a2b758cf 100644 --- a/resources/i18n/OpenBoard_en.ts +++ b/resources/i18n/OpenBoard_en.ts @@ -1198,13 +1198,6 @@ - - UBDocumentNavigator - - Page %0 - - - UBDocumentTreeWidget @@ -1233,6 +1226,13 @@ + + UBDraggableThumbnailView + + Page %0 + + + UBExportAdaptor @@ -1338,10 +1338,6 @@ Add to page - - Set as background - - Add to library @@ -1480,6 +1476,10 @@ Go to Content Source + + Set as background + + UBGraphicsMediaItem @@ -1865,6 +1865,13 @@ Do you want to ignore these errors for this host? + + UBThumbnailTextItem + + Page %0 + + + UBToolsManager @@ -2335,11 +2342,11 @@ p, li { white-space: pre-wrap; } - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_en_UK.ts b/resources/i18n/OpenBoard_en_UK.ts index 423c1e7d..3c656bcc 100644 --- a/resources/i18n/OpenBoard_en_UK.ts +++ b/resources/i18n/OpenBoard_en_UK.ts @@ -1198,13 +1198,6 @@ - - UBDocumentNavigator - - Page %0 - - - UBDocumentTreeWidget @@ -1233,6 +1226,13 @@ + + UBDraggableThumbnailView + + Page %0 + + + UBExportAdaptor @@ -1338,10 +1338,6 @@ Add to page - - Set as background - - Add to library @@ -1480,6 +1476,10 @@ Go to Content Source + + Set as background + + UBGraphicsMediaItem @@ -1865,6 +1865,13 @@ Do you want to ignore these errors for this host? + + UBThumbnailTextItem + + Page %0 + + + UBToolsManager @@ -2335,11 +2342,11 @@ p, li { white-space: pre-wrap; } - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_es.ts b/resources/i18n/OpenBoard_es.ts index 0c05c8c7..8d3cb58e 100644 --- a/resources/i18n/OpenBoard_es.ts +++ b/resources/i18n/OpenBoard_es.ts @@ -1211,7 +1211,7 @@ UBDocumentNavigator Page %0 - Página %0 + Página %0 @@ -1243,6 +1243,13 @@ Cancelar + + UBDraggableThumbnailView + + Page %0 + Página %0 + + UBExportAdaptor @@ -1397,7 +1404,7 @@ Set as background - Definir como fondo + Definir como fondo Add to library @@ -1537,6 +1544,10 @@ Go to Content Source Ir a fuente de contenido + + Set as background + Definir como fondo + UBGraphicsMediaItem @@ -1945,6 +1956,13 @@ Do you want to ignore these errors for this host? %1 miniaturas generadas... + + UBThumbnailTextItem + + Page %0 + Página %0 + + UBToolsManager @@ -2420,11 +2438,11 @@ p, li { white-space: pre-wrap; } El bolígrafo es sensible a la presión - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_fr.ts b/resources/i18n/OpenBoard_fr.ts index dca5946a..66613b38 100644 --- a/resources/i18n/OpenBoard_fr.ts +++ b/resources/i18n/OpenBoard_fr.ts @@ -1217,7 +1217,7 @@ UBDocumentNavigator Page %0 - Page %0 + Page %0 @@ -1249,6 +1249,13 @@ Annuler + + UBDraggableThumbnailView + + Page %0 + Page %0 + + UBExportAdaptor @@ -1429,7 +1436,7 @@ Set as background j'ai choisi de rendre le bouton plus compact (mais info moins complète) - Ajout en fond + Ajout en fond Add to library @@ -1570,6 +1577,10 @@ Go to Content Source Aller à la source du contenu + + Set as background + Mettre en fond de page + UBGraphicsMediaItem @@ -1984,6 +1995,13 @@ Voulez-vous ignorer les erreurs pour ce serveur ? %1 vignettes créées ... + + UBThumbnailTextItem + + Page %0 + Page %0 + + UBToolsManager @@ -2455,17 +2473,25 @@ p, li { white-space: pre-wrap; } Fine Fine + + Show preview circle from + Visualiser la taille depuis + Pen is Pressure Sensitive Stylet sensible à la pression Smooth strokes (experimental) - Lissage des traits (expérimental) + Lissage des traits (expérimental) Simplify strokes after drawing (experimental) - Simplification des traits post-dessin (expérimental) + Simplification des traits post-dessin (expérimental) + + + px + px diff --git a/resources/i18n/OpenBoard_fr_CH.ts b/resources/i18n/OpenBoard_fr_CH.ts index a60e44f9..5c4e6a38 100644 --- a/resources/i18n/OpenBoard_fr_CH.ts +++ b/resources/i18n/OpenBoard_fr_CH.ts @@ -1217,7 +1217,7 @@ UBDocumentNavigator Page %0 - Page %0 + Page %0 @@ -1249,6 +1249,13 @@ Annuler + + UBDraggableThumbnailView + + Page %0 + Page %0 + + UBExportAdaptor @@ -1429,7 +1436,7 @@ Set as background j'ai choisi de rendre le bouton plus compact (mais info moins complète) - Ajout en fond + mettre en fond de page Add to library @@ -1570,6 +1577,10 @@ Go to Content Source Aller à la source du contenu + + Set as background + mettre en fond de page + UBGraphicsMediaItem @@ -1984,6 +1995,13 @@ Voulez-vous ignorer les erreurs pour ce serveur ? %1 vignettes créées ... + + UBThumbnailTextItem + + Page %0 + Page %0 + + UBToolsManager @@ -2455,17 +2473,25 @@ p, li { white-space: pre-wrap; } Fine Fine + + Show preview circle from + Visualiser la taille depuis + Pen is Pressure Sensitive Stylet sensible à la pression Smooth strokes (experimental) - Lissage des traits (expérimental) + Lissage des traits (expérimental) Simplify strokes after drawing (experimental) - Simplification des traits post-dessin (expérimental) + Simplification des traits post-dessin (expérimental) + + + px + px diff --git a/resources/i18n/OpenBoard_iw.ts b/resources/i18n/OpenBoard_iw.ts index e232651e..d303522d 100644 --- a/resources/i18n/OpenBoard_iw.ts +++ b/resources/i18n/OpenBoard_iw.ts @@ -1212,7 +1212,7 @@ UBDocumentNavigator Page %0 - עמוד %0 + עמוד %0 @@ -1244,6 +1244,13 @@ בטל + + UBDraggableThumbnailView + + Page %0 + עמוד %0 + + UBExportAdaptor @@ -1399,7 +1406,7 @@ Set as background - קבע כרקע + קבע כרקע Add to library @@ -1539,6 +1546,10 @@ Go to Content Source עבור למקור התוכן + + Set as background + קבע כרקע + UBGraphicsMediaItem @@ -1948,6 +1959,13 @@ Do you want to ignore these errors for this host? נוצרה תמונה מוקטנת של %1... + + UBThumbnailTextItem + + Page %0 + עמוד %0 + + UBToolsManager @@ -2419,11 +2437,11 @@ p, li { white-space: pre-wrap; } העט רגיש ללחץ - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_ja.ts b/resources/i18n/OpenBoard_ja.ts index 977e8ae3..492517da 100644 --- a/resources/i18n/OpenBoard_ja.ts +++ b/resources/i18n/OpenBoard_ja.ts @@ -1202,7 +1202,7 @@ UBDocumentNavigator Page %0 - %0ページ + %0ページ @@ -1233,6 +1233,13 @@ キャンセル + + UBDraggableThumbnailView + + Page %0 + %0ページ + + UBExportAdaptor @@ -1387,7 +1394,7 @@ Set as background - 背景として設定 + 背景として設定 Add to library @@ -1527,6 +1534,10 @@ Go to Content Source コンテンツのソースへ移動 + + Set as background + 背景として設定 + UBGraphicsMediaItem @@ -1942,6 +1953,13 @@ Do you want to ignore these errors for this host? %1 サムネイル作成済み ... + + UBThumbnailTextItem + + Page %0 + %0ページ + + UBToolsManager @@ -2413,11 +2431,11 @@ p, li { white-space: pre-wrap; } ペンは感圧性です。 - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_ko.ts b/resources/i18n/OpenBoard_ko.ts index e8d068a9..db650365 100644 --- a/resources/i18n/OpenBoard_ko.ts +++ b/resources/i18n/OpenBoard_ko.ts @@ -1210,7 +1210,7 @@ UBDocumentNavigator Page %0 - %0 페이지 + %0 페이지 @@ -1244,6 +1244,13 @@ 취소 + + UBDraggableThumbnailView + + Page %0 + %0 페이지 + + UBExportAdaptor @@ -1398,7 +1405,7 @@ Set as background - 배경으로 지정 + 배경으로 지정 Add to library @@ -1538,6 +1545,10 @@ Go to Content Source 콘텐츠 소스로 이동 + + Set as background + 배경으로 지정 + UBGraphicsMediaItem @@ -1952,6 +1963,13 @@ Do you want to ignore these errors for this host? %1 썸네일 생성됨 ... + + UBThumbnailTextItem + + Page %0 + %0 페이지 + + UBToolsManager @@ -2427,11 +2445,11 @@ p, li { white-space: pre-wrap; } 펜은 압력 감지식입니다 - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_mg.ts b/resources/i18n/OpenBoard_mg.ts index 9d2c93e1..3f62107d 100644 --- a/resources/i18n/OpenBoard_mg.ts +++ b/resources/i18n/OpenBoard_mg.ts @@ -1211,7 +1211,7 @@ UBDocumentNavigator Page %0 - Pejy %0 + Pejy %0 @@ -1243,6 +1243,13 @@ Ajanony + + UBDraggableThumbnailView + + Page %0 + Pejy %0 + + UBExportAdaptor @@ -1397,7 +1404,7 @@ Set as background - Apetraka ambadika + Apetraka ambadika Add to library @@ -1537,6 +1544,10 @@ Go to Content Source Hande any amin'ny fototr'ilay mpiatiny + + Set as background + Apetraka ambadika + UBGraphicsMediaItem @@ -1951,6 +1962,13 @@ Tena tsy te hiraharaha an'ireo tsy mety ho an'ilay milina ve ianao?%1 ny kisarisary no voaforona ... + + UBThumbnailTextItem + + Page %0 + Pejy %0 + + UBToolsManager @@ -2426,11 +2444,11 @@ p, li { white-space: pre-wrap; } Ny penina dia sarotiny amin'ny fitsindrina - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_nb.ts b/resources/i18n/OpenBoard_nb.ts index e0f6296f..016852b4 100644 --- a/resources/i18n/OpenBoard_nb.ts +++ b/resources/i18n/OpenBoard_nb.ts @@ -1212,7 +1212,7 @@ UBDocumentNavigator Page %0 - Side %0 + Side %0 @@ -1244,6 +1244,13 @@ Avbryt + + UBDraggableThumbnailView + + Page %0 + Side %0 + + UBExportAdaptor @@ -1398,7 +1405,7 @@ Set as background - Bruk som bakgrunn + Bruk som bakgrunn Add to library @@ -1538,6 +1545,10 @@ Go to Content Source Gå til kildeinnhold + + Set as background + Bruk som bakgrunn + UBGraphicsMediaItem @@ -1947,6 +1958,13 @@ Do you want to ignore these errors for this host? %1 miniatyrbilder generert ... + + UBThumbnailTextItem + + Page %0 + Side %0 + + UBToolsManager @@ -2421,11 +2439,11 @@ p, li { white-space: pre-wrap; } Pennen er trykksensitiv - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_nl.ts b/resources/i18n/OpenBoard_nl.ts index 1b2211c9..4770b569 100644 --- a/resources/i18n/OpenBoard_nl.ts +++ b/resources/i18n/OpenBoard_nl.ts @@ -1203,7 +1203,7 @@ UBDocumentNavigator Page %0 - Pagina %0 + Pagina %0 @@ -1235,6 +1235,13 @@ Annuleren + + UBDraggableThumbnailView + + Page %0 + Pagina %0 + + UBExportAdaptor @@ -1389,7 +1396,7 @@ Set as background - Als achtergrond gebruiken + Als achtergrond gebruiken Add to library @@ -1529,6 +1536,10 @@ Go to Content Source Naar inhoudsbron + + Set as background + Als achtergrond gebruiken + UBGraphicsMediaItem @@ -1937,6 +1948,13 @@ Do you want to ignore these errors for this host? %1 miniaturen opgeladen... + + UBThumbnailTextItem + + Page %0 + Pagina %0 + + UBToolsManager @@ -2411,11 +2429,11 @@ p, li { white-space: pre-wrap; } Pen is drukgevoelig - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_pl.ts b/resources/i18n/OpenBoard_pl.ts index c8cbd911..2d458738 100644 --- a/resources/i18n/OpenBoard_pl.ts +++ b/resources/i18n/OpenBoard_pl.ts @@ -1216,7 +1216,7 @@ UBDocumentNavigator Page %0 - Strona %0 + Strona %0 @@ -1250,6 +1250,13 @@ Anuluj + + UBDraggableThumbnailView + + Page %0 + Strona %0 + + UBExportAdaptor @@ -1404,7 +1411,7 @@ Set as background - Ustaw jako tło + Ustaw jako tło Add to library @@ -1544,6 +1551,10 @@ Go to Content Source Przejdź do źródła zawartości + + Set as background + Ustaw jako tło + UBGraphicsMediaItem @@ -1958,6 +1969,13 @@ Czy chcesz ignorować te błędy dla tego hosta? Wygenerowano %1 miniatur... + + UBThumbnailTextItem + + Page %0 + Strona %0 + + UBToolsManager @@ -2437,11 +2455,11 @@ p, li { white-space: pre-wrap; } Pióro jest czułe na nacisk - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_pt.ts b/resources/i18n/OpenBoard_pt.ts index 153067ba..51e504f0 100644 --- a/resources/i18n/OpenBoard_pt.ts +++ b/resources/i18n/OpenBoard_pt.ts @@ -1213,7 +1213,7 @@ UBDocumentNavigator Page %0 - Página %0 + Página %0 @@ -1245,6 +1245,13 @@ Cancelar + + UBDraggableThumbnailView + + Page %0 + Página %0 + + UBExportAdaptor @@ -1423,7 +1430,7 @@ Set as background - Definir como fundo + Definir como fundo Add to library @@ -1564,6 +1571,10 @@ Go to Content Source Ir para a Fonte do Conteúdo + + Set as background + Definir como fundo + UBGraphicsMediaItem @@ -1971,6 +1982,13 @@ Quer ignorar estes erros, deste servidor? %1 de miniaturas geradas ... + + UBThumbnailTextItem + + Page %0 + Página %0 + + UBToolsManager @@ -2448,11 +2466,11 @@ p, li { white-space: pre-wrap; } Caneta sensível à pressão - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_ro.ts b/resources/i18n/OpenBoard_ro.ts index 12224ea9..28e332cc 100644 --- a/resources/i18n/OpenBoard_ro.ts +++ b/resources/i18n/OpenBoard_ro.ts @@ -1211,7 +1211,7 @@ UBDocumentNavigator Page %0 - Pagina %0 + Pagina %0 @@ -1243,6 +1243,13 @@ Anulare + + UBDraggableThumbnailView + + Page %0 + Pagina %0 + + UBExportAdaptor @@ -1397,7 +1404,7 @@ Set as background - Setare ca fundal + Setare ca fundal Add to library @@ -1537,6 +1544,10 @@ Go to Content Source Accesare sursă conţinut + + Set as background + Setare ca fundal + UBGraphicsMediaItem @@ -1951,6 +1962,13 @@ Doriţi să ignoraţi aceste erori pentru acest host? %1 miniaturi generate ... + + UBThumbnailTextItem + + Page %0 + Pagina %0 + + UBToolsManager @@ -2426,11 +2444,11 @@ p, li { white-space: pre-wrap; } Stiloul este sensibil la apăsare - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_ru.ts b/resources/i18n/OpenBoard_ru.ts index 916cd852..1b524491 100644 --- a/resources/i18n/OpenBoard_ru.ts +++ b/resources/i18n/OpenBoard_ru.ts @@ -1211,7 +1211,7 @@ UBDocumentNavigator Page %0 - Страница %0 + Страница %0 @@ -1243,6 +1243,13 @@ Отмена + + UBDraggableThumbnailView + + Page %0 + Страница %0 + + UBExportAdaptor @@ -1397,7 +1404,7 @@ Set as background - Сделать фоновым изображением + Сделать фоновым изображением Add to library @@ -1537,6 +1544,10 @@ Go to Content Source Перейти к источнику содержимого + + Set as background + Сделать фоновым изображением + UBGraphicsMediaItem @@ -1951,6 +1962,13 @@ Do you want to ignore these errors for this host? сгенерированы эскизы %1... + + UBThumbnailTextItem + + Page %0 + Страница %0 + + UBToolsManager @@ -2426,11 +2444,11 @@ p, li { white-space: pre-wrap; } Перо чувствительно к нажиму - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_sk.ts b/resources/i18n/OpenBoard_sk.ts index 143a28fa..32f85cb6 100644 --- a/resources/i18n/OpenBoard_sk.ts +++ b/resources/i18n/OpenBoard_sk.ts @@ -1216,7 +1216,7 @@ UBDocumentNavigator Page %0 - Stránka %0 + Stránka %0 @@ -1249,6 +1249,13 @@ Zrušiť + + UBDraggableThumbnailView + + Page %0 + Stránka %0 + + UBExportAdaptor @@ -1427,7 +1434,7 @@ Set as background - Nastaviť ako pozadie + Nastaviť ako pozadie Add to library @@ -1567,6 +1574,10 @@ Visible on Extended Screen Zobraziť na rozšírenej obrazovke + + Set as background + Nastaviť ako pozadie + UBGraphicsMediaItem @@ -1983,6 +1994,13 @@ Chcete ignorovať tieto chyby na tomto serveri? Vytvárajú sa ukážky miniatúr... + + UBThumbnailTextItem + + Page %0 + Stránka %0 + + UBToolsManager @@ -2459,11 +2477,11 @@ p, li { white-space: pre-wrap; } Na tmavom pozadí - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_sv.ts b/resources/i18n/OpenBoard_sv.ts index 5f736c78..c96c3c8a 100644 --- a/resources/i18n/OpenBoard_sv.ts +++ b/resources/i18n/OpenBoard_sv.ts @@ -1212,7 +1212,7 @@ UBDocumentNavigator Page %0 - Sida %0 + Sida %0 @@ -1244,6 +1244,13 @@ Avsluta + + UBDraggableThumbnailView + + Page %0 + Sida %0 + + UBExportAdaptor @@ -1398,7 +1405,7 @@ Set as background - Infoga som bakgrund + Infoga som bakgrund Add to library @@ -1538,6 +1545,10 @@ Go to Content Source Gå till innehållskällan + + Set as background + Infoga som bakgrund + UBGraphicsMediaItem @@ -1952,6 +1963,13 @@ Vill du ignorera felen för den här värden? %1 miniatybil genererad ... + + UBThumbnailTextItem + + Page %0 + Sida %0 + + UBToolsManager @@ -2427,11 +2445,11 @@ p, li { white-space: pre-wrap; } Pennan är tryckkänslig - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_tr.ts b/resources/i18n/OpenBoard_tr.ts index b3fefd7d..ecdb5d00 100644 --- a/resources/i18n/OpenBoard_tr.ts +++ b/resources/i18n/OpenBoard_tr.ts @@ -1210,7 +1210,7 @@ UBDocumentNavigator Page %0 - Sayfa %0 + Sayfa %0 @@ -1242,6 +1242,13 @@ İptal + + UBDraggableThumbnailView + + Page %0 + Sayfa %0 + + UBExportAdaptor @@ -1396,7 +1403,7 @@ Set as background - Arkaplan olarak tanımla + Arkaplan olarak tanımla Add to library @@ -1536,6 +1543,10 @@ Go to Content Source İçerik Kaynağına Git + + Set as background + Arkaplan olarak tanımla + UBGraphicsMediaItem @@ -1949,6 +1960,13 @@ Bu host için yukarıdaki hatalar yok sayılsın mı? %1 adet önizleme resmi oluşturuldu ... + + UBThumbnailTextItem + + Page %0 + Sayfa %0 + + UBToolsManager @@ -2424,11 +2442,11 @@ p, li { white-space: pre-wrap; } Kalem Basınca Duyarlıdır - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_zh.ts b/resources/i18n/OpenBoard_zh.ts index af14e1f9..d926ecd3 100644 --- a/resources/i18n/OpenBoard_zh.ts +++ b/resources/i18n/OpenBoard_zh.ts @@ -1210,7 +1210,7 @@ UBDocumentNavigator Page %0 - 页面 %0 + 页面 %0 @@ -1241,6 +1241,13 @@ 取消 + + UBDraggableThumbnailView + + Page %0 + 页面 %0 + + UBExportAdaptor @@ -1395,7 +1402,7 @@ Set as background - 设置为背景 + 设置为背景 Add to library @@ -1535,6 +1542,10 @@ Go to Content Source 访问内容来源 + + Set as background + 设置为背景 + UBGraphicsMediaItem @@ -1949,6 +1960,13 @@ Do you want to ignore these errors for this host? 已为%1生成缩略图…… + + UBThumbnailTextItem + + Page %0 + 页面 %0 + + UBToolsManager @@ -2424,11 +2442,11 @@ p, li { white-space: pre-wrap; } 使用压感笔 - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_zh_CN.ts b/resources/i18n/OpenBoard_zh_CN.ts index af14e1f9..d926ecd3 100644 --- a/resources/i18n/OpenBoard_zh_CN.ts +++ b/resources/i18n/OpenBoard_zh_CN.ts @@ -1210,7 +1210,7 @@ UBDocumentNavigator Page %0 - 页面 %0 + 页面 %0 @@ -1241,6 +1241,13 @@ 取消 + + UBDraggableThumbnailView + + Page %0 + 页面 %0 + + UBExportAdaptor @@ -1395,7 +1402,7 @@ Set as background - 设置为背景 + 设置为背景 Add to library @@ -1535,6 +1542,10 @@ Go to Content Source 访问内容来源 + + Set as background + 设置为背景 + UBGraphicsMediaItem @@ -1949,6 +1960,13 @@ Do you want to ignore these errors for this host? 已为%1生成缩略图…… + + UBThumbnailTextItem + + Page %0 + 页面 %0 + + UBToolsManager @@ -2424,11 +2442,11 @@ p, li { white-space: pre-wrap; } 使用压感笔 - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px diff --git a/resources/i18n/OpenBoard_zh_TW.ts b/resources/i18n/OpenBoard_zh_TW.ts index cf800729..e8085aa0 100644 --- a/resources/i18n/OpenBoard_zh_TW.ts +++ b/resources/i18n/OpenBoard_zh_TW.ts @@ -1210,7 +1210,7 @@ UBDocumentNavigator Page %0 - 第 %0 頁 + 第 %0 頁 @@ -1241,6 +1241,13 @@ 取消 + + UBDraggableThumbnailView + + Page %0 + 第 %0 頁 + + UBExportAdaptor @@ -1395,7 +1402,7 @@ Set as background - 設定成背景 + 設定成背景 Add to library @@ -1535,6 +1542,10 @@ Go to Content Source 至內容來源 + + Set as background + 設定成背景 + UBGraphicsMediaItem @@ -1936,6 +1947,13 @@ Do you want to ignore these errors for this host? 已產生縮圖 %1... + + UBThumbnailTextItem + + Page %0 + 第 %0 頁 + + UBToolsManager @@ -2411,11 +2429,11 @@ p, li { white-space: pre-wrap; } 感壓筆 - Smooth strokes (experimental) + Show preview circle from - Simplify strokes after drawing (experimental) + px From 34b9365928978dee0bfa5bb39b383d29116c09aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 13 Nov 2017 12:39:26 +0100 Subject: [PATCH 083/134] fixed a bug where visibility state on extended screen was not persisted for strokes --- src/adaptors/UBSvgSubsetAdaptor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 2c3b04e9..63ad5c69 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -1217,6 +1217,9 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(UBDocumentProxy* proxy, if (!locked.isNull() && locked.toBool()) mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "locked", xmlTrue); + QVariant layer = sg->data(UBGraphicsItemData::ItemLayerType); + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "layer", QString("%1").arg(layer.toInt())); + QMatrix matrix = sg->sceneMatrix(); if (!matrix.isIdentity()) mXmlWriter.writeAttribute("transform", toSvgTransform(matrix)); From 773dab5cf7ab66832cd30cf4d89343ebccc3a734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 13 Nov 2017 14:18:30 +0100 Subject: [PATCH 084/134] persist view position on each scene of a document (only during session) --- src/board/UBBoardController.cpp | 22 +++++++++++++++++++++- src/board/UBBoardController.h | 1 + src/core/UBApplicationController.cpp | 5 +---- src/domain/UBGraphicsScene.cpp | 10 ++++++++++ src/domain/UBGraphicsScene.h | 19 +++++++++++++++++-- src/gui/UBBoardThumbnailsView.cpp | 2 ++ 6 files changed, 52 insertions(+), 7 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 49f0eef8..53f94efb 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -503,6 +503,7 @@ void UBBoardController::stylusToolDoubleClicked(int tool) else if (tool == UBStylusTool::Hand) { centerRestore(); + mActiveScene->setLastCenter(QPointF(0,0)); } } @@ -511,6 +512,7 @@ void UBBoardController::stylusToolDoubleClicked(int tool) void UBBoardController::addScene() { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + persistViewPositionOnCurrentScene(); persistCurrentScene(false,true); UBDocumentContainer::addPage(mActiveSceneIndex + 1); @@ -790,6 +792,8 @@ void UBBoardController::clearScene() { freezeW3CWidgets(true); mActiveScene->clearContent(UBGraphicsScene::clearItemsAndAnnotations); + mActiveScene->setLastCenter(QPointF(0,0)); + mControlView->centerOn(mActiveScene->lastCenter()); updateActionStates(); } } @@ -959,14 +963,23 @@ void UBBoardController::handScroll(qreal dx, qreal dy) emit controlViewportChanged(); } +void UBBoardController::persistViewPositionOnCurrentScene() +{ + QRect rect = mControlView->rect(); + QPoint center(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2); + QPointF viewRelativeCenter = mControlView->mapToScene(center); + mActiveScene->setLastCenter(viewRelativeCenter); +} void UBBoardController::previousScene() { if (mActiveSceneIndex > 0) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + persistViewPositionOnCurrentScene(); persistCurrentScene(); setActiveDocumentScene(mActiveSceneIndex - 1); + mControlView->centerOn(mActiveScene->lastCenter()); QApplication::restoreOverrideCursor(); } @@ -979,8 +992,10 @@ void UBBoardController::nextScene() if (mActiveSceneIndex < selectedDocument()->pageCount() - 1) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + persistViewPositionOnCurrentScene(); persistCurrentScene(); setActiveDocumentScene(mActiveSceneIndex + 1); + mControlView->centerOn(mActiveScene->lastCenter()); QApplication::restoreOverrideCursor(); } @@ -993,8 +1008,10 @@ void UBBoardController::firstScene() if (mActiveSceneIndex > 0) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + persistViewPositionOnCurrentScene(); persistCurrentScene(); setActiveDocumentScene(0); + mControlView->centerOn(mActiveScene->lastCenter()); QApplication::restoreOverrideCursor(); } @@ -1007,8 +1024,10 @@ void UBBoardController::lastScene() if (mActiveSceneIndex < selectedDocument()->pageCount() - 1) { QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + persistViewPositionOnCurrentScene(); persistCurrentScene(); setActiveDocumentScene(selectedDocument()->pageCount() - 1); + mControlView->centerOn(mActiveScene->lastCenter()); QApplication::restoreOverrideCursor(); } @@ -2093,7 +2112,8 @@ void UBBoardController::saveViewState() { mActiveScene->setViewState(UBGraphicsScene::SceneViewState(currentZoom(), mControlView->horizontalScrollBar()->value(), - mControlView->verticalScrollBar()->value())); + mControlView->verticalScrollBar()->value(), + mActiveScene->lastCenter())); } } diff --git a/src/board/UBBoardController.h b/src/board/UBBoardController.h index 1b66c1e8..da3ee403 100644 --- a/src/board/UBBoardController.h +++ b/src/board/UBBoardController.h @@ -159,6 +159,7 @@ class UBBoardController : public UBDocumentContainer return mSystemScaleFactor; } qreal currentZoom(); + void persistViewPositionOnCurrentScene(); void persistCurrentScene(bool isAnAutomaticBackup = false, bool forceImmediateSave = false); void showNewVersionAvailable(bool automatic, const UBVersion &installedVersion, const UBSoftwareUpdate &softwareUpdate); void setBoxing(QRect displayRect); diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index d8bdc89f..030a0da0 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -233,15 +233,12 @@ void UBApplicationController::adjustDisplayView() tr.scale(scaleFactor, scaleFactor); - QRect rect = mControlView->rect(); - QPoint center(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2); - QTransform recentTransform = mDisplayView->transform(); if (recentTransform != tr) mDisplayView->setTransform(tr); - mDisplayView->centerOn(mControlView->mapToScene(center)); + mDisplayView->centerOn(UBApplication::boardController->activeScene()->lastCenter()); } } diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 43d35cda..f120ff3a 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -385,6 +385,16 @@ void UBGraphicsScene::selectionChangedProcessing() } } +void UBGraphicsScene::setLastCenter(QPointF center) +{ + mViewState.setLastSceneCenter(center); +} + +QPointF UBGraphicsScene::lastCenter() +{ + return mViewState.lastSceneCenter(); +} + bool UBGraphicsScene::inputDevicePress(const QPointF& scenePos, const qreal& pressure) { bool accepted = false; diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h index 1f1b2a1e..91625103 100644 --- a/src/domain/UBGraphicsScene.h +++ b/src/domain/UBGraphicsScene.h @@ -156,7 +156,8 @@ class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem UBGraphicsW3CWidgetItem* addW3CWidget(const QUrl& pWidgetUrl, const QPointF& pPos = QPointF(0, 0)); void addGraphicsWidget(UBGraphicsWidgetItem* graphicsWidget, const QPointF& pPos = QPointF(0, 0)); - + QPointF lastCenter(); + void setLastCenter(QPointF center); UBGraphicsMediaItem* addMedia(const QUrl& pMediaFileUrl, bool shouldPlayAsap, const QPointF& pPos = QPointF(0, 0)); UBGraphicsMediaItem* addVideo(const QUrl& pVideoFileUrl, bool shouldPlayAsap, const QPointF& pPos = QPointF(0, 0)); @@ -256,15 +257,29 @@ class UBGraphicsScene: public UBCoreGraphicsScene, public UBItem zoomFactor = 1; horizontalPosition = 0; verticalPostition = 0; + mLastSceneCenter = QPointF(); } - SceneViewState(qreal pZoomFactor, int pHorizontalPosition, int pVerticalPostition) + SceneViewState(qreal pZoomFactor, int pHorizontalPosition, int pVerticalPostition, QPointF sceneCenter = QPointF())// 1595/1605 { zoomFactor = pZoomFactor; horizontalPosition = pHorizontalPosition; verticalPostition = pVerticalPostition; + mLastSceneCenter = sceneCenter; + } + + QPointF lastSceneCenter() // Save Scene Center to replace the view when the scene becomes active + { + return mLastSceneCenter; } + void setLastSceneCenter(QPointF center) + { + mLastSceneCenter = center; + } + + QPointF mLastSceneCenter; + qreal zoomFactor; int horizontalPosition; int verticalPostition; diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index 74a314c6..ee90f077 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -197,8 +197,10 @@ void UBBoardThumbnailsView::mousePressEvent(QMouseEvent *event) if (item) { + UBApplication::boardController->persistViewPositionOnCurrentScene(); UBApplication::boardController->persistCurrentScene(); UBApplication::boardController->setActiveDocumentScene(item->sceneIndex()); + UBApplication::boardController->centerOn(UBApplication::boardController->activeScene()->lastCenter()); } QGraphicsView::mousePressEvent(event); From d4a3a1984544be3a719c0ea0e06c93b3b641be5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 13 Nov 2017 14:35:42 +0100 Subject: [PATCH 085/134] same behavior as Marker Circle for pen circle --- src/board/UBBoardView.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 6bf80853..311d9f25 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -1719,12 +1719,7 @@ void UBBoardView::setToolCursor (int tool) switch (tool) { case UBStylusTool::Pen: - if (UBSettings::settings()->showPenPreviewCircle->get().toBool() && - UBSettings::settings()->currentPenWidth() >= UBSettings::settings()->penPreviewFromSize->get().toInt()) { - controlViewport->setCursor (QCursor (Qt::BlankCursor)); - } else { - controlViewport->setCursor (UBResources::resources ()->penCursor); - } + controlViewport->setCursor (UBResources::resources ()->penCursor); break; case UBStylusTool::Eraser: controlViewport->setCursor (UBResources::resources ()->eraserCursor); From 79c09ab665c0d1d34cfcd2cbfd2a3a3e51b177c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 14 Nov 2017 10:34:51 +0100 Subject: [PATCH 086/134] improved active scene lisibility and changed color + fix update view on dropEvent --- src/gui/UBBoardThumbnailsView.cpp | 2 ++ src/gui/UBThumbnailWidget.h | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index ee90f077..aca126c4 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -317,4 +317,6 @@ void UBBoardThumbnailsView::dropEvent(QDropEvent *event) mDropSource = NULL; mDropTarget = NULL; mDropBar->hide(); + + update(); } diff --git a/src/gui/UBThumbnailWidget.h b/src/gui/UBThumbnailWidget.h index c0a93737..64b1bf77 100644 --- a/src/gui/UBThumbnailWidget.h +++ b/src/gui/UBThumbnailWidget.h @@ -488,10 +488,11 @@ class UBDraggableThumbnailView : public UBDraggableThumbnail void setPageNumber(int i) { mPageNumber->setPlainText(tr("Page %0").arg(i+1)); + if (UBApplication::boardController->activeSceneIndex() == i) - mPageNumber->setDefaultTextColor(QColor("#6682b5")); + mPageNumber->setHtml("" + tr("Page %0").arg(i+1) + ""); else - mPageNumber->setDefaultTextColor(QColor("#000000")); + mPageNumber->setHtml("" + tr("Page %0").arg(i+1) + ""); } private: From a28b58992ee8ffa67af190c53ecf2e8332bbc6aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 14 Nov 2017 11:34:27 +0100 Subject: [PATCH 087/134] changed build version to 1.4-b4 --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index 358f63c7..effc516a 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -12,7 +12,7 @@ VERSION_MAJ = 1 VERSION_MIN = 4 VERSION_PATCH = 0 VERSION_TYPE = b # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_BUILD = 3 +VERSION_BUILD = 4 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}" From 1f9a4858e1532df092564a1594422dbf7b509e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 20 Nov 2017 15:21:23 +0100 Subject: [PATCH 088/134] replaced previous workaround on thumbnail views by a fix --- src/board/UBBoardController.cpp | 5 +---- src/core/UBPersistenceManager.cpp | 3 ++- src/gui/UBBoardThumbnailsView.cpp | 6 ++++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 53f94efb..78afff8b 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1592,10 +1592,6 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, if (sceneChange) { - //should not be necessary, but no more time to investigate on it for the moment : - //for some reason, certain thumbnail views are not updating except if we load the document twice.... - //the only workaroud I found for the moment.. - emit initThumbnailsRequired(this); emit activeSceneChanged(); } } @@ -1810,6 +1806,7 @@ void UBBoardController::selectionChanged() { updateActionStates(); emit pageSelectionChanged(activeSceneIndex()); + emit updateThumbnailsRequired(); } diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index e2dc31ea..543853b0 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -179,10 +179,11 @@ void UBPersistenceManager::errorString(QString error) void UBPersistenceManager::onSceneLoaded(QByteArray scene, UBDocumentProxy* proxy, int sceneIndex) { + Q_UNUSED(scene); qDebug() << "scene loaded " << sceneIndex; QTime time; time.start(); - mSceneCache.insert(proxy,sceneIndex,UBSvgSubsetAdaptor::loadScene(proxy,scene)); + mSceneCache.insert(proxy, sceneIndex, loadDocumentScene(proxy, sceneIndex)); qDebug() << "millisecond for sceneCache " << time.elapsed(); } diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index aca126c4..f2e0f23f 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -175,6 +175,7 @@ void UBBoardThumbnailsView::updateThumbnailsPos() } scene()->setSceneRect(scene()->itemsBoundingRect()); + update(); } void UBBoardThumbnailsView::resizeEvent(QResizeEvent *event) @@ -312,11 +313,12 @@ void UBBoardThumbnailsView::dropEvent(QDropEvent *event) { Q_UNUSED(event); - UBApplication::boardController->moveSceneToIndex(mDropSource->sceneIndex(), mDropTarget->sceneIndex()); + if (mDropSource->sceneIndex() != mDropTarget->sceneIndex()) + UBApplication::boardController->moveSceneToIndex(mDropSource->sceneIndex(), mDropTarget->sceneIndex()); mDropSource = NULL; mDropTarget = NULL; mDropBar->hide(); - update(); + updateThumbnailsPos(); } From 80a7b898beebd53c71e0f7fc0780847a8e1e15b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 21 Nov 2017 11:42:35 +0100 Subject: [PATCH 089/134] (WIP) fixed some bugs where 'Locked' and 'Visible on extended screen' properties were not persisted for groups' --- src/adaptors/UBSvgSubsetAdaptor.cpp | 32 +++++++++++++++++---- src/domain/UBGraphicsGroupContainerItem.cpp | 13 ++++++++- src/domain/UBGraphicsItemDelegate.cpp | 29 ++++++++++--------- src/domain/UBGraphicsItemDelegate.h | 1 + 4 files changed, 55 insertions(+), 20 deletions(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 63ad5c69..2cc7c8e5 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -975,6 +975,24 @@ UBGraphicsGroupContainerItem* UBSvgSubsetAdaptor::UBSvgSubsetReader::readGroup() if(mStrokesList.contains(id)) shouldSkipSubElements = true; + QString ubLocked = mXmlReader.attributes().value(mNamespaceUri, "locked").toString(); + if (!ubLocked.isEmpty()) + { + bool isLocked = ubLocked.contains(xmlTrue); + group->setData(UBGraphicsItemData::ItemLocked, QVariant(isLocked)); + } + + QStringRef ubLayer = mXmlReader.attributes().value(mNamespaceUri, "layer"); + if (!ubLayer.isNull()) + { + bool ok; + int layerAsInt = ubLayer.toString().toInt(&ok); + + if (ok) + group->setData(UBGraphicsItemData::ItemLayerType, QVariant(layerAsInt)); + } + + mXmlReader.readNext(); while (!mXmlReader.atEnd()) { @@ -1031,13 +1049,9 @@ void UBSvgSubsetAdaptor::UBSvgSubsetReader::readGroupRoot() } else if (mXmlReader.isStartElement()) { if (mXmlReader.name() == tGroup) { - QString ubLocked = mXmlReader.attributes().value(UBSettings::uniboardDocumentNamespaceUri, "locked").toString(); + UBGraphicsGroupContainerItem *curGroup = readGroup(); - if (!ubLocked.isEmpty()) - { - bool isLocked = ubLocked.contains(xmlTrue); - curGroup->Delegate()->setLocked(isLocked); - } + if (curGroup) { mScene->addGroup(curGroup); } @@ -1400,6 +1414,10 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(UBDocumentProxy* proxy, if(curElement.hasAttribute("locked")){ mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri,"locked",curElement.attribute("locked")); } + if(curElement.hasAttribute("layer")){ + mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri,"layer",curElement.attribute("layer")); + } + QDomElement curSubElement = curElement.firstChildElement(); while (!curSubElement.isNull()) { if (curSubElement.hasAttribute(aId)) { @@ -1444,6 +1462,8 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistGroupToDom(QGraphicsItem *gro curGroupElement.setAttribute("locked", xmlTrue); else curGroupElement.setAttribute("locked", xmlFalse); + + curGroupElement.setAttribute("layer", group->data(UBGraphicsItemData::ItemLayerType).toString()); } curParent->appendChild(curGroupElement); foreach (QGraphicsItem *item, groupItem->childItems()) { diff --git a/src/domain/UBGraphicsGroupContainerItem.cpp b/src/domain/UBGraphicsGroupContainerItem.cpp index 646f8b6d..53b74acf 100644 --- a/src/domain/UBGraphicsGroupContainerItem.cpp +++ b/src/domain/UBGraphicsGroupContainerItem.cpp @@ -84,12 +84,23 @@ void UBGraphicsGroupContainerItem::addToGroup(QGraphicsItem *item) if (!UBGraphicsItem::isLocked(this) && UBGraphicsItem::isLocked(item)) { Delegate()->setLocked(true); } + /* + if (data(UBGraphicsItemData::itemLayerType).toInt() != UBItemLayerType::Control + && item->data(UBGraphicsItemData::itemLayerType).toInt() == UBItemLayerType::Control) + setData(UBGraphicsItemData::itemLayerType, UBItemLayerType::Control); + */ + //setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); } else { Delegate()->setUBFlag(GF_FLIPPABLE_ALL_AXIS, UBGraphicsItem::isFlippable(item)); Delegate()->setUBFlag(GF_REVOLVABLE, UBGraphicsItem::isRotatable(item)); Delegate()->setLocked(UBGraphicsItem::isLocked(item)); - } + + setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); + //setData(UBGraphicsItemData::itemLayerType, item->data(UBGraphicsItemData::itemLayerType)); + } + + qDebug() << item->data(UBGraphicsItemData::itemLayerType); // COMBINE bool ok; diff --git a/src/domain/UBGraphicsItemDelegate.cpp b/src/domain/UBGraphicsItemDelegate.cpp index 336e7b50..b2d45850 100644 --- a/src/domain/UBGraphicsItemDelegate.cpp +++ b/src/domain/UBGraphicsItemDelegate.cpp @@ -565,25 +565,20 @@ void UBGraphicsItemDelegate::increaseZlevelBottom() void UBGraphicsItemDelegate::lock(bool locked) { - if (locked) - { - mDelegated->setData(UBGraphicsItemData::ItemLocked, QVariant(true)); - } - else - { - mDelegated->setData(UBGraphicsItemData::ItemLocked, QVariant(false)); - } - + setLockedRecurs(locked, mDelegated); mDelegated->update(); + positionHandles(); mFrame->positionHandles(); } -void UBGraphicsItemDelegate::showHideRecurs(const QVariant &pShow, QGraphicsItem *pItem) + +void UBGraphicsItemDelegate::setLockedRecurs(const QVariant &pLock, QGraphicsItem *pItem) { - pItem->setData(UBGraphicsItemData::ItemLayerType, pShow); - foreach (QGraphicsItem *insideItem, pItem->childItems()) { - showHideRecurs(pShow, insideItem); + pItem->setData(UBGraphicsItemData::ItemLocked, pLock); + foreach (QGraphicsItem *insideItem, pItem->childItems()) + { + setLockedRecurs(pLock, insideItem); } } @@ -596,6 +591,14 @@ void UBGraphicsItemDelegate::showHide(bool show) emit showOnDisplayChanged(show); } +void UBGraphicsItemDelegate::showHideRecurs(const QVariant &pShow, QGraphicsItem *pItem) +{ + pItem->setData(UBGraphicsItemData::ItemLayerType, pShow); + foreach (QGraphicsItem *insideItem, pItem->childItems()) { + showHideRecurs(pShow, insideItem); + } +} + /** * @brief Set delegate as background for the scene, replacing any existing background. */ diff --git a/src/domain/UBGraphicsItemDelegate.h b/src/domain/UBGraphicsItemDelegate.h index ad249dc1..bfa30bd5 100644 --- a/src/domain/UBGraphicsItemDelegate.h +++ b/src/domain/UBGraphicsItemDelegate.h @@ -326,6 +326,7 @@ class UBGraphicsItemDelegate : public QObject virtual void updateMenuActionState(); void showHideRecurs(const QVariant &pShow, QGraphicsItem *pItem); + void setLockedRecurs(const QVariant &pLock, QGraphicsItem *pItem); QList buttons() {return mButtons;} QGraphicsItem* mDelegated; From ca8949f82fa76ee8a874a322790d207ab24b2994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 21 Nov 2017 11:46:26 +0100 Subject: [PATCH 090/134] fixed handscroll on extended screen --- src/core/UBApplicationController.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index 030a0da0..d8bdc89f 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -233,12 +233,15 @@ void UBApplicationController::adjustDisplayView() tr.scale(scaleFactor, scaleFactor); + QRect rect = mControlView->rect(); + QPoint center(rect.x() + rect.width() / 2, rect.y() + rect.height() / 2); + QTransform recentTransform = mDisplayView->transform(); if (recentTransform != tr) mDisplayView->setTransform(tr); - mDisplayView->centerOn(UBApplication::boardController->activeScene()->lastCenter()); + mDisplayView->centerOn(mControlView->mapToScene(center)); } } From b2f7c0c46dba046e4f2d8e6118a4005dba5069bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 21 Nov 2017 13:29:03 +0100 Subject: [PATCH 091/134] (finished) fixed some bugs where 'Locked' and 'Visible on extended screen' properties were not persisted for groups --- src/domain/UBGraphicsGroupContainerItem.cpp | 12 ++---------- src/domain/UBGraphicsItemDelegate.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/src/domain/UBGraphicsGroupContainerItem.cpp b/src/domain/UBGraphicsGroupContainerItem.cpp index 53b74acf..1ce3826d 100644 --- a/src/domain/UBGraphicsGroupContainerItem.cpp +++ b/src/domain/UBGraphicsGroupContainerItem.cpp @@ -84,23 +84,15 @@ void UBGraphicsGroupContainerItem::addToGroup(QGraphicsItem *item) if (!UBGraphicsItem::isLocked(this) && UBGraphicsItem::isLocked(item)) { Delegate()->setLocked(true); } - /* - if (data(UBGraphicsItemData::itemLayerType).toInt() != UBItemLayerType::Control - && item->data(UBGraphicsItemData::itemLayerType).toInt() == UBItemLayerType::Control) - setData(UBGraphicsItemData::itemLayerType, UBItemLayerType::Control); - */ - //setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); } else { Delegate()->setUBFlag(GF_FLIPPABLE_ALL_AXIS, UBGraphicsItem::isFlippable(item)); Delegate()->setUBFlag(GF_REVOLVABLE, UBGraphicsItem::isRotatable(item)); Delegate()->setLocked(UBGraphicsItem::isLocked(item)); - - setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); - //setData(UBGraphicsItemData::itemLayerType, item->data(UBGraphicsItemData::itemLayerType)); } - qDebug() << item->data(UBGraphicsItemData::itemLayerType); + if (item->data(UBGraphicsItemData::ItemLayerType) == UBItemLayerType::Control) + setData(UBGraphicsItemData::ItemLayerType, item->data(UBGraphicsItemData::ItemLayerType)); // COMBINE bool ok; diff --git a/src/domain/UBGraphicsItemDelegate.cpp b/src/domain/UBGraphicsItemDelegate.cpp index b2d45850..c7c7098c 100644 --- a/src/domain/UBGraphicsItemDelegate.cpp +++ b/src/domain/UBGraphicsItemDelegate.cpp @@ -287,7 +287,12 @@ QVariant UBGraphicsItemDelegate::itemChange(QGraphicsItem::GraphicsItemChange ch } } break; - + case QGraphicsItem::ItemVisibleHasChanged : + { + bool shownOnDisplay = mDelegated->data(UBGraphicsItemData::ItemLayerType).toInt() != UBItemLayerType::Control; + showHide(shownOnDisplay); + break; + } case QGraphicsItem::ItemPositionHasChanged : case QGraphicsItem::ItemTransformHasChanged : case QGraphicsItem::ItemZValueHasChanged : From 00f50c953c8e989175c8643d40ccece81401b2a7 Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sun, 22 Oct 2017 15:46:35 -0400 Subject: [PATCH 092/134] Fix saving and loading of polygons' fill rule This fixes a bug introduced in commit 8365f2f and improves the previous, suboptimal behaviour. Now, polygon fill rules should be saved and loaded correctly; and the changes should be reverse compatible (so that files created with an older version will be loaded correctly as well). --- src/adaptors/UBSvgSubsetAdaptor.cpp | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 2cc7c8e5..9ebde9fe 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -1752,25 +1752,15 @@ UBGraphicsPolygonItem* UBSvgSubsetAdaptor::UBSvgSubsetReader::polygonItemFromPol polygonItem->setColorOnLightBackground(color); } - /* - - Unfortunately the fill rule was never saved correctly until OpenBoard v1.4, - before then, it was always saved as even-odd. So we can't load it safely here. - Saving is now fixed, but any old documents would be loaded incorrectly if the code - below is used. It should be activated at some point in the future though. + // Before OpenBoard v1.4, fill rule was only saved if it was "Even-odd". Therefore if no fill rule + // is specified, we assume that it should be Winding fill. QStringRef fillRule = mXmlReader.attributes().value("fill-rule"); - if (!fillRule.isNull()) { - QString value = fillRule.toString(); - - if (value == "evenodd") - polygonItem->setFillRule(Qt::OddEvenFill); - else - polygonItem->setFillRule(Qt::WindingFill); - } - */ - polygonItem->setFillRule(Qt::WindingFill); + if (!fillRule.isNull() && fillRule.toString() == "evenodd") + polygonItem->setFillRule(Qt::OddEvenFill); + else + polygonItem->setFillRule(Qt::WindingFill); return polygonItem; From 75ecc33bcf7abb93fa96f0be2e5c692b1720101b Mon Sep 17 00:00:00 2001 From: Craig Watson Date: Sun, 26 Nov 2017 22:44:39 -0500 Subject: [PATCH 093/134] When creating a new page, set the background grid size to the same as the last active page --- src/adaptors/UBSvgSubsetAdaptor.cpp | 2 -- src/core/UBPersistenceManager.cpp | 1 + src/gui/UBBackgroundPalette.cpp | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp index 9ebde9fe..53bef3e1 100644 --- a/src/adaptors/UBSvgSubsetAdaptor.cpp +++ b/src/adaptors/UBSvgSubsetAdaptor.cpp @@ -466,7 +466,6 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx if (!ubGridSize.isNull()) { int gridSize = ubGridSize.toInt(); - UBSettings::settings()->crossSize = gridSize; mScene->setBackgroundGridSize(gridSize); } } @@ -482,7 +481,6 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx if (!ubGridSize.isNull()) { int gridSize = ubGridSize.toInt(); - UBSettings::settings()->crossSize = gridSize; mScene->setBackgroundGridSize(gridSize); } } diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index 543853b0..f0791119 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -661,6 +661,7 @@ UBGraphicsScene* UBPersistenceManager::createDocumentSceneAt(UBDocumentProxy* pr newScene->setBackground(UBSettings::settings()->isDarkBackground(), UBSettings::settings()->UBSettings::pageBackground()); + newScene->setBackgroundGridSize(UBSettings::settings()->crossSize); persistDocumentScene(proxy, newScene, index); proxy->incPageCount(); diff --git a/src/gui/UBBackgroundPalette.cpp b/src/gui/UBBackgroundPalette.cpp index d10fcc08..4cb6b3b1 100644 --- a/src/gui/UBBackgroundPalette.cpp +++ b/src/gui/UBBackgroundPalette.cpp @@ -134,6 +134,7 @@ void UBBackgroundPalette::showEvent(QShowEvent* event) void UBBackgroundPalette::sliderValueChanged(int value) { UBApplication::boardController->activeScene()->setBackgroundGridSize(value); + UBSettings::settings()->crossSize = value; // since this function is called (indirectly, by refresh) when we switch scenes, the settings will always have the current scene's cross size. } void UBBackgroundPalette::backgroundChanged() From 1f9e6bd8bb343c77e253b220358e0797adf51d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 28 Nov 2017 09:40:39 +0100 Subject: [PATCH 094/134] fixed a crash where a scene was removed : the compactCache method has no more sense now that we load each scene to create a view on it (thumbnail views) --- src/core/UBSceneCache.cpp | 40 --------------------------------------- src/core/UBSceneCache.h | 2 -- 2 files changed, 42 deletions(-) diff --git a/src/core/UBSceneCache.cpp b/src/core/UBSceneCache.cpp index 086535e5..756acef4 100644 --- a/src/core/UBSceneCache.cpp +++ b/src/core/UBSceneCache.cpp @@ -81,11 +81,6 @@ void UBSceneCache::insert (UBDocumentProxy* proxy, int pageIndex, UBGraphicsScen } else { - if (mCachedSceneCount >= UBSettings::settings()->pageCacheSize->get().toInt()) - { - compactCache(); - } - QHash::insert(key, scene); mCachedKeyFIFO.enqueue(key); @@ -231,41 +226,6 @@ void UBSceneCache::internalMoveScene(UBDocumentProxy* proxy, int sourceIndex, in } } - -void UBSceneCache::compactCache() -{ - bool foundUnusedScene = false; - int count = 0; - - do - { - if (!mCachedKeyFIFO.isEmpty()) - { - const UBSceneCacheID nextKey = mCachedKeyFIFO.dequeue(); - - if (QHash::contains(nextKey)) - { - UBGraphicsScene* scene = QHash::value(nextKey); - - if (scene && scene->views().size() == 0) - { - removeScene(nextKey.documentProxy, nextKey.pageIndex); - foundUnusedScene = true; - } - else - { - mCachedKeyFIFO.enqueue(nextKey); - } - } - } - - count++; - } - while (!foundUnusedScene && count < mCachedKeyFIFO.size()); - -} - - void UBSceneCache::dumpCacheContent() { foreach(UBSceneCacheID key, keys()) diff --git a/src/core/UBSceneCache.h b/src/core/UBSceneCache.h index dcc47fb3..ea80320e 100644 --- a/src/core/UBSceneCache.h +++ b/src/core/UBSceneCache.h @@ -107,8 +107,6 @@ class UBSceneCache : public QHash void dumpCacheContent(); - void compactCache(); - int mCachedSceneCount; QQueue mCachedKeyFIFO; From a97bdc4b217fcb194f227290140cefa4c311d42c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 28 Nov 2017 15:40:20 +0100 Subject: [PATCH 095/134] (WIP) improved global behavior on thumbnails views positioning (resizing, page format, ...) --- src/board/UBBoardController.h | 1 + src/gui/UBBoardThumbnailsView.cpp | 28 +++++++++++++++++++--------- src/gui/UBBoardThumbnailsView.h | 3 ++- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/src/board/UBBoardController.h b/src/board/UBBoardController.h index da3ee403..23fc688f 100644 --- a/src/board/UBBoardController.h +++ b/src/board/UBBoardController.h @@ -264,6 +264,7 @@ class UBBoardController : public UBDocumentContainer void documentReorganized(int index); void displayMetadata(QMap metadata); void pageSelectionChanged(int index); + void centerOnThumbnailRequired(int index); void npapiWidgetCreated(const QString &Url); protected: diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index f2e0f23f..f2ccafd7 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -85,7 +85,8 @@ UBBoardThumbnailsView::UBBoardThumbnailsView(QWidget *parent, const char *name) connect(this, SIGNAL(mousePressAndHoldEventRequired(QPoint)), this, SLOT(mousePressAndHoldEvent(QPoint)), Qt::UniqueConnection); - connect(UBApplication::boardController, SIGNAL(pageSelectionChanged(int)), this, SLOT(scrollToSelectedPage(int)), Qt::UniqueConnection); + connect(UBApplication::boardController, SIGNAL(pageSelectionChanged(int)), this, SLOT(ensureVisibleThumbnail(int)), Qt::UniqueConnection); + connect(UBApplication::boardController, SIGNAL(centerOnThumbnailRequired(int)), this, SLOT(centerOnThumbnail(int)), Qt::UniqueConnection); } void UBBoardThumbnailsView::moveThumbnail(int from, int to) @@ -158,11 +159,16 @@ void UBBoardThumbnailsView::initThumbnails(UBDocumentContainer* source) updateThumbnailsPos(); } -void UBBoardThumbnailsView::scrollToSelectedPage(int index) +void UBBoardThumbnailsView::centerOnThumbnail(int index) { centerOn(mThumbnails.at(index)); } +void UBBoardThumbnailsView::ensureVisibleThumbnail(int index) +{ + ensureVisible(mThumbnails.at(index)); +} + void UBBoardThumbnailsView::updateThumbnailsPos() { qreal thumbnailHeight = mThumbnailWidth / UBSettings::minScreenRatio; @@ -174,7 +180,8 @@ void UBBoardThumbnailsView::updateThumbnailsPos() mThumbnails.at(i)->updatePos(mThumbnailWidth, thumbnailHeight); } - scene()->setSceneRect(scene()->itemsBoundingRect()); + scene()->setSceneRect(0, 0, scene()->itemsBoundingRect().size().width() - verticalScrollBar()->width(), scene()->itemsBoundingRect().size().height()); + update(); } @@ -183,10 +190,12 @@ void UBBoardThumbnailsView::resizeEvent(QResizeEvent *event) Q_UNUSED(event); // Update the thumbnails width - mThumbnailWidth = (width() > mThumbnailMinWidth) ? width() - 2*mMargin : mThumbnailMinWidth; + mThumbnailWidth = (width() > mThumbnailMinWidth) ? width() - verticalScrollBar()->width() - 2*mMargin : mThumbnailMinWidth; // Refresh the scene updateThumbnailsPos(); + + emit UBApplication::boardController->centerOnThumbnailRequired(UBApplication::boardController->activeSceneIndex()); } void UBBoardThumbnailsView::mousePressEvent(QMouseEvent *event) @@ -280,7 +289,7 @@ void UBBoardThumbnailsView::dragMoveEvent(QDragMoveEvent *event) qreal scale = item->transform().m11(); - QPointF itemCenter(item->pos().x() + item->boundingRect().width() * scale / 2, + QPointF itemCenter(item->pos().x() + (item->boundingRect().width()-verticalScrollBar()->width()) * scale, item->pos().y() + item->boundingRect().height() * scale / 2); bool dropAbove = mapToScene(position.toPoint()).y() < itemCenter.y(); @@ -293,7 +302,7 @@ void UBBoardThumbnailsView::dragMoveEvent(QDragMoveEvent *event) { y = item->pos().y() - UBSettings::thumbnailSpacing / 2; if (mDropBar->y() != y) - mDropBar->setRect(QRectF(item->pos().x(), y, item->boundingRect().width() * scale, 3)); + mDropBar->setRect(QRectF(item->pos().x(), y, mThumbnailWidth-verticalScrollBar()->width(), 3)); } } else @@ -302,10 +311,11 @@ void UBBoardThumbnailsView::dragMoveEvent(QDragMoveEvent *event) { y = item->pos().y() + item->boundingRect().height() * scale + UBSettings::thumbnailSpacing / 2; if (mDropBar->y() != y) - mDropBar->setRect(QRectF(item->pos().x(), y, item->boundingRect().width() * scale, 3)); + mDropBar->setRect(QRectF(item->pos().x(), y, mThumbnailWidth-verticalScrollBar()->width(), 3)); } } } + event->acceptProposedAction(); } @@ -318,7 +328,7 @@ void UBBoardThumbnailsView::dropEvent(QDropEvent *event) mDropSource = NULL; mDropTarget = NULL; - mDropBar->hide(); - updateThumbnailsPos(); + mDropBar->setRect(QRectF()); + mDropBar->hide(); } diff --git a/src/gui/UBBoardThumbnailsView.h b/src/gui/UBBoardThumbnailsView.h index 5dff6a59..27574828 100644 --- a/src/gui/UBBoardThumbnailsView.h +++ b/src/gui/UBBoardThumbnailsView.h @@ -45,7 +45,8 @@ public: UBBoardThumbnailsView(QWidget* parent=0, const char* name="UBBoardThumbnailsView"); public slots: - void scrollToSelectedPage(int index); + void ensureVisibleThumbnail(int index); + void centerOnThumbnail(int index); void clearThumbnails(); void initThumbnails(UBDocumentContainer* source); From 0d66ec255d815a58880f2fb8ff2de6ee04a5c58c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Wed, 6 Dec 2017 16:19:16 +0100 Subject: [PATCH 096/134] revert on composition mode on polygon items --- src/domain/UBGraphicsPolygonItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/UBGraphicsPolygonItem.cpp b/src/domain/UBGraphicsPolygonItem.cpp index ad1cdb9c..4e74420a 100644 --- a/src/domain/UBGraphicsPolygonItem.cpp +++ b/src/domain/UBGraphicsPolygonItem.cpp @@ -184,7 +184,7 @@ void UBGraphicsPolygonItem::copyItemParameters(UBItem *copy) const void UBGraphicsPolygonItem::paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) { if(mHasAlpha && scene() && scene()->isLightBackground()) - painter->setCompositionMode(QPainter::CompositionMode_Darken); + painter->setCompositionMode(QPainter::CompositionMode_SourceOver); painter->setRenderHints(QPainter::Antialiasing); From c6c0120aab557c22c731a070e6a1165fe8139c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Wed, 6 Dec 2017 16:23:28 +0100 Subject: [PATCH 097/134] added grid tab on preferences to handle grid color and opacity parameters --- resources/etc/OpenBoard.config | 4 +- resources/forms/brushProperties.ui | 313 +++++++++----------- resources/forms/preferences.ui | 428 +++++++++++++++++++++++---- src/core/UBPreferencesController.cpp | 117 ++++++++ src/core/UBPreferencesController.h | 8 +- src/core/UBSetting.cpp | 22 +- src/core/UBSettings.cpp | 11 +- src/core/UBSettings.h | 3 + 8 files changed, 656 insertions(+), 250 deletions(-) diff --git a/resources/etc/OpenBoard.config b/resources/etc/OpenBoard.config index d016619f..81088661 100644 --- a/resources/etc/OpenBoard.config +++ b/resources/etc/OpenBoard.config @@ -25,12 +25,14 @@ UseSystemOnScreenKeyboard=true [Board] AutoSaveIntervalInMinutes=3 -CrossColorDarkBackground=#C8C0C0C0 +CrossColorDarkBackground=#C82C2C2C CrossColorLightBackground=#A5E1FF DarkBackground=0 DefaultPageSize=@Size(1280 960) EraserCircleWidthIndex=1 FeatureSliderPosition=40 +GridDarkBackgroundColors=#FFFFFF, #FF3400, #66C0FF, #81FF5C, #FFFF00, #B68360, #FF497E, #8D69FF, #C82C2C2C +GridLightBackgroundColors=#000000, #FF0000, #004080, #008000, #FFDD00, #C87400, #800040, #008080, #5F2D0A, #A5E1FF InterpolateMarkerStrokes=true InterpolatePenStrokes=true KeyboardPaletteKeyBtnSize=16x16 diff --git a/resources/forms/brushProperties.ui b/resources/forms/brushProperties.ui index f149562f..5c4de12c 100644 --- a/resources/forms/brushProperties.ui +++ b/resources/forms/brushProperties.ui @@ -20,7 +20,7 @@ QFrame::Plain - + QFrame::NoFrame @@ -70,24 +70,78 @@ - - - - Qt::Vertical - - - QSizePolicy::Fixed + + + + QFrame::NoFrame - - - 20 - 40 - + + QFrame::Raised - + + + + + Qt::Horizontal + + + + 154 + 20 + + + + + + + + Opacity + + + + + + + 20 + + + 100 + + + 50 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 20 + + + + + + + Qt::Horizontal + + + + 156 + 20 + + + + + + - + + + Qt::LeftToRight + QFrame::NoFrame @@ -146,6 +200,19 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -197,74 +264,7 @@ - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - Qt::Horizontal - - - - 154 - 20 - - - - - - - - Opacity - - - - - - - 20 - - - 100 - - - 50 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 20 - - - - - - - Qt::Horizontal - - - - 156 - 20 - - - - - - - - + @@ -458,7 +458,7 @@ - + Qt::Vertical @@ -471,118 +471,79 @@ - - - - Qt::Horizontal + + + + QFrame::NoFrame - - - 0 - 0 - + + QFrame::Raised - + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + Show preview circle from + + + + + + + + + + px + + + + + - - + + Qt::Horizontal - 0 - 0 + 198 + 20 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 0 - 0 - - - - Show preview circle from - - - - - - - - - - px - - - - - - - Qt::Horizontal - - - - 198 - 20 - - - - - - - - + - UBCircleFrame + UBColorPicker QFrame -
gui/UBCircleFrame.h
+
gui/UBColorPicker.h
1
- UBColorPicker + UBCircleFrame QFrame -
gui/UBColorPicker.h
+
gui/UBCircleFrame.h
1
diff --git a/resources/forms/preferences.ui b/resources/forms/preferences.ui index 0ddcafe3..f179bbb8 100644 --- a/resources/forms/preferences.ui +++ b/resources/forms/preferences.ui @@ -14,6 +14,64 @@ Preferences + + + + QFrame::NoFrame + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Default Settings + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Close + + + true + + + + + + + + @@ -24,7 +82,7 @@ - 6 + 1 @@ -477,6 +535,300 @@ + + + Grid + + + + true + + + + -1 + -1 + 741 + 591 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + 0 + 0 + 741 + 611 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 260 + 30 + 221 + 50 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + On Dark Background + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 0 + 90 + 741 + 52 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + Qt::Horizontal + + + + 154 + 20 + + + + + + + + Opacity + + + + + + + 20 + + + 100 + + + 50 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 20 + + + + + + + Qt::Horizontal + + + + 156 + 20 + + + + + + + + + + 260 + 150 + 221 + 51 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + On Light Background + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 0 + 210 + 741 + 52 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + Qt::Horizontal + + + + 154 + 20 + + + + + + + + Opacity + + + + + + + 20 + + + 100 + + + 50 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 20 + + + + + + + Qt::Horizontal + + + + 156 + 20 + + + + + + + + + Pen @@ -2657,7 +3009,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:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; 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> @@ -2751,7 +3103,7 @@ 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:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; 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;"> @@ -2770,8 +3122,8 @@ p, li { white-space: pre-wrap; } <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-family:'.Helvetica Neue DeskInterface'; 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-family:'.Helvetica Neue DeskInterface'; 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;"><a href="http://www.openboard.ch"><span style=" font-family:'.Helvetica Neue DeskInterface'; 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-family:'.Helvetica Neue DeskInterface'; 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> @@ -2859,66 +3211,16 @@ p, li { white-space: pre-wrap; }
- - - - QFrame::NoFrame - - - QFrame::Raised - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Default Settings - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Close - - - true - - - - - - - - + + + UBColorPicker + QFrame +
gui/UBColorPicker.h
+ 1 +
+
mainTabWidget useExternalBrowserCheckBox diff --git a/src/core/UBPreferencesController.cpp b/src/core/UBPreferencesController.cpp index 4c87c6ac..94041b37 100644 --- a/src/core/UBPreferencesController.cpp +++ b/src/core/UBPreferencesController.cpp @@ -39,6 +39,7 @@ #include "core/UBDisplayManager.h" #include "board/UBBoardController.h" +#include "domain/UBGraphicsScene.h" #include "board/UBDrawingController.h" #include "podcast/UBPodcastController.h" @@ -76,6 +77,8 @@ UBPreferencesController::UBPreferencesController(QWidget *parent) , mPreferencesUI(0) , mPenProperties(0) , mMarkerProperties(0) + , mDarkBackgroundGridColorPicker(0) + , mLightBackgroundGridColorPicker(0) { mDesktop = qApp->desktop(); mPreferencesWindow = new UBPreferencesDialog(this,parent, Qt::Dialog); @@ -97,6 +100,10 @@ UBPreferencesController::~UBPreferencesController() delete mPenProperties; delete mMarkerProperties; + + delete mDarkBackgroundGridColorPicker; + + delete mLightBackgroundGridColorPicker; } void UBPreferencesController::adjustScreens(int screen) @@ -149,6 +156,43 @@ void UBPreferencesController::wire() connect(mPreferencesUI->verticalChoice, SIGNAL(clicked(bool)), this, SLOT(toolbarOrientationVertical(bool))); connect(mPreferencesUI->toolbarDisplayTextCheckBox, SIGNAL(clicked(bool)), settings->appToolBarDisplayText, SLOT(setBool(bool))); + //grid tab + //On light background + QList gridLightBackgroundColors = settings->boardGridLightBackgroundColors->colors(); + QColor selectedCrossColorLightBackground(settings->boardCrossColorLightBackground->get().toString()); + + mLightBackgroundGridColorPicker = new UBColorPicker(mPreferencesUI->crossColorLightBackgroundFrame); + mLightBackgroundGridColorPicker->setObjectName(QString::fromUtf8("crossColorLightBackgroundFrame")); + mLightBackgroundGridColorPicker->setMinimumSize(QSize(32, 32)); + mLightBackgroundGridColorPicker->setFrameShape(QFrame::StyledPanel); + mLightBackgroundGridColorPicker->setFrameShadow(QFrame::Raised); + + mPreferencesUI->crossColorLightBackgroundLayout->addWidget(mLightBackgroundGridColorPicker); + mLightBackgroundGridColorPicker->setColors(gridLightBackgroundColors); + mLightBackgroundGridColorPicker->setSelectedColorIndex(gridLightBackgroundColors.indexOf(selectedCrossColorLightBackground)); + mPreferencesUI->lightBackgroundOpacitySlider->setValue(selectedCrossColorLightBackground.alpha()*100 / 255); + + QObject::connect(mLightBackgroundGridColorPicker, SIGNAL(colorSelected(const QColor&)), this, SLOT(setCrossColorOnLightBackground(const QColor&))); + connect(mPreferencesUI->lightBackgroundOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(lightBackgroundCrossOpacityValueChanged(int))); + + //On dark background + QList gridDarkBackgroundColors = settings->boardGridDarkBackgroundColors->colors(); + QColor selectedCrossColorDarkBackground(settings->boardCrossColorDarkBackground->get().toString()); + + mDarkBackgroundGridColorPicker = new UBColorPicker(mPreferencesUI->crossColorDarkBackgroundFrame); + mDarkBackgroundGridColorPicker->setObjectName(QString::fromUtf8("crossColorDarkBackgroundFrame")); + mDarkBackgroundGridColorPicker->setMinimumSize(QSize(32, 32)); + mDarkBackgroundGridColorPicker->setFrameShape(QFrame::StyledPanel); + mDarkBackgroundGridColorPicker->setFrameShadow(QFrame::Raised); + + mPreferencesUI->crossColorDarkBackgroundLayout->addWidget(mDarkBackgroundGridColorPicker); + mDarkBackgroundGridColorPicker->setColors(gridDarkBackgroundColors); + mDarkBackgroundGridColorPicker->setSelectedColorIndex(gridDarkBackgroundColors.indexOf(selectedCrossColorDarkBackground)); + mPreferencesUI->darkBackgroundOpacitySlider->setValue(selectedCrossColorDarkBackground.alpha()*100 / 255); + + QObject::connect(mDarkBackgroundGridColorPicker, SIGNAL(colorSelected(const QColor&)), this, SLOT(setCrossColorOnDarkBackground(const QColor&))); + connect(mPreferencesUI->darkBackgroundOpacitySlider, SIGNAL(valueChanged(int)), this, SLOT(darkBackgroundCrossOpacityValueChanged(int))); + // pen QList penLightBackgroundColors = settings->boardPenLightBackgroundColors->colors(); QList penDarkBackgroundColors = settings->boardPenDarkBackgroundColors->colors(); @@ -340,6 +384,54 @@ void UBPreferencesController::defaultSettings() } +void UBPreferencesController::darkBackgroundCrossOpacityValueChanged(int value) +{ + UBSettings* settings = UBSettings::settings(); + int opacity = value * 255 / 100; + + QList gridDarkBackgroundColors = settings->boardGridDarkBackgroundColors->colors(); + + int index = mDarkBackgroundGridColorPicker->selectedColorIndex(); + QColor currentColor = gridDarkBackgroundColors.at(index); + currentColor.setAlpha(opacity); + gridDarkBackgroundColors.replace(index, currentColor); + mDarkBackgroundGridColorPicker->setColors(gridDarkBackgroundColors); + + settings->boardGridDarkBackgroundColors->setColor(index, currentColor); + + UBSettings::settings()->boardCrossColorDarkBackground->set(currentColor.name(QColor::HexArgb)); + + if (UBApplication::boardController && UBApplication::boardController->activeScene()) + { + foreach(QGraphicsView* view, UBApplication::boardController->activeScene()->views()) + view->resetCachedContent(); + } +} + +void UBPreferencesController::lightBackgroundCrossOpacityValueChanged(int value) +{ + UBSettings* settings = UBSettings::settings(); + int opacity = value * 255 / 100; + + QList gridLightBackgroundColors = settings->boardGridLightBackgroundColors->colors(); + + int index = mLightBackgroundGridColorPicker->selectedColorIndex(); + QColor currentColor = gridLightBackgroundColors.at(index); + currentColor.setAlpha(opacity); + gridLightBackgroundColors.replace(index, currentColor); + mLightBackgroundGridColorPicker->setColors(gridLightBackgroundColors); + + settings->boardGridLightBackgroundColors->setColor(index, currentColor); + + UBSettings::settings()->boardCrossColorLightBackground->set(currentColor.name(QColor::HexArgb)); + + if (UBApplication::boardController && UBApplication::boardController->activeScene()) + { + foreach(QGraphicsView* view, UBApplication::boardController->activeScene()->views()) + view->resetCachedContent(); + } +} + void UBPreferencesController::penPreviewFromSizeChanged(int value) { UBSettings::settings()->setPenPreviewFromSize(value); @@ -446,6 +538,31 @@ void UBPreferencesController::colorSelected(const QColor& color) } +void UBPreferencesController::setCrossColorOnDarkBackground(const QColor& color) +{ + UBSettings::settings()->boardCrossColorDarkBackground->set(color.name(QColor::HexArgb)); + + mPreferencesUI->darkBackgroundOpacitySlider->setValue(color.alpha() * 100 / 255); + + if (UBApplication::boardController && UBApplication::boardController->activeScene()) + { + foreach(QGraphicsView* view, UBApplication::boardController->activeScene()->views()) + view->resetCachedContent(); + } +} + +void UBPreferencesController::setCrossColorOnLightBackground(const QColor& color) +{ + UBSettings::settings()->boardCrossColorLightBackground->set(color.name(QColor::HexArgb)); + + mPreferencesUI->lightBackgroundOpacitySlider->setValue(color.alpha() * 100 / 255); + + if (UBApplication::boardController && UBApplication::boardController->activeScene()) + { + foreach(QGraphicsView* view, UBApplication::boardController->activeScene()->views()) + view->resetCachedContent(); + } +} void UBPreferencesController::toolbarPositionChanged(bool checked) { diff --git a/src/core/UBPreferencesController.h b/src/core/UBPreferencesController.h index ea4d8b32..b25fdbc7 100644 --- a/src/core/UBPreferencesController.h +++ b/src/core/UBPreferencesController.h @@ -47,7 +47,6 @@ namespace Ui class UBBrushPropertiesFrame; - class UBPreferencesDialog : public QDialog { Q_OBJECT; @@ -84,15 +83,21 @@ class UBPreferencesController : public QObject Ui::preferencesDialog* mPreferencesUI; UBBrushPropertiesFrame* mPenProperties; UBBrushPropertiesFrame* mMarkerProperties; + UBColorPicker* mDarkBackgroundGridColorPicker; + UBColorPicker* mLightBackgroundGridColorPicker; protected slots: void close(); void defaultSettings(); void penPreviewFromSizeChanged(int value); + void darkBackgroundCrossOpacityValueChanged(int value); + void lightBackgroundCrossOpacityValueChanged(int value); void widthSliderChanged(int value); void opacitySliderChanged(int value); void colorSelected(const QColor&); + void setCrossColorOnDarkBackground(const QColor& color); + void setCrossColorOnLightBackground(const QColor& color); void toolbarPositionChanged(bool checked); void toolbarOrientationVertical(bool checked); void toolbarOrientationHorizontal(bool checked); @@ -122,5 +127,4 @@ class UBBrushPropertiesFrame : public Ui::brushProperties }; - #endif /* UBPREFERENCESCONTROLLER_H_ */ diff --git a/src/core/UBSetting.cpp b/src/core/UBSetting.cpp index 3340ea8f..b4fab800 100644 --- a/src/core/UBSetting.cpp +++ b/src/core/UBSetting.cpp @@ -105,13 +105,16 @@ UBColorListSetting::UBColorListSetting(UBSettings* owner, const QString& pDomain : UBSetting(owner, pDomain, pKey, pDefaultValue) , mAlpha(pAlpha) { + foreach(QString s, get().toStringList()) { QColor color; color.setNamedColor(s); - color.setAlphaF(mAlpha); + if (mAlpha>=0) + color.setAlphaF(mAlpha); mColors.append(color); } + } UBColorListSetting::~UBColorListSetting() @@ -129,7 +132,9 @@ QVariant UBColorListSetting::reset() { QColor color; color.setNamedColor(s); - color.setAlphaF(mAlpha); + if (mAlpha>=0) + color.setAlphaF(mAlpha); + mColors.append(color); } @@ -146,10 +151,15 @@ QList UBColorListSetting::colors() const void UBColorListSetting::setColor(int pIndex, const QColor& color) { QStringList list = get().toStringList(); - list.replace(pIndex, color.name()); - QColor c = color; - c.setAlphaF(mAlpha); - mColors.replace(pIndex, c); + list.replace(pIndex, color.name(QColor::HexArgb)); + if (mAlpha>=0) + { + QColor c = color; + c.setAlphaF(mAlpha); + mColors.replace(pIndex, c); + } + else + mColors.replace(pIndex, color); set(list); } diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index 2b51e724..c8f4a29f 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -286,10 +286,17 @@ void UBSettings::init() pageSize = new UBSetting(this, "Board", "DefaultPageSize", documentSizes.value(DocumentSizeRatio::Ratio4_3)); - - boardCrossColorDarkBackground = new UBSetting(this, "Board", "CrossColorDarkBackground", "#C8C0C0C0"); + boardCrossColorDarkBackground = new UBSetting(this, "Board", "CrossColorDarkBackground", "#C82C2C2C"); boardCrossColorLightBackground = new UBSetting(this, "Board", "CrossColorLightBackground", "#A5E1FF"); + QStringList gridLightBackgroundColors; + gridLightBackgroundColors << "#FFFFFF" << "#FF3400" << "#66C0FF" << "#81FF5C" << "#FFFF00" << "#B68360" << "#FF497E" << "#8D69FF" << "#C82C2C2C"; + boardGridLightBackgroundColors = new UBColorListSetting(this, "Board", "GridLightBackgroundColors", gridLightBackgroundColors, -1.0); + + QStringList gridDarkBackgroundColors; + gridDarkBackgroundColors << "#000000" << "#FF0000" << "#004080" << "#008000" << "#FFDD00" << "#C87400" << "#800040" << "#008080" << "#A5E1FF"; + boardGridDarkBackgroundColors = new UBColorListSetting(this, "Board", "GridDarkBackgroundColors", gridDarkBackgroundColors, -1.0); + QStringList penLightBackgroundColors; penLightBackgroundColors << "#000000" << "#FF0000" <<"#004080" << "#008000" << "#FFDD00" << "#C87400" << "#800040" << "#008080" << "#5F2D0A" << "#FFFFFF"; boardPenLightBackgroundColors = new UBColorListSetting(this, "Board", "PenLightBackgroundColors", penLightBackgroundColors, 1.0); diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index e00c8e9c..91d6dc25 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -294,6 +294,9 @@ class UBSettings : public QObject UBSetting* boardCrossColorDarkBackground; UBSetting* boardCrossColorLightBackground; + UBColorListSetting* boardGridLightBackgroundColors; + UBColorListSetting* boardGridDarkBackgroundColors; + UBColorListSetting* boardPenLightBackgroundColors; UBColorListSetting* boardPenLightBackgroundSelectedColors; From 7ba25e9d5e3bcacd3ba4f8d78176ab8845adc58a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Wed, 6 Dec 2017 17:26:54 +0100 Subject: [PATCH 098/134] adapted image transformation when setting an image as a background --- src/domain/UBGraphicsItemDelegate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/UBGraphicsItemDelegate.cpp b/src/domain/UBGraphicsItemDelegate.cpp index c7c7098c..6d1065e5 100644 --- a/src/domain/UBGraphicsItemDelegate.cpp +++ b/src/domain/UBGraphicsItemDelegate.cpp @@ -618,7 +618,7 @@ void UBGraphicsItemDelegate::setAsBackground() item->resetTransform(); item->setPos(item->sceneBoundingRect().width()/-2., item->sceneBoundingRect().height()/-2.); - scene->setAsBackgroundObject(item); + scene->setAsBackgroundObject(item, true); UBGraphicsItemTransformUndoCommand *uc = new UBGraphicsItemTransformUndoCommand(mDelegated, From 4ca97d5c8200064e89354d2f351f26d276e8c685 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Thu, 7 Dec 2017 18:01:23 +0100 Subject: [PATCH 099/134] added translations + new image for setAsBackround action --- resources/forms/preferences.ui | 16 +- resources/i18n/OpenBoard_ar.ts | 16 + resources/i18n/OpenBoard_bg.ts | 16 + resources/i18n/OpenBoard_ca.ts | 16 + resources/i18n/OpenBoard_cs.ts | 16 + resources/i18n/OpenBoard_da.ts | 16 + resources/i18n/OpenBoard_de.ts | 16 + resources/i18n/OpenBoard_el.ts | 16 + resources/i18n/OpenBoard_en.ts | 16 + resources/i18n/OpenBoard_en_UK.ts | 16 + resources/i18n/OpenBoard_es.ts | 16 + resources/i18n/OpenBoard_fr.ts | 16 + resources/i18n/OpenBoard_fr_CH.ts | 18 +- resources/i18n/OpenBoard_it.ts | 6 - resources/i18n/OpenBoard_iw.ts | 16 + resources/i18n/OpenBoard_ja.ts | 16 + resources/i18n/OpenBoard_ko.ts | 16 + resources/i18n/OpenBoard_mg.ts | 16 + resources/i18n/OpenBoard_nb.ts | 16 + resources/i18n/OpenBoard_nl.ts | 18 +- resources/i18n/OpenBoard_pl.ts | 16 + resources/i18n/OpenBoard_pt.ts | 16 + resources/i18n/OpenBoard_ro.ts | 16 + resources/i18n/OpenBoard_ru.ts | 16 + resources/i18n/OpenBoard_sk.ts | 16 + resources/i18n/OpenBoard_sv.ts | 16 + resources/i18n/OpenBoard_tr.ts | 16 + resources/i18n/OpenBoard_zh.ts | 16 + resources/i18n/OpenBoard_zh_CN.ts | 16 + resources/i18n/OpenBoard_zh_TW.ts | 16 + resources/images/setAsBackground.svg | 462 ++++++++++++++++++++++----- 31 files changed, 833 insertions(+), 103 deletions(-) diff --git a/resources/forms/preferences.ui b/resources/forms/preferences.ui index f179bbb8..7c3900eb 100644 --- a/resources/forms/preferences.ui +++ b/resources/forms/preferences.ui @@ -575,9 +575,9 @@ - 260 + 250 30 - 221 + 241 50 @@ -702,9 +702,9 @@ - 260 + 250 150 - 221 + 241 51 @@ -1008,7 +1008,7 @@ - 4 + 1 @@ -3107,13 +3107,13 @@ p, li { white-space: pre-wrap; } <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.3.0</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.4.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 © 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-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 </span><a href="https://github.com/DIP-SEM/OpenBoard"><span style=" font-family:'.Helvetica Neue DeskInterface'; 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-family:'.Helvetica Neue DeskInterface'; 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-family:'.Helvetica Neue DeskInterface'; 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 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-family:'.Helvetica Neue DeskInterface'; font-size:10pt; text-decoration: underline; color:#0000ff;">github.com/OpenBoard-org</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> @@ -3124,7 +3124,7 @@ p, li { white-space: pre-wrap; } <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-family:'.Helvetica Neue DeskInterface'; 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-family:'.Helvetica Neue DeskInterface'; 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> +<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;">emails: </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>, <a href="mailto:sem.logistique@edu.ge.ch"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#0000ff;">support@openboard.ch</span></a></p></td></tr></table></body></html> true diff --git a/resources/i18n/OpenBoard_ar.ts b/resources/i18n/OpenBoard_ar.ts index 1a16c385..167894f3 100644 --- a/resources/i18n/OpenBoard_ar.ts +++ b/resources/i18n/OpenBoard_ar.ts @@ -2641,6 +2641,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + في خلفية داكنة + + + Opacity + معدل الشفافية + + + On Light Background + في خلفية مضيئة + trapFlashDialog diff --git a/resources/i18n/OpenBoard_bg.ts b/resources/i18n/OpenBoard_bg.ts index 8d3c40a3..938034d3 100644 --- a/resources/i18n/OpenBoard_bg.ts +++ b/resources/i18n/OpenBoard_bg.ts @@ -2636,6 +2636,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + На тъмен фон + + + Opacity + Непрозрачност + + + On Light Background + На светъл фон + trapFlashDialog diff --git a/resources/i18n/OpenBoard_ca.ts b/resources/i18n/OpenBoard_ca.ts index 51443cf1..e0d035fd 100644 --- a/resources/i18n/OpenBoard_ca.ts +++ b/resources/i18n/OpenBoard_ca.ts @@ -2629,6 +2629,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + Sobre fons fosc + + + Opacity + Opacitat + + + On Light Background + Sobre fons clar + trapFlashDialog diff --git a/resources/i18n/OpenBoard_cs.ts b/resources/i18n/OpenBoard_cs.ts index b429c870..c865257b 100644 --- a/resources/i18n/OpenBoard_cs.ts +++ b/resources/i18n/OpenBoard_cs.ts @@ -2639,6 +2639,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + Na tmavém pozadí + + + Opacity + Průhlednost + + + On Light Background + Na světlém pozadí + trapFlashDialog diff --git a/resources/i18n/OpenBoard_da.ts b/resources/i18n/OpenBoard_da.ts index 0ee8a7c5..59096c0b 100644 --- a/resources/i18n/OpenBoard_da.ts +++ b/resources/i18n/OpenBoard_da.ts @@ -2632,6 +2632,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + På mørk baggrund + + + Opacity + Gennemsigtighed + + + On Light Background + På lys baggrund + trapFlashDialog diff --git a/resources/i18n/OpenBoard_de.ts b/resources/i18n/OpenBoard_de.ts index ddc0b4c1..06a7acd8 100644 --- a/resources/i18n/OpenBoard_de.ts +++ b/resources/i18n/OpenBoard_de.ts @@ -2661,6 +2661,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: Tastengröße der integrierten virtuellen Tastatur + + Grid + + + + On Dark Background + Auf dunklem Hintergrund + + + Opacity + Deckkraft + + + On Light Background + Auf hellem Hintergrund + trapFlashDialog diff --git a/resources/i18n/OpenBoard_el.ts b/resources/i18n/OpenBoard_el.ts index c5bd61f6..4093a9db 100644 --- a/resources/i18n/OpenBoard_el.ts +++ b/resources/i18n/OpenBoard_el.ts @@ -2636,6 +2636,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + Σε σκοτεινό παρασκήνιο + + + Opacity + Διαφάνεια + + + On Light Background + Σε φωτεινό παρασκήνιο + trapFlashDialog diff --git a/resources/i18n/OpenBoard_en.ts b/resources/i18n/OpenBoard_en.ts index a2b758cf..751d2447 100644 --- a/resources/i18n/OpenBoard_en.ts +++ b/resources/i18n/OpenBoard_en.ts @@ -2530,6 +2530,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + + + + Opacity + + + + On Light Background + + trapFlashDialog diff --git a/resources/i18n/OpenBoard_en_UK.ts b/resources/i18n/OpenBoard_en_UK.ts index 3c656bcc..57b71e94 100644 --- a/resources/i18n/OpenBoard_en_UK.ts +++ b/resources/i18n/OpenBoard_en_UK.ts @@ -2530,6 +2530,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + + + + Opacity + + + + On Light Background + + trapFlashDialog diff --git a/resources/i18n/OpenBoard_es.ts b/resources/i18n/OpenBoard_es.ts index 8d3cb58e..a10155e7 100644 --- a/resources/i18n/OpenBoard_es.ts +++ b/resources/i18n/OpenBoard_es.ts @@ -2630,6 +2630,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + Sobre fondo oscuro + + + Opacity + Opacidad + + + On Light Background + Sobre fondo claro + trapFlashDialog diff --git a/resources/i18n/OpenBoard_fr.ts b/resources/i18n/OpenBoard_fr.ts index 66613b38..6a044792 100644 --- a/resources/i18n/OpenBoard_fr.ts +++ b/resources/i18n/OpenBoard_fr.ts @@ -2678,6 +2678,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: Taille des touches du clavier virtuel integré : + + Grid + + + + On Dark Background + Sur fond foncé + + + Opacity + Opacité + + + On Light Background + Sur fond clair + trapFlashDialog diff --git a/resources/i18n/OpenBoard_fr_CH.ts b/resources/i18n/OpenBoard_fr_CH.ts index 5c4e6a38..14f1b709 100644 --- a/resources/i18n/OpenBoard_fr_CH.ts +++ b/resources/i18n/OpenBoard_fr_CH.ts @@ -2475,7 +2475,7 @@ p, li { white-space: pre-wrap; } Show preview circle from - Visualiser la taille depuis + Visualiser la taille dès Pen is Pressure Sensitive @@ -2678,6 +2678,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: Taille des touches du clavier virtuel integré : + + Grid + Quadrillage + + + On Dark Background + Sur fond foncé + + + Opacity + Opacité + + + On Light Background + Sur fond clair + trapFlashDialog diff --git a/resources/i18n/OpenBoard_it.ts b/resources/i18n/OpenBoard_it.ts index e217bf25..bc99f047 100644 --- a/resources/i18n/OpenBoard_it.ts +++ b/resources/i18n/OpenBoard_it.ts @@ -1319,8 +1319,6 @@ Export to OpenBoard Format Esporta nel formato OpenBoard -<<<<<<< HEAD -======= Export failed: location not writable Exportazione fallita: posizione non scrivibile @@ -1333,7 +1331,6 @@ Unable to export to the selected location. You do not have the permissions necessary to save the file. Impossibile esportare nella posizione selezionata. Non possiedi i permessi necessari a salvare il file. ->>>>>>> dev UBExportFullPDF @@ -1353,8 +1350,6 @@ Export to PDF Esporta in PDF -<<<<<<< HEAD -======= Export failed: location not writable Esportazione fallita: posizione non scrivibile @@ -1367,7 +1362,6 @@ Unable to export to the selected location. You do not have the permissions necessary to save the file. Impossibile esportare alla posizione selezionata. Non possiedi i permessi necessari a salvare il file. ->>>>>>> dev UBExportPDF diff --git a/resources/i18n/OpenBoard_iw.ts b/resources/i18n/OpenBoard_iw.ts index d303522d..31fcfdf3 100644 --- a/resources/i18n/OpenBoard_iw.ts +++ b/resources/i18n/OpenBoard_iw.ts @@ -2629,6 +2629,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + על רקע כהה + + + Opacity + אטימות + + + On Light Background + על רקע בהיר + trapFlashDialog diff --git a/resources/i18n/OpenBoard_ja.ts b/resources/i18n/OpenBoard_ja.ts index 492517da..8ec9be01 100644 --- a/resources/i18n/OpenBoard_ja.ts +++ b/resources/i18n/OpenBoard_ja.ts @@ -2623,6 +2623,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + 暗い背景で + + + Opacity + 不透明性 + + + On Light Background + 明るい背景で + trapFlashDialog diff --git a/resources/i18n/OpenBoard_ko.ts b/resources/i18n/OpenBoard_ko.ts index db650365..8b176af0 100644 --- a/resources/i18n/OpenBoard_ko.ts +++ b/resources/i18n/OpenBoard_ko.ts @@ -2637,6 +2637,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + 어두운 배경 + + + Opacity + 불투명도 + + + On Light Background + 밝은 배경 + trapFlashDialog diff --git a/resources/i18n/OpenBoard_mg.ts b/resources/i18n/OpenBoard_mg.ts index 3f62107d..90d64b22 100644 --- a/resources/i18n/OpenBoard_mg.ts +++ b/resources/i18n/OpenBoard_mg.ts @@ -2636,6 +2636,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + Amin'ny ambadika maizina + + + Opacity + Hateviny + + + On Light Background + Amin'ny ambadika mazava + trapFlashDialog diff --git a/resources/i18n/OpenBoard_nb.ts b/resources/i18n/OpenBoard_nb.ts index 016852b4..df6f98e6 100644 --- a/resources/i18n/OpenBoard_nb.ts +++ b/resources/i18n/OpenBoard_nb.ts @@ -2633,6 +2633,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + Med mørk bakgrunn + + + Opacity + Ugjennomsiktig + + + On Light Background + Med lys bakgrunn + trapFlashDialog diff --git a/resources/i18n/OpenBoard_nl.ts b/resources/i18n/OpenBoard_nl.ts index 4770b569..aa428f39 100644 --- a/resources/i18n/OpenBoard_nl.ts +++ b/resources/i18n/OpenBoard_nl.ts @@ -761,7 +761,7 @@ OpenBoard - Sankoré openen + OpenBoard Quit OpenBoard @@ -2621,6 +2621,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + Op een Donkere Achtergrond + + + Opacity + lichtondoorlatendheid + + + On Light Background + Op een Lichte Achtergrond + trapFlashDialog diff --git a/resources/i18n/OpenBoard_pl.ts b/resources/i18n/OpenBoard_pl.ts index 2d458738..f3b73ac8 100644 --- a/resources/i18n/OpenBoard_pl.ts +++ b/resources/i18n/OpenBoard_pl.ts @@ -2647,6 +2647,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + Na ciemnym tle + + + Opacity + Nieprzezroczystość + + + On Light Background + Na jasnym tle + trapFlashDialog diff --git a/resources/i18n/OpenBoard_pt.ts b/resources/i18n/OpenBoard_pt.ts index 51e504f0..f09d4f06 100644 --- a/resources/i18n/OpenBoard_pt.ts +++ b/resources/i18n/OpenBoard_pt.ts @@ -2660,6 +2660,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: Tamanho da tecla do teclado virtual embarcado: + + Grid + + + + On Dark Background + Num fundo preto + + + Opacity + Opacidade + + + On Light Background + Num fundo branco + trapFlashDialog diff --git a/resources/i18n/OpenBoard_ro.ts b/resources/i18n/OpenBoard_ro.ts index 28e332cc..047d7cfb 100644 --- a/resources/i18n/OpenBoard_ro.ts +++ b/resources/i18n/OpenBoard_ro.ts @@ -2636,6 +2636,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + Pe fundal închis + + + Opacity + Opacitate + + + On Light Background + Pe fundal deschis + trapFlashDialog diff --git a/resources/i18n/OpenBoard_ru.ts b/resources/i18n/OpenBoard_ru.ts index 1b524491..41101d12 100644 --- a/resources/i18n/OpenBoard_ru.ts +++ b/resources/i18n/OpenBoard_ru.ts @@ -2636,6 +2636,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + На темном фоне + + + Opacity + Непрозрачность + + + On Light Background + На светлом фоне + trapFlashDialog diff --git a/resources/i18n/OpenBoard_sk.ts b/resources/i18n/OpenBoard_sk.ts index 32f85cb6..328af7aa 100644 --- a/resources/i18n/OpenBoard_sk.ts +++ b/resources/i18n/OpenBoard_sk.ts @@ -2669,6 +2669,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: Veľkosť tlačidla zabudovanej virtuálnej klávesnice: + + Grid + + + + On Dark Background + Na tmavom pozadí + + + Opacity + Priehľadnosť + + + On Light Background + Na svetlom pozadí + trapFlashDialog diff --git a/resources/i18n/OpenBoard_sv.ts b/resources/i18n/OpenBoard_sv.ts index c96c3c8a..af2123c0 100644 --- a/resources/i18n/OpenBoard_sv.ts +++ b/resources/i18n/OpenBoard_sv.ts @@ -2637,6 +2637,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + På mörk bakgrund + + + Opacity + Genomskinlighet + + + On Light Background + På ljus bakgrund + trapFlashDialog diff --git a/resources/i18n/OpenBoard_tr.ts b/resources/i18n/OpenBoard_tr.ts index ecdb5d00..43eae4e4 100644 --- a/resources/i18n/OpenBoard_tr.ts +++ b/resources/i18n/OpenBoard_tr.ts @@ -2634,6 +2634,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + Kapalı Arkaplan Üzerine + + + Opacity + Saydamlık + + + On Light Background + Açık Arkaplan Üzerine + trapFlashDialog diff --git a/resources/i18n/OpenBoard_zh.ts b/resources/i18n/OpenBoard_zh.ts index d926ecd3..d1c6017c 100644 --- a/resources/i18n/OpenBoard_zh.ts +++ b/resources/i18n/OpenBoard_zh.ts @@ -2634,6 +2634,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + 黑色背景 + + + Opacity + 透明度 + + + On Light Background + 白色背景 + trapFlashDialog diff --git a/resources/i18n/OpenBoard_zh_CN.ts b/resources/i18n/OpenBoard_zh_CN.ts index d926ecd3..d1c6017c 100644 --- a/resources/i18n/OpenBoard_zh_CN.ts +++ b/resources/i18n/OpenBoard_zh_CN.ts @@ -2634,6 +2634,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + 黑色背景 + + + Opacity + 透明度 + + + On Light Background + 白色背景 + trapFlashDialog diff --git a/resources/i18n/OpenBoard_zh_TW.ts b/resources/i18n/OpenBoard_zh_TW.ts index e8085aa0..f2e2d424 100644 --- a/resources/i18n/OpenBoard_zh_TW.ts +++ b/resources/i18n/OpenBoard_zh_TW.ts @@ -2621,6 +2621,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: + + Grid + + + + On Dark Background + 深色背景 + + + Opacity + 透明度 + + + On Light Background + 淡色背景 + trapFlashDialog diff --git a/resources/images/setAsBackground.svg b/resources/images/setAsBackground.svg index 080542cc..8c83a086 100644 --- a/resources/images/setAsBackground.svg +++ b/resources/images/setAsBackground.svg @@ -1,87 +1,375 @@ - - - - - - - - - - - -]> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + +image/svg+xml \ No newline at end of file From ad4eec200c432c57cafa54f9fac3c0e951f6de6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Sat, 9 Dec 2017 00:02:17 +0100 Subject: [PATCH 100/134] corrected/changed settings initialisation of grid parameters --- resources/etc/OpenBoard.config | 4 ++-- src/core/UBPreferencesController.cpp | 20 +++++++++++++++----- src/core/UBSettings.cpp | 6 +++--- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/resources/etc/OpenBoard.config b/resources/etc/OpenBoard.config index 81088661..ab5e710a 100644 --- a/resources/etc/OpenBoard.config +++ b/resources/etc/OpenBoard.config @@ -25,13 +25,13 @@ UseSystemOnScreenKeyboard=true [Board] AutoSaveIntervalInMinutes=3 -CrossColorDarkBackground=#C82C2C2C +CrossColorDarkBackground=#C8C0C0C0 CrossColorLightBackground=#A5E1FF DarkBackground=0 DefaultPageSize=@Size(1280 960) EraserCircleWidthIndex=1 FeatureSliderPosition=40 -GridDarkBackgroundColors=#FFFFFF, #FF3400, #66C0FF, #81FF5C, #FFFF00, #B68360, #FF497E, #8D69FF, #C82C2C2C +GridDarkBackgroundColors=#FFFFFF, #FF3400, #66C0FF, #81FF5C, #FFFF00, #B68360, #FF497E, #8D69FF, #C8C0C0C0 GridLightBackgroundColors=#000000, #FF0000, #004080, #008000, #FFDD00, #C87400, #800040, #008080, #5F2D0A, #A5E1FF InterpolateMarkerStrokes=true InterpolatePenStrokes=true diff --git a/src/core/UBPreferencesController.cpp b/src/core/UBPreferencesController.cpp index 94041b37..32899af0 100644 --- a/src/core/UBPreferencesController.cpp +++ b/src/core/UBPreferencesController.cpp @@ -100,10 +100,6 @@ UBPreferencesController::~UBPreferencesController() delete mPenProperties; delete mMarkerProperties; - - delete mDarkBackgroundGridColorPicker; - - delete mLightBackgroundGridColorPicker; } void UBPreferencesController::adjustScreens(int screen) @@ -158,6 +154,21 @@ void UBPreferencesController::wire() //grid tab //On light background + QPalette lightBackgroundPalette = QApplication::palette(); + lightBackgroundPalette.setColor(QPalette::Window, Qt::white); + + mPreferencesUI->crossColorLightBackgroundFrame->setAutoFillBackground(true); + mPreferencesUI->crossColorLightBackgroundFrame->setPalette(lightBackgroundPalette); + + QPalette darkBackgroundPalette = QApplication::palette(); + darkBackgroundPalette.setColor(QPalette::Window, Qt::black); + darkBackgroundPalette.setColor(QPalette::ButtonText, Qt::white); + darkBackgroundPalette.setColor(QPalette::WindowText, Qt::white); + + mPreferencesUI->crossColorDarkBackgroundFrame->setAutoFillBackground(true); + mPreferencesUI->crossColorDarkBackgroundFrame->setPalette(darkBackgroundPalette); + mPreferencesUI->crossColorDarkBackgroundLabel->setPalette(darkBackgroundPalette); + QList gridLightBackgroundColors = settings->boardGridLightBackgroundColors->colors(); QColor selectedCrossColorLightBackground(settings->boardCrossColorLightBackground->get().toString()); @@ -381,7 +392,6 @@ void UBPreferencesController::defaultSettings() mPreferencesUI->webHomePage->setText(settings->webHomePage->reset().toString()); } - } void UBPreferencesController::darkBackgroundCrossOpacityValueChanged(int value) diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index c8f4a29f..131ae78c 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -286,15 +286,15 @@ void UBSettings::init() pageSize = new UBSetting(this, "Board", "DefaultPageSize", documentSizes.value(DocumentSizeRatio::Ratio4_3)); - boardCrossColorDarkBackground = new UBSetting(this, "Board", "CrossColorDarkBackground", "#C82C2C2C"); + boardCrossColorDarkBackground = new UBSetting(this, "Board", "CrossColorDarkBackground", "#C8C0C0C0"); boardCrossColorLightBackground = new UBSetting(this, "Board", "CrossColorLightBackground", "#A5E1FF"); QStringList gridLightBackgroundColors; - gridLightBackgroundColors << "#FFFFFF" << "#FF3400" << "#66C0FF" << "#81FF5C" << "#FFFF00" << "#B68360" << "#FF497E" << "#8D69FF" << "#C82C2C2C"; + gridLightBackgroundColors << "#000000" << "#FF0000" << "#004080" << "#008000" << "#FFDD00" << "#C87400" << "#800040" << "#008080" << "#A5E1FF"; boardGridLightBackgroundColors = new UBColorListSetting(this, "Board", "GridLightBackgroundColors", gridLightBackgroundColors, -1.0); QStringList gridDarkBackgroundColors; - gridDarkBackgroundColors << "#000000" << "#FF0000" << "#004080" << "#008000" << "#FFDD00" << "#C87400" << "#800040" << "#008080" << "#A5E1FF"; + gridDarkBackgroundColors << "#FFFFFF" << "#FF3400" << "#66C0FF" << "#81FF5C" << "#FFFF00" << "#B68360" << "#FF497E" << "#8D69FF" << "#C8C0C0C0"; boardGridDarkBackgroundColors = new UBColorListSetting(this, "Board", "GridDarkBackgroundColors", gridDarkBackgroundColors, -1.0); QStringList penLightBackgroundColors; From c2e16e5c878fed1f14778317ab1daae3de39c0e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 11 Dec 2017 14:38:25 +0100 Subject: [PATCH 101/134] fixed a bug where erasing a pen stroke with simplifyPenStrokes=true ereased every overlapping polygons of it --- src/domain/UBGraphicsScene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index f120ff3a..95fd9a0d 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -1024,7 +1024,7 @@ void UBGraphicsScene::eraseLineTo(const QPointF &pEndPoint, const qreal &pWidth) } else if (eraserPath.intersects(itemPainterPath)) { - + itemPainterPath.setFillRule(Qt::WindingFill); QPainterPath newPath = itemPainterPath.subtracted(eraserPath); #pragma omp critical { From 01d2b845aeab9a21348d2652b99f125fe3e8ee89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 11 Dec 2017 15:50:14 +0100 Subject: [PATCH 102/134] changed some default values --- resources/etc/OpenBoard.config | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/etc/OpenBoard.config b/resources/etc/OpenBoard.config index ab5e710a..78a0b810 100644 --- a/resources/etc/OpenBoard.config +++ b/resources/etc/OpenBoard.config @@ -1,6 +1,6 @@ [App] AngleTolerance=4 -HideCheckForSoftwareUpdate=false +HideCheckForSoftwareUpdate=true EnableAutomaticSoftwareUpdates=true EnableSoftwareUpdates=true EnableStartupHints=true @@ -70,8 +70,8 @@ ShowMarkerPreviewCircle=true ShowPenPreviewCircle=true PenPreviewFromSize=5 ShowToolsPalette=false -SimplifyMarkerStrokes=false -SimplifyPenStrokes=false +SimplifyMarkerStrokes=true +SimplifyPenStrokes=true SimplifyPenStrokesThresholdAngle=3 SimplifyPenStrokesThresholdWidthDifference=2 StartupKeyboardLocale=0 From e75fb8f4d6a91a6ee7766ec3662a6d7ad79062e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 11 Dec 2017 16:23:59 +0100 Subject: [PATCH 103/134] changed HideCheckForSoftwareUpdate default value to false --- resources/etc/OpenBoard.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/etc/OpenBoard.config b/resources/etc/OpenBoard.config index 78a0b810..2ccc834e 100644 --- a/resources/etc/OpenBoard.config +++ b/resources/etc/OpenBoard.config @@ -1,6 +1,6 @@ [App] AngleTolerance=4 -HideCheckForSoftwareUpdate=true +HideCheckForSoftwareUpdate=false EnableAutomaticSoftwareUpdates=true EnableSoftwareUpdates=true EnableStartupHints=true From c1ee274e118ea48e472d5741aa9312152b9e9120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 11 Dec 2017 16:24:57 +0100 Subject: [PATCH 104/134] changed build version to 1.4RC1 --- OpenBoard.pro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index effc516a..82d21586 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -11,8 +11,8 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 VERSION_MIN = 4 VERSION_PATCH = 0 -VERSION_TYPE = b # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_BUILD = 4 +VERSION_TYPE = rc # a = alpha, b = beta, rc = release candidate, r = release, other => error +VERSION_BUILD = 1 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}" From b73d0e22f85e38f84d8c79c819743281eed0a713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 12 Dec 2017 10:31:48 +0100 Subject: [PATCH 105/134] added translations to Openboard_fr.ts --- resources/i18n/OpenBoard_fr.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/i18n/OpenBoard_fr.ts b/resources/i18n/OpenBoard_fr.ts index 6a044792..c64c15e0 100644 --- a/resources/i18n/OpenBoard_fr.ts +++ b/resources/i18n/OpenBoard_fr.ts @@ -2475,7 +2475,7 @@ p, li { white-space: pre-wrap; } Show preview circle from - Visualiser la taille depuis + Visualiser la taille dès Pen is Pressure Sensitive @@ -2680,7 +2680,7 @@ p, li { white-space: pre-wrap; } Grid - + Quadrillage On Dark Background From a7feaed72974d9b374a018a57ed59e1bbee93831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 12 Dec 2017 23:25:47 +0100 Subject: [PATCH 106/134] resized preferences dialog --- resources/forms/preferences.ui | 512 ++++++++++++++++----------------- 1 file changed, 248 insertions(+), 264 deletions(-) diff --git a/resources/forms/preferences.ui b/resources/forms/preferences.ui index 7c3900eb..d2669e8d 100644 --- a/resources/forms/preferences.ui +++ b/resources/forms/preferences.ui @@ -6,7 +6,7 @@ 0 0 - 759 + 800 718 @@ -557,275 +557,259 @@ QFrame::Raised - + 0 - 0 + 90 741 - 611 + 52 - QFrame::StyledPanel + QFrame::NoFrame QFrame::Raised - - - - 250 - 30 - 241 - 50 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - On Dark Background - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - 0 - 90 - 741 - 52 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - Qt::Horizontal - - - - 154 - 20 - - - - - - - - Opacity - - - - - - - 20 - - - 100 - - - 50 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 20 - - - - - - - Qt::Horizontal - - - - 156 - 20 - - - - - - - - - - 250 - 150 - 241 - 51 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - On Light Background - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - 0 - 210 - 741 - 52 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - Qt::Horizontal - - - - 154 - 20 - - - - - - - - Opacity - - - - - - - 20 - - - 100 - - - 50 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 20 - - - - - - - Qt::Horizontal - - - - 156 - 20 - - - - - - + + + + + Qt::Horizontal + + + + 154 + 20 + + + + + + + + Opacity + + + + + + + 20 + + + 100 + + + 50 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 20 + + + + + + + Qt::Horizontal + + + + 156 + 20 + + + + + + + + + + 250 + 30 + 241 + 50 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + On Dark Background + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + 0 + 210 + 741 + 52 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + Qt::Horizontal + + + + 154 + 20 + + + + + + + + Opacity + + + + + + + 20 + + + 100 + + + 50 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 20 + + + + + + + Qt::Horizontal + + + + 156 + 20 + + + + + + + + + + 250 + 150 + 241 + 51 + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + On Light Background + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + @@ -3009,7 +2993,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:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; 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> @@ -3103,7 +3087,7 @@ 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:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; 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;"> @@ -3122,9 +3106,9 @@ p, li { white-space: pre-wrap; } <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-family:'.Helvetica Neue DeskInterface'; 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-family:'.Helvetica Neue DeskInterface'; 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;">emails: </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>, <a href="mailto:sem.logistique@edu.ge.ch"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#0000ff;">support@openboard.ch</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;"><a href="http://www.openboard.ch"><span style=" font-family:'.Helvetica Neue DeskInterface'; 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-family:'.Helvetica Neue DeskInterface'; 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;">emails: </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><span style=" font-family:'Ubuntu'; font-size:11pt;">, </span><a href="mailto:sem.logistique@edu.ge.ch"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#0000ff;">support@openboard.ch</span></a></p></td></tr></table></body></html> true From 66447700d7a6e91f840738870877329384b7a340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Wed, 13 Dec 2017 00:00:41 +0100 Subject: [PATCH 107/134] default settings on grid Tab --- src/core/UBPreferencesController.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/core/UBPreferencesController.cpp b/src/core/UBPreferencesController.cpp index 32899af0..b7f4dfdd 100644 --- a/src/core/UBPreferencesController.cpp +++ b/src/core/UBPreferencesController.cpp @@ -392,6 +392,33 @@ void UBPreferencesController::defaultSettings() mPreferencesUI->webHomePage->setText(settings->webHomePage->reset().toString()); } + else if(mPreferencesUI->mainTabWidget->currentWidget() == mPreferencesUI->gridTab) + { + settings->boardCrossColorDarkBackground->reset(); + settings->boardGridDarkBackgroundColors->reset(); + + QList gridDarkBackgroundColors = settings->boardGridDarkBackgroundColors->colors(); + QColor selectedCrossColorDarkBackground(settings->boardCrossColorDarkBackground->get().toString()); + + mDarkBackgroundGridColorPicker->setColors(gridDarkBackgroundColors); + mDarkBackgroundGridColorPicker->setSelectedColorIndex(gridDarkBackgroundColors.indexOf(selectedCrossColorDarkBackground)); + int darkBackgroundOpacity = selectedCrossColorDarkBackground.alpha()*100 / 255; + mPreferencesUI->darkBackgroundOpacitySlider->setValue(darkBackgroundOpacity); + darkBackgroundCrossOpacityValueChanged(darkBackgroundOpacity); + + settings->boardCrossColorLightBackground->reset(); + settings->boardGridLightBackgroundColors->reset(); + + QList gridLightBackgroundColors = settings->boardGridLightBackgroundColors->colors(); + QColor selectedCrossColorLightBackground(settings->boardCrossColorLightBackground->get().toString()); + + mLightBackgroundGridColorPicker->setColors(gridLightBackgroundColors); + mLightBackgroundGridColorPicker->setSelectedColorIndex(gridLightBackgroundColors.indexOf(selectedCrossColorLightBackground)); + int lightBackgroundOpacity = selectedCrossColorLightBackground.alpha()*100 / 255; + mPreferencesUI->lightBackgroundOpacitySlider->setValue(lightBackgroundOpacity); + lightBackgroundCrossOpacityValueChanged(lightBackgroundOpacity); + + } } void UBPreferencesController::darkBackgroundCrossOpacityValueChanged(int value) From 1dcd59e307524985c9f8aa566bf73992e3b189c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 19 Dec 2017 23:47:39 +0100 Subject: [PATCH 108/134] changed old compass behavior to match with new strokes simplification --- src/domain/UBGraphicsScene.cpp | 1 + src/frameworks/UBGeometryUtils.cpp | 21 ++++++--------------- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 95fd9a0d..c6ffe7e3 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -1094,6 +1094,7 @@ void UBGraphicsScene::drawArcTo(const QPointF& pCenterPoint, qreal pSpanAngle) penWidth /= UBApplication::boardController->currentZoom(); mArcPolygonItem = arcToPolygonItem(QLineF(pCenterPoint, mPreviousPoint), pSpanAngle, penWidth); + mArcPolygonItem->setFillRule(Qt::WindingFill); mArcPolygonItem->setStroke(mCurrentStroke); mAddedItems.insert(mArcPolygonItem); addItem(mArcPolygonItem); diff --git a/src/frameworks/UBGeometryUtils.cpp b/src/frameworks/UBGeometryUtils.cpp index 01c1fe1a..3dabcc5c 100644 --- a/src/frameworks/UBGeometryUtils.cpp +++ b/src/frameworks/UBGeometryUtils.cpp @@ -225,21 +225,12 @@ QPolygonF UBGeometryUtils::arcToPolygon(const QLineF& startRadius, qreal spanAng endAngleInDegrees = - endAngleInDegrees; spanAngleInDegrees = - spanAngleInDegrees; - if (overlap) - { - painterPath.addEllipse(outerSquare); - QPainterPath innerPainterPath; - innerPainterPath.addEllipse(innerSquare); - painterPath = painterPath.subtracted(innerPainterPath); - } - else - { - painterPath.arcTo(innerSquare, startAngleInDegrees, spanAngleInDegrees); - painterPath.arcTo(endSquare, 180.0 + endAngleInDegrees, spanAngleInDegrees > 0 ? -180.0 : 180.0); - painterPath.arcTo(outerSquare, endAngleInDegrees, - spanAngleInDegrees); - painterPath.arcTo(startSquare, startAngleInDegrees, spanAngleInDegrees > 0 ? -180.0 : 180.0); - painterPath.closeSubpath(); - } + painterPath.setFillRule(Qt::WindingFill); + painterPath.arcTo(innerSquare, startAngleInDegrees, spanAngleInDegrees); + painterPath.arcTo(endSquare, 180.0 + endAngleInDegrees, spanAngleInDegrees > 0 ? -180.0 : 180.0); + painterPath.arcTo(outerSquare, endAngleInDegrees, - spanAngleInDegrees); + painterPath.arcTo(startSquare, startAngleInDegrees, spanAngleInDegrees > 0 ? -180.0 : 180.0); + painterPath.closeSubpath(); return painterPath.toFillPolygon(); } From 2a92fc1ba1cfc1187199e84e0f5b27b13d9bf40d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 19 Dec 2017 23:49:46 +0100 Subject: [PATCH 109/134] fade grid opacity on zooms lower than 0.7 --- src/board/UBBoardView.cpp | 2 +- src/domain/UBGraphicsScene.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/board/UBBoardView.cpp b/src/board/UBBoardView.cpp index 311d9f25..52936055 100644 --- a/src/board/UBBoardView.cpp +++ b/src/board/UBBoardView.cpp @@ -1609,7 +1609,7 @@ void UBBoardView::drawBackground (QPainter *painter, const QRectF &rect) else bgCrossColor = QColor(UBSettings::settings()->boardCrossColorLightBackground->get().toString()); - if (transform ().m11 () < 1.0) + if (transform ().m11 () < 0.7) { int alpha = 255 * transform ().m11 () / 2; bgCrossColor.setAlpha (alpha); // fade the crossing on small zooms diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index c6ffe7e3..eb6e9dfe 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -2628,7 +2628,7 @@ void UBGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect) bgCrossColor = QColor(UBSettings::settings()->boardCrossColorDarkBackground->get().toString()); else bgCrossColor = QColor(UBSettings::settings()->boardCrossColorLightBackground->get().toString()); - if (mZoomFactor < 1.0) + if (mZoomFactor < 0.7) { int alpha = 255 * mZoomFactor / 2; bgCrossColor.setAlpha (alpha); // fade the crossing on small zooms From 68c7da58fef6b6eba9bb4a9195802ecbfd5e691c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Wed, 20 Dec 2017 11:40:34 +0100 Subject: [PATCH 110/134] persist document before possible crash on ClearUndoStack (when using eraser then clearBoard button --- src/board/UBBoardController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 78afff8b..1a983df3 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1885,9 +1885,9 @@ void UBBoardController::appMainModeChanged(UBApplicationController::MainMode md) void UBBoardController::closing() { mIsClosing = true; + lastWindowClosed(); ClearUndoStack(); showKeyboard(false); - lastWindowClosed(); } void UBBoardController::lastWindowClosed() From 8fec7b23c3c94a3fcee17f938656abdcf66b653b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Wed, 20 Dec 2017 13:18:31 +0100 Subject: [PATCH 111/134] preventing bad behavior when playing with eraser --- src/domain/UBGraphicsScene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index eb6e9dfe..5dcb30b6 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -2025,7 +2025,7 @@ QRectF UBGraphicsScene::annotationsBoundingRect() const bool UBGraphicsScene::isEmpty() const { - return mItemCount == 0; + return mItemCount <= 0; // mItemCount can currently be negative when playing with eraser } QGraphicsItem* UBGraphicsScene::setAsBackgroundObject(QGraphicsItem* item, bool pAdaptTransformation, bool pExpand) From e084bdbfb9721219d7a7ac8d4b404eee12320a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Wed, 20 Dec 2017 13:20:43 +0100 Subject: [PATCH 112/134] Revert "preventing bad behavior when playing with eraser" This reverts commit 8fec7b23c3c94a3fcee17f938656abdcf66b653b. --- src/domain/UBGraphicsScene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp index 5dcb30b6..eb6e9dfe 100644 --- a/src/domain/UBGraphicsScene.cpp +++ b/src/domain/UBGraphicsScene.cpp @@ -2025,7 +2025,7 @@ QRectF UBGraphicsScene::annotationsBoundingRect() const bool UBGraphicsScene::isEmpty() const { - return mItemCount <= 0; // mItemCount can currently be negative when playing with eraser + return mItemCount == 0; } QGraphicsItem* UBGraphicsScene::setAsBackgroundObject(QGraphicsItem* item, bool pAdaptTransformation, bool pExpand) From 8a2ce95145d9b85d822ebd48c6d71166e6201d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Wed, 20 Dec 2017 13:23:44 +0100 Subject: [PATCH 113/134] chenaged build version to 1.4-rc2 --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index 82d21586..b1a87f3c 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -12,7 +12,7 @@ VERSION_MAJ = 1 VERSION_MIN = 4 VERSION_PATCH = 0 VERSION_TYPE = rc # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_BUILD = 1 +VERSION_BUILD = 2 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}" From 723ef7b2633e3717d9a1dc5c7c7b8ebeac882d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 23 Jan 2018 11:15:26 +0100 Subject: [PATCH 114/134] fixed a bug where adding an existing page to the curent document resulted in a crash --- src/board/UBBoardController.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 1a983df3..e5ce8e36 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -550,6 +550,7 @@ void UBBoardController::addScene(UBGraphicsScene* scene, bool replaceActiveIfEmp if (replaceActiveIfEmpty && mActiveScene->isEmpty()) { UBPersistenceManager::persistenceManager()->insertDocumentSceneAt(selectedDocument(), clone, mActiveSceneIndex); + emit addThumbnailRequired(this, mActiveSceneIndex); setActiveDocumentScene(mActiveSceneIndex); deleteScene(mActiveSceneIndex + 1); } @@ -557,6 +558,7 @@ void UBBoardController::addScene(UBGraphicsScene* scene, bool replaceActiveIfEmp { persistCurrentScene(false,true); UBPersistenceManager::persistenceManager()->insertDocumentSceneAt(selectedDocument(), clone, mActiveSceneIndex + 1); + emit addThumbnailRequired(this, mActiveSceneIndex + 1); setActiveDocumentScene(mActiveSceneIndex + 1); } From ae1a2a533872d335b0d7d73e8520958b0d26d49c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 23 Jan 2018 11:20:22 +0100 Subject: [PATCH 115/134] due to suspected instability with persistance Worker (randomly not persisted scenes, very hard to reproduce), switched to 'immediateSave mode' (at least for now) --- src/core/UBPersistenceManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/UBPersistenceManager.h b/src/core/UBPersistenceManager.h index 19d10f66..9208c5c0 100644 --- a/src/core/UBPersistenceManager.h +++ b/src/core/UBPersistenceManager.h @@ -77,7 +77,7 @@ class UBPersistenceManager : public QObject virtual void duplicateDocumentScene(UBDocumentProxy* pDocumentProxy, int index); virtual void persistDocumentScene(UBDocumentProxy* pDocumentProxy, - UBGraphicsScene* pScene, const int pSceneIndex, bool isAnAutomaticBackup = false, bool forceImmediateSaving = false); + UBGraphicsScene* pScene, const int pSceneIndex, bool isAnAutomaticBackup = false, bool forceImmediateSaving = true); virtual UBGraphicsScene* createDocumentSceneAt(UBDocumentProxy* pDocumentProxy, int index, bool useUndoRedoStack = true); From 7d35b53a689e4e93b18979bd919cd95fa95314cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 23 Jan 2018 11:37:35 +0100 Subject: [PATCH 116/134] autoresize of the grid tab (in preferences) --- resources/forms/preferences.ui | 543 ++++++++++++++++----------------- 1 file changed, 265 insertions(+), 278 deletions(-) diff --git a/resources/forms/preferences.ui b/resources/forms/preferences.ui index d2669e8d..da315e55 100644 --- a/resources/forms/preferences.ui +++ b/resources/forms/preferences.ui @@ -539,279 +539,266 @@ Grid - - - true - - - - -1 - -1 - 741 - 591 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - 0 - 90 - 741 - 52 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - Qt::Horizontal - - - - 154 - 20 - - - - - - - - Opacity - - - - - - - 20 - - - 100 - - - 50 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 20 - - - - - - - Qt::Horizontal - - - - 156 - 20 - - - - - - - - - - 250 - 30 - 241 - 50 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - On Dark Background - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - - - 0 - 210 - 741 - 52 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - Qt::Horizontal - - - - 154 - 20 - - - - - - - - Opacity - - - - - - - 20 - - - 100 - - - 50 - - - Qt::Horizontal - - - QSlider::TicksAbove - - - 20 - - - - - - - Qt::Horizontal - - - - 156 - 20 - - - - - - - - - - 250 - 150 - 241 - 51 - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - On Light Background - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - 32 - 32 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - + + + + + true + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + On Light Background + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + Qt::Horizontal + + + + 154 + 20 + + + + + + + + Opacity + + + + + + + 20 + + + 100 + + + 50 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 20 + + + + + + + Qt::Horizontal + + + + 156 + 20 + + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + On Dark Background + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + Qt::Horizontal + + + + 154 + 20 + + + + + + + + Opacity + + + + + + + 20 + + + 100 + + + 50 + + + Qt::Horizontal + + + QSlider::TicksAbove + + + 20 + + + + + + + Qt::Horizontal + + + + 156 + 20 + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 342 + + + + + @@ -2993,7 +2980,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:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; 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> @@ -3087,7 +3074,7 @@ 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:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; 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;"> @@ -3106,9 +3093,9 @@ p, li { white-space: pre-wrap; } <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-family:'.Helvetica Neue DeskInterface'; 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-family:'.Helvetica Neue DeskInterface'; 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;">emails: </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><span style=" font-family:'Ubuntu'; font-size:11pt;">, </span><a href="mailto:sem.logistique@edu.ge.ch"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#0000ff;">support@openboard.ch</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;"><a href="http://www.openboard.ch"><span style=" font-family:'.Helvetica Neue DeskInterface'; 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-family:'.Helvetica Neue DeskInterface'; 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;">emails: </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>, <a href="mailto:sem.logistique@edu.ge.ch"><span style=" font-family:'Cantarell'; font-size:10pt; text-decoration: underline; color:#0000ff;">support@openboard.ch</span></a></p></td></tr></table></body></html> true From a7287d1618e5343259fbe44c653522981ff31c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 23 Jan 2018 11:44:07 +0100 Subject: [PATCH 117/134] removed Planete Sankore widgets --- .../search/Audio Planete.wgs/config.xml | 16 - .../search/Audio Planete.wgs/css/basic.css | 315 ------------------ .../library/search/Audio Planete.wgs/icon.png | Bin 8966 -> 0 bytes .../Audio Planete.wgs/icon.thumbnail.png | Bin 8966 -> 0 bytes .../search/Audio Planete.wgs/images/down.png | Bin 1192 -> 0 bytes .../Audio Planete.wgs/images/greySquare.png | Bin 214 -> 0 bytes .../Audio Planete.wgs/images/icon-close.png | Bin 1507 -> 0 bytes .../Audio Planete.wgs/images/popupBack.png | Bin 931 -> 0 bytes .../Audio Planete.wgs/images/search.png | Bin 1797 -> 0 bytes .../Audio Planete.wgs/images/search_app.png | Bin 1104 -> 0 bytes .../images/thumbnail_icon.png | Bin 10376 -> 0 bytes .../Audio Planete.wgs/images/trgDown.png | Bin 475 -> 0 bytes .../search/Audio Planete.wgs/images/trgUp.png | Bin 448 -> 0 bytes .../search/Audio Planete.wgs/images/up.png | Bin 1196 -> 0 bytes .../search/Audio Planete.wgs/index.html | 253 -------------- .../scripts/jquery-1.6.2.min.js | 18 - .../search/Flash Planete.wgs/config.xml | 16 - .../search/Flash Planete.wgs/css/basic.css | 315 ------------------ .../library/search/Flash Planete.wgs/icon.png | Bin 8869 -> 0 bytes .../Flash Planete.wgs/icon.thumbnail.png | Bin 8869 -> 0 bytes .../search/Flash Planete.wgs/images/down.png | Bin 1192 -> 0 bytes .../Flash Planete.wgs/images/greySquare.png | Bin 214 -> 0 bytes .../Flash Planete.wgs/images/icon-close.png | Bin 1507 -> 0 bytes .../Flash Planete.wgs/images/popupBack.png | Bin 931 -> 0 bytes .../Flash Planete.wgs/images/search.png | Bin 1797 -> 0 bytes .../Flash Planete.wgs/images/search_app.png | Bin 1104 -> 0 bytes .../images/thumbnail_icon.png | Bin 11435 -> 0 bytes .../Flash Planete.wgs/images/trgDown.png | Bin 475 -> 0 bytes .../search/Flash Planete.wgs/images/trgUp.png | Bin 448 -> 0 bytes .../search/Flash Planete.wgs/images/up.png | Bin 1196 -> 0 bytes .../search/Flash Planete.wgs/index.html | 253 -------------- .../scripts/jquery-1.6.2.min.js | 18 - .../search/Image Planete.wgs/config.xml | 16 - .../search/Image Planete.wgs/css/basic.css | 314 ----------------- .../library/search/Image Planete.wgs/icon.png | Bin 9854 -> 0 bytes .../Image Planete.wgs/icon.thumbnail.png | Bin 9854 -> 0 bytes .../search/Image Planete.wgs/images/down.png | Bin 1192 -> 0 bytes .../Image Planete.wgs/images/greySquare.png | Bin 214 -> 0 bytes .../Image Planete.wgs/images/icon-close.png | Bin 1507 -> 0 bytes .../Image Planete.wgs/images/popupBack.png | Bin 931 -> 0 bytes .../Image Planete.wgs/images/search.png | Bin 1797 -> 0 bytes .../Image Planete.wgs/images/search_app.png | Bin 1104 -> 0 bytes .../Image Planete.wgs/images/trgDown.png | Bin 475 -> 0 bytes .../search/Image Planete.wgs/images/trgUp.png | Bin 448 -> 0 bytes .../search/Image Planete.wgs/images/up.png | Bin 1196 -> 0 bytes .../search/Image Planete.wgs/index.html | 268 --------------- .../scripts/jquery-1.6.2.min.js | 18 - .../search/Video Planete.wgs/config.xml | 16 - .../search/Video Planete.wgs/css/basic.css | 315 ------------------ .../library/search/Video Planete.wgs/icon.png | Bin 9195 -> 0 bytes .../Video Planete.wgs/icon.thumbnail.png | Bin 9195 -> 0 bytes .../search/Video Planete.wgs/images/down.png | Bin 1192 -> 0 bytes .../Video Planete.wgs/images/greySquare.png | Bin 214 -> 0 bytes .../Video Planete.wgs/images/icon-close.png | Bin 1507 -> 0 bytes .../Video Planete.wgs/images/popupBack.png | Bin 931 -> 0 bytes .../Video Planete.wgs/images/search.png | Bin 1797 -> 0 bytes .../Video Planete.wgs/images/search_app.png | Bin 1104 -> 0 bytes .../images/thumbnail_icon.png | Bin 10911 -> 0 bytes .../Video Planete.wgs/images/trgDown.png | Bin 475 -> 0 bytes .../search/Video Planete.wgs/images/trgUp.png | Bin 448 -> 0 bytes .../search/Video Planete.wgs/images/up.png | Bin 1196 -> 0 bytes .../search/Video Planete.wgs/index.html | 254 -------------- .../scripts/jquery-1.6.2.min.js | 18 - 63 files changed, 2423 deletions(-) delete mode 100755 resources/library/search/Audio Planete.wgs/config.xml delete mode 100755 resources/library/search/Audio Planete.wgs/css/basic.css delete mode 100755 resources/library/search/Audio Planete.wgs/icon.png delete mode 100755 resources/library/search/Audio Planete.wgs/icon.thumbnail.png delete mode 100755 resources/library/search/Audio Planete.wgs/images/down.png delete mode 100755 resources/library/search/Audio Planete.wgs/images/greySquare.png delete mode 100755 resources/library/search/Audio Planete.wgs/images/icon-close.png delete mode 100755 resources/library/search/Audio Planete.wgs/images/popupBack.png delete mode 100755 resources/library/search/Audio Planete.wgs/images/search.png delete mode 100755 resources/library/search/Audio Planete.wgs/images/search_app.png delete mode 100755 resources/library/search/Audio Planete.wgs/images/thumbnail_icon.png delete mode 100755 resources/library/search/Audio Planete.wgs/images/trgDown.png delete mode 100755 resources/library/search/Audio Planete.wgs/images/trgUp.png delete mode 100755 resources/library/search/Audio Planete.wgs/images/up.png delete mode 100755 resources/library/search/Audio Planete.wgs/index.html delete mode 100755 resources/library/search/Audio Planete.wgs/scripts/jquery-1.6.2.min.js delete mode 100755 resources/library/search/Flash Planete.wgs/config.xml delete mode 100755 resources/library/search/Flash Planete.wgs/css/basic.css delete mode 100755 resources/library/search/Flash Planete.wgs/icon.png delete mode 100755 resources/library/search/Flash Planete.wgs/icon.thumbnail.png delete mode 100755 resources/library/search/Flash Planete.wgs/images/down.png delete mode 100755 resources/library/search/Flash Planete.wgs/images/greySquare.png delete mode 100755 resources/library/search/Flash Planete.wgs/images/icon-close.png delete mode 100755 resources/library/search/Flash Planete.wgs/images/popupBack.png delete mode 100755 resources/library/search/Flash Planete.wgs/images/search.png delete mode 100755 resources/library/search/Flash Planete.wgs/images/search_app.png delete mode 100755 resources/library/search/Flash Planete.wgs/images/thumbnail_icon.png delete mode 100755 resources/library/search/Flash Planete.wgs/images/trgDown.png delete mode 100755 resources/library/search/Flash Planete.wgs/images/trgUp.png delete mode 100755 resources/library/search/Flash Planete.wgs/images/up.png delete mode 100755 resources/library/search/Flash Planete.wgs/index.html delete mode 100755 resources/library/search/Flash Planete.wgs/scripts/jquery-1.6.2.min.js delete mode 100755 resources/library/search/Image Planete.wgs/config.xml delete mode 100755 resources/library/search/Image Planete.wgs/css/basic.css delete mode 100755 resources/library/search/Image Planete.wgs/icon.png delete mode 100755 resources/library/search/Image Planete.wgs/icon.thumbnail.png delete mode 100755 resources/library/search/Image Planete.wgs/images/down.png delete mode 100755 resources/library/search/Image Planete.wgs/images/greySquare.png delete mode 100755 resources/library/search/Image Planete.wgs/images/icon-close.png delete mode 100755 resources/library/search/Image Planete.wgs/images/popupBack.png delete mode 100755 resources/library/search/Image Planete.wgs/images/search.png delete mode 100755 resources/library/search/Image Planete.wgs/images/search_app.png delete mode 100755 resources/library/search/Image Planete.wgs/images/trgDown.png delete mode 100755 resources/library/search/Image Planete.wgs/images/trgUp.png delete mode 100755 resources/library/search/Image Planete.wgs/images/up.png delete mode 100755 resources/library/search/Image Planete.wgs/index.html delete mode 100755 resources/library/search/Image Planete.wgs/scripts/jquery-1.6.2.min.js delete mode 100755 resources/library/search/Video Planete.wgs/config.xml delete mode 100755 resources/library/search/Video Planete.wgs/css/basic.css delete mode 100755 resources/library/search/Video Planete.wgs/icon.png delete mode 100755 resources/library/search/Video Planete.wgs/icon.thumbnail.png delete mode 100755 resources/library/search/Video Planete.wgs/images/down.png delete mode 100755 resources/library/search/Video Planete.wgs/images/greySquare.png delete mode 100755 resources/library/search/Video Planete.wgs/images/icon-close.png delete mode 100755 resources/library/search/Video Planete.wgs/images/popupBack.png delete mode 100755 resources/library/search/Video Planete.wgs/images/search.png delete mode 100755 resources/library/search/Video Planete.wgs/images/search_app.png delete mode 100755 resources/library/search/Video Planete.wgs/images/thumbnail_icon.png delete mode 100755 resources/library/search/Video Planete.wgs/images/trgDown.png delete mode 100755 resources/library/search/Video Planete.wgs/images/trgUp.png delete mode 100755 resources/library/search/Video Planete.wgs/images/up.png delete mode 100755 resources/library/search/Video Planete.wgs/index.html delete mode 100755 resources/library/search/Video Planete.wgs/scripts/jquery-1.6.2.min.js diff --git a/resources/library/search/Audio Planete.wgs/config.xml b/resources/library/search/Audio Planete.wgs/config.xml deleted file mode 100755 index d7cc14eb..00000000 --- a/resources/library/search/Audio Planete.wgs/config.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - Choisir - Mnemis SA - Choisir widget - - - diff --git a/resources/library/search/Audio Planete.wgs/css/basic.css b/resources/library/search/Audio Planete.wgs/css/basic.css deleted file mode 100755 index 80b50fbc..00000000 --- a/resources/library/search/Audio Planete.wgs/css/basic.css +++ /dev/null @@ -1,315 +0,0 @@ -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; - border: 1px solid #666; - border-radius: 5px; - -webkit-box-shadow: #dadada -1px 0 4px; - -webkit-border-radius: 5px; - box-shadow: #666 -1px 0 4px; - vertical-align: top; -} - - -.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/Audio Planete.wgs/icon.png b/resources/library/search/Audio Planete.wgs/icon.png deleted file mode 100755 index 17286306a2ada1d56ab306673ce6f7272b019bda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8966 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 KMU=iY3i>|>)ZGjK diff --git a/resources/library/search/Audio Planete.wgs/icon.thumbnail.png b/resources/library/search/Audio Planete.wgs/icon.thumbnail.png deleted file mode 100755 index 17286306a2ada1d56ab306673ce6f7272b019bda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8966 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 KMU=iY3i>|>)ZGjK diff --git a/resources/library/search/Audio Planete.wgs/images/down.png b/resources/library/search/Audio Planete.wgs/images/down.png deleted file mode 100755 index 1de37e16ff7500ef6f776158baf7fdd9ded21190..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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^ diff --git a/resources/library/search/Audio Planete.wgs/images/greySquare.png b/resources/library/search/Audio Planete.wgs/images/greySquare.png deleted file mode 100755 index c0a7f14e8cc02340252ef48d9b5893d72b72239a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^UO+6v!3HFcv1`r-Qgc0B978H@y}fD3cgTRpE%AP* zvcghXA^y^sbNyO*jJg|H=4zdYvGxAXYFAmU^ft&#T=!?5nQi{&{4?7(a7^C7sVv#{ zI%4(O2QvCOQelEu_b_~_UiDP*ocZ6myVo+g+;3pw(pUf@*hB&x7+HaYA(*@19KUPK ziyrQYNe5n>2o?O!u|Srw#Q)W-=~g($@^iH5Tk`d%-?cw2}%pE)tDgY(m6A=;N zpP!$vtE;O!S6NwUzIN@}`P$mrgvQ3k#MszaV|I47v8=2t9REWC0s=I&hSw_GZNMEV z?Oa7l5)%`3_wL=Z^z`&(&CJZSEiW(sgx{eUD=RCn=jZ49y1Tn`($dmQI-M?vH=tr& zUMCUDSx~Ll>jTo$(<7Rino?f8c=5fI?CH~|`x6rr`_l1e&z^k;4@E{tM;rY8{k5cv zb;{il3zquQj%_xZxxKwTcXf63Pf`d=58&Dzc;GE$*2I9jH)?8Xb`}>G4_NjMtiO)9 zM`$#fK+-9-TuQ3;^YaUWa`U4{kMf~pn-q0*b?t?QhOSEqr7)RH8$&}wdxG^?SB$Z9 zOs*D_3qJ+NLu)phBayK-So#+&Zfk9dC{2qg~Yk_!ptLoT*jt+6dFEw^dG z!otEnV(sGI3l}bI#KpxOiE&_H;CfC@&X$jlk8@0^RIW`=Pw$eh-rn9XpzA%12XUz> z1Y$odG9Zgn#>dCMCE@$`@9&6}qe*NC?kg`Z-xkKh!ooH{;7BS;KJl8oyu2+MpPiju zz1{w}CLyb< zNoa0vZqFSlTBVazh@U6&fq{WdnlCOceyCEZKE_y>3$eGiccQ^yxPx~0F9}LZ3CXc8 zCMEZ#q@=jS{OZ-KTheBN-t8zUG^R>$93j?Y@FLuOb8KvEi3AG^3tf~@mLC^Wal)a^ z?uyq?U*`km7rb8wK9agx2VyHul|r1e->~qmxFHC2NmfY{i4F;JwbV;!9FE%W?ChMz z`=@|QayiNgh())_!eTpW^Yw9cc^X`~a%GcS=0B+CMvU2rLtIV@Zs3s$h2qlLvuE$1 ztiBf9N(xR(N^KRFgMH5C35?waE=e1RoPAF1%nCQ=qnUh;Cht7_OG``tx8<3cnVYC{ z2Wekl-z$vSflo-cv}MZKbZX#cAQj{{aeMd@{d!6u9~l|h%E-vrl*V10Nd5i&&IAPM z&lrCQ+#sE-+vSjO9*cZ*S%AwRzl#!T#U*d*$&)9)3kt~^YJ<2EZ4m|s2e*Wh;U4gJ zb#*lz3a!9h(#1ND9E&a&0e}we4}mNqhlRB3LEJD`P-?$P?^psRCnx{FrQsE-V~8y! z(k#|>>_x!k>I2X&sBqU^t=73I)=?z|M zWnFHsJ}#F%7BsSpC>!&DQs6V-0kZ!qpaahx^bF5D;JH$ky~Jyctjq0X@5uF*T|;p> z&pRh&nLq(h1e7p}cr24;th^?ab)0y;m3~F2xXc1si3x~iORRj-#PhR-=S(ac$ZJ*Z zz9u|YSX>olJ*CvC2|PA_&2hxX9uT z%|Z*aXvo59U9^a}GK-63R)Z2k4Mht`hi}!`jQ{P3ZdvG)9!?SoOq*iE< zMrbq4!M8bHmT*`3#8`#2LOWr-@Oj6363WU&<2vLLGzYr_|JZR>f+=4aw;@-cw_#=Y zCC7CMTSsoW4-u%s4Bk6ZLQv9TNLK{66=lPcck7g`pgXjE;*ubzxNCUq-7Lkz(eJm3 zRzatt*O2$_9;F;~k+x1W3Yrzp(B|D`%AKH3XjRrj8lX+EH2g)!f`mzB#drpC9@+)V z!Vf#Dgt?l5c1SO@P)n@rI4@yYxn=Bz4A%_I!B-vEB)nDb8577u=sfHV{J!IR2_Kb* zMnP6FYMAzTNw*!uQ{T}(2r`O%Ev~0@i?z63({==HitZSL#|Yh{Ak)<6v<*R8(Q0V- z$k1I4GDe-Dz4*PWdLiz4-N?11ACvW8=3>)uKUa7FoH%`iI?T+TjpFg22frOS{@;nu zQ>Q-reyRD7D4iSZ&)zz_@zZZ3#bWYz(>KlaU4Q;_?ZPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2ipr5 z2qi4q3-!kU00xCgL_t(o!^M?rP?YBt$N$gXcVXFOSyW(E@B%VTMns~uL5$IvPBEdH zNHru*lWCi(ok`lU7bzc_8Ph2lFPLZ)JC&xUA_z^?Ne#iOpbIP%5xL)Ci|Dd+kzJO( zz570=AApV@I&Ibq{m;B}o_XGR=lss)JqP$7TArMuDfsZ?__OEEFaO!T{U!j?*>^8x zy^1HUcYgYF0KoGbHZQ(+EpdyMDYm@)%A-5pv-ch3=O2lyti0k`leYR-0Ky#)Tqi_MbwpIm zIsXmk^d=|TBoNIbqS?$X{K=j@m;QYAT-{?wUtC;LxnTah_mbCS>VhJT6HyE2R7^y_ zC88g5qRbH@rHu$(0b=!bJ_Es`e_wdA<8Z;Te8@Cdm%cG{=Sj)m_|B(i&I|xhyS%~6 zL}cZhR}fJlC(7kSuRDnh4~VpOBHdjgU6(+*ntNQ==%g?J8K+Jaj%H?UQ-$hV0ssYv z4<9>GSoD#(%ad*oO5Z2I$rzg?z|8Gs{o=@K%|-w87@PlPR}A;<1m)pqMo6l z;oBOO=IxLHV&fJjNDwp)xtBM7Gf{PBfrehT13%<|mjQwZ*hD~-0?`t{C2m(43l6h5ym_W7sG(nBH)w) zaRe|40GgRZQUYWWK%rz11W@df)ngJ*PtweM2z+e-nM}GkEKECTij0m0;0E9bXV@qJ zEnc8o3K-Z!17r5g*tC^Mrfpn&qI$f4NDd$z!1&h&n3!;SjnPrMd!oz;z)#abLJllr zfKmh|9{zv;@EJ=0L=FT5u-I6=dbq_y0DK{pptrAYP_2~Dmj^JP1A-Kg6QBmbMIe#` zVY8{nL(YSkZjgW%@OXe2gCx4Ur_Tz&6B59r%X#P4?dGWsThgBCxktXlI2I-l7-LZQ z0J#Jp=|cb_0D%BM13W%pauSdciSYk3xxJ(Fe8^1*z;@uk?>^g}ot^Vlo33A@rwEyv zsbzr384QYyR4Q^ zHQ8vY#YIz{0dfx#x$n+A!$j^rk=(6Qb^-QLf=a@WwMIl<-h22U|9umH z5$EJ2bXslb006=bhN!%<^0NKu85`-!ZDJ!12CWXzXr_NRAuwHY!4Irm0eW^3*pY%` z*t+ezXlrS`mGQ#*laV^z=|Ss1kg#~sBb7ocl_~ZgI(Wo(f5b|z08y)z_{|QY>up4J z-9-JPL_R?vi=~cU&E9!SsZzf-IAnEveDW0CFq>)8?fx+Bxee@b7NY`S&qYQWPvz`- z(@|dj8MU^yQg>Gu)z{b4(WA#{{f12g3Z;7Q%+!TuPrzh~Wfw2~RpW3tnteY1W&ju-9>G(UQmJGn)55KtUESV~ zj-Q~L=34sn>^VL>eAiaC%?<8Q3Bu`6A+g0Dt=r8~L0vAP* z+S)tFHfo^rpCSRzWXiAp=2>Ju~{YO%j`v;{AnO3Cnp{Nevz9ycLaL9 no&i_~K!yLKq%&pt_r<>e3DP04`(KF000000NkvXXu0mjf(Na=@ diff --git a/resources/library/search/Audio Planete.wgs/images/search_app.png b/resources/library/search/Audio Planete.wgs/images/search_app.png deleted file mode 100755 index efd8ea4a12012eb26b752d8e34010722dab5e9d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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? diff --git a/resources/library/search/Audio Planete.wgs/images/thumbnail_icon.png b/resources/library/search/Audio Planete.wgs/images/thumbnail_icon.png deleted file mode 100755 index 5eedb793d66ecc263e7973e0c216c464478921ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10376 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 diff --git a/resources/library/search/Audio Planete.wgs/images/trgDown.png b/resources/library/search/Audio Planete.wgs/images/trgDown.png deleted file mode 100755 index 632be5fb5560dde4c9a5c76430e7878d817381b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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_ - - - - Planete Sankore Image Search - - - - - - -
- - diff --git a/resources/library/search/Audio Planete.wgs/scripts/jquery-1.6.2.min.js b/resources/library/search/Audio Planete.wgs/scripts/jquery-1.6.2.min.js deleted file mode 100755 index e67db747..00000000 --- a/resources/library/search/Audio Planete.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/Flash Planete.wgs/config.xml b/resources/library/search/Flash Planete.wgs/config.xml deleted file mode 100755 index d7cc14eb..00000000 --- a/resources/library/search/Flash Planete.wgs/config.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - Choisir - Mnemis SA - Choisir widget - - - diff --git a/resources/library/search/Flash Planete.wgs/css/basic.css b/resources/library/search/Flash Planete.wgs/css/basic.css deleted file mode 100755 index 80b50fbc..00000000 --- a/resources/library/search/Flash Planete.wgs/css/basic.css +++ /dev/null @@ -1,315 +0,0 @@ -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; - border: 1px solid #666; - border-radius: 5px; - -webkit-box-shadow: #dadada -1px 0 4px; - -webkit-border-radius: 5px; - box-shadow: #666 -1px 0 4px; - vertical-align: top; -} - - -.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/Flash Planete.wgs/icon.png b/resources/library/search/Flash Planete.wgs/icon.png deleted file mode 100755 index 1f06b0e8d4ea69f31ea927444802590fa367c87d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8869 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 YuWVi1PYQLjbwC5e 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 diff --git a/resources/library/search/Flash Planete.wgs/images/greySquare.png b/resources/library/search/Flash Planete.wgs/images/greySquare.png deleted file mode 100755 index c0a7f14e8cc02340252ef48d9b5893d72b72239a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214 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 diff --git a/resources/library/search/Flash Planete.wgs/images/search_app.png b/resources/library/search/Flash Planete.wgs/images/search_app.png deleted file mode 100755 index efd8ea4a12012eb26b752d8e34010722dab5e9d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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? diff --git a/resources/library/search/Flash Planete.wgs/images/thumbnail_icon.png b/resources/library/search/Flash Planete.wgs/images/thumbnail_icon.png deleted file mode 100755 index 1590c3e070e597a84e543cbf66b4c8c2d9d0ea18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11435 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 FV1iAU(I5Z- diff --git a/resources/library/search/Flash Planete.wgs/images/trgDown.png b/resources/library/search/Flash Planete.wgs/images/trgDown.png deleted file mode 100755 index 632be5fb5560dde4c9a5c76430e7878d817381b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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_ - - - - Planete Sankore Image Search - - - - - - -
- - diff --git a/resources/library/search/Flash Planete.wgs/scripts/jquery-1.6.2.min.js b/resources/library/search/Flash Planete.wgs/scripts/jquery-1.6.2.min.js deleted file mode 100755 index e67db747..00000000 --- a/resources/library/search/Flash Planete.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/Image Planete.wgs/config.xml b/resources/library/search/Image Planete.wgs/config.xml deleted file mode 100755 index d7cc14eb..00000000 --- a/resources/library/search/Image Planete.wgs/config.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - Choisir - Mnemis SA - Choisir widget - - - diff --git a/resources/library/search/Image Planete.wgs/css/basic.css b/resources/library/search/Image Planete.wgs/css/basic.css deleted file mode 100755 index e7fabb8a..00000000 --- a/resources/library/search/Image Planete.wgs/css/basic.css +++ /dev/null @@ -1,314 +0,0 @@ -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/Image Planete.wgs/icon.png b/resources/library/search/Image Planete.wgs/icon.png deleted file mode 100755 index b9cd7783bff723c22d9c2e42b8d776499bdb4674..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9854 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 diff --git a/resources/library/search/Image Planete.wgs/images/greySquare.png b/resources/library/search/Image Planete.wgs/images/greySquare.png deleted file mode 100755 index c0a7f14e8cc02340252ef48d9b5893d72b72239a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214 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 diff --git a/resources/library/search/Image Planete.wgs/images/search_app.png b/resources/library/search/Image Planete.wgs/images/search_app.png deleted file mode 100755 index efd8ea4a12012eb26b752d8e34010722dab5e9d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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? diff --git a/resources/library/search/Image Planete.wgs/images/trgDown.png b/resources/library/search/Image Planete.wgs/images/trgDown.png deleted file mode 100755 index 632be5fb5560dde4c9a5c76430e7878d817381b7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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_ - - - - Planete Sankore Image Search - - - - - - -
- - diff --git a/resources/library/search/Image Planete.wgs/scripts/jquery-1.6.2.min.js b/resources/library/search/Image Planete.wgs/scripts/jquery-1.6.2.min.js deleted file mode 100755 index e67db747..00000000 --- a/resources/library/search/Image Planete.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/Video Planete.wgs/config.xml b/resources/library/search/Video Planete.wgs/config.xml deleted file mode 100755 index d7cc14eb..00000000 --- a/resources/library/search/Video Planete.wgs/config.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - Choisir - Mnemis SA - Choisir widget - - - diff --git a/resources/library/search/Video Planete.wgs/css/basic.css b/resources/library/search/Video Planete.wgs/css/basic.css deleted file mode 100755 index 80b50fbc..00000000 --- a/resources/library/search/Video Planete.wgs/css/basic.css +++ /dev/null @@ -1,315 +0,0 @@ -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; - border: 1px solid #666; - border-radius: 5px; - -webkit-box-shadow: #dadada -1px 0 4px; - -webkit-border-radius: 5px; - box-shadow: #666 -1px 0 4px; - vertical-align: top; -} - - -.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/Video Planete.wgs/icon.png b/resources/library/search/Video Planete.wgs/icon.png deleted file mode 100755 index abda6d9d406e6f1b9098bcba6cc2cfe75d6a13f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9195 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 diff --git a/resources/library/search/Video Planete.wgs/icon.thumbnail.png b/resources/library/search/Video Planete.wgs/icon.thumbnail.png deleted file mode 100755 index abda6d9d406e6f1b9098bcba6cc2cfe75d6a13f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9195 zcmXwf1yq#J_x`dV9ZQ4M0!w!{5=)Boiqc3Uy>x>}NvFWlDXG+oNVjwgOGrtBNJ;

!SY2&3BK)WL004kULmjG*E-nAdxIpyN<>r?gy1;W+ ze+>r!i2MG_7#TdobZ8LAOXGzK&N4OzfiRXIBKPb6AeC2Mir!uhZk~Wob))KNh|miS zL2cpIo{sKbj&801ay({MG>-otuI%RS@9Ajo;03558I?w(#Q#G*ZLR(j1$#NV*aF0^ zNbt}#c>mQHxY>F6T6x+6%-kRU6DRmz=Z-CSI3UA+L8qnVv(4EsMZLq{)XTR`RUGzS0x253MP z4gC;D!M=W`bIm8lfd%4ba}9AYKI-9>f%m^ZzA zt7*SG7OD4xtm6Cm z-&iE{JlmIL0GFogYXW{DWXAGt{^5dCUXqzMav+=X{IkpP00=lv35|L0M>U)w$B39W zzU-^_>aczqO%^CbBc7SG`z()|v0C`{n5&Od`*5Ib8j4xLl8UA}j zqT~*-KC95ve&VOJ(L=vBcDk2#ec-ys(5J=P2| z{L@1YG1|1vx>jjscjUG9*#-(bT1N^77JBaCf=QbNk2E*4F0UBs9ti z)lzp*q&xK5Hda$tOL=fpxCNAe^+bM-ecB&K0gH?j7Z>#Ah{S|<+}qdJ*W26M#pURD zr7bWZ;9FapiLtTWIHL7Ue_XbRz5L_dnU4JRR*MTNQ@|pGY*%uN_m%xNJ~JYLlR4}S z4O>S>e1P272oOWryZAu@iXNdOkpXlkx3{;sIXRbyi;Zq;9ZO3~>FE>&6G-%XZ!}4D z)lFK#oz32KS$li?N#|pTi3#fWSgsl{9as9aN;;&WMB86d;fsZsIcPwzOqH0E9asNH zVq)TaO9>_>W|3tKTw6h36V*br;@&E1w(#M@2N`K;Zf@?&;}z8G?Cj*^~SiCnji zMHGqvQ0|D&Or~ZJnNVM38Wzc{7P{FPe+INq0b65<#*n>HQyUy-kg3qhZm=2NC?6O| zpnLoVA54rIz-G~hc^8I)X$UVbE=cvvLmnDzN2mnM?9ULAmeYR3|b93|de&Oq@ zbDF*(5VTGJ`22RK?&4qpQ{koE@7A4sx>zV$Yx@TWMm4WI*56atnYK-Yc*3nY7F;}8YtSEJ|!qjdHMnSNS0Bu-?w$yKF|C2`Q8k?p|KJE*F5-QuA(4>-AOfem%8)c_D27Q$j=LP zuhDarb-n6&Z%;388n{iFRd3q7f7Ka!v-Gwe^>0;mJfpmP0KLTAR^bzeQt(WEvz(lq zA2e_%yPYVzLt&n%wBYodyB3r=()P7^y|0aq$2>(cmV)dny{VOz;Q8$59akr7GJb!$ zs^+SxM=f;qjU(bOuCCCgb#e6`z3fkiTaw~9s8>90^WutKfBqTx=8Z%)wIBk=TRU$q z9`Uf1b>uE)$#rDESawHbSpl~(RpB|R@MQ&%m-FI`pD($uv3tq*D0-B`~1_~w@8PjNYj)WfT5 z>9&BZ>v0}#{w)M8zZ^aO!Yn;EAKzHE=-x+~2~&!dlt-?OSw*3t8!z<^g+UQFYH#r_>=&6Qo^{6FYG1R)?wLz?1eX ziXtgCykhH>>LL=HsaR-9;N_uNo6kj=MaTI-{i^%wd+LAp4^aaH%Nl7>UoO2!M4Owc zzx8~5*-=qdUEThr`BPQZ-}3t4qy6f-VvkU9^Fa9X(CgsY>Y zM^5|2yh&b4y;^l*?78MF)@{`t*woXjh&s($YNh*Qo2cyP2pkMJb$j)>U}nU zd6`J$)_MP@m&DiGD-FFnX1oh{!+EzGN$SjXbzHytXQ5W-?zkWM(D13fq@=bzc&=(L zUPuL&ndfT`e-4)cj^K*?Vqrcz8${ z-5X8JkR##7_@8|bv>cJEa0Kus5P&)#A8yq$xVXy79a-5DNvY%IAN&q_-k&jEFDfHz z+JsoGH>MITU0ur|!y7M8k|!`SD4Uy`qpyxowkXU-yKyhto5R;4=td)5T?z&UY3ZJ; z-~HtaLYL0>m_p9=BinLUmF2r=o7I0;)RzU5^%%#&#->p5Xqp%Ttm9!qIoARX1giOsucrwnv~pa%cS~#mV4vdV!i;~_=87_LYZy5=qQJ10EcXWF@GQx8==EkUe zDY+Rpc+~Ot2aoUJ&!WnGkqKE=4bM8xIM3hNJ0K0_-P5&uc45nA@dcN)mhJLf*BZ&s z0%Wm4XZe9zBVO|-ag;m*mt+Gf9Hi1#VLnHz&CYw%d`!WjWu*`?F@r*W=TB9ZOQlu# za9#~sYCtmBx$4<;X{9V1n}(jK3aqt?CWi|5ABWb*LMQGW{LQ#xPJlwBeyWRsrm>SG zjUMb_28ZeHqMorpkh!G3e!;8F1r?`SqK&oFsEVV_BGKtMg9Eo4<6Sc_7xd4m3;ga{ z$GzN=!V`DoYz7zt0O-wdaNFkjccPqypRmkt*nF(oydiNGbgHodNJF)7C_PL5$1G#B(II zaHB%V5eRsLi?xfzML+5_HYr-$T$bT6Kx0oR27|ZBeRHLWBA^u>z)Jze76C__T!=)u z_}JC;D3$Gphq*G-Rx#b3rPMO|C(cEd{tiwlCbChPya`t*Y^xYN$bY(@rWD~K0+9Mz z-8-476b2wn20=g=oH%JP2@(l?^wcOs^P^hR380Y5FT1Uo%!bKEqFkewYdwSyk zKFB-fW^N}T#6msIl!MJyQrd5S@QqNkfO;6=p-kEpYpLZ$5T?FQMQDGUL?X19tEzla zKh-e;OX{n?-f}`0KoO_`z%Hc2-dr9&7a2$v%0ksvRaJdrOo|31d#FV~iZuvnK#Tgq zbxZh0`qSq%HSr8>KCd&MKx33g3fT6`^W$O?$OY+qQqbmZxb~C!@XS8}*Q%Z?d#fv~ z6l+Tzm`o}RPy)W;45JCJJ7{rv&P7TeHhFX@I4;^dY09sliVIX1rihGF;3}*2EEiN* zIcR3L_3WH5f&~wem7~8mF7r@J86*{QDtUP>c;tVB5%-BPZY0Ov)|NR-txbu%vE3&3 zUd}iW#O{XyV#6mk1(D)Magw@lk!HV867#a?I{CR+(7`f8)VuA8xk;uj2pZzmcsUC+ z>8^AkOM`yWNEc&nJaV||xWB!<32+%nSNfT$3wwbtHPEL`AZ?97(fDp7IJ96wqQq+; zkZ!GQvjxR+e;<_}R2e&6aS8(AxTY8|^*iH{DS`#T8#sXJVSfEt+WvIzJL->GvDjd1T_Q>q{; zr0KsS+zA-oP(cSRlQ1K*{NHDqVP#|t+}lI?BE%ox{t%;+VS_VScFPDV@VB=dJIgSlKk}tEg5Di z04oj(nx2=-hm6M}iis-%;%J1+KbhCzVktVH`uMP|=pYgW!%mw1z81o8FPzM*%=uZi$x;D3SQ3P(Pvhw0XIv}`TcK@6Ntde*RRPj z&&oG)bGJKsc?Ad{5u%DyDUIC;YwW|4B&B7-(9|A0K_D1IJvFr`R{>xwp3M&JDcu7Z z`Wc3;zY}?02{C#acRTp(Ch3DweU41qENvL;)VK1o((-Snbt$cDGf&1O0STr*6USc~ zidT4Dme=^^2cI^Fw!K}!GV%)f@^BiW*oBE){P4dp>hno{3{Z?!f9oK_;O58+ul~jT}R< zy2^N-RFSAeM^R|1`VuE(iRz=CXbC7*0YWIZQe2j>ZMQL<-4!b#E+K!uTOabT-Oc}g zm~aU1H@h%$)Bl=7F&6vi*-?_NUTbk>Rq_3CEJs$JZ^y#Uhz=6RxkfgUy)eRZ$>BMK zt}NX~#EKLzos5^x86y)g1C;?zaYD6d@suGkMIdhfY6uSj0q^Gkr4Ch{b1%X8i8Dl6-%tND3(H?%M+CjA{CF`EL&f0gr0;6F)gzRBAN|Q`cmK3E}QI-z7KGqG<6rL;? zoG#Z7(I=hf`*a1)i$O>o47Oh}mIn~qz&hlhuQ zgWIEA0X<)3mMSFkBLqCj$SBUH5TwbdZM1K$sjbPKZHx;QXuq4jS&%qC$IFA|wkN&-_VD{BIMXK*_IT?-V19`~1q9dx*bydBGW$;EvZ0DLhv zwulb1UoV=OsmaI$@^JH@-E1>M!}RP7TH^PBFc0~t)Wn1!XD{teV$ZK2J@wdM2sZ#2 z7+InwljPIV(&TlxdOAFQ)E0;nG3-eG_Y7V^p);H-I(#HVze1V_U0Om_ag!`8%*`{% z^G@c=*pJ6;k4#A4YN?1(;H8oRoNu?%|s zW4%+f4;ak79y+o$d}@S~N2p+pD^7}z%hBoL;$m)Y4rXMuFgJ%pB5{e;; zeaZ#%U`oJ~+jlwTnk)k!(_Eeg`mx%td$wweD4-psDEz++QM#O4hRcLlI6dp#-*R<1 zZFZwjn?i)Wn?7tD9JfL8JF7pXIKp)7O^kd?YidSMNKCz^RCJ!54JMqlXXWJ`o!vOS zeQQ6Kb9&*8tcsgPp$YbuD#tg z>+K}@Q~DqO*li*Jc?zdW5xadoN#i@XmE2WzbgoH*N1g{cs*foPQn0Hhxcs4$_R&_j-KTA$*Z@m86q+#~$l+@@dM*Q1aUek;fIrlDq< zn)<=Pn50^{;$uv>cMn&glAj+7*FB|r7#~^lsH9zz%H1K$ddjB;Y^h;j4Hgg>lmhAL z#%vlaW!r$g3W5Q5z88MBe7Jkk8N3l2@m<5n%=?M5vx5Vfl6JN+q9E(4=YxRrTF1)K zY2V1yUe3b5j#n(TgddUz?HCP&wBuAYV{v)4lM?UWl7zgkKEnna^n8?7NCG+f=1byu1S4Z=ltt1w9Nkr`vCdzrHkK!=kgPl^F7W*G)5rS^fsSQCKTlOAB;V4ED( zq7^)bnrFw2UPd$Q{M<{ZU%Yk~J|P#{pJDW|y!q|baql-hedE;JtewAKkwJfBlbb9b zmXGUPvqorI9Q)iFVrNb^`QJaq z`nN;L%QyLj$V}&8=>RCcfir}k&EtJI1OWV{pw0=BN=u~3>uVz4!T>k<+)@yxVRiAR^?hgfA|phtu0XWh3|L+1|TsrQqG^j zCe7C2DISYT1W`OQm?If04&1H4+>nBqMsHcExsGKYqBN}y)g~olxw#MNwVj<~aCLEf z-MU{qKYw|1qsnD#Y^f@>J>Az^sWvi!W1&4n?ZC;-*utr!@ZVzK(0S#doZ@?Im z5m>Q6z(>e9NI~5uZmWmO--^Y&B7eY4T=kvax9(|OG`S$vfM&p>qM|-5)VVl0qe-Y_ z@Ql8J2!}QzIsePs1^)VptgI~5uUfGH{egx;|n1KnvbX?A+K4X>g3{Czieb@Spe zNkbU592eRsrf11YN)5AHrue%&o>EbeP(xvm+$< z#Rc>G>JQX>KZevzd{!G=P%V2oFLiZw11rUOcn%;Gp!oF6q z>TUl#Pf9gXtF;WAj@wYr-kMu%o3G6-I%b(p-%e$=AkCARbFOC#^cPHnp2GfeB4R{o z64(dhQ&W?fK@3u!HfU}!r@Z!c>Z^jUNxxfX}H$Dk+x@GQT@t&p(;Dh(Biw+*glr2sZ1r z?v(vIWPP?4EVFlLiv^|6wt@B~_gTsw%@)!|C#%mdES#($sd4#@zx>_gGg(3^dr?fkb3R7X|yn9n!0>F@l?ac(20t}ssV z)Q`ZE(vVpKjx=zC^GW*jr)Rfwql2Mec5X(XpGi_^iU6@%_yGQACSEb>nu-c&dX#PE zIbpBgaqAA1fT^gEwUYOX7yka)wjWAMORvwU50{!p1PMi+%1tFER+qwt37GC^g$Wtz z;M*@$*+(5J|3+UarGsHqkM$>>S=g>(ewDv>a|K?z99hOT@Vp!kg%gDT>SG%!5`I6y zjg;8R5>%_DprR5UpxFt1IQw8^>c2gn*XHEp6yu=k=&0%RBYt|i$i4>gO2C>z0QYg0 zRw+3r)$@FA=jg%mjHy637(>6rNn3mRJ&$_ay@bWg={WZB#S@;V39=_$Yd+^$ZdVie zZXzbkDuU0GfhDbAYps9K>^v<24Pe;!@3MoTLHomNwWjS+@Q{ChtWXWq0@AE4gE z7dsa253xDm!3D+g_j$GX-|sA8bMt3Z++i)Yjp0r6g^sVGiP1~T%RyV}_s4(b&<6qjCMIto zWEwip1q1|4+5^P8{y1NJm3APsr)*pGAGv4_-CMqqsAfIWuC9vTo1v)$;%Y$1Jf$g##C9X3#oVD-$=MnGluu{^ zk6WLa`E@@bA|jG$aqGPPolB12msq%&$cT4GkO_`)pJN_}v=W+-VF=Qdj-N+3`_>`X zyP4FarCYJ8s||p5X1?SRpKse}nKg2URB6g2U6-W_I5|j}ty8gmv7nMyqRA1p9mhhT<=cO}sm2n`4x7usaTh-Y)N-VU(|Ge+2QdbQXvM1vCw26J^i*tnnvKds_nee+ zQ#uuG77Z;$jK~t_ zGwb@SFSObOQc8VNzKr1#*s8s3oCEf(rMxDK?RyNV@gD`*w|`*dGE)P@!!$}kP?-S3 z&@K@vIls?6hbJefCL#YtXP7UZY9v_W$JG4Y&om~!%K#wMLsUFB%@^;zlJ&C~?{u?K ztL?ZAncHRbF*4h0El)lP6BcM&63|@*|2L-Z96?0p`0l|Lq~e@$p^_BQg@2 z`p$5pk0Zr{#9BM@3=$($UR71@h(4xv-jym7ijS&bRBh%hO;=La=xI58$ZInwr{p4U z*k`(*m|wdeV59+LMGx5l2tO()DZKgFhV1yWHlJ~K-Z_ldNgM@{A29%Os1Tp0s6#05 zF~WqQC8{HqhGCX}7A?W0TrOl}&NJx>Jq^xS>_fmJ5V-2nyw`Ow$h0AuOdV}Qk%D^exut+^JS+_*l??Dldg*g5 zGBz?baQIMc@{rwliR&XXCnH$=X+l+LQZ7f_C&KH;ZcL<(Uv83HV!xd8vB+Frs6q0QZAtmjD0& diff --git a/resources/library/search/Video Planete.wgs/images/down.png b/resources/library/search/Video Planete.wgs/images/down.png deleted file mode 100755 index 1de37e16ff7500ef6f776158baf7fdd9ded21190..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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^ diff --git a/resources/library/search/Video Planete.wgs/images/greySquare.png b/resources/library/search/Video Planete.wgs/images/greySquare.png deleted file mode 100755 index c0a7f14e8cc02340252ef48d9b5893d72b72239a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 214 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 diff --git a/resources/library/search/Video Planete.wgs/images/search_app.png b/resources/library/search/Video Planete.wgs/images/search_app.png deleted file mode 100755 index efd8ea4a12012eb26b752d8e34010722dab5e9d5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 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? diff --git a/resources/library/search/Video Planete.wgs/images/thumbnail_icon.png b/resources/library/search/Video Planete.wgs/images/thumbnail_icon.png deleted file mode 100755 index e296e4a9cf40e2ee6c3e087c50da641b94cdebcf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10911 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 - - - - Planete Sankore Image Search - - - - - - -

- - diff --git a/resources/library/search/Video Planete.wgs/scripts/jquery-1.6.2.min.js b/resources/library/search/Video Planete.wgs/scripts/jquery-1.6.2.min.js deleted file mode 100755 index e67db747..00000000 --- a/resources/library/search/Video Planete.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 From ac21d9ed208b805996b573b7f93ccd16ea038d63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 23 Jan 2018 12:51:15 +0100 Subject: [PATCH 118/134] edited/added some translations --- resources/i18n/OpenBoard_de.ts | 26 ++++----- resources/i18n/OpenBoard_fr.ts | 4 +- resources/i18n/OpenBoard_fr_CH.ts | 6 +- resources/i18n/OpenBoard_it.ts | 94 +++++++++++++++++++++---------- 4 files changed, 82 insertions(+), 48 deletions(-) diff --git a/resources/i18n/OpenBoard_de.ts b/resources/i18n/OpenBoard_de.ts index 06a7acd8..317fa87f 100644 --- a/resources/i18n/OpenBoard_de.ts +++ b/resources/i18n/OpenBoard_de.ts @@ -481,7 +481,7 @@ Grid Light Background - Heller Hintergrund, kariert + Hell karierten Hintergrund Plain Dark Background @@ -493,7 +493,7 @@ Grid Dark Background - Dunkler Hintergrund, kariert + Dunkel karierten Hintergrund Podcast @@ -801,11 +801,11 @@ Ruled Light Background - + Hell linierter Hintergrund Ruled Dark Background - + Dunkel linierter Hintergrund @@ -903,7 +903,7 @@ UBBackgroundPalette Grid size - + Gittergrösse @@ -1247,7 +1247,7 @@ UBDraggableThumbnailView Page %0 - Seite %0 + Seite %0 @@ -1570,7 +1570,7 @@ Set as background - Als Hintergrund festlegen + Als Hintergrund einfügen @@ -2469,11 +2469,11 @@ p, li { white-space: pre-wrap; } Show preview circle from - + Ansichtsgrösse von px - + px @@ -2663,19 +2663,19 @@ p, li { white-space: pre-wrap; } Grid - + Gitter On Dark Background - Auf dunklem Hintergrund + Auf dunklem Hintergrund Opacity - Deckkraft + Deckkraft On Light Background - Auf hellem Hintergrund + Auf hellem Hintergrund diff --git a/resources/i18n/OpenBoard_fr.ts b/resources/i18n/OpenBoard_fr.ts index c64c15e0..225ed68e 100644 --- a/resources/i18n/OpenBoard_fr.ts +++ b/resources/i18n/OpenBoard_fr.ts @@ -117,11 +117,11 @@ Grid Light Background - Grille sur fond clair + Fonds quadrillé clair Grid Dark Background - Grille sur fond foncé + Fonds quadrillé foncé Start Screen Recording diff --git a/resources/i18n/OpenBoard_fr_CH.ts b/resources/i18n/OpenBoard_fr_CH.ts index 14f1b709..49a18cb0 100644 --- a/resources/i18n/OpenBoard_fr_CH.ts +++ b/resources/i18n/OpenBoard_fr_CH.ts @@ -117,11 +117,11 @@ Grid Light Background - Grille sur fond clair + Fonds quadrillé clair Grid Dark Background - Grille sur fond foncé + Fonds quadrillé foncé Start Screen Recording @@ -169,7 +169,7 @@ Pages - Pages + Page %0 New Page diff --git a/resources/i18n/OpenBoard_it.ts b/resources/i18n/OpenBoard_it.ts index bc99f047..3470fe46 100644 --- a/resources/i18n/OpenBoard_it.ts +++ b/resources/i18n/OpenBoard_it.ts @@ -1,6 +1,6 @@ - + BlackoutWidget @@ -801,11 +801,11 @@ Ruled Light Background - + Sfondo chiaro lineato Ruled Dark Background - + Sfundo scuro lineato @@ -850,11 +850,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 @@ -903,7 +903,7 @@ UBBackgroundPalette Grid size - + Dimensione della griglia @@ -1211,7 +1211,7 @@ UBDocumentNavigator Page %0 - Pagina %0 + Pagina %0 @@ -1243,6 +1243,13 @@ Annulla + + UBDraggableThumbnailView + + Page %0 + Pagina %0 + + UBExportAdaptor @@ -1255,7 +1262,7 @@ Export failed - + Esportazione fallita Unable to export to the selected location. You do not have the permissions necessary to save the file. @@ -1274,23 +1281,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. @@ -1321,15 +1328,15 @@ Export failed: location not writable - Exportazione fallita: posizione non scrivibile + Exportazione fallita: posizione non scrivibile Export failed - Esportazione fallita + Esportazione fallita Unable to export to the selected location. You do not have the permissions necessary to save the file. - Impossibile esportare nella posizione selezionata. Non possiedi i permessi necessari a salvare il file. + Impossibile esportare nella posizione selezionata. Non possiedi i permessi necessari a salvare il file. @@ -1352,15 +1359,15 @@ Export failed: location not writable - Esportazione fallita: posizione non scrivibile + Esportazione fallita: posizione non scrivibile Export failed - Esportazione fallita + Esportazione fallita Unable to export to the selected location. You do not have the permissions necessary to save the file. - Impossibile esportare alla posizione selezionata. Non possiedi i permessi necessari a salvare il file. + Impossibile esportare alla posizione selezionata. Non possiedi i permessi necessari a salvare il file. @@ -1421,7 +1428,7 @@ Set as background - Imposta come sfondo + Imposta come sfondo Add to library @@ -1561,6 +1568,10 @@ Go to Content Source Vai alla sorgente del contenuto + + Set as background + Imposta come sfondo + UBGraphicsMediaItem @@ -1628,23 +1639,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. @@ -1975,6 +1986,13 @@ Vuoi ignorare gli errori per questo host? %1 miniature generate... + + UBThumbnailTextItem + + Page %0 + Pagina %0 + + UBToolsManager @@ -2450,12 +2468,12 @@ p, li { white-space: pre-wrap; } La penna è sensibile alla pressione - Smooth strokes (experimental) - + Show preview circle from + Mostra l'anteprima del cerchio a partire da - Simplify strokes after drawing (experimental) - + px + px @@ -2528,7 +2546,7 @@ p, li { white-space: pre-wrap; } Keyboard button size: - Dimensione pulsanti tastiera: + Dimensione pulsanti tastiera: Toolbar @@ -2642,6 +2660,22 @@ p, li { white-space: pre-wrap; } Built-in virtual keyboard button size: Dimensione pulsanti tastiera virtuale incorporata: + + Grid + Griglia + + + On Light Background + Su sfondo chiaro + + + Opacity + Opacità + + + On Dark Background + Su sfondo scuro + trapFlashDialog From c464de1238ce05c2b73ec9fb5c0f73001676a545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 23 Jan 2018 13:53:31 +0100 Subject: [PATCH 119/134] added Horloge.wgt --- .../applications/Horloge.wgt/config.xml | 13 + .../library/applications/Horloge.wgt/icon.png | Bin 0 -> 14003 bytes .../applications/Horloge.wgt/index.html | 60 +++ .../applications/Horloge.wgt/station-clock.js | 488 ++++++++++++++++++ 4 files changed, 561 insertions(+) create mode 100644 resources/library/applications/Horloge.wgt/config.xml create mode 100644 resources/library/applications/Horloge.wgt/icon.png create mode 100644 resources/library/applications/Horloge.wgt/index.html create mode 100644 resources/library/applications/Horloge.wgt/station-clock.js diff --git a/resources/library/applications/Horloge.wgt/config.xml b/resources/library/applications/Horloge.wgt/config.xml new file mode 100644 index 00000000..5c055751 --- /dev/null +++ b/resources/library/applications/Horloge.wgt/config.xml @@ -0,0 +1,13 @@ + + + Horloge + fbocquet@laposte.net + + + diff --git a/resources/library/applications/Horloge.wgt/icon.png b/resources/library/applications/Horloge.wgt/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1b069c308ec40f16eb47e27c59eb2915bad4ca53 GIT binary patch literal 14003 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 SSNP9I1X5!1qSe9%LH`G)rSV_@ literal 0 HcmV?d00001 diff --git a/resources/library/applications/Horloge.wgt/index.html b/resources/library/applications/Horloge.wgt/index.html new file mode 100644 index 00000000..9e809d48 --- /dev/null +++ b/resources/library/applications/Horloge.wgt/index.html @@ -0,0 +1,60 @@ + + + + Horloge + + + + + + + + + + + +
+
+
+ + + Horloge + +
+ + + diff --git a/resources/library/applications/Horloge.wgt/station-clock.js b/resources/library/applications/Horloge.wgt/station-clock.js new file mode 100644 index 00000000..b5550059 --- /dev/null +++ b/resources/library/applications/Horloge.wgt/station-clock.js @@ -0,0 +1,488 @@ +/*! + * station-clock.js + * + * Copyright (c) 2010 Ruediger Appel + * ludi at mac dot com + * + * Date: 2016-02-16 + * Version: 1.0.1 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Known Issues: + * + * Shadows for some second hands is not on one layer + * + * Thanks to Paul Schröfl for the Wiener Würfeluhr + */ + +// clock body (Uhrgehäuse) +StationClock.NoBody = 0; +StationClock.SmallWhiteBody = 1; +StationClock.RoundBody = 2; +StationClock.RoundGreenBody = 3; +StationClock.SquareBody = 4; +StationClock.ViennaBody = 5; + +// stroke dial (Zifferblatt) +StationClock.NoDial = 0; +StationClock.GermanHourStrokeDial = 1; +StationClock.GermanStrokeDial = 2; +StationClock.AustriaStrokeDial = 3; +StationClock.SwissStrokeDial = 4; +StationClock.ViennaStrokeDial = 5; + +//clock hour hand (Stundenzeiger) +StationClock.PointedHourHand = 1; +StationClock.BarHourHand = 2; +StationClock.SwissHourHand = 3; +StationClock.ViennaHourHand = 4; + +//clock minute hand (Minutenzeiger) +StationClock.PointedMinuteHand = 1; +StationClock.BarMinuteHand = 2; +StationClock.SwissMinuteHand = 3; +StationClock.ViennaMinuteHand = 4; + +//clock second hand (Sekundenzeiger) +StationClock.NoSecondHand = 0; +StationClock.BarSecondHand = 1; +StationClock.HoleShapedSecondHand = 2; +StationClock.NewHoleShapedSecondHand = 3; +StationClock.SwissSecondHand = 4; + +// clock boss (Zeigerabdeckung) +StationClock.NoBoss = 0; +StationClock.BlackBoss = 1; +StationClock.RedBoss = 2; +StationClock.ViennaBoss = 3; + +// minute hand behavoir +StationClock.CreepingMinuteHand = 0; +StationClock.BouncingMinuteHand = 1; +StationClock.ElasticBouncingMinuteHand = 2; + +// second hand behavoir +StationClock.CreepingSecondHand = 0; +StationClock.BouncingSecondHand = 1; +StationClock.ElasticBouncingSecondHand = 2; +StationClock.OverhastySecondHand = 3; + + +function StationClock(clockId) { + this.clockId = clockId; + this.radius = 0; + + // hour offset + this.hourOffset = 0; + + // clock body + this.body = StationClock.RoundBody; + this.bodyShadowColor = "rgba(0,0,0,0.5)"; + this.bodyShadowOffsetX = 0.03; + this.bodyShadowOffsetY = 0.03; + this.bodyShadowBlur = 0.06; + + // body dial + this.dial = StationClock.GermanStrokeDial; + this.dialColor = 'rgb(60,60,60)'; + + // clock hands + this.hourHand = StationClock.PointedHourHand; + this.minuteHand = StationClock.PointedMinuteHand; + this.secondHand = StationClock.HoleShapedSecondHand; + this.handShadowColor = 'rgba(0,0,0,0.3)'; + this.handShadowOffsetX = 0.03; + this.handShadowOffsetY = 0.03; + this.handShadowBlur = 0.04; + + // clock colors + this.hourHandColor = 'rgb(0,0,0)'; + this.minuteHandColor = 'rgb(0,0,0)'; + this.secondHandColor = 'rgb(200,0,0)'; + + // clock boss + this.boss = StationClock.NoBoss; + this.bossShadowColor = "rgba(0,0,0,0.2)"; + this.bossShadowOffsetX = 0.02; + this.bossShadowOffsetY = 0.02; + this.bossShadowBlur = 0.03; + + // hand behavoir + this.minuteHandBehavoir = StationClock.CreepingMinuteHand; + this.secondHandBehavoir = StationClock.OverhastySecondHand; + + // hand animation + this.minuteHandAnimationStep = 0; + this.secondHandAnimationStep = 0; + this.lastMinute = 0; + this.lastSecond = 0; +}; + +StationClock.prototype.draw = function() { + var clock = document.getElementById(this.clockId); + if (clock) { + var context = clock.getContext('2d'); + if (context) { + this.radius = 0.75 * (Math.min(clock.width, clock.height) / 2); + + // clear canvas and set new origin + context.clearRect(0, 0, clock.width, clock.height); + context.save(); + context.translate(clock.width / 2, clock.height / 2); + + // draw body + if (this.body != StationClock.NoStrokeBody) { + context.save(); + switch (this.body) { + case StationClock.SmallWhiteBody: + this.fillCircle(context, "rgb(255,255,255)", 0, 0, 1); + break; + case StationClock.RoundBody: + this.fillCircle(context, "rgb(255,255,255)", 0, 0, 1.1); + context.save(); + this.setShadow(context, this.bodyShadowColor, this.bodyShadowOffsetX, this.bodyShadowOffsetY, this.bodyShadowBlur); + this.strokeCircle(context, "rgb(0,0,0)", 0, 0, 1.1, 0.07); + context.restore(); + break; + case StationClock.RoundGreenBody: + this.fillCircle(context, "rgb(235,236,212)", 0, 0, 1.1); + context.save(); + this.setShadow(context, this.bodyShadowColor, this.bodyShadowOffsetX, this.bodyShadowOffsetY, this.bodyShadowBlur); + this.strokeCircle(context, "rgb(180,180,180)", 0, 0, 1.1, 0.2); + context.restore(); + this.strokeCircle(context, "rgb(29,84,31)", 0, 0, 1.15, 0.1); + context.save(); + this.setShadow(context, "rgba(235,236,212,100)", -0.02, -0.02, 0.09); + this.strokeCircle(context, 'rgb(76,128,110)', 0, 0, 1.1, 0.08); + context.restore(); + break; + case StationClock.SquareBody: + context.save(); + this.setShadow(context, this.bodyShadowColor, this.bodyShadowOffsetX, this.bodyShadowOffsetY, this.bodyShadowBlur); + this.fillSquare(context, 'rgb(237,235,226)', 0, 0, 2.4); + this.strokeSquare(context, 'rgb(38,106,186)', 0, 0, 2.32, 0.16); + context.restore(); + context.save(); + this.setShadow(context, this.bodyShadowColor, this.bodyShadowOffsetX, this.bodyShadowOffsetY, this.bodyShadowBlur); + this.strokeSquare(context, 'rgb(42,119,208)', 0, 0, 2.24, 0.08); + context.restore(); + break; + case StationClock.ViennaBody: + context.save(); + this.fillSymmetricPolygon(context, 'rgb(156,156,156)', [[-1.2,1.2],[-1.2,-1.2]],0.1); + this.fillPolygon(context, 'rgb(156,156,156)', 0,1.2 , 1.2,1.2 , 1.2,0); + this.fillCircle(context, 'rgb(255,255,255)', 0, 0, 1.05, 0.08); + this.strokeCircle(context, 'rgb(0,0,0)', 0, 0, 1.05, 0.01); + this.strokeCircle(context, 'rgb(100,100,100)', 0, 0, 1.1, 0.01); + this.fillPolygon(context, 'rgb(100,100,100)', 0.45,1.2 , 1.2,1.2 , 1.2,0.45); + this.fillPolygon(context, 'rgb(170,170,170)', 0.45,-1.2 , 1.2,-1.2 , 1.2,-0.45); + this.fillPolygon(context, 'rgb(120,120,120)', -0.45,1.2 , -1.2,1.2 , -1.2,0.45); + this.fillPolygon(context, 'rgb(200,200,200)', -0.45,-1.2 , -1.2,-1.2 , -1.2,-0.45); + this.strokeSymmetricPolygon(context, 'rgb(156,156,156)', [[-1.2,1.2],[-1.2,-1.2]],0.01); + this.fillPolygon(context, 'rgb(255,0,0)', 0.05,-0.6 , 0.15,-0.6 , 0.15,-0.45 , 0.05,-0.45); + this.fillPolygon(context, 'rgb(255,0,0)', -0.05,-0.6 , -0.15,-0.6 , -0.15,-0.45 , -0.05,-0.45); + this.fillPolygon(context, 'rgb(255,0,0)', 0.05,-0.35 , 0.15,-0.35 , 0.15,-0.30 , 0.10,-0.20 , 0.05,-0.20); + this.fillPolygon(context, 'rgb(255,0,0)', -0.05,-0.35 , -0.15,-0.35 , -0.15,-0.30 , -0.10,-0.20 , -0.05,-0.20); + context.restore(); + break; + } + context.restore(); + } + + // draw dial + for (var i = 0; i < 60; i++) { + context.save(); + context.rotate(i * Math.PI / 30); + switch (this.dial) { + case StationClock.SwissStrokeDial: + if ((i % 5) == 0) { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.75, 0.07); + } else { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.92, 0.026); + } + break; + case StationClock.AustriaStrokeDial: + if ((i % 5) == 0) { + this.fillPolygon(context, this.dialColor, -0.04, -1.0, 0.04, -1.0, 0.03, -0.78, -0.03, -0.78); + } else { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.94, 0.02); + } + break; + case StationClock.GermanStrokeDial: + if ((i % 15) == 0) { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.70, 0.08); + } else if ((i % 5) == 0) { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.76, 0.08); + } else { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.92, 0.036); + } + break; + case StationClock.GermanHourStrokeDial: + if ((i % 15) == 0) { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.70, 0.10); + } else if ((i % 5) == 0) { + this.strokeLine(context, this.dialColor, 0.0, -1.0, 0.0, -0.74, 0.08); + } + break; + case StationClock.ViennaStrokeDial: + if ((i % 15) == 0) { + this.fillPolygon(context, this.dialColor, 0.7,-0.1, 0.6,0, 0.7,0.1, 1,0.03, 1,-0.03); + } else if ((i % 5) == 0) { + this.fillPolygon(context, this.dialColor, 0.85,-0.06, 0.78,0, 0.85,0.06, 1,0.03, 1,-0.03); + } + this.fillCircle(context, this.dialColor, 0.0, -1.0, 0.03); + break; + } + context.restore(); + } + + // get current time + var time = new Date(); + var millis = time.getMilliseconds() / 1000.0; + var seconds = time.getSeconds(); + var minutes = time.getMinutes(); + var hours = time.getHours() + this.hourOffset; + + // draw hour hand + context.save(); + context.rotate(hours * Math.PI / 6 + minutes * Math.PI / 360); + this.setShadow(context, this.handShadowColor, this.handShadowOffsetX, this.handShadowOffsetY, this.handShadowBlur); + switch (this.hourHand) { + case StationClock.BarHourHand: + this.fillPolygon(context, this.hourHandColor, -0.05, -0.6, 0.05, -0.6, 0.05, 0.15, -0.05, 0.15); + break; + case StationClock.PointedHourHand: + this.fillPolygon(context, this.hourHandColor, 0.0, -0.6, 0.065, -0.53, 0.065, 0.19, -0.065, 0.19, -0.065, -0.53); + break; + case StationClock.SwissHourHand: + this.fillPolygon(context, this.hourHandColor, -0.05, -0.6, 0.05, -0.6, 0.065, 0.26, -0.065, 0.26); + break; + case StationClock.ViennaHourHand: + this.fillSymmetricPolygon(context, this.hourHandColor, [[-0.02,-0.72],[-0.08,-0.56],[-0.15,-0.45],[-0.06,-0.30],[-0.03,0],[-0.1,0.2],[-0.05,0.23],[-0.03,0.2]]); + } + context.restore(); + + // draw minute hand + context.save(); + switch (this.minuteHandBehavoir) { + case StationClock.CreepingMinuteHand: + context.rotate((minutes + seconds / 60) * Math.PI / 30); + break; + case StationClock.BouncingMinuteHand: + context.rotate(minutes * Math.PI / 30); + break; + case StationClock.ElasticBouncingMinuteHand: + if (this.lastMinute != minutes) { + this.minuteHandAnimationStep = 3; + this.lastMinute = minutes; + } + context.rotate((minutes + this.getAnimationOffset(this.minuteHandAnimationStep)) * Math.PI / 30); + this.minuteHandAnimationStep--; + break; + } + this.setShadow(context, this.handShadowColor, this.handShadowOffsetX, this.handShadowOffsetY, this.handShadowBlur); + switch (this.minuteHand) { + case StationClock.BarMinuteHand: + this.fillPolygon(context, this.minuteHandColor, -0.05, -0.9, 0.035, -0.9, 0.035, 0.23, -0.05, 0.23); + break; + case StationClock.PointedMinuteHand: + this.fillPolygon(context, this.minuteHandColor, 0.0, -0.93, 0.045, -0.885, 0.045, 0.23, -0.045, 0.23, -0.045, -0.885); + break; + case StationClock.SwissMinuteHand: + this.fillPolygon(context, this.minuteHandColor, -0.035, -0.93, 0.035, -0.93, 0.05, 0.25, -0.05, 0.25); + break; + case StationClock.ViennaMinuteHand: + this.fillSymmetricPolygon(context, this.minuteHandColor, [[-0.02,-0.98],[-0.09,-0.7],[-0.03,0],[-0.05,0.2],[-0.01,0.4]]); + } + context.restore(); + + // draw second hand + context.save(); + switch (this.secondHandBehavoir) { + case StationClock.OverhastySecondHand: + context.rotate(Math.min((seconds + millis) * (60.0 / 58.5), 60.0) * Math.PI / 30); + break; + case StationClock.CreepingSecondHand: + context.rotate((seconds + millis) * Math.PI / 30); + break; + case StationClock.BouncingSecondHand: + context.rotate(seconds * Math.PI / 30); + break; + case StationClock.ElasticBouncingSecondHand: + if (this.lastSecond != seconds) { + this.secondHandAnimationStep = 3; + this.lastSecond = seconds; + } + context.rotate((seconds + this.getAnimationOffset(this.secondHandAnimationStep)) * Math.PI / 30); + this.secondHandAnimationStep--; + break; + } + this.setShadow(context, this.handShadowColor, this.handShadowOffsetX, this.handShadowOffsetY, this.handShadowBlur); + switch (this.secondHand) { + case StationClock.BarSecondHand: + this.fillPolygon(context, this.secondHandColor, -0.006, -0.92, 0.006, -0.92, 0.028, 0.23, -0.028, 0.23); + break; + case StationClock.HoleShapedSecondHand: + this.fillPolygon(context, this.secondHandColor, 0.0, -0.9, 0.011, -0.889, 0.01875, -0.6, -0.01875, -0.6, -0.011, -0.889); + this.fillPolygon(context, this.secondHandColor, 0.02, -0.4, 0.025, 0.22, -0.025, 0.22, -0.02, -0.4); + this.strokeCircle(context, this.secondHandColor, 0, -0.5, 0.083, 0.066); + break; + case StationClock.NewHoleShapedSecondHand: + this.fillPolygon(context, this.secondHandColor, 0.0, -0.95, 0.015, -0.935, 0.0187, -0.65, -0.0187, -0.65, -0.015, -0.935); + this.fillPolygon(context, this.secondHandColor, 0.022, -0.45, 0.03, 0.27, -0.03, 0.27, -0.022, -0.45); + this.strokeCircle(context, this.secondHandColor, 0, -0.55, 0.085, 0.07); + break; + case StationClock.SwissSecondHand: + this.strokeLine(context, this.secondHandColor, 0.0, -0.6, 0.0, 0.35, 0.026); + this.fillCircle(context, this.secondHandColor, 0, -0.64, 0.1); + break; + case StationClock.ViennaSecondHand: + this.strokeLine(context, this.secondHandColor, 0.0, -0.6, 0.0, 0.35, 0.026); + this.fillCircle(context, this.secondHandColor, 0, -0.64, 0.1); + break; + } + context.restore(); + + // draw clock boss + if (this.boss != StationClock.NoBoss) { + context.save(); + this.setShadow(context, this.bossShadowColor, this.bossShadowOffsetX, this.bossShadowOffsetY, this.bossShadowBlur); + switch (this.boss) { + case StationClock.BlackBoss: + this.fillCircle(context, 'rgb(0,0,0)', 0, 0, 0.1); + break; + case StationClock.RedBoss: + this.fillCircle(context, 'rgb(220,0,0)', 0, 0, 0.06); + break; + case StationClock.ViennaBoss: + this.fillCircle(context, 'rgb(0,0,0)', 0, 0, 0.07); + break; + } + context.restore(); + } + + context.restore(); + } + } +}; + +StationClock.prototype.getAnimationOffset = function(animationStep) { + switch (animationStep) { + case 3: return 0.2; + case 2: return -0.1; + case 1: return 0.05; + } + return 0; +}; + +StationClock.prototype.setShadow = function(context, color, offsetX, offsetY, blur) { + if (color) { + context.shadowColor = color; + context.shadowOffsetX = this.radius * offsetX; + context.shadowOffsetY = this.radius * offsetY; + context.shadowBlur = this.radius * blur; + } +}; + +StationClock.prototype.fillCircle = function(context, color, x, y, radius) { + if (color) { + context.beginPath(); + context.fillStyle = color; + context.arc(x * this.radius, y * this.radius, radius * this.radius, 0, 2 * Math.PI, true); + context.fill(); + } +}; + +StationClock.prototype.strokeCircle = function(context, color, x, y, radius, lineWidth) { + if (color) { + context.beginPath(); + context.strokeStyle = color; + context.lineWidth = lineWidth * this.radius; + context.arc(x * this.radius, y * this.radius, radius * this.radius, 0, 2 * Math.PI, true); + context.stroke(); + } +}; + +StationClock.prototype.fillSquare = function(context, color, x, y, size) { + if (color) { + context.fillStyle = color; + context.fillRect((x - size / 2) * this.radius, (y -size / 2) * this.radius, size * this.radius, size * this.radius); + } +}; + +StationClock.prototype.strokeSquare = function(context, color, x, y, size, lineWidth) { + if (color) { + context.strokeStyle = color; + context.lineWidth = lineWidth * this.radius; + context.strokeRect((x - size / 2) * this.radius, (y -size / 2) * this.radius, size * this.radius, size * this.radius); + } +}; + +StationClock.prototype.strokeLine = function(context, color, x1, y1, x2, y2, width) { + if (color) { + context.beginPath(); + context.strokeStyle = color; + context.moveTo(x1 * this.radius, y1 * this.radius); + context.lineTo(x2 * this.radius, y2 * this.radius); + context.lineWidth = width * this.radius; + context.stroke(); + } +}; + +StationClock.prototype.fillPolygon = function(context, color, x1, y1, x2, y2, x3, y3, x4, y4, x5, y5) { + if (color) { + context.beginPath(); + context.fillStyle = color; + context.moveTo(x1 * this.radius, y1 * this.radius); + context.lineTo(x2 * this.radius, y2 * this.radius); + context.lineTo(x3 * this.radius, y3 * this.radius); + context.lineTo(x4 * this.radius, y4 * this.radius); + if ((x5 != undefined) && (y5 != undefined)) { + context.lineTo(x5 * this.radius, y5 * this.radius); + } + context.lineTo(x1 * this.radius, y1 * this.radius); + context.fill(); + } +}; + +StationClock.prototype.fillSymmetricPolygon = function(context, color, points) { + context.beginPath(); + context.fillStyle = color; + context.moveTo(points[0][0] * this.radius, points[0][1] * this.radius); + for (var i = 1; i < points.length; i++) { + context.lineTo(points[i][0] * this.radius, points[i][1] * this.radius); + } + for (var i = points.length - 1; i >= 0; i--) { + context.lineTo(0 - points[i][0] * this.radius, points[i][1] * this.radius); + } + context.lineTo(points[0][0] * this.radius, points[0][1] * this.radius); + context.fill(); +}; + +StationClock.prototype.strokeSymmetricPolygon = function(context, color, points, width) { + context.beginPath(); + context.strokeStyle = color; + context.moveTo(points[0][0] * this.radius, points[0][1] * this.radius); + for (var i = 1; i < points.length; i++) { + context.lineTo(points[i][0] * this.radius, points[i][1] * this.radius); + } + for (var i = points.length - 1; i >= 0; i--) { + context.lineTo(0 - points[i][0] * this.radius, points[i][1] * this.radius); + } + context.lineTo(points[0][0] * this.radius, points[0][1] * this.radius); + context.lineWidth = width * this.radius; + context.stroke(); +}; + + From 08f7b3c1d58be484f6a2f11652230897c3548c73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 23 Jan 2018 15:00:33 +0100 Subject: [PATCH 120/134] force saving of current scene, while not explicitely asked to not --- src/board/UBBoardController.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/board/UBBoardController.h b/src/board/UBBoardController.h index 23fc688f..10c616ae 100644 --- a/src/board/UBBoardController.h +++ b/src/board/UBBoardController.h @@ -160,7 +160,7 @@ class UBBoardController : public UBDocumentContainer } qreal currentZoom(); void persistViewPositionOnCurrentScene(); - void persistCurrentScene(bool isAnAutomaticBackup = false, bool forceImmediateSave = false); + void persistCurrentScene(bool isAnAutomaticBackup = false, bool forceImmediateSave = true); void showNewVersionAvailable(bool automatic, const UBVersion &installedVersion, const UBSoftwareUpdate &softwareUpdate); void setBoxing(QRect displayRect); void setToolbarTexts(); From 38f4e5e63359b1f2be4139d69efb8fe46b57648d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 23 Jan 2018 15:34:07 +0100 Subject: [PATCH 121/134] corrected french translation --- resources/i18n/OpenBoard_fr.ts | 4 ++-- resources/i18n/OpenBoard_fr_CH.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/resources/i18n/OpenBoard_fr.ts b/resources/i18n/OpenBoard_fr.ts index 225ed68e..83b29477 100644 --- a/resources/i18n/OpenBoard_fr.ts +++ b/resources/i18n/OpenBoard_fr.ts @@ -117,11 +117,11 @@ Grid Light Background - Fonds quadrillé clair + Fond quadrillé clair Grid Dark Background - Fonds quadrillé foncé + Fond quadrillé foncé Start Screen Recording diff --git a/resources/i18n/OpenBoard_fr_CH.ts b/resources/i18n/OpenBoard_fr_CH.ts index 49a18cb0..a752f3a5 100644 --- a/resources/i18n/OpenBoard_fr_CH.ts +++ b/resources/i18n/OpenBoard_fr_CH.ts @@ -117,11 +117,11 @@ Grid Light Background - Fonds quadrillé clair + Fond quadrillé clair Grid Dark Background - Fonds quadrillé foncé + Fond quadrillé foncé Start Screen Recording @@ -169,7 +169,7 @@ Pages - Page %0 + Pages New Page From 9b4073b860baecd9090082f88f217be585340887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 23 Jan 2018 15:35:02 +0100 Subject: [PATCH 122/134] changed release name to 1.4-rc3 --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index b1a87f3c..5b6f2afe 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -12,7 +12,7 @@ VERSION_MAJ = 1 VERSION_MIN = 4 VERSION_PATCH = 0 VERSION_TYPE = rc # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_BUILD = 2 +VERSION_BUILD = 3 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}" From 92297181b515f79637de5028173c3cbd01ea57db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Tue, 23 Jan 2018 15:57:31 +0100 Subject: [PATCH 123/134] increased preferences default width --- resources/forms/preferences.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/forms/preferences.ui b/resources/forms/preferences.ui index da315e55..bf5e8b64 100644 --- a/resources/forms/preferences.ui +++ b/resources/forms/preferences.ui @@ -6,7 +6,7 @@ 0 0 - 800 + 820 718 From 532ed5331fc2e86ccca51b0b6355fa3eb5f638ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Wed, 31 Jan 2018 14:51:09 +0100 Subject: [PATCH 124/134] Revert "force saving of current scene, while not explicitely asked to not" This reverts commit 08f7b3c1d58be484f6a2f11652230897c3548c73. --- src/board/UBBoardController.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/board/UBBoardController.h b/src/board/UBBoardController.h index 10c616ae..23fc688f 100644 --- a/src/board/UBBoardController.h +++ b/src/board/UBBoardController.h @@ -160,7 +160,7 @@ class UBBoardController : public UBDocumentContainer } qreal currentZoom(); void persistViewPositionOnCurrentScene(); - void persistCurrentScene(bool isAnAutomaticBackup = false, bool forceImmediateSave = true); + void persistCurrentScene(bool isAnAutomaticBackup = false, bool forceImmediateSave = false); void showNewVersionAvailable(bool automatic, const UBVersion &installedVersion, const UBSoftwareUpdate &softwareUpdate); void setBoxing(QRect displayRect); void setToolbarTexts(); From 2b7d01ad15638cf9e01bc9b772c5946c02a9839c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Wed, 31 Jan 2018 14:51:31 +0100 Subject: [PATCH 125/134] Revert "due to suspected instability with persistance Worker (randomly not persisted scenes, very hard to reproduce), switched to 'immediateSave mode' (at least for now)" This reverts commit ae1a2a533872d335b0d7d73e8520958b0d26d49c. --- src/core/UBPersistenceManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/UBPersistenceManager.h b/src/core/UBPersistenceManager.h index 9208c5c0..19d10f66 100644 --- a/src/core/UBPersistenceManager.h +++ b/src/core/UBPersistenceManager.h @@ -77,7 +77,7 @@ class UBPersistenceManager : public QObject virtual void duplicateDocumentScene(UBDocumentProxy* pDocumentProxy, int index); virtual void persistDocumentScene(UBDocumentProxy* pDocumentProxy, - UBGraphicsScene* pScene, const int pSceneIndex, bool isAnAutomaticBackup = false, bool forceImmediateSaving = true); + UBGraphicsScene* pScene, const int pSceneIndex, bool isAnAutomaticBackup = false, bool forceImmediateSaving = false); virtual UBGraphicsScene* createDocumentSceneAt(UBDocumentProxy* pDocumentProxy, int index, bool useUndoRedoStack = true); From 012e8384918dc73337b7ac988b68d0db1209112f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 19 Feb 2018 13:20:09 +0100 Subject: [PATCH 126/134] added a 'reset background grid size' button in the background palette --- resources/OpenBoard.qrc | 1 + resources/forms/mainWindow.ui | 12 +++++++++++ .../resetDefaultGridSize.svg | 21 +++++++++++++++++++ src/core/UBSettings.cpp | 1 + src/core/UBSettings.h | 1 + src/gui/UBBackgroundPalette.cpp | 15 +++++++++++++ src/gui/UBBackgroundPalette.h | 2 ++ 7 files changed, 53 insertions(+) create mode 100644 resources/images/backgroundPalette/resetDefaultGridSize.svg diff --git a/resources/OpenBoard.qrc b/resources/OpenBoard.qrc index 4f7d7765..18c33750 100644 --- a/resources/OpenBoard.qrc +++ b/resources/OpenBoard.qrc @@ -359,5 +359,6 @@ images/groupItems.svg images/ungroupItems.svg images/setAsBackground.svg + images/backgroundPalette/resetDefaultGridSize.svg diff --git a/resources/forms/mainWindow.ui b/resources/forms/mainWindow.ui index d1c27a4b..c8002440 100644 --- a/resources/forms/mainWindow.ui +++ b/resources/forms/mainWindow.ui @@ -1647,6 +1647,18 @@ Open the tutorial web page + + + + :/images/backgroundPalette/resetDefaultGridSize.svg:/images/backgroundPalette/resetDefaultGridSize.svg + + + Default Grid Size + + + return to Default Grid Size + + diff --git a/resources/images/backgroundPalette/resetDefaultGridSize.svg b/resources/images/backgroundPalette/resetDefaultGridSize.svg new file mode 100644 index 00000000..5df55a0f --- /dev/null +++ b/resources/images/backgroundPalette/resetDefaultGridSize.svg @@ -0,0 +1,21 @@ + + + + + + + + + diff --git a/src/core/UBSettings.cpp b/src/core/UBSettings.cpp index 131ae78c..d30855cc 100644 --- a/src/core/UBSettings.cpp +++ b/src/core/UBSettings.cpp @@ -47,6 +47,7 @@ QPointer UBSettings::sSingleton = 0; int UBSettings::pointerDiameter = 40; int UBSettings::crossSize = 24; +int UBSettings::defaultCrossSize = 24; int UBSettings::minCrossSize = 12; int UBSettings::maxCrossSize = 96; //TODO: user-settable? int UBSettings::colorPaletteSize = 5; diff --git a/src/core/UBSettings.h b/src/core/UBSettings.h index 91d6dc25..28af670b 100644 --- a/src/core/UBSettings.h +++ b/src/core/UBSettings.h @@ -188,6 +188,7 @@ class UBSettings : public QObject // Background grid static int crossSize; + static int defaultCrossSize; static int minCrossSize; static int maxCrossSize; diff --git a/src/gui/UBBackgroundPalette.cpp b/src/gui/UBBackgroundPalette.cpp index 4cb6b3b1..92ce0bd8 100644 --- a/src/gui/UBBackgroundPalette.cpp +++ b/src/gui/UBBackgroundPalette.cpp @@ -1,5 +1,7 @@ #include "UBBackgroundPalette.h" +#include "gui/UBMainWindow.h" + UBBackgroundPalette::UBBackgroundPalette(QList actions, QWidget * parent) : UBActionPalette(parent) { @@ -47,9 +49,16 @@ void UBBackgroundPalette::init() mSliderLabel = new QLabel(tr("Grid size")); + mResetDefaultGridSizeButton = createPaletteButton(UBApplication::mainWindow->actionDefaultGridSize, this); + mResetDefaultGridSizeButton->setFixedSize(24,24); + mActions << UBApplication::mainWindow->actionDefaultGridSize; + + connect(UBApplication::mainWindow->actionDefaultGridSize, SIGNAL(triggered()), this, SLOT(defaultBackgroundGridSize())); + mBottomLayout->addSpacing(16); mBottomLayout->addWidget(mSliderLabel); mBottomLayout->addWidget(mSlider); + mBottomLayout->addWidget(mResetDefaultGridSizeButton); mBottomLayout->addSpacing(16); updateLayout(); @@ -137,6 +146,12 @@ void UBBackgroundPalette::sliderValueChanged(int value) UBSettings::settings()->crossSize = value; // since this function is called (indirectly, by refresh) when we switch scenes, the settings will always have the current scene's cross size. } +void UBBackgroundPalette::defaultBackgroundGridSize() +{ + mSlider->setValue(UBSettings::settings()->defaultCrossSize); + sliderValueChanged(UBSettings::settings()->defaultCrossSize); +} + void UBBackgroundPalette::backgroundChanged() { bool dark = UBApplication::boardController->activeScene()->isDarkBackground(); diff --git a/src/gui/UBBackgroundPalette.h b/src/gui/UBBackgroundPalette.h index c9f6ffe1..83472d47 100644 --- a/src/gui/UBBackgroundPalette.h +++ b/src/gui/UBBackgroundPalette.h @@ -27,6 +27,7 @@ class UBBackgroundPalette : public UBActionPalette protected slots: void sliderValueChanged(int value); + void defaultBackgroundGridSize(); protected: virtual void updateLayout(); @@ -39,6 +40,7 @@ class UBBackgroundPalette : public UBActionPalette QSlider* mSlider; QLabel* mSliderLabel; + UBActionPaletteButton* mResetDefaultGridSizeButton; }; From e2aef9f0aa53f2e4abdb9872fc7b705be1a184de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 19 Feb 2018 13:23:28 +0100 Subject: [PATCH 127/134] increased messages during document loading + optimized some calls --- src/adaptors/UBThumbnailAdaptor.cpp | 1 + src/board/UBBoardController.cpp | 6 ++++-- src/core/UBApplicationController.cpp | 1 + src/core/UBPersistenceManager.cpp | 1 + src/document/UBDocumentContainer.cpp | 1 - src/document/UBDocumentContainer.h | 1 - src/document/UBDocumentController.cpp | 3 ++- src/gui/UBBoardThumbnailsView.cpp | 27 ++++++++++++++++----------- src/gui/UBMessageWindow.cpp | 4 ++-- src/gui/UBThumbnailWidget.cpp | 14 ++++++++++++-- 10 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/adaptors/UBThumbnailAdaptor.cpp b/src/adaptors/UBThumbnailAdaptor.cpp index b0b6a141..3d87e123 100644 --- a/src/adaptors/UBThumbnailAdaptor.cpp +++ b/src/adaptors/UBThumbnailAdaptor.cpp @@ -85,6 +85,7 @@ void UBThumbnailAdaptor::generateMissingThumbnails(UBDocumentProxy* proxy) const QPixmap* UBThumbnailAdaptor::get(UBDocumentProxy* proxy, int pageIndex) { + UBApplication::showMessage(tr("loading thumbnail of page %1").arg(pageIndex + 1)); QString fileName = proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", pageIndex); QFile file(fileName); diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index e5ce8e36..ffa576ec 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -189,6 +189,7 @@ void UBBoardController::initBackgroundGridSize() int gridSize = (resolutionRatio * 10. * dpi) / UBGeometryUtils::inchSize; UBSettings::settings()->crossSize = gridSize; + UBSettings::settings()->defaultCrossSize = gridSize; mActiveScene->setBackgroundGridSize(gridSize); //qDebug() << "grid size: " << gridSize; @@ -228,10 +229,11 @@ void UBBoardController::setupViews() mDisplayView->setInteractive(false); mDisplayView->setTransformationAnchor(QGraphicsView::NoAnchor); - mMessageWindow = new UBMessageWindow(mControlView); + mPaletteManager = new UBBoardPaletteManager(mControlContainer, this); + + mMessageWindow = new UBMessageWindow(mControlContainer); mMessageWindow->hide(); - mPaletteManager = new UBBoardPaletteManager(mControlContainer, this); connect(this, SIGNAL(activeSceneChanged()), mPaletteManager, SLOT(activeSceneChanged())); } diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index d8bdc89f..4e062425 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -358,6 +358,7 @@ void UBApplicationController::showBoard() } } + UBApplication::showMessage(tr("Drawing active scene and thumbnail previews")); mMainMode = Board; adaptToolBar(); diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index f0791119..a28cb35f 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -777,6 +777,7 @@ void UBPersistenceManager::persistDocumentScene(UBDocumentProxy* pDocumentProxy, if (pDocumentProxy->isModified()) persistDocumentMetadata(pDocumentProxy, forceImmediateSaving); + UBApplication::showMessage(tr("saving document thumbnail for the page %1").arg(pSceneIndex+1)); UBThumbnailAdaptor::persistScene(pDocumentProxy, pScene, pSceneIndex); if(forceImmediateSaving) UBSvgSubsetAdaptor::persistScene(pDocumentProxy,pScene,pSceneIndex); diff --git a/src/document/UBDocumentContainer.cpp b/src/document/UBDocumentContainer.cpp index 9bc9601c..2d30f607 100644 --- a/src/document/UBDocumentContainer.cpp +++ b/src/document/UBDocumentContainer.cpp @@ -54,7 +54,6 @@ void UBDocumentContainer::setDocument(UBDocumentProxy* document, bool forceReloa emit initThumbnailsRequired(this); emit documentSet(mCurrentDocument); - reloadThumbnails(); } } diff --git a/src/document/UBDocumentContainer.h b/src/document/UBDocumentContainer.h index 8ee9b5c0..f47e08ea 100644 --- a/src/document/UBDocumentContainer.h +++ b/src/document/UBDocumentContainer.h @@ -61,7 +61,6 @@ class UBDocumentContainer : public QObject void insertThumbPage(int index); - private: UBDocumentProxy* mCurrentDocument; QList mDocumentThumbs; diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index 04d53136..7c6b3406 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -168,6 +168,7 @@ void UBDocumentController::selectDocument(UBDocumentProxy* proxy, bool setAsCurr if (selected) { setDocument(proxy); + reloadThumbnails(); selected->setSelected(true); @@ -267,7 +268,7 @@ void UBDocumentController::itemSelectionChanged() { updateCurrentSelection(); - reloadThumbnails(); + emit documentThumbnailsUpdated(this); if (multipleSelection()) mSelectionType = Multiple; diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index f2ccafd7..c7fa4b9b 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -115,6 +115,8 @@ void UBBoardThumbnailsView::removeThumbnail(int i) UBDraggableThumbnailView* UBBoardThumbnailsView::createThumbnail(UBDocumentContainer* source, int i) { + UBApplication::showMessage(tr("Loading document scene (%1/%2)").arg(i+1).arg(source->selectedDocument()->pageCount())); + UBGraphicsScene* pageScene = UBPersistenceManager::persistenceManager()->loadDocumentScene(source->selectedDocument(), i); UBThumbnailView* pageView = new UBThumbnailView(pageScene); @@ -200,20 +202,23 @@ void UBBoardThumbnailsView::resizeEvent(QResizeEvent *event) void UBBoardThumbnailsView::mousePressEvent(QMouseEvent *event) { - mLongPressTimer.start(); - mLastPressedMousePos = event->pos(); - - UBDraggableThumbnailView* item = dynamic_cast(itemAt(event->pos())); + QGraphicsView::mousePressEvent(event); - if (item) + if (!event->isAccepted()) { - UBApplication::boardController->persistViewPositionOnCurrentScene(); - UBApplication::boardController->persistCurrentScene(); - UBApplication::boardController->setActiveDocumentScene(item->sceneIndex()); - UBApplication::boardController->centerOn(UBApplication::boardController->activeScene()->lastCenter()); - } + mLongPressTimer.start(); + mLastPressedMousePos = event->pos(); - QGraphicsView::mousePressEvent(event); + UBDraggableThumbnailView* item = dynamic_cast(itemAt(event->pos())); + + if (item) + { + UBApplication::boardController->persistViewPositionOnCurrentScene(); + UBApplication::boardController->persistCurrentScene(); + UBApplication::boardController->setActiveDocumentScene(item->sceneIndex()); + UBApplication::boardController->centerOn(UBApplication::boardController->activeScene()->lastCenter()); + } + } } void UBBoardThumbnailsView::mouseMoveEvent(QMouseEvent *event) diff --git a/src/gui/UBMessageWindow.cpp b/src/gui/UBMessageWindow.cpp index 1d499a98..14adbbb6 100644 --- a/src/gui/UBMessageWindow.cpp +++ b/src/gui/UBMessageWindow.cpp @@ -42,7 +42,7 @@ UBMessageWindow::UBMessageWindow(QWidget *parent) mLabel = new QLabel(parent); mLabel->setStyleSheet(QString("QLabel { color: white; background-color: transparent; border: none; font-family: Arial; font-size: 14px }")); - mOriginalAlpha = mBackgroundBrush.color().alpha(); + mOriginalAlpha = 255; mLayout->setContentsMargins(radius() + 15, 4, radius() + 15, 4); @@ -79,7 +79,7 @@ void UBMessageWindow::showMessage(const QString& message, bool showSpinningWheel { mSpinningWheel->hide(); mSpinningWheel->stopAnimation(); - mTimer.start(200, this); + mTimer.start(50, this); } adjustSizeAndPosition(); diff --git a/src/gui/UBThumbnailWidget.cpp b/src/gui/UBThumbnailWidget.cpp index 788c7f6d..5d6acbaf 100644 --- a/src/gui/UBThumbnailWidget.cpp +++ b/src/gui/UBThumbnailWidget.cpp @@ -898,17 +898,27 @@ void UBDraggableThumbnail::mousePressEvent(QGraphicsSceneMouseEvent *event) if (triggered(p.y())) { if(deletable() && getIcon("close")->triggered(p.x())) + { + event->accept(); deletePage(); + } else if(getIcon("duplicate")->triggered(p.x())) + { + event->accept(); duplicatePage(); + } /* else if(movableUp() && getIcon("moveUp")->triggered(p.x())) moveUpPage(); else if (movableDown() && getIcon("moveDown")->triggered(p.x())) moveDownPage();*/ - } - event->accept(); + event->ignore(); + } + else + { + event->ignore(); + } } void UBDraggableThumbnail::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) From 0344a4c29350950c84fef0e058853259059d91f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 19 Feb 2018 15:37:36 +0100 Subject: [PATCH 128/134] added translations --- resources/forms/mainWindow.ui | 4 +- resources/i18n/OpenBoard_ar.ts | 23 ++++++++++++ resources/i18n/OpenBoard_bg.ts | 23 ++++++++++++ resources/i18n/OpenBoard_ca.ts | 23 ++++++++++++ resources/i18n/OpenBoard_cs.ts | 23 ++++++++++++ resources/i18n/OpenBoard_da.ts | 23 ++++++++++++ resources/i18n/OpenBoard_de.ts | 56 +++++++++++++++++++++------- resources/i18n/OpenBoard_el.ts | 23 ++++++++++++ resources/i18n/OpenBoard_en.ts | 23 ++++++++++++ resources/i18n/OpenBoard_en_UK.ts | 23 ++++++++++++ resources/i18n/OpenBoard_es.ts | 23 ++++++++++++ resources/i18n/OpenBoard_fr.ts | 31 +++++++++++++++ resources/i18n/OpenBoard_fr_CH.ts | 31 +++++++++++++++ resources/i18n/OpenBoard_it.ts | 27 +++++++++++++- resources/i18n/OpenBoard_iw.ts | 23 ++++++++++++ resources/i18n/OpenBoard_ja.ts | 23 ++++++++++++ resources/i18n/OpenBoard_ko.ts | 23 ++++++++++++ resources/i18n/OpenBoard_mg.ts | 23 ++++++++++++ resources/i18n/OpenBoard_nb.ts | 23 ++++++++++++ resources/i18n/OpenBoard_nl.ts | 23 ++++++++++++ resources/i18n/OpenBoard_pl.ts | 23 ++++++++++++ resources/i18n/OpenBoard_pt.ts | 23 ++++++++++++ resources/i18n/OpenBoard_ro.ts | 23 ++++++++++++ resources/i18n/OpenBoard_ru.ts | 23 ++++++++++++ resources/i18n/OpenBoard_sk.ts | 23 ++++++++++++ resources/i18n/OpenBoard_sv.ts | 23 ++++++++++++ resources/i18n/OpenBoard_tr.ts | 23 ++++++++++++ resources/i18n/OpenBoard_zh.ts | 23 ++++++++++++ resources/i18n/OpenBoard_zh_CN.ts | 23 ++++++++++++ resources/i18n/OpenBoard_zh_TW.ts | 23 ++++++++++++ src/core/UBApplicationController.cpp | 2 +- src/core/UBPersistenceManager.cpp | 2 +- src/gui/UBBoardThumbnailsView.cpp | 2 +- src/gui/UBThumbnailWidget.h | 2 + 34 files changed, 711 insertions(+), 21 deletions(-) diff --git a/resources/forms/mainWindow.ui b/resources/forms/mainWindow.ui index c8002440..24c04b61 100644 --- a/resources/forms/mainWindow.ui +++ b/resources/forms/mainWindow.ui @@ -1653,10 +1653,10 @@ :/images/backgroundPalette/resetDefaultGridSize.svg:/images/backgroundPalette/resetDefaultGridSize.svg - Default Grid Size + Reset grid size - return to Default Grid Size + Reset grid size diff --git a/resources/i18n/OpenBoard_ar.ts b/resources/i18n/OpenBoard_ar.ts index 167894f3..e522fd59 100644 --- a/resources/i18n/OpenBoard_ar.ts +++ b/resources/i18n/OpenBoard_ar.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update التحيين + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ صورة ملتقطة + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1801,6 +1816,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1964,6 +1983,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... 1 % صور مصغرة مولّدة + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_bg.ts b/resources/i18n/OpenBoard_bg.ts index 938034d3..fa3812dc 100644 --- a/resources/i18n/OpenBoard_bg.ts +++ b/resources/i18n/OpenBoard_bg.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update Обновления + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ Уловени изображения + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1799,6 +1814,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1962,6 +1981,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... %1 икони са създадени ... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_ca.ts b/resources/i18n/OpenBoard_ca.ts index e0d035fd..afef7740 100644 --- a/resources/i18n/OpenBoard_ca.ts +++ b/resources/i18n/OpenBoard_ca.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update Actualitza + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ CapturedImage + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1798,6 +1813,10 @@ Voleu ignorar aquests errors per a aquest amfitrió? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1954,6 +1973,10 @@ Voleu ignorar aquests errors per a aquest amfitrió? %1 thumbnails generated ... S'han generat %1 miniatures... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_cs.ts b/resources/i18n/OpenBoard_cs.ts index c865257b..1617c60d 100644 --- a/resources/i18n/OpenBoard_cs.ts +++ b/resources/i18n/OpenBoard_cs.ts @@ -808,6 +808,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -899,6 +903,10 @@ Update available K dispozici je aktualizace + + Board drawing... + + UBBackgroundPalette @@ -973,6 +981,13 @@ Zachycenýobrázek + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1801,6 +1816,10 @@ Chcete ignorovat tyto chyby na tomto serveru? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1964,6 +1983,10 @@ Chcete ignorovat tyto chyby na tomto serveru? Generating preview thumbnails ... Vytváří se miniatury obrázků ... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_da.ts b/resources/i18n/OpenBoard_da.ts index 59096c0b..cea4f1ec 100644 --- a/resources/i18n/OpenBoard_da.ts +++ b/resources/i18n/OpenBoard_da.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update Opdatering + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ HentetBillede + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1798,6 +1813,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1961,6 +1980,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... %1 miniaturebilleder genereret... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_de.ts b/resources/i18n/OpenBoard_de.ts index 317fa87f..90f163dd 100644 --- a/resources/i18n/OpenBoard_de.ts +++ b/resources/i18n/OpenBoard_de.ts @@ -807,6 +807,10 @@ Ruled Dark Background Dunkel linierter Hintergrund + + Reset grid size + Rastergröße zurücksetzen + PasswordDialog @@ -858,7 +862,7 @@ Remove Page - Seite entfernen + Seite entfernen Are you sure you want to remove 1 page from the selected document '%0'? @@ -898,6 +902,10 @@ Update Aktualisierung + + Board drawing... + Brettzeichnung... + UBBackgroundPalette @@ -942,15 +950,15 @@ Add file operation failed: file copying error - Dokument hinzufügen fehlgeschlagen: Fehler beim Kopieren + Dokument hinzufügen fehlgeschlagen: Fehler beim Kopieren Group - Gruppieren + Gruppieren Ungroup - Gruppierung auflösen + Gruppierung auflösen Saving document... @@ -972,6 +980,13 @@ erfasstes Bild + + UBBoardThumbnailsView + + Loading page (%1/%2) + Ladeseite (%1/%2) + + UBCachePropertiesWidget @@ -1145,11 +1160,11 @@ Folder does not contain any image files - Das Verzeichnis enthält keine Bilder + Das Verzeichnis enthält keine Bilder Untitled Documents - Unbenanntes Dokument + Unbenanntes Dokument The document '%1' has been generated with a newer version of OpenBoard (%2). By opening it, you may lose some information. Do you want to proceed? @@ -1192,11 +1207,11 @@ Inserting page %1 of %2 - Hinzufügen der Seite %1 von %2 + Hinzufügen der Seite %1 von %2 Import successful. - Import erfolgreich. + Import erfolgreich. Import of file %1 successful. @@ -1547,11 +1562,11 @@ UBGraphicsGroupContainerItemDelegate Locked - Gesperrt + Gesperrt Visible on Extended Screen - Auf erweitertem Bildschirm sichtbar + Auf erweitertem Bildschirm sichtbar @@ -1614,14 +1629,14 @@ UBGraphicsW3CWidgetItem Web - Web + Web UBGraphicsWidgetItem Loading ... - Lädt... + Lädt... @@ -1743,7 +1758,7 @@ UBMessagesDialog Close - Schließen + Schließen @@ -1822,6 +1837,14 @@ Möchten Sie diese Fehler für diesen Computer ignorieren? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. Verbindung zum Dokumentenarchiv verloren. Um fehlerhafte Daten zu vermeiden muss die Anwendung leider geschlossen werden. Letzte Änderungen können auch verloren gehen. + + saving document thumbnail for the page %1 + Backup Übersichtsseite %1 + + + Saving thumbnail of page %1 + Miniaturansicht der Seite %1 speichern + UBPlatformUtils @@ -1985,12 +2008,17 @@ Möchten Sie diese Fehler für diesen Computer ignorieren? %1 thumbnails generated ... Miniaturansicht %1 wird erstellt... + + loading thumbnail of page %1 + +Miniaturansicht der Seite %1 wird geladen + UBThumbnailTextItem Page %0 - Seite %0 + Seite %0 diff --git a/resources/i18n/OpenBoard_el.ts b/resources/i18n/OpenBoard_el.ts index 4093a9db..19ea8028 100644 --- a/resources/i18n/OpenBoard_el.ts +++ b/resources/i18n/OpenBoard_el.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update Ενημέρωση + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ Εικόνα από σύλληψη στιγμιότυπου + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1798,6 +1813,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1961,6 +1980,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... %1 μικρογραφίες δημιουργήθηκαν... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_en.ts b/resources/i18n/OpenBoard_en.ts index 751d2447..0d2c94cd 100644 --- a/resources/i18n/OpenBoard_en.ts +++ b/resources/i18n/OpenBoard_en.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -890,6 +894,10 @@ Update + + Board drawing... + + UBBackgroundPalette @@ -964,6 +972,13 @@ + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1701,6 +1716,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1864,6 +1883,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_en_UK.ts b/resources/i18n/OpenBoard_en_UK.ts index 57b71e94..4b6f86a8 100644 --- a/resources/i18n/OpenBoard_en_UK.ts +++ b/resources/i18n/OpenBoard_en_UK.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -890,6 +894,10 @@ Update + + Board drawing... + + UBBackgroundPalette @@ -964,6 +972,13 @@ + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1701,6 +1716,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1864,6 +1883,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_es.ts b/resources/i18n/OpenBoard_es.ts index a10155e7..edf1e0ca 100644 --- a/resources/i18n/OpenBoard_es.ts +++ b/resources/i18n/OpenBoard_es.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update Actualizar + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ Imagen capturada + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1792,6 +1807,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1955,6 +1974,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... %1 miniaturas generadas... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_fr.ts b/resources/i18n/OpenBoard_fr.ts index 83b29477..456d505e 100644 --- a/resources/i18n/OpenBoard_fr.ts +++ b/resources/i18n/OpenBoard_fr.ts @@ -808,6 +808,10 @@ Ruled Dark Background Fond ligné foncé + + Reset grid size + Réinitialiser la taille du quadrillage + PasswordDialog @@ -899,6 +903,14 @@ Update Mettre à jour + + Drawing active scene and thumbnail previews + Dessin de la page active et des aperçus + + + Board drawing... + Dessin du tableau... + UBBackgroundPalette @@ -973,6 +985,13 @@ Image capturée + + UBBoardThumbnailsView + + Loading page (%1/%2) + Chargement page (%1/%2) + + UBCachePropertiesWidget @@ -1831,6 +1850,14 @@ Voulez-vous ignorer les erreurs pour ce serveur ? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. a perdu l'accès au répertoire des documents '%1'. Malheureusement, l'application sera fermée afin d'éviter la corruption des données. Les dernières modifications pourraient être également perdues. + + saving document thumbnail for the page %1 + Sauvegarde aperçu page %1 + + + Saving thumbnail of page %1 + Sauvegarde aperçu page %1 + UBPlatformUtils @@ -1994,6 +2021,10 @@ Voulez-vous ignorer les erreurs pour ce serveur ? %1 thumbnails generated ... %1 vignettes créées ... + + loading thumbnail of page %1 + Chargement aperçu page %1 + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_fr_CH.ts b/resources/i18n/OpenBoard_fr_CH.ts index a752f3a5..2cd3a5ba 100644 --- a/resources/i18n/OpenBoard_fr_CH.ts +++ b/resources/i18n/OpenBoard_fr_CH.ts @@ -808,6 +808,10 @@ Ruled Dark Background Fond ligné foncé + + Reset grid size + Réinitialiser la taille du quadrillage + PasswordDialog @@ -899,6 +903,14 @@ Update Mettre à jour + + Drawing active scene and thumbnail previews + Dessin de la page active et des aperçus + + + Board drawing... + Dessin du tableau... + UBBackgroundPalette @@ -973,6 +985,13 @@ Image capturée + + UBBoardThumbnailsView + + Loading page (%1/%2) + Chargement page (%1/%2) + + UBCachePropertiesWidget @@ -1831,6 +1850,14 @@ Voulez-vous ignorer les erreurs pour ce serveur ? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. a perdu l'accès au répertoire des documents '%1'. Malheureusement, l'application sera fermée afin d'éviter la corruption des données. Les dernières modifications pourraient être également perdues. + + saving document thumbnail for the page %1 + Sauvegarde aperçu page %1 + + + Saving thumbnail of page %1 + Sauvegarde aperçu page %1 + UBPlatformUtils @@ -1994,6 +2021,10 @@ Voulez-vous ignorer les erreurs pour ce serveur ? %1 thumbnails generated ... %1 vignettes créées ... + + loading thumbnail of page %1 + Chargement aperçu page %1 + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_it.ts b/resources/i18n/OpenBoard_it.ts index 3470fe46..a1e249c7 100644 --- a/resources/i18n/OpenBoard_it.ts +++ b/resources/i18n/OpenBoard_it.ts @@ -807,6 +807,10 @@ Ruled Dark Background Sfundo scuro lineato + + Reset grid size + Ripristina la dimensione della griglia + PasswordDialog @@ -898,6 +902,10 @@ Update Aggiornamento + + Board drawing... + Disegno della lavagna... + UBBackgroundPalette @@ -972,6 +980,13 @@ ImmagineCatturata + + UBBoardThumbnailsView + + Loading page (%1/%2) + Caricamento pagina (%1/%2) + + UBCachePropertiesWidget @@ -1226,7 +1241,7 @@ %1 pages copied - + %1 pagina copiata %1 pagine copiate @@ -1822,6 +1837,10 @@ Vuoi ignorare gli errori per questo host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. ha perso l'accesso al repository documenti "%1". Sfortunatamente l'applicazione deve essere chiusa per evitare di rivinare i dati. Gli ultimi cambiamenti potrebbero andare persi. + + Saving thumbnail of page %1 + Salvataggio della miniatura della pagina %1 + UBPlatformUtils @@ -1985,12 +2004,16 @@ Vuoi ignorare gli errori per questo host? %1 thumbnails generated ... %1 miniature generate... + + loading thumbnail of page %1 + Caricamento miniatura della pagina %1 + UBThumbnailTextItem Page %0 - Pagina %0 + Pagina %0 diff --git a/resources/i18n/OpenBoard_iw.ts b/resources/i18n/OpenBoard_iw.ts index 31fcfdf3..45101bd2 100644 --- a/resources/i18n/OpenBoard_iw.ts +++ b/resources/i18n/OpenBoard_iw.ts @@ -808,6 +808,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -899,6 +903,10 @@ Update עדכון + + Board drawing... + + UBBackgroundPalette @@ -973,6 +981,13 @@ תמונה שנלכדה + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1795,6 +1810,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1958,6 +1977,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... נוצרה תמונה מוקטנת של %1... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_ja.ts b/resources/i18n/OpenBoard_ja.ts index 8ec9be01..37888ee6 100644 --- a/resources/i18n/OpenBoard_ja.ts +++ b/resources/i18n/OpenBoard_ja.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -890,6 +894,10 @@ Update 更新 + + Board drawing... + + UBBackgroundPalette @@ -964,6 +972,13 @@ キャプチャされた画像 + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1789,6 +1804,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1952,6 +1971,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... %1 サムネイル作成済み ... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_ko.ts b/resources/i18n/OpenBoard_ko.ts index 8b176af0..e90acdaf 100644 --- a/resources/i18n/OpenBoard_ko.ts +++ b/resources/i18n/OpenBoard_ko.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update 업데이트 + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ 캡처한 이미지 + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1799,6 +1814,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1962,6 +1981,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... %1 썸네일 생성됨 ... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_mg.ts b/resources/i18n/OpenBoard_mg.ts index 90d64b22..c02aaa7b 100644 --- a/resources/i18n/OpenBoard_mg.ts +++ b/resources/i18n/OpenBoard_mg.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update Avaozy + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ Sary nalaina + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1798,6 +1813,10 @@ Tena tsy te hiraharaha an'ireo tsy mety ho an'ilay milina ve ianao?has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1961,6 +1980,10 @@ Tena tsy te hiraharaha an'ireo tsy mety ho an'ilay milina ve ianao?%1 thumbnails generated ... %1 ny kisarisary no voaforona ... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_nb.ts b/resources/i18n/OpenBoard_nb.ts index df6f98e6..1a6dfbdf 100644 --- a/resources/i18n/OpenBoard_nb.ts +++ b/resources/i18n/OpenBoard_nb.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update Oppdatering + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ Tatt bilde + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1794,6 +1809,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1957,6 +1976,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... %1 miniatyrbilder generert ... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_nl.ts b/resources/i18n/OpenBoard_nl.ts index aa428f39..87a95506 100644 --- a/resources/i18n/OpenBoard_nl.ts +++ b/resources/i18n/OpenBoard_nl.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -890,6 +894,10 @@ Update Update + + Board drawing... + + UBBackgroundPalette @@ -964,6 +972,13 @@ Gegrepen afbeelding + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1784,6 +1799,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1947,6 +1966,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... %1 miniaturen opgeladen... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_pl.ts b/resources/i18n/OpenBoard_pl.ts index f3b73ac8..2b8b8ebb 100644 --- a/resources/i18n/OpenBoard_pl.ts +++ b/resources/i18n/OpenBoard_pl.ts @@ -811,6 +811,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -902,6 +906,10 @@ Update Aktualizacja + + Board drawing... + + UBBackgroundPalette @@ -976,6 +984,13 @@ PrzechwyconyObraz + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1805,6 +1820,10 @@ Czy chcesz ignorować te błędy dla tego hosta? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1968,6 +1987,10 @@ Czy chcesz ignorować te błędy dla tego hosta? %1 thumbnails generated ... Wygenerowano %1 miniatur... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_pt.ts b/resources/i18n/OpenBoard_pt.ts index f09d4f06..e26e9bb1 100644 --- a/resources/i18n/OpenBoard_pt.ts +++ b/resources/i18n/OpenBoard_pt.ts @@ -809,6 +809,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -900,6 +904,10 @@ Update Atualizar + + Board drawing... + + UBBackgroundPalette @@ -974,6 +982,13 @@ Imagem capturada + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1825,6 +1840,10 @@ Quer ignorar estes erros, deste servidor? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. Acesso ao repositório '%1' foi perdido. Infelizmente a aplicação deverá desligar para avitar a corrupção de dados. As últimas alterações também serão perdidas. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1981,6 +2000,10 @@ Quer ignorar estes erros, deste servidor? %1 thumbnails generated ... %1 de miniaturas geradas ... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_ro.ts b/resources/i18n/OpenBoard_ro.ts index 047d7cfb..d15c5d93 100644 --- a/resources/i18n/OpenBoard_ro.ts +++ b/resources/i18n/OpenBoard_ro.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update Actualizare + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ ImagineCapturată + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1798,6 +1813,10 @@ Doriţi să ignoraţi aceste erori pentru acest host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1961,6 +1980,10 @@ Doriţi să ignoraţi aceste erori pentru acest host? %1 thumbnails generated ... %1 miniaturi generate ... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_ru.ts b/resources/i18n/OpenBoard_ru.ts index 41101d12..6f85864c 100644 --- a/resources/i18n/OpenBoard_ru.ts +++ b/resources/i18n/OpenBoard_ru.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update Обновить + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ Захватить изображение + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1798,6 +1813,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1961,6 +1980,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... сгенерированы эскизы %1... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_sk.ts b/resources/i18n/OpenBoard_sk.ts index 328af7aa..29c50d7c 100644 --- a/resources/i18n/OpenBoard_sk.ts +++ b/resources/i18n/OpenBoard_sk.ts @@ -811,6 +811,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -902,6 +906,10 @@ Update available K dispozícii je aktualizácia + + Board drawing... + + UBBackgroundPalette @@ -976,6 +984,13 @@ Označený obrázok + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1828,6 +1843,10 @@ Chcete ignorovať tieto chyby na tomto serveri? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. stratil prístup k úložisku dokumentov '%1'. Aplikácia sa musí zatvoriť, aby sa predišlo poškodeniu dát. Možno nebudú uložené ani najnovšie zmeny. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1993,6 +2012,10 @@ Chcete ignorovať tieto chyby na tomto serveri? Generating preview thumbnails ... Vytvárajú sa ukážky miniatúr... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_sv.ts b/resources/i18n/OpenBoard_sv.ts index af2123c0..4f3869a4 100644 --- a/resources/i18n/OpenBoard_sv.ts +++ b/resources/i18n/OpenBoard_sv.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update Uppdatera + + Board drawing... + + UBBackgroundPalette @@ -973,6 +981,13 @@ FångadBild + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1799,6 +1814,10 @@ Vill du ignorera felen för den här värden? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1962,6 +1981,10 @@ Vill du ignorera felen för den här värden? %1 thumbnails generated ... %1 miniatybil genererad ... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_tr.ts b/resources/i18n/OpenBoard_tr.ts index 43eae4e4..5fbc25a5 100644 --- a/resources/i18n/OpenBoard_tr.ts +++ b/resources/i18n/OpenBoard_tr.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update Güncelle + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ YakalananResim + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1796,6 +1811,10 @@ Bu host için yukarıdaki hatalar yok sayılsın mı? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1959,6 +1978,10 @@ Bu host için yukarıdaki hatalar yok sayılsın mı? %1 thumbnails generated ... %1 adet önizleme resmi oluşturuldu ... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_zh.ts b/resources/i18n/OpenBoard_zh.ts index d1c6017c..cc8f79fe 100644 --- a/resources/i18n/OpenBoard_zh.ts +++ b/resources/i18n/OpenBoard_zh.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update 更新 + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ 图像截图 + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1796,6 +1811,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1959,6 +1978,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... 已为%1生成缩略图…… + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_zh_CN.ts b/resources/i18n/OpenBoard_zh_CN.ts index d1c6017c..cc8f79fe 100644 --- a/resources/i18n/OpenBoard_zh_CN.ts +++ b/resources/i18n/OpenBoard_zh_CN.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update 更新 + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ 图像截图 + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1796,6 +1811,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1959,6 +1978,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... 已为%1生成缩略图…… + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/resources/i18n/OpenBoard_zh_TW.ts b/resources/i18n/OpenBoard_zh_TW.ts index f2e2d424..22c9fd4f 100644 --- a/resources/i18n/OpenBoard_zh_TW.ts +++ b/resources/i18n/OpenBoard_zh_TW.ts @@ -807,6 +807,10 @@ Ruled Dark Background + + Reset grid size + + PasswordDialog @@ -898,6 +902,10 @@ Update 更新 + + Board drawing... + + UBBackgroundPalette @@ -972,6 +980,13 @@ 圖像擷取 + + UBBoardThumbnailsView + + Loading page (%1/%2) + + + UBCachePropertiesWidget @@ -1790,6 +1805,10 @@ Do you want to ignore these errors for this host? has lost access to the document repository '%1'. Unfortunately the application must shut down to avoid data corruption. Latest changes may be lost as well. + + Saving thumbnail of page %1 + + UBPlatformUtils @@ -1946,6 +1965,10 @@ Do you want to ignore these errors for this host? %1 thumbnails generated ... 已產生縮圖 %1... + + loading thumbnail of page %1 + + UBThumbnailTextItem diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index 4e062425..b08edcef 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -358,7 +358,7 @@ void UBApplicationController::showBoard() } } - UBApplication::showMessage(tr("Drawing active scene and thumbnail previews")); + UBApplication::showMessage(tr("Board drawing...")); mMainMode = Board; adaptToolBar(); diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index a28cb35f..be5fcd62 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -777,7 +777,7 @@ void UBPersistenceManager::persistDocumentScene(UBDocumentProxy* pDocumentProxy, if (pDocumentProxy->isModified()) persistDocumentMetadata(pDocumentProxy, forceImmediateSaving); - UBApplication::showMessage(tr("saving document thumbnail for the page %1").arg(pSceneIndex+1)); + UBApplication::showMessage(tr("Saving thumbnail of page %1").arg(pSceneIndex+1)); UBThumbnailAdaptor::persistScene(pDocumentProxy, pScene, pSceneIndex); if(forceImmediateSaving) UBSvgSubsetAdaptor::persistScene(pDocumentProxy,pScene,pSceneIndex); diff --git a/src/gui/UBBoardThumbnailsView.cpp b/src/gui/UBBoardThumbnailsView.cpp index c7fa4b9b..1c512182 100644 --- a/src/gui/UBBoardThumbnailsView.cpp +++ b/src/gui/UBBoardThumbnailsView.cpp @@ -115,7 +115,7 @@ void UBBoardThumbnailsView::removeThumbnail(int i) UBDraggableThumbnailView* UBBoardThumbnailsView::createThumbnail(UBDocumentContainer* source, int i) { - UBApplication::showMessage(tr("Loading document scene (%1/%2)").arg(i+1).arg(source->selectedDocument()->pageCount())); + UBApplication::showMessage(tr("Loading page (%1/%2)").arg(i+1).arg(source->selectedDocument()->pageCount())); UBGraphicsScene* pageScene = UBPersistenceManager::persistenceManager()->loadDocumentScene(source->selectedDocument(), i); UBThumbnailView* pageView = new UBThumbnailView(pageScene); diff --git a/src/gui/UBThumbnailWidget.h b/src/gui/UBThumbnailWidget.h index 64b1bf77..887edc7e 100644 --- a/src/gui/UBThumbnailWidget.h +++ b/src/gui/UBThumbnailWidget.h @@ -210,6 +210,7 @@ class UBThumbnail class UBThumbnailTextItem : public QGraphicsTextItem { + Q_OBJECT public: UBThumbnailTextItem(int index) : QGraphicsTextItem(tr("Page %0").arg(index+1)) @@ -457,6 +458,7 @@ class UBDraggableThumbnailPixmap : public UBDraggableThumbnail class UBDraggableThumbnailView : public UBDraggableThumbnail { + Q_OBJECT public: UBDraggableThumbnailView(UBThumbnailView* thumbnailView, UBDocumentProxy* documentProxy, int index) : UBDraggableThumbnail(documentProxy, index) From 08e718f56736449ddcc24a5f9fea0574fa55797d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 19 Feb 2018 16:23:33 +0100 Subject: [PATCH 129/134] changed build version to 1.4.0-rc4 --- OpenBoard.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index 5b6f2afe..6cf509e8 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -12,7 +12,7 @@ VERSION_MAJ = 1 VERSION_MIN = 4 VERSION_PATCH = 0 VERSION_TYPE = rc # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_BUILD = 3 +VERSION_BUILD = 4 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}" From cd1b2e00870a241083619d4ca4a2cbd5e08ed8b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 19 Feb 2018 18:39:04 +0100 Subject: [PATCH 130/134] added code lost in auto-resolved conflicts during my last 'stash apply' --- src/board/UBBoardController.cpp | 6 ++---- src/core/UBPersistenceManager.cpp | 2 +- src/document/UBDocumentContainer.h | 2 +- src/document/UBDocumentController.cpp | 4 ++-- src/gui/UBThumbnailWidget.cpp | 6 ++++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index ffa576ec..082c1b0f 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -773,7 +773,7 @@ void UBBoardController::deleteScene(int nIndex) mDeletingSceneIndex = nIndex; QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); persistCurrentScene(); - showMessage(tr("Delete page %1 from document").arg(nIndex), true); + showMessage(tr("Deleting page %1").arg(nIndex+1), true); QList scIndexes; scIndexes << nIndex; @@ -783,7 +783,7 @@ void UBBoardController::deleteScene(int nIndex) if (nIndex >= pageCount()) nIndex = pageCount()-1; setActiveDocumentScene(nIndex); - showMessage(tr("Page %1 deleted").arg(nIndex)); + showMessage(tr("Page %1 deleted").arg(nIndex+1)); QApplication::restoreOverrideCursor(); mDeletingSceneIndex = -1; } @@ -1564,8 +1564,6 @@ void UBBoardController::setActiveDocumentScene(UBDocumentProxy* pDocumentProxy, setDocument(pDocumentProxy, forceReload); - persistCurrentScene(); - updateSystemScaleFactor(); mControlView->setScene(mActiveScene); diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index be5fcd62..bcd8db64 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -505,6 +505,7 @@ void UBPersistenceManager::deleteDocumentScenes(UBDocumentProxy* proxy, const QL QFile::rename(source, target); } + UBApplication::showMessage("Moving page to trash folder..."); insertDocumentSceneAt(trashDocProxy, scene, trashDocProxy->pageCount()); } } @@ -777,7 +778,6 @@ void UBPersistenceManager::persistDocumentScene(UBDocumentProxy* pDocumentProxy, if (pDocumentProxy->isModified()) persistDocumentMetadata(pDocumentProxy, forceImmediateSaving); - UBApplication::showMessage(tr("Saving thumbnail of page %1").arg(pSceneIndex+1)); UBThumbnailAdaptor::persistScene(pDocumentProxy, pScene, pSceneIndex); if(forceImmediateSaving) UBSvgSubsetAdaptor::persistScene(pDocumentProxy,pScene,pSceneIndex); diff --git a/src/document/UBDocumentContainer.h b/src/document/UBDocumentContainer.h index f47e08ea..428a2b30 100644 --- a/src/document/UBDocumentContainer.h +++ b/src/document/UBDocumentContainer.h @@ -44,7 +44,7 @@ class UBDocumentContainer : public QObject void setDocument(UBDocumentProxy* document, bool forceReload = false); UBDocumentProxy* selectedDocument(){return mCurrentDocument;} - int pageCount(){return mDocumentThumbs.size();} + int pageCount(){return mCurrentDocument->pageCount();} const QPixmap* pageAt(int index){return mDocumentThumbs[index];} static int pageFromSceneIndex(int sceneIndex); diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index 7c6b3406..f86fe466 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -168,7 +168,7 @@ void UBDocumentController::selectDocument(UBDocumentProxy* proxy, bool setAsCurr if (selected) { setDocument(proxy); - reloadThumbnails(); + emit documentThumbnailsUpdated(this); selected->setSelected(true); @@ -1441,7 +1441,7 @@ void UBDocumentController::documentSceneChanged(UBDocumentProxy* proxy, int pSce if (proxy == selectedDocumentProxy()) { - reloadThumbnails(); + emit documentThumbnailsUpdated(this); } } diff --git a/src/gui/UBThumbnailWidget.cpp b/src/gui/UBThumbnailWidget.cpp index 5d6acbaf..60755aa4 100644 --- a/src/gui/UBThumbnailWidget.cpp +++ b/src/gui/UBThumbnailWidget.cpp @@ -907,13 +907,15 @@ void UBDraggableThumbnail::mousePressEvent(QGraphicsSceneMouseEvent *event) event->accept(); duplicatePage(); } + else + { + event->ignore(); + } /* else if(movableUp() && getIcon("moveUp")->triggered(p.x())) moveUpPage(); else if (movableDown() && getIcon("moveDown")->triggered(p.x())) moveDownPage();*/ - - event->ignore(); } else { From dcf039448cb9d2ab0ec2ff9dfe287c667855303b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Mon, 19 Feb 2018 18:50:08 +0100 Subject: [PATCH 131/134] added translations --- resources/i18n/OpenBoard_ar.ts | 8 ++++++-- resources/i18n/OpenBoard_bg.ts | 8 ++++++-- resources/i18n/OpenBoard_ca.ts | 8 ++++++-- resources/i18n/OpenBoard_cs.ts | 8 ++++++-- resources/i18n/OpenBoard_da.ts | 8 ++++++-- resources/i18n/OpenBoard_de.ts | 30 +++++++++++++++++++----------- resources/i18n/OpenBoard_el.ts | 8 ++++++-- resources/i18n/OpenBoard_en.ts | 10 +++++----- resources/i18n/OpenBoard_en_UK.ts | 10 +++++----- resources/i18n/OpenBoard_es.ts | 8 ++++++-- resources/i18n/OpenBoard_fr.ts | 12 ++++++++++-- resources/i18n/OpenBoard_fr_CH.ts | 12 ++++++++++-- resources/i18n/OpenBoard_it.ts | 16 ++++++++++++---- resources/i18n/OpenBoard_iw.ts | 8 ++++++-- resources/i18n/OpenBoard_ja.ts | 10 +++++----- resources/i18n/OpenBoard_ko.ts | 8 ++++++-- resources/i18n/OpenBoard_mg.ts | 8 ++++++-- resources/i18n/OpenBoard_nb.ts | 8 ++++++-- resources/i18n/OpenBoard_nl.ts | 10 +++++----- resources/i18n/OpenBoard_pl.ts | 8 ++++++-- resources/i18n/OpenBoard_pt.ts | 8 ++++++-- resources/i18n/OpenBoard_ro.ts | 8 ++++++-- resources/i18n/OpenBoard_ru.ts | 8 ++++++-- resources/i18n/OpenBoard_sk.ts | 8 ++++++-- resources/i18n/OpenBoard_sv.ts | 8 ++++++-- resources/i18n/OpenBoard_tr.ts | 8 ++++++-- resources/i18n/OpenBoard_zh.ts | 8 ++++++-- resources/i18n/OpenBoard_zh_CN.ts | 8 ++++++-- resources/i18n/OpenBoard_zh_TW.ts | 8 ++++++-- src/core/UBPersistenceManager.cpp | 2 +- 30 files changed, 198 insertions(+), 82 deletions(-) diff --git a/resources/i18n/OpenBoard_ar.ts b/resources/i18n/OpenBoard_ar.ts index e522fd59..799c03ed 100644 --- a/resources/i18n/OpenBoard_ar.ts +++ b/resources/i18n/OpenBoard_ar.ts @@ -942,7 +942,7 @@ Delete page %1 from document - إزالة صفحة%1 من الوثيقة + إزالة صفحة%1 من الوثيقة Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1817,7 +1821,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_bg.ts b/resources/i18n/OpenBoard_bg.ts index fa3812dc..7bde5b29 100644 --- a/resources/i18n/OpenBoard_bg.ts +++ b/resources/i18n/OpenBoard_bg.ts @@ -942,7 +942,7 @@ Delete page %1 from document - Изтрий страница %1 от документа + Изтрий страница %1 от документа Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1815,7 +1819,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_ca.ts b/resources/i18n/OpenBoard_ca.ts index afef7740..b5751001 100644 --- a/resources/i18n/OpenBoard_ca.ts +++ b/resources/i18n/OpenBoard_ca.ts @@ -942,7 +942,7 @@ Delete page %1 from document - Elimina la pàgina %1 del document + Elimina la pàgina %1 del document Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1814,7 +1818,7 @@ Voleu ignorar aquests errors per a aquest amfitrió? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_cs.ts b/resources/i18n/OpenBoard_cs.ts index 1617c60d..dca8766a 100644 --- a/resources/i18n/OpenBoard_cs.ts +++ b/resources/i18n/OpenBoard_cs.ts @@ -943,7 +943,7 @@ Delete page %1 from document - Odstranit stránku %1 z dokumentu + Odstranit stránku %1 z dokumentu Page %1 deleted @@ -969,6 +969,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1817,7 +1821,7 @@ Chcete ignorovat tyto chyby na tomto serveru? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_da.ts b/resources/i18n/OpenBoard_da.ts index cea4f1ec..f043b446 100644 --- a/resources/i18n/OpenBoard_da.ts +++ b/resources/i18n/OpenBoard_da.ts @@ -942,7 +942,7 @@ Delete page %1 from document - Slet side %1 fra dokumentet + Slet side %1 fra dokumentet Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1814,7 +1818,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_de.ts b/resources/i18n/OpenBoard_de.ts index 90f163dd..ac5702cc 100644 --- a/resources/i18n/OpenBoard_de.ts +++ b/resources/i18n/OpenBoard_de.ts @@ -942,7 +942,7 @@ Delete page %1 from document - Seite %1 des Dokuments löschen + Seite %1 des Dokuments löschen Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... Dokument wurde gespeichert... + + Deleting page %1 + Seite %1 löschen + UBBoardPaletteManager @@ -1269,19 +1273,19 @@ UBExportAdaptor Warnings during export was appeared - Warnungen beim Exportieren aufgetreten + Warnungen beim Exportieren aufgetreten Exporting document... - Dokument wird exportiert... + Dokument wird exportiert... Export failed - Export fehlgeschlagen + Export fehlgeschlagen Unable to export to the selected location. You do not have the permissions necessary to save the file. - Export im ausgewählten Zielpfad nicht möglich. Sie haben nicht die erforderliche Berechtigung um die Datei zu speichern. + Export im ausgewählten Zielpfad nicht möglich. Sie haben nicht die erforderliche Berechtigung um die Datei zu speichern. Export failed: location not writable @@ -1289,7 +1293,7 @@ Export successful. - Export erfolgreich. + Export erfolgreich. @@ -1812,7 +1816,7 @@ Möchten Sie diese Fehler für diesen Computer ignorieren? Cancel - Abbrechen + Abbrechen Proceed @@ -1843,7 +1847,11 @@ Möchten Sie diese Fehler für diesen Computer ignorieren? Saving thumbnail of page %1 - Miniaturansicht der Seite %1 speichern + Miniaturansicht der Seite %1 speichern + + + Moving page to trash folder... + Die Seite in den Papierkorb verschieben... @@ -1929,7 +1937,7 @@ Möchten Sie diese Fehler für diesen Computer ignorieren? OpenBoard Cast - + OpenBoard Cast @@ -1988,7 +1996,7 @@ Möchten Sie diese Fehler für diesen Computer ignorieren? UBStartupHintsPalette Visible next time - + Sichtbar beim nächsten Mal @@ -2458,7 +2466,7 @@ p, li { white-space: pre-wrap; } OpenBoard - OpenBoard + OpenBoard diff --git a/resources/i18n/OpenBoard_el.ts b/resources/i18n/OpenBoard_el.ts index 19ea8028..d5592f3d 100644 --- a/resources/i18n/OpenBoard_el.ts +++ b/resources/i18n/OpenBoard_el.ts @@ -942,7 +942,7 @@ Delete page %1 from document - Διαγραφή της σελιδας %1 από το έγγραφο + Διαγραφή της σελιδας %1 από το έγγραφο Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1814,7 +1818,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_en.ts b/resources/i18n/OpenBoard_en.ts index 0d2c94cd..da2fb299 100644 --- a/resources/i18n/OpenBoard_en.ts +++ b/resources/i18n/OpenBoard_en.ts @@ -932,10 +932,6 @@ Unknown content type %1 - - Delete page %1 from document - - Page %1 deleted @@ -960,6 +956,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1717,7 +1717,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_en_UK.ts b/resources/i18n/OpenBoard_en_UK.ts index 4b6f86a8..77024a0e 100644 --- a/resources/i18n/OpenBoard_en_UK.ts +++ b/resources/i18n/OpenBoard_en_UK.ts @@ -932,10 +932,6 @@ All Supported (%1) - - Delete page %1 from document - - Page %1 deleted @@ -960,6 +956,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1717,7 +1717,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_es.ts b/resources/i18n/OpenBoard_es.ts index edf1e0ca..dc4a675c 100644 --- a/resources/i18n/OpenBoard_es.ts +++ b/resources/i18n/OpenBoard_es.ts @@ -942,7 +942,7 @@ Delete page %1 from document - Borrar la página %1 del documento + Borrar la página %1 del documento Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1808,7 +1812,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_fr.ts b/resources/i18n/OpenBoard_fr.ts index 456d505e..15a12773 100644 --- a/resources/i18n/OpenBoard_fr.ts +++ b/resources/i18n/OpenBoard_fr.ts @@ -947,7 +947,7 @@ Delete page %1 from document - Supprimer la page %1 du document + Supprimer la page %1 du document Page %1 deleted @@ -973,6 +973,10 @@ Document has just been saved... Le document vient d'être sauvegardé... + + Deleting page %1 + Supression de la page %1 + UBBoardPaletteManager @@ -1856,7 +1860,11 @@ Voulez-vous ignorer les erreurs pour ce serveur ? Saving thumbnail of page %1 - Sauvegarde aperçu page %1 + Sauvegarde aperçu page %1 + + + Moving page to trash folder... + Déplacement de la page dans la corbeille... diff --git a/resources/i18n/OpenBoard_fr_CH.ts b/resources/i18n/OpenBoard_fr_CH.ts index 2cd3a5ba..e69ec1d0 100644 --- a/resources/i18n/OpenBoard_fr_CH.ts +++ b/resources/i18n/OpenBoard_fr_CH.ts @@ -947,7 +947,7 @@ Delete page %1 from document - Supprimer la page %1 du document + Supprimer la page %1 du document Page %1 deleted @@ -973,6 +973,10 @@ Document has just been saved... Le document vient d'être sauvegardé... + + Deleting page %1 + Supression de la page %1 + UBBoardPaletteManager @@ -1856,7 +1860,11 @@ Voulez-vous ignorer les erreurs pour ce serveur ? Saving thumbnail of page %1 - Sauvegarde aperçu page %1 + Sauvegarde aperçu page %1 + + + Moving page to trash folder... + Déplacement de la page dans la corbeille... diff --git a/resources/i18n/OpenBoard_it.ts b/resources/i18n/OpenBoard_it.ts index a1e249c7..98dde0df 100644 --- a/resources/i18n/OpenBoard_it.ts +++ b/resources/i18n/OpenBoard_it.ts @@ -942,7 +942,7 @@ Delete page %1 from document - Rimuovi pagina %1 dal documento + Rimuovi pagina %1 dal documento Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... Il documento è stato appena salvato... + + Deleting page %1 + eliminazione della pagina %1 + UBBoardPaletteManager @@ -1273,11 +1277,11 @@ Exporting document... - Esportazione documento in corso... + Esportazione documento in corso... Export failed - Esportazione fallita + Esportazione fallita Unable to export to the selected location. You do not have the permissions necessary to save the file. @@ -1839,7 +1843,11 @@ Vuoi ignorare gli errori per questo host? Saving thumbnail of page %1 - Salvataggio della miniatura della pagina %1 + Salvataggio della miniatura della pagina %1 + + + Moving page to trash folder... + Spostamento della pagina nella cartella del cestino... diff --git a/resources/i18n/OpenBoard_iw.ts b/resources/i18n/OpenBoard_iw.ts index 45101bd2..7b1f382c 100644 --- a/resources/i18n/OpenBoard_iw.ts +++ b/resources/i18n/OpenBoard_iw.ts @@ -943,7 +943,7 @@ Delete page %1 from document - מחק עמוד %1 מהמסמך + מחק עמוד %1 מהמסמך Page %1 deleted @@ -969,6 +969,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1811,7 +1815,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_ja.ts b/resources/i18n/OpenBoard_ja.ts index 37888ee6..fa5d596f 100644 --- a/resources/i18n/OpenBoard_ja.ts +++ b/resources/i18n/OpenBoard_ja.ts @@ -940,10 +940,6 @@ Ungroup - - Delete page %1 from document - - Page %1 deleted @@ -960,6 +956,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1805,7 +1805,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_ko.ts b/resources/i18n/OpenBoard_ko.ts index e90acdaf..6e7e8575 100644 --- a/resources/i18n/OpenBoard_ko.ts +++ b/resources/i18n/OpenBoard_ko.ts @@ -942,7 +942,7 @@ Delete page %1 from document - 문서에서 %1페이지 삭제 + 문서에서 %1페이지 삭제 Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1815,7 +1819,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_mg.ts b/resources/i18n/OpenBoard_mg.ts index c02aaa7b..eec1f0ed 100644 --- a/resources/i18n/OpenBoard_mg.ts +++ b/resources/i18n/OpenBoard_mg.ts @@ -942,7 +942,7 @@ Delete page %1 from document - Fafao ny pejy %1 amin'ilay rakitra + Fafao ny pejy %1 amin'ilay rakitra Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1814,7 +1818,7 @@ Tena tsy te hiraharaha an'ireo tsy mety ho an'ilay milina ve ianao? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_nb.ts b/resources/i18n/OpenBoard_nb.ts index 1a6dfbdf..1a883288 100644 --- a/resources/i18n/OpenBoard_nb.ts +++ b/resources/i18n/OpenBoard_nb.ts @@ -942,7 +942,7 @@ Delete page %1 from document - Slett side %1 fra dokument + Slett side %1 fra dokument Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1810,7 +1814,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_nl.ts b/resources/i18n/OpenBoard_nl.ts index 87a95506..ccbd4741 100644 --- a/resources/i18n/OpenBoard_nl.ts +++ b/resources/i18n/OpenBoard_nl.ts @@ -932,10 +932,6 @@ All Supported (%1) Alle ondersteunden (%1) - - Delete page %1 from document - - Page %1 deleted @@ -960,6 +956,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1800,7 +1800,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_pl.ts b/resources/i18n/OpenBoard_pl.ts index 2b8b8ebb..c059c784 100644 --- a/resources/i18n/OpenBoard_pl.ts +++ b/resources/i18n/OpenBoard_pl.ts @@ -946,7 +946,7 @@ Delete page %1 from document - Usuń stronę %1 z dokumentu + Usuń stronę %1 z dokumentu Page %1 deleted @@ -972,6 +972,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1821,7 +1825,7 @@ Czy chcesz ignorować te błędy dla tego hosta? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_pt.ts b/resources/i18n/OpenBoard_pt.ts index e26e9bb1..46439908 100644 --- a/resources/i18n/OpenBoard_pt.ts +++ b/resources/i18n/OpenBoard_pt.ts @@ -944,7 +944,7 @@ Delete page %1 from document - Apagar a página %1 do documento + Apagar a página %1 do documento Page %1 deleted @@ -970,6 +970,10 @@ Document has just been saved... Documento acaba de ser gravado... + + Deleting page %1 + + UBBoardPaletteManager @@ -1841,7 +1845,7 @@ Quer ignorar estes erros, deste servidor? Acesso ao repositório '%1' foi perdido. Infelizmente a aplicação deverá desligar para avitar a corrupção de dados. As últimas alterações também serão perdidas. - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_ro.ts b/resources/i18n/OpenBoard_ro.ts index d15c5d93..f7039047 100644 --- a/resources/i18n/OpenBoard_ro.ts +++ b/resources/i18n/OpenBoard_ro.ts @@ -942,7 +942,7 @@ Delete page %1 from document - Ștergere pagina %1 din document + Ștergere pagina %1 din document Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1814,7 +1818,7 @@ Doriţi să ignoraţi aceste erori pentru acest host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_ru.ts b/resources/i18n/OpenBoard_ru.ts index 6f85864c..1e023a35 100644 --- a/resources/i18n/OpenBoard_ru.ts +++ b/resources/i18n/OpenBoard_ru.ts @@ -942,7 +942,7 @@ Delete page %1 from document - Удалить страницу %1 из документа + Удалить страницу %1 из документа Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1814,7 +1818,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_sk.ts b/resources/i18n/OpenBoard_sk.ts index 29c50d7c..3b1597f7 100644 --- a/resources/i18n/OpenBoard_sk.ts +++ b/resources/i18n/OpenBoard_sk.ts @@ -946,7 +946,7 @@ Delete page %1 from document - Vymazať stránku %1 z dokumentu + Vymazať stránku %1 z dokumentu Page %1 deleted @@ -972,6 +972,10 @@ Document has just been saved... Dokument bol uložený. + + Deleting page %1 + + UBBoardPaletteManager @@ -1844,7 +1848,7 @@ Chcete ignorovať tieto chyby na tomto serveri? stratil prístup k úložisku dokumentov '%1'. Aplikácia sa musí zatvoriť, aby sa predišlo poškodeniu dát. Možno nebudú uložené ani najnovšie zmeny. - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_sv.ts b/resources/i18n/OpenBoard_sv.ts index 4f3869a4..b36e36b9 100644 --- a/resources/i18n/OpenBoard_sv.ts +++ b/resources/i18n/OpenBoard_sv.ts @@ -942,7 +942,7 @@ Delete page %1 from document - Radera sida %1 från dokument + Radera sida %1 från dokument Page %1 deleted @@ -969,6 +969,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1815,7 +1819,7 @@ Vill du ignorera felen för den här värden? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_tr.ts b/resources/i18n/OpenBoard_tr.ts index 5fbc25a5..963f341e 100644 --- a/resources/i18n/OpenBoard_tr.ts +++ b/resources/i18n/OpenBoard_tr.ts @@ -942,7 +942,7 @@ Delete page %1 from document - %1 Sayfayı dökümandan sil + %1 Sayfayı dökümandan sil Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1812,7 +1816,7 @@ Bu host için yukarıdaki hatalar yok sayılsın mı? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_zh.ts b/resources/i18n/OpenBoard_zh.ts index cc8f79fe..80444d6c 100644 --- a/resources/i18n/OpenBoard_zh.ts +++ b/resources/i18n/OpenBoard_zh.ts @@ -942,7 +942,7 @@ Delete page %1 from document - 删除文件的%1页 + 删除文件的%1页 Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1812,7 +1816,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_zh_CN.ts b/resources/i18n/OpenBoard_zh_CN.ts index cc8f79fe..80444d6c 100644 --- a/resources/i18n/OpenBoard_zh_CN.ts +++ b/resources/i18n/OpenBoard_zh_CN.ts @@ -942,7 +942,7 @@ Delete page %1 from document - 删除文件的%1页 + 删除文件的%1页 Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1812,7 +1816,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/resources/i18n/OpenBoard_zh_TW.ts b/resources/i18n/OpenBoard_zh_TW.ts index 22c9fd4f..5f84109a 100644 --- a/resources/i18n/OpenBoard_zh_TW.ts +++ b/resources/i18n/OpenBoard_zh_TW.ts @@ -942,7 +942,7 @@ Delete page %1 from document - 刪除文件的第 %1 頁 + 刪除文件的第 %1 頁 Page %1 deleted @@ -968,6 +968,10 @@ Document has just been saved... + + Deleting page %1 + + UBBoardPaletteManager @@ -1806,7 +1810,7 @@ Do you want to ignore these errors for this host? - Saving thumbnail of page %1 + Moving page to trash folder... diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index bcd8db64..e579f111 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -505,7 +505,7 @@ void UBPersistenceManager::deleteDocumentScenes(UBDocumentProxy* proxy, const QL QFile::rename(source, target); } - UBApplication::showMessage("Moving page to trash folder..."); + UBApplication::showMessage(tr("Moving page to trash folder...")); insertDocumentSceneAt(trashDocProxy, scene, trashDocProxy->pageCount()); } } From 3860e97b49a9861df722d631d665362d9a934ccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Wed, 14 Mar 2018 17:21:45 +0100 Subject: [PATCH 132/134] 1.4 release without real time previews on left palette --- resources/style.qss | 1 + src/adaptors/UBThumbnailAdaptor.cpp | 1 - src/board/UBBoardController.cpp | 1 + src/core/UBApplicationController.cpp | 1 - src/core/UBPersistenceManager.cpp | 2 +- src/document/UBDocumentContainer.cpp | 3 +- src/document/UBDocumentController.cpp | 26 +- src/gui/UBDocumentNavigator.cpp | 442 ++++++++++++++++++++++++++ src/gui/UBDocumentNavigator.h | 108 +++++++ src/gui/UBDocumentThumbnailWidget.cpp | 8 +- src/gui/UBMessageWindow.cpp | 1 + src/gui/UBPageNavigationWidget.cpp | 2 +- src/gui/UBPageNavigationWidget.h | 3 +- src/gui/UBThumbnailWidget.cpp | 154 ++++++++- src/gui/UBThumbnailWidget.h | 176 +++++++--- src/gui/gui.pri | 6 +- 16 files changed, 858 insertions(+), 77 deletions(-) create mode 100644 src/gui/UBDocumentNavigator.cpp create mode 100644 src/gui/UBDocumentNavigator.h diff --git a/resources/style.qss b/resources/style.qss index 92bd8d6b..a877c11b 100644 --- a/resources/style.qss +++ b/resources/style.qss @@ -1,4 +1,5 @@ QWidget#DockPaletteWidgetBox, +QWidget#documentNavigator, QWidget#UBBoardThumbnailsView, QWidget#UBLibPathViewer, QWidget#UBLibNavigatorWidget, diff --git a/src/adaptors/UBThumbnailAdaptor.cpp b/src/adaptors/UBThumbnailAdaptor.cpp index 3d87e123..b0b6a141 100644 --- a/src/adaptors/UBThumbnailAdaptor.cpp +++ b/src/adaptors/UBThumbnailAdaptor.cpp @@ -85,7 +85,6 @@ void UBThumbnailAdaptor::generateMissingThumbnails(UBDocumentProxy* proxy) const QPixmap* UBThumbnailAdaptor::get(UBDocumentProxy* proxy, int pageIndex) { - UBApplication::showMessage(tr("loading thumbnail of page %1").arg(pageIndex + 1)); QString fileName = proxy->persistencePath() + UBFileSystemUtils::digitFileFormat("/page%1.thumbnail.jpg", pageIndex); QFile file(fileName); diff --git a/src/board/UBBoardController.cpp b/src/board/UBBoardController.cpp index 082c1b0f..e9ba86c1 100644 --- a/src/board/UBBoardController.cpp +++ b/src/board/UBBoardController.cpp @@ -1994,6 +1994,7 @@ void UBBoardController::persistCurrentScene(bool isAnAutomaticBackup, bool force && (mActiveScene->isModified())) { UBPersistenceManager::persistenceManager()->persistDocumentScene(selectedDocument(), mActiveScene, mActiveSceneIndex, isAnAutomaticBackup,forceImmediateSave); + updatePage(mActiveSceneIndex); } } diff --git a/src/core/UBApplicationController.cpp b/src/core/UBApplicationController.cpp index b08edcef..d8bdc89f 100644 --- a/src/core/UBApplicationController.cpp +++ b/src/core/UBApplicationController.cpp @@ -358,7 +358,6 @@ void UBApplicationController::showBoard() } } - UBApplication::showMessage(tr("Board drawing...")); mMainMode = Board; adaptToolBar(); diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp index e579f111..4f3f9704 100644 --- a/src/core/UBPersistenceManager.cpp +++ b/src/core/UBPersistenceManager.cpp @@ -183,7 +183,7 @@ void UBPersistenceManager::onSceneLoaded(QByteArray scene, UBDocumentProxy* prox qDebug() << "scene loaded " << sceneIndex; QTime time; time.start(); - mSceneCache.insert(proxy, sceneIndex, loadDocumentScene(proxy, sceneIndex)); + mSceneCache.insert(proxy, sceneIndex, loadDocumentScene(proxy, sceneIndex, false)); qDebug() << "millisecond for sceneCache " << time.elapsed(); } diff --git a/src/document/UBDocumentContainer.cpp b/src/document/UBDocumentContainer.cpp index 2d30f607..7af9e433 100644 --- a/src/document/UBDocumentContainer.cpp +++ b/src/document/UBDocumentContainer.cpp @@ -52,7 +52,7 @@ void UBDocumentContainer::setDocument(UBDocumentProxy* document, bool forceReloa { mCurrentDocument = document; - emit initThumbnailsRequired(this); + reloadThumbnails(); emit documentSet(mCurrentDocument); } } @@ -130,6 +130,7 @@ void UBDocumentContainer::deleteThumbPage(int index) void UBDocumentContainer::updateThumbPage(int index) { mDocumentThumbs[index] = UBThumbnailAdaptor::get(mCurrentDocument, index); + emit documentPageUpdated(index); } void UBDocumentContainer::insertThumbPage(int index) diff --git a/src/document/UBDocumentController.cpp b/src/document/UBDocumentController.cpp index f86fe466..47eeee22 100644 --- a/src/document/UBDocumentController.cpp +++ b/src/document/UBDocumentController.cpp @@ -468,11 +468,11 @@ void UBDocumentController::openSelectedItem() if (selectedItems.count() > 0) { - UBThumbnailPixmap* thumb = dynamic_cast (selectedItems.last()); + UBSceneThumbnailPixmap* thumb = dynamic_cast (selectedItems.last()); if (thumb) { - UBDocumentProxy* proxy = thumb->documentProxy(); + UBDocumentProxy* proxy = thumb->proxy(); if (proxy && isOKToOpenDocument(proxy)) { @@ -505,10 +505,10 @@ void UBDocumentController::duplicateSelectedItem() QList selectedSceneIndexes; foreach (QGraphicsItem *item, selectedItems) { - UBThumbnailPixmap *thumb = dynamic_cast(item); + UBSceneThumbnailPixmap *thumb = dynamic_cast(item); if (thumb) { - UBDocumentProxy *proxy = thumb->documentProxy(); + UBDocumentProxy *proxy = thumb->proxy(); if (proxy) { @@ -1366,7 +1366,7 @@ void UBDocumentController::selectionChanged() mMainWindow->actionDuplicate->setEnabled(!trashSelected); else{ for(int i = 0; i < selection.count() && !firstSceneSelected; i += 1){ - if(dynamic_cast(selection.at(i))->sceneIndex() == 0){ + if(dynamic_cast(selection.at(i))->sceneIndex() == 0){ mMainWindow->actionDuplicate->setEnabled(!trashSelected); firstSceneSelected = true; } @@ -1516,11 +1516,11 @@ void UBDocumentController::addToDocument() foreach (QGraphicsItem* item, selectedItems) { - UBThumbnailPixmap* thumb = dynamic_cast (item); + UBSceneThumbnailPixmap* thumb = dynamic_cast (item); - if (thumb && thumb->documentProxy()) + if (thumb && thumb->proxy()) { - QPair pageInfo(thumb->documentProxy(), thumb->sceneIndex()); + QPair pageInfo(thumb->proxy(), thumb->sceneIndex()); pageInfoList << pageInfo; } } @@ -1809,11 +1809,11 @@ void UBDocumentController::deletePages(QList itemsToDelete) foreach (QGraphicsItem* item, itemsToDelete) { - UBThumbnailPixmap* thumb = dynamic_cast (item); + UBSceneThumbnailPixmap* thumb = dynamic_cast (item); if (thumb) { - proxy = thumb->documentProxy(); + proxy = thumb->proxy(); if (proxy) { sceneIndexes.append(thumb->sceneIndex()); @@ -1843,7 +1843,7 @@ int UBDocumentController::getSelectedItemIndex() if (selectedItems.count() > 0) { - UBThumbnailPixmap* thumb = dynamic_cast (selectedItems.last()); + UBSceneThumbnailPixmap* thumb = dynamic_cast (selectedItems.last()); return thumb->sceneIndex(); } else return -1; @@ -1872,7 +1872,7 @@ void UBDocumentController::refreshDocumentThumbnailsView(UBDocumentContainer*) for (int i = 0; i < selectedDocument()->pageCount(); i++) { const QPixmap* pix = pageAt(i); - QGraphicsPixmapItem *pixmapItem = new UBThumbnailPixmap(*pix, proxy, i); // deleted by the tree widget + QGraphicsPixmapItem *pixmapItem = new UBSceneThumbnailPixmap(*pix, proxy, i); // deleted by the tree widget if (proxy == mBoardController->selectedDocument() && mBoardController->activeSceneIndex() == i) { @@ -1899,7 +1899,7 @@ void UBDocumentController::refreshDocumentThumbnailsView(UBDocumentContainer*) if (selection) { disconnect(mDocumentUI->thumbnailWidget->scene(), SIGNAL(selectionChanged()), this, SLOT(pageSelectionChanged())); - UBThumbnailPixmap *currentScene = dynamic_cast(selection); + UBSceneThumbnailPixmap *currentScene = dynamic_cast(selection); if (currentScene) mDocumentUI->thumbnailWidget->hightlightItem(currentScene->sceneIndex()); connect(mDocumentUI->thumbnailWidget->scene(), SIGNAL(selectionChanged()), this, SLOT(pageSelectionChanged())); diff --git a/src/gui/UBDocumentNavigator.cpp b/src/gui/UBDocumentNavigator.cpp new file mode 100644 index 00000000..7dc1564c --- /dev/null +++ b/src/gui/UBDocumentNavigator.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM) + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include "core/UBApplication.h" +#include "UBDocumentNavigator.h" +#include "board/UBBoardController.h" +#include "adaptors/UBThumbnailAdaptor.h" +#include "adaptors/UBSvgSubsetAdaptor.h" +#include "document/UBDocumentController.h" +#include "domain/UBGraphicsScene.h" +#include "board/UBBoardPaletteManager.h" +#include "core/UBApplicationController.h" + +#include "core/memcheck.h" + +/** + * \brief Constructor + * @param parent as the parent widget + * @param name as the object name + */ +UBDocumentNavigator::UBDocumentNavigator(QWidget *parent, const char *name):QGraphicsView(parent) + , mScene(NULL) + , mNbColumns(1) + , mThumbnailWidth(0) + , mThumbnailMinWidth(100) + , mSelectedThumbnail(NULL) + , mDropSource(NULL) + , mDropTarget(NULL) + , mDropBar(new QGraphicsRectItem()) + , mLongPressInterval(350) +{ + setObjectName(name); + mScene = new QGraphicsScene(this); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setScene(mScene); + mThumbnailWidth = width() - 2*border(); + + mDropBar->setPen(QPen(Qt::darkGray)); + mDropBar->setBrush(QBrush(Qt::lightGray)); + scene()->addItem(mDropBar); + mDropBar->hide(); + + mLongPressTimer.setInterval(mLongPressInterval); + mLongPressTimer.setSingleShot(true); + + setFrameShadow(QFrame::Plain); + + connect(UBApplication::boardController, SIGNAL(documentThumbnailsUpdated(UBDocumentContainer*)), this, SLOT(generateThumbnails(UBDocumentContainer*))); + connect(UBApplication::boardController, SIGNAL(documentPageUpdated(int)), this, SLOT(updateSpecificThumbnail(int))); + connect(UBApplication::boardController, SIGNAL(pageSelectionChanged(int)), this, SLOT(onScrollToSelectedPage(int))); + + connect(&mLongPressTimer, SIGNAL(timeout()), this, SLOT(longPressTimeout()), Qt::UniqueConnection); + + connect(this, SIGNAL(mousePressAndHoldEventRequired(QPoint)), this, SLOT(mousePressAndHoldEvent(QPoint)), Qt::UniqueConnection); +} + +/** + * \brief Destructor + */ +UBDocumentNavigator::~UBDocumentNavigator() +{ + if(NULL != mScene) + { + delete mScene; + mScene = NULL; + } +} + +/** + * \brief Generate the thumbnails + */ +void UBDocumentNavigator::generateThumbnails(UBDocumentContainer* source) +{ + mThumbsWithLabels.clear(); + int selectedIndex = -1; + QList graphicsItemList = mScene->items(); + for(int i = 0; i < graphicsItemList.size(); i+=1) + { + QGraphicsItem* item = graphicsItemList.at(i); + if(item->isSelected()) + selectedIndex = i; + + if (item != mDropBar) + { + mScene->removeItem(item); + delete item; + item = NULL; + } + } + + for(int i = 0; i < source->selectedDocument()->pageCount(); i++) + { + //claudio This is a very bad hack and shows a architectural problem + // source->selectedDocument()->pageCount() != source->pageCount() + if(i>=source->pageCount() || source->pageAt(i)->isNull()) + source->insertThumbPage(i); + + const QPixmap* pix = source->pageAt(i); + Q_ASSERT(!pix->isNull()); + int pageIndex = UBDocumentContainer::pageFromSceneIndex(i); + + UBSceneThumbnailNavigPixmap* pixmapItem = new UBSceneThumbnailNavigPixmap(*pix, source->selectedDocument(), i); + + QString label = tr("Page %0").arg(pageIndex); + UBThumbnailTextItem *labelItem = new UBThumbnailTextItem(label); + + UBImgTextThumbnailElement thumbWithText(pixmapItem, labelItem); + thumbWithText.setBorder(border()); + mThumbsWithLabels.append(thumbWithText); + + mScene->addItem(pixmapItem); + mScene->addItem(labelItem); + } + + if (selectedIndex >= 0 && selectedIndex < mThumbsWithLabels.count()) + mSelectedThumbnail = mThumbsWithLabels.at(selectedIndex).getThumbnail(); + else + mSelectedThumbnail = NULL; + + // Draw the items + refreshScene(); +} + +void UBDocumentNavigator::onScrollToSelectedPage(int index) +{ + int c = 0; + foreach(UBImgTextThumbnailElement el, mThumbsWithLabels) + { + if (c==index) + { + el.getThumbnail()->setSelected(true); + mSelectedThumbnail = el.getThumbnail(); + } + else + { + el.getThumbnail()->setSelected(false); + } + c++; + } + if(NULL != mSelectedThumbnail) + centerOn(mSelectedThumbnail); +} + +/** + * \brief Refresh the given thumbnail + * @param iPage as the given page related thumbnail + */ +void UBDocumentNavigator::updateSpecificThumbnail(int iPage) +{ + const QPixmap* pix = UBApplication::boardController->pageAt(iPage); + UBSceneThumbnailNavigPixmap* newItem = new UBSceneThumbnailNavigPixmap(*pix, UBApplication::boardController->selectedDocument(), iPage); + + // Get the old thumbnail + UBSceneThumbnailNavigPixmap* oldItem = mThumbsWithLabels.at(iPage).getThumbnail(); + if(NULL != oldItem) + { + mScene->removeItem(oldItem); + mScene->addItem(newItem); + mThumbsWithLabels[iPage].setThumbnail(newItem); + delete oldItem; + oldItem = NULL; + } + +} + +/** + * \brief Put the element in the right place in the scene. + */ +void UBDocumentNavigator::refreshScene() +{ + qreal thumbnailHeight = mThumbnailWidth / UBSettings::minScreenRatio; + + for(int i = 0; i < mThumbsWithLabels.size(); i++) + { + // Get the item + UBImgTextThumbnailElement& item = mThumbsWithLabels[i]; + int columnIndex = i % mNbColumns; + int rowIndex = i / mNbColumns; + item.Place(rowIndex, columnIndex, mThumbnailWidth, thumbnailHeight); + } + scene()->setSceneRect(scene()->itemsBoundingRect()); +} + +/** + * \brief Set the number of thumbnails columns + * @param nbColumns as the number of columns + */ +void UBDocumentNavigator::setNbColumns(int nbColumns) +{ + mNbColumns = nbColumns; +} + +/** + * \brief Get the number of columns + * @return the number of thumbnails columns + */ +int UBDocumentNavigator::nbColumns() +{ + return mNbColumns; +} + +/** + * \brief Set the thumbnails minimum width + * @param width as the minimum width + */ +void UBDocumentNavigator::setThumbnailMinWidth(int width) +{ + mThumbnailMinWidth = width; +} + +/** + * \brief Get the thumbnails minimum width + * @return the minimum thumbnails width + */ +int UBDocumentNavigator::thumbnailMinWidth() +{ + return mThumbnailMinWidth; +} + +/** + * \brief Get the border size + * @return the border size in pixels + */ +int UBDocumentNavigator::border() +{ + return 20; +} + +/** + * \brief Handle the resize event + * @param event as the resize event + */ +void UBDocumentNavigator::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + + // Update the thumbnails width + mThumbnailWidth = (width() > mThumbnailMinWidth) ? width() - 2*border() : mThumbnailMinWidth; + + if(mSelectedThumbnail) + centerOn(mSelectedThumbnail); + + // Refresh the scene + refreshScene(); +} + +/** + * \brief Handle the mouse press event + * @param event as the mouse event + */ +void UBDocumentNavigator::mousePressEvent(QMouseEvent *event) +{ + mLongPressTimer.start(); + mLastPressedMousePos = event->pos(); + + QGraphicsItem* pClickedItem = itemAt(event->pos()); + if(NULL != pClickedItem) + { + + // First, select the clicked item + UBSceneThumbnailNavigPixmap* pCrntItem = dynamic_cast(pClickedItem); + + if(NULL == pCrntItem) + { + // If we fall here we may have clicked on the label instead of the thumbnail + UBThumbnailTextItem* pTextItem = dynamic_cast(pClickedItem); + if(NULL != pTextItem) + { + for(int i = 0; i < mThumbsWithLabels.size(); i++) + { + const UBImgTextThumbnailElement& el = mThumbsWithLabels.at(i); + if(el.getCaption() == pTextItem) + { + pCrntItem = el.getThumbnail(); + break; + } + } + } + } + + int index = 0; + for(int i = 0; i < mThumbsWithLabels.size(); i++) + { + if (mThumbsWithLabels.at(i).getThumbnail() == pCrntItem) + { + mSelectedThumbnail = pCrntItem; + index = i; + break; + } + } + UBApplication::boardController->persistViewPositionOnCurrentScene(); + UBApplication::boardController->persistCurrentScene(); + UBApplication::boardController->setActiveDocumentScene(index); + UBApplication::boardController->centerOn(UBApplication::boardController->activeScene()->lastCenter()); + } + QGraphicsView::mousePressEvent(event); +} + +void UBDocumentNavigator::mouseReleaseEvent(QMouseEvent *event) +{ + event->accept(); +} + +void UBDocumentNavigator::longPressTimeout() +{ + if (QApplication::mouseButtons() != Qt::NoButton) + emit mousePressAndHoldEventRequired(mLastPressedMousePos); + + mLongPressTimer.stop(); +} + +void UBDocumentNavigator::mousePressAndHoldEvent(QPoint pos) +{ + UBSceneThumbnailNavigPixmap* item = dynamic_cast(itemAt(pos)); + if (item) + { + mDropSource = item; + mDropTarget = item; + + QPixmap pixmap = item->pixmap().scaledToWidth(mThumbnailWidth/2); + + QDrag *drag = new QDrag(this); + drag->setMimeData(new QMimeData()); + drag->setPixmap(pixmap); + drag->setHotSpot(QPoint(pixmap.width()/2, pixmap.height()/2)); + + drag->exec(); + } +} + +void UBDocumentNavigator::dragEnterEvent(QDragEnterEvent *event) +{ + mDropBar->show(); + + if (event->source() == this) + { + event->setDropAction(Qt::MoveAction); + event->accept(); + } + else + { + event->acceptProposedAction(); + } +} + +void UBDocumentNavigator::dragMoveEvent(QDragMoveEvent *event) +{ + QPointF position = event->pos(); + + //autoscroll during drag'n'drop + QPointF scenePos = mapToScene(position.toPoint()); + int thumbnailHeight = mThumbnailWidth / UBSettings::minScreenRatio; + QRectF thumbnailArea(0, scenePos.y() - thumbnailHeight/2, mThumbnailWidth, thumbnailHeight); + + ensureVisible(thumbnailArea); + + UBSceneThumbnailNavigPixmap* item = dynamic_cast(itemAt(position.toPoint())); + if (item) + { + if (item != mDropTarget) + mDropTarget = item; + + qreal scale = item->transform().m11(); + + QPointF itemCenter(item->pos().x() + (item->boundingRect().width()-verticalScrollBar()->width()) * scale, + item->pos().y() + item->boundingRect().height() * scale / 2); + + bool dropAbove = mapToScene(position.toPoint()).y() < itemCenter.y(); + bool movingUp = mDropSource->sceneIndex() > item->sceneIndex(); + qreal y = 0; + + if (movingUp) + { + if (dropAbove) + { + y = item->pos().y() - UBSettings::thumbnailSpacing / 2; + if (mDropBar->y() != y) + mDropBar->setRect(QRectF(item->pos().x(), y, mThumbnailWidth-verticalScrollBar()->width(), 3)); + } + } + else + { + if (!dropAbove) + { + y = item->pos().y() + item->boundingRect().height() * scale + UBSettings::thumbnailSpacing / 2; + if (mDropBar->y() != y) + mDropBar->setRect(QRectF(item->pos().x(), y, mThumbnailWidth-verticalScrollBar()->width(), 3)); + } + } + } + + event->acceptProposedAction(); +} + +void UBDocumentNavigator::dropEvent(QDropEvent *event) +{ + Q_UNUSED(event); + + if (mDropSource->sceneIndex() != mDropTarget->sceneIndex()) + UBApplication::boardController->moveSceneToIndex(mDropSource->sceneIndex(), mDropTarget->sceneIndex()); + + mDropSource = NULL; + mDropTarget = NULL; + + mDropBar->setRect(QRectF()); + mDropBar->hide(); +} diff --git a/src/gui/UBDocumentNavigator.h b/src/gui/UBDocumentNavigator.h new file mode 100644 index 00000000..3b68dbd7 --- /dev/null +++ b/src/gui/UBDocumentNavigator.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2015-2016 Département de l'Instruction Publique (DIP-SEM) + * + * 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 . + */ + + + + +#ifndef UBDOCUMENTNAVIGATOR_H +#define UBDOCUMENTNAVIGATOR_H + +#include +#include +#include +#include +#include + +#include "document/UBDocumentProxy.h" +#include "document/UBDocumentContainer.h" +#include "UBThumbnailWidget.h" + +#define NO_PAGESELECTED -1 + +class UBDocumentNavigator : public QGraphicsView +{ + Q_OBJECT +public: + UBDocumentNavigator(QWidget* parent=0, const char* name="documentNavigator"); + ~UBDocumentNavigator(); + + void setNbColumns(int nbColumns); + int nbColumns(); + void setThumbnailMinWidth(int width); + int thumbnailMinWidth(); + +public slots: + void onScrollToSelectedPage(int index);// { if (mCrntItem) centerOn(mCrntItem); } + void generateThumbnails(UBDocumentContainer* source); + void updateSpecificThumbnail(int iPage); + + void longPressTimeout(); + void mousePressAndHoldEvent(QPoint pos); + +protected: + virtual void resizeEvent(QResizeEvent *event); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); + + virtual void dragEnterEvent(QDragEnterEvent* event); + virtual void dragMoveEvent(QDragMoveEvent* event); + virtual void dropEvent(QDropEvent* event); + +signals: + void mousePressAndHoldEventRequired(QPoint pos); + void moveThumbnailRequired(int from, int to); + +private: + + void refreshScene(); + int border(); + + /** The scene */ + QGraphicsScene* mScene; + /** The current selected item */ + //UBSceneThumbnailNavigPixmap* mCrntItem; + /** The list of current thumbnails with labels*/ + QList mThumbsWithLabels; + /** The current number of columns */ + int mNbColumns; + /** The current thumbnails width */ + int mThumbnailWidth; + /** The current thumbnails minimum width */ + int mThumbnailMinWidth; + /** The selected thumbnail */ + UBSceneThumbnailNavigPixmap* mSelectedThumbnail; + + UBSceneThumbnailNavigPixmap* mDropSource; + UBSceneThumbnailNavigPixmap* mDropTarget; + QGraphicsRectItem *mDropBar; + + int mLongPressInterval; + QTimer mLongPressTimer; + QPoint mLastPressedMousePos; +}; + +#endif // UBDOCUMENTNAVIGATOR_H + diff --git a/src/gui/UBDocumentThumbnailWidget.cpp b/src/gui/UBDocumentThumbnailWidget.cpp index b70f3926..f700530b 100644 --- a/src/gui/UBDocumentThumbnailWidget.cpp +++ b/src/gui/UBDocumentThumbnailWidget.cpp @@ -75,17 +75,17 @@ void UBDocumentThumbnailWidget::mouseMoveEvent(QMouseEvent *event) QList graphicsItems = items(mMousePressPos); - UBThumbnailPixmap* sceneItem = 0; + UBSceneThumbnailPixmap* sceneItem = 0; while (!graphicsItems.isEmpty() && !sceneItem) - sceneItem = dynamic_cast(graphicsItems.takeFirst()); + sceneItem = dynamic_cast(graphicsItems.takeFirst()); if (sceneItem) { QDrag *drag = new QDrag(this); QList mimeDataItems; foreach (QGraphicsItem *item, selectedItems()) - mimeDataItems.append(UBMimeDataItem(sceneItem->documentProxy(), mGraphicItems.indexOf(item))); + mimeDataItems.append(UBMimeDataItem(sceneItem->proxy(), mGraphicItems.indexOf(item))); UBMimeData *mime = new UBMimeData(mimeDataItems); drag->setMimeData(mime); @@ -305,7 +305,7 @@ void UBDocumentThumbnailWidget::hightlightItem(int index) } if (0 <= index && index < mGraphicItems.length()) { - UBThumbnailPixmap *thumbnail = dynamic_cast(mGraphicItems.at(index)); + UBSceneThumbnailPixmap *thumbnail = dynamic_cast(mGraphicItems.at(index)); if (thumbnail) thumbnail->highlight(); } diff --git a/src/gui/UBMessageWindow.cpp b/src/gui/UBMessageWindow.cpp index 14adbbb6..d973810a 100644 --- a/src/gui/UBMessageWindow.cpp +++ b/src/gui/UBMessageWindow.cpp @@ -88,6 +88,7 @@ void UBMessageWindow::showMessage(const QString& message, bool showSpinningWheel repaint(); // I mean it, *right now*, also on Mac qApp->flush(); + //qApp->sendPostedEvents(); } void UBMessageWindow::timerEvent(QTimerEvent *event) diff --git a/src/gui/UBPageNavigationWidget.cpp b/src/gui/UBPageNavigationWidget.cpp index eba9e401..a6564573 100644 --- a/src/gui/UBPageNavigationWidget.cpp +++ b/src/gui/UBPageNavigationWidget.cpp @@ -60,7 +60,7 @@ UBPageNavigationWidget::UBPageNavigationWidget(QWidget *parent, const char *name mLayout = new QVBoxLayout(this); setLayout(mLayout); - mNavigator = new UBBoardThumbnailsView(this); + mNavigator = new UBDocumentNavigator(this); mLayout->addWidget(mNavigator, 1); mHLayout = new QHBoxLayout(); diff --git a/src/gui/UBPageNavigationWidget.h b/src/gui/UBPageNavigationWidget.h index bba9cc86..e72b74f4 100644 --- a/src/gui/UBPageNavigationWidget.h +++ b/src/gui/UBPageNavigationWidget.h @@ -39,6 +39,7 @@ #include #include "UBBoardThumbnailsView.h" +#include "UBDocumentNavigator.h" #include "UBDockPaletteWidget.h" #include "document/UBDocumentProxy.h" @@ -70,7 +71,7 @@ private: int border(); /** The thumbnails navigator widget */ - UBBoardThumbnailsView* mNavigator; + UBDocumentNavigator* mNavigator; /** The layout */ QVBoxLayout* mLayout; QHBoxLayout* mHLayout; diff --git a/src/gui/UBThumbnailWidget.cpp b/src/gui/UBThumbnailWidget.cpp index 60755aa4..2d83213a 100644 --- a/src/gui/UBThumbnailWidget.cpp +++ b/src/gui/UBThumbnailWidget.cpp @@ -771,7 +771,117 @@ UBThumbnail::~UBThumbnail() delete mSelectionItem; } -void UBWidgetTextThumbnailElement::Place(int row, int col, qreal width, qreal height) +UBSceneThumbnailNavigPixmap::UBSceneThumbnailNavigPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) + : UBSceneThumbnailPixmap(pix, proxy, pSceneIndex) + , bButtonsVisible(false) + , bCanDelete(false) + , bCanMoveUp(false) + , bCanMoveDown(false) +{ + if(0 <= UBDocumentContainer::pageFromSceneIndex(pSceneIndex)){ + setAcceptHoverEvents(true); + setFlag(QGraphicsItem::ItemIsSelectable, true); + } +} + +UBSceneThumbnailNavigPixmap::~UBSceneThumbnailNavigPixmap() +{ + +} + +void UBSceneThumbnailNavigPixmap::hoverEnterEvent(QGraphicsSceneHoverEvent *event) +{ + event->accept(); + bButtonsVisible = true; + bCanDelete = true; + bCanMoveDown = false; + bCanMoveUp = false; + if(sceneIndex() < proxy()->pageCount() - 1) + bCanMoveDown = true; + if(sceneIndex() > 0) + bCanMoveUp = true; + if(proxy()->pageCount() == 1) + bCanDelete = false; + update(); +} + +void UBSceneThumbnailNavigPixmap::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + event->accept(); + bButtonsVisible = false; + update(); +} + +void UBSceneThumbnailNavigPixmap::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) +{ + Q_UNUSED(option); + Q_UNUSED(widget); + + UBSceneThumbnailPixmap::paint(painter, option, widget); + if(bButtonsVisible) + { + if(bCanDelete) + painter->drawPixmap(0, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/close.svg")); + else + painter->drawPixmap(0, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/closeDisabled.svg")); + + painter->drawPixmap(BUTTONSIZE + BUTTONSPACING, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/duplicate.svg")); + + if(bCanMoveUp) + painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUp.svg")); + else + painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUpDisabled.svg")); + if(bCanMoveDown) + painter->drawPixmap(3*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menu.svg")); + else + painter->drawPixmap(3*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menuDisabled.svg")); + } +} + +void UBSceneThumbnailNavigPixmap::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + QPointF p = event->pos(); + + // Here we check the position of the click and verify if it has to trig an action or not. + if(bCanDelete && p.x() >= 0 && p.x() <= BUTTONSIZE && p.y() >= 0 && p.y() <= BUTTONSIZE) + deletePage(); + if(p.x() >= BUTTONSIZE + BUTTONSPACING && p.x() <= 2*BUTTONSIZE + BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) + duplicatePage(); + + if(bCanMoveUp && p.x() >= 2*(BUTTONSIZE + BUTTONSPACING) && p.x() <= 3*BUTTONSIZE + 2*BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) + moveUpPage(); + if(bCanMoveDown && p.x() >= 3*(BUTTONSIZE + BUTTONSPACING) && p.x() <= 4*BUTTONSIZE + 3*BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) + moveDownPage(); + + event->accept(); +} + +void UBSceneThumbnailNavigPixmap::deletePage() +{ + if(UBApplication::mainWindow->yesNoQuestion(QObject::tr("Remove Page"), QObject::tr("Are you sure you want to remove 1 page from the selected document '%0'?").arg(UBApplication::documentController->selectedDocument()->metaData(UBSettings::documentName).toString()))){ + UBApplication::boardController->deleteScene(sceneIndex()); + } +} + +void UBSceneThumbnailNavigPixmap::duplicatePage() +{ + UBApplication::boardController->duplicateScene(sceneIndex()); +} + +void UBSceneThumbnailNavigPixmap::moveUpPage() +{ + if (sceneIndex()!=0) + UBApplication::boardController->moveSceneToIndex(sceneIndex(), sceneIndex() - 1); +} + +void UBSceneThumbnailNavigPixmap::moveDownPage() +{ + if (sceneIndex() < UBApplication::boardController->selectedDocument()->pageCount()-1) + UBApplication::boardController->moveSceneToIndex(sceneIndex(), sceneIndex() + 1); +} + + +void UBImgTextThumbnailElement::Place(int row, int col, qreal width, qreal height) { int labelSpacing = 0; if(this->caption) @@ -802,8 +912,11 @@ void UBWidgetTextThumbnailElement::Place(int row, int col, qreal width, qreal he pix->setRow(row); } - QPointF pos(border + (width - w * scaleFactor) / 2 + col * (width + border), - border + row * (height + border + labelSpacing) + (height - h * scaleFactor) / 2); + QPointF pos((width - w * scaleFactor) / 2, + row * (height + labelSpacing) + (height - h * scaleFactor) / 2); + + /*QPointF pos(border + (width - w * scaleFactor) / 2 + col * (width + border), + border + row * (height + border + labelSpacing) + (height - h * scaleFactor) / 2);*/ this->thumbnail->setPos(pos); @@ -816,7 +929,7 @@ void UBWidgetTextThumbnailElement::Place(int row, int col, qreal width, qreal he this->caption->setWidth(fm.width(elidedText) + 2 * this->caption->document()->documentMargin()); pos.setY(pos.y() + (height + h * scaleFactor) / 2 + 5); // What is this 5 ?? qreal labelWidth = fm.width(elidedText); - pos.setX(border + (width - labelWidth) / 2 + col * (width + border)); + pos.setX((width - labelWidth) / 2 + col * (width + border)); this->caption->setPos(pos); } } @@ -929,7 +1042,7 @@ void UBDraggableThumbnail::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) } -void UBDraggableThumbnailView::updatePos(qreal width, qreal height) +void UBDraggableThumbnail::updatePos(qreal width, qreal height) { QFontMetrics fm(mPageNumber->font()); int labelSpacing = UBSettings::thumbnailSpacing + fm.height(); @@ -959,6 +1072,37 @@ void UBDraggableThumbnailView::updatePos(qreal width, qreal height) mPageNumber->setPos(position); } +void UBDraggableThumbnailPixmap::updatePos(qreal width, qreal height) +{ + QFontMetrics fm(mPageNumber->font()); + int labelSpacing = UBSettings::thumbnailSpacing + fm.height(); + + int w = thumbnailPixmap()->boundingRect().width(); + int h = thumbnailPixmap()->boundingRect().height(); + + qreal scaledWidth = width / w; + qreal scaledHeight = height / h; + qreal scaledFactor = qMin(scaledWidth, scaledHeight); + + QTransform transform; + transform.scale(scaledFactor, scaledFactor); + + // Apply the scaling + thumbnailPixmap()->setTransform(transform); + thumbnailPixmap()->setFlag(QGraphicsItem::ItemIsSelectable, true); + + QPointF position((width - w * scaledFactor) / 2, + sceneIndex() * (height + labelSpacing) + (height - h * scaledFactor) / 2); + + thumbnailPixmap()->setPos(position); + + position.setY(position.y() + (height + h * scaledFactor) / 2); + position.setX(position.x() + (w * scaledFactor - fm.width(mPageNumber->toPlainText())) / 2); + + mPageNumber->setPos(position); +} + + UBThumbnailUI::UBThumbnailUIIcon* UBThumbnailUI::addIcon(const QString& thumbnailIcon, int pos) { QString thumbnailIconPath = ":images/" + thumbnailIcon + ".svg"; diff --git a/src/gui/UBThumbnailWidget.h b/src/gui/UBThumbnailWidget.h index 887edc7e..d47f0f6b 100644 --- a/src/gui/UBThumbnailWidget.h +++ b/src/gui/UBThumbnailWidget.h @@ -48,6 +48,8 @@ #define STARTDRAGTIME 1000000 +#define BUTTONSIZE 48 +#define BUTTONSPACING 5 class UBDocumentProxy; class UBThumbnailTextItem; @@ -274,44 +276,9 @@ class UBThumbnailTextItem : public QGraphicsTextItem bool mIsHighlighted; }; -class UBWidgetTextThumbnailElement -{ -protected: - QGraphicsItem* thumbnail; - UBThumbnailTextItem* caption; - int border; - -public: - UBWidgetTextThumbnailElement(QGraphicsProxyWidget* proxyWidget, UBThumbnailTextItem* text) - : thumbnail(proxyWidget) - , caption(text) - , border(0) - { - } - - QGraphicsItem* getThumbnail() const { return this->thumbnail; } - void setThumbnail(QGraphicsItem* newGItem) { this->thumbnail = newGItem; } - - UBThumbnailTextItem* getCaption() const { return this->caption; } - void setCaption(UBThumbnailTextItem* newcaption) { this->caption = newcaption; } - - void Place(int row, int col, qreal width, qreal height); - - int getBorder() const { return this->border; } - void setBorder(int newBorder) { this->border = newBorder; } -}; - class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail { public: - UBThumbnailPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) - : QGraphicsPixmapItem(pix) - , mDocumentProxy(proxy) - , mSceneIndex(pSceneIndex) - { - - } - UBThumbnailPixmap(const QPixmap& pix) : QGraphicsPixmapItem(pix) { @@ -320,6 +287,11 @@ class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); } + virtual ~UBThumbnailPixmap() + { + // NOOP + } + virtual QPainterPath shape () const { QPainterPath path; @@ -327,6 +299,7 @@ class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail return path; } + virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { QStyleOptionGraphicsItem styleOption = UBThumbnail::muteStyleOption(option); @@ -338,26 +311,94 @@ class UBThumbnailPixmap : public QGraphicsPixmapItem, public UBThumbnail UBThumbnail::itemChange(this, change, value); return QGraphicsPixmapItem::itemChange(change, value); } +}; - void highlight() +class UBSceneThumbnailPixmap : public UBThumbnailPixmap +{ + public: + UBSceneThumbnailPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex) + : UBThumbnailPixmap(pix) + , mProxy(proxy) + , mSceneIndex(pSceneIndex) { + // NOOP + } + virtual ~UBSceneThumbnailPixmap() + { + // NOOP } - UBDocumentProxy* documentProxy() + UBDocumentProxy* proxy() { - return mDocumentProxy; + return mProxy; } int sceneIndex() { return mSceneIndex; } - protected: - UBDocumentProxy* mDocumentProxy; + + void highlight() + { + //NOOP + } + + private: + UBDocumentProxy* mProxy; int mSceneIndex; }; +class UBSceneThumbnailNavigPixmap : public UBSceneThumbnailPixmap +{ + public: + UBSceneThumbnailNavigPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex); + ~UBSceneThumbnailNavigPixmap(); + + protected: + void hoverEnterEvent(QGraphicsSceneHoverEvent *event); + void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + void mousePressEvent(QGraphicsSceneMouseEvent *event); + + private: + void deletePage(); + void duplicatePage(); + void moveUpPage(); + void moveDownPage(); + + bool bButtonsVisible; + bool bCanDelete; + bool bCanMoveUp; + bool bCanMoveDown; +}; + +class UBImgTextThumbnailElement +{ +private: + UBSceneThumbnailNavigPixmap* thumbnail; + UBThumbnailTextItem* caption; + int border; + +public: + UBImgTextThumbnailElement(UBSceneThumbnailNavigPixmap* thumb, UBThumbnailTextItem* text): border(0) + { + this->thumbnail = thumb; + this->caption = text; + } + + UBSceneThumbnailNavigPixmap* getThumbnail() const { return this->thumbnail; } + void setThumbnail(UBSceneThumbnailNavigPixmap* newGItem) { this->thumbnail = newGItem; } + + UBThumbnailTextItem* getCaption() const { return this->caption; } + void setCaption(UBThumbnailTextItem* newcaption) { this->caption = newcaption; } + + void Place(int row, int col, qreal width, qreal height); + + int getBorder() const { return this->border; } + void setBorder(int newBorder) { this->border = newBorder; } +}; + class UBThumbnailProxyWidget : public QGraphicsProxyWidget { public: @@ -393,11 +434,17 @@ class UBDraggableThumbnail : public UBThumbnailProxyWidget public: UBDraggableThumbnail(UBDocumentProxy* documentProxy, int index) : UBThumbnailProxyWidget(documentProxy, index) + , mPageNumber(new UBThumbnailTextItem(index)) , mEditable(false) { } + ~UBDraggableThumbnail() + { + delete mPageNumber; // not a child of "this" QObject so it has to be deleted manually + } + bool editable() { return mEditable; @@ -433,6 +480,23 @@ class UBDraggableThumbnail : public UBThumbnailProxyWidget mEditable = editable; } + UBThumbnailTextItem* pageNumber() + { + return mPageNumber; + } + + void setPageNumber(int i) + { + mPageNumber->setPlainText(tr("Page %0").arg(i+1)); + + if (UBApplication::boardController->activeSceneIndex() == i) + mPageNumber->setHtml("" + tr("Page %0").arg(i+1) + ""); + else + mPageNumber->setHtml("" + tr("Page %0").arg(i+1) + ""); + } + + virtual void updatePos(qreal w, qreal h); + protected: void hoverEnterEvent(QGraphicsSceneHoverEvent *event); void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); @@ -440,6 +504,7 @@ class UBDraggableThumbnail : public UBThumbnailProxyWidget void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + UBThumbnailTextItem* mPageNumber; private: void deletePage(); void duplicatePage(); @@ -451,9 +516,30 @@ class UBDraggableThumbnail : public UBThumbnailProxyWidget class UBDraggableThumbnailPixmap : public UBDraggableThumbnail { + Q_OBJECT public: - UBDraggableThumbnailPixmap(const QPixmap& pix, UBDocumentProxy* proxy, int pSceneIndex); - ~UBDraggableThumbnailPixmap(); + UBDraggableThumbnailPixmap(UBThumbnailPixmap* thumbnailPixmap, UBDocumentProxy* documentProxy, int index) + : UBDraggableThumbnail(documentProxy, index) + , mThumbnailPixmap(thumbnailPixmap) + { + setFlag(QGraphicsItem::ItemIsSelectable, true); + setAcceptDrops(true); + } + + ~UBDraggableThumbnailPixmap() + { + + } + + UBThumbnailPixmap* thumbnailPixmap() + { + return mThumbnailPixmap; + } + + void updatePos(qreal w, qreal h); + + private: + UBThumbnailPixmap* mThumbnailPixmap; }; class UBDraggableThumbnailView : public UBDraggableThumbnail @@ -463,7 +549,6 @@ class UBDraggableThumbnailView : public UBDraggableThumbnail UBDraggableThumbnailView(UBThumbnailView* thumbnailView, UBDocumentProxy* documentProxy, int index) : UBDraggableThumbnail(documentProxy, index) , mThumbnailView(thumbnailView) - , mPageNumber(new UBThumbnailTextItem(index)) { setFlag(QGraphicsItem::ItemIsSelectable, true); setWidget(mThumbnailView); @@ -475,8 +560,6 @@ class UBDraggableThumbnailView : public UBDraggableThumbnail delete mPageNumber; // not a child of "this" QObject so it has to be deleted manually } - void updatePos(qreal w, qreal h); - UBThumbnailView* thumbnailView() { return mThumbnailView; @@ -498,8 +581,7 @@ class UBDraggableThumbnailView : public UBDraggableThumbnail } private: - UBThumbnailView* mThumbnailView; - UBThumbnailTextItem* mPageNumber; + UBThumbnailView* mThumbnailView; }; namespace UBThumbnailUI diff --git a/src/gui/gui.pri b/src/gui/gui.pri index 8f9dea58..fe59b318 100644 --- a/src/gui/gui.pri +++ b/src/gui/gui.pri @@ -41,7 +41,8 @@ HEADERS += src/gui/UBThumbnailView.h \ src/gui/UBOpenSankoreImporterWidget.h \ src/gui/UBStartupHintsPalette.h \ src/gui/UBBackgroundPalette.h \ - src/gui/UBBoardThumbnailsView.h + src/gui/UBBoardThumbnailsView.h \ + src/gui/UBDocumentNavigator.h SOURCES += src/gui/UBThumbnailView.cpp \ src/gui/UBFloatingPalette.cpp \ src/gui/UBToolbarButtonGroup.cpp \ @@ -85,7 +86,8 @@ SOURCES += src/gui/UBThumbnailView.cpp \ src/gui/UBOpenSankoreImporterWidget.cpp \ src/gui/UBStartupHintsPalette.cpp \ src/gui/UBBackgroundPalette.cpp \ - src/gui/UBBoardThumbnailsView.cpp + src/gui/UBBoardThumbnailsView.cpp \ + src/gui/UBDocumentNavigator.cpp win32:SOURCES += src/gui/UBKeyboardPalette_win.cpp macx:OBJECTIVE_SOURCES += src/gui/UBKeyboardPalette_mac.mm linux-g++:SOURCES += src/gui/UBKeyboardPalette_linux.cpp From 2540bdfc47a16b3813b58769d89a54e8983ed1fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Thu, 15 Mar 2018 10:56:05 +0100 Subject: [PATCH 133/134] changed release name to 1.4.0 --- OpenBoard.pro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenBoard.pro b/OpenBoard.pro index 6cf509e8..68a88989 100644 --- a/OpenBoard.pro +++ b/OpenBoard.pro @@ -11,8 +11,8 @@ CONFIG += debug_and_release \ VERSION_MAJ = 1 VERSION_MIN = 4 VERSION_PATCH = 0 -VERSION_TYPE = rc # a = alpha, b = beta, rc = release candidate, r = release, other => error -VERSION_BUILD = 4 +VERSION_TYPE = r # a = alpha, b = beta, rc = release candidate, r = release, other => error +VERSION_BUILD = 0 VERSION = "$${VERSION_MAJ}.$${VERSION_MIN}.$${VERSION_PATCH}-$${VERSION_TYPE}.$${VERSION_BUILD}" From 21b98e5663146a5e428facd66343383503cdaab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fauconnier?= Date: Fri, 16 Mar 2018 08:48:45 +0100 Subject: [PATCH 134/134] removed moveUp and moveDown icons --- src/gui/UBThumbnailWidget.cpp | 24 ++++++++++++------------ src/gui/UBThumbnailWidget.h | 4 ++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/gui/UBThumbnailWidget.cpp b/src/gui/UBThumbnailWidget.cpp index 2d83213a..a21f4546 100644 --- a/src/gui/UBThumbnailWidget.cpp +++ b/src/gui/UBThumbnailWidget.cpp @@ -827,14 +827,14 @@ void UBSceneThumbnailNavigPixmap::paint(QPainter *painter, const QStyleOptionGra painter->drawPixmap(BUTTONSIZE + BUTTONSPACING, 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/duplicate.svg")); - if(bCanMoveUp) - painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUp.svg")); - else - painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUpDisabled.svg")); - if(bCanMoveDown) - painter->drawPixmap(3*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menu.svg")); - else - painter->drawPixmap(3*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menuDisabled.svg")); +// if(bCanMoveUp) +// painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUp.svg")); +// else +// painter->drawPixmap(2*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/moveUpDisabled.svg")); +// if(bCanMoveDown) +// painter->drawPixmap(3*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menu.svg")); +// else +// painter->drawPixmap(3*(BUTTONSIZE + BUTTONSPACING), 0, BUTTONSIZE, BUTTONSIZE, QPixmap(":images/menuDisabled.svg")); } } @@ -848,10 +848,10 @@ void UBSceneThumbnailNavigPixmap::mousePressEvent(QGraphicsSceneMouseEvent *even if(p.x() >= BUTTONSIZE + BUTTONSPACING && p.x() <= 2*BUTTONSIZE + BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) duplicatePage(); - if(bCanMoveUp && p.x() >= 2*(BUTTONSIZE + BUTTONSPACING) && p.x() <= 3*BUTTONSIZE + 2*BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) - moveUpPage(); - if(bCanMoveDown && p.x() >= 3*(BUTTONSIZE + BUTTONSPACING) && p.x() <= 4*BUTTONSIZE + 3*BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) - moveDownPage(); +// if(bCanMoveUp && p.x() >= 2*(BUTTONSIZE + BUTTONSPACING) && p.x() <= 3*BUTTONSIZE + 2*BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) +// moveUpPage(); +// if(bCanMoveDown && p.x() >= 3*(BUTTONSIZE + BUTTONSPACING) && p.x() <= 4*BUTTONSIZE + 3*BUTTONSPACING && p.y() >= 0 && p.y() <= BUTTONSIZE) +// moveDownPage(); event->accept(); } diff --git a/src/gui/UBThumbnailWidget.h b/src/gui/UBThumbnailWidget.h index d47f0f6b..75b025b2 100644 --- a/src/gui/UBThumbnailWidget.h +++ b/src/gui/UBThumbnailWidget.h @@ -48,8 +48,8 @@ #define STARTDRAGTIME 1000000 -#define BUTTONSIZE 48 -#define BUTTONSPACING 5 +#define BUTTONSIZE 96 +#define BUTTONSPACING 10 class UBDocumentProxy; class UBThumbnailTextItem;