Commit be45f656 authored by Craig Watson's avatar Craig Watson

Merge branch 'dev' into 1.4-dev

parents a4b83e2c 3d46bd0b
......@@ -119,7 +119,7 @@ Source: "{#QtDir}\plugins\mediaservice\wmfengine.dll"; DestDir: "{app}\mediaserv
Source: "{#QtDir}\plugins\mediaservice\wmfengined.dll"; DestDir: "{app}\mediaservice"; Flags: ignoreversion
;OpenBoardImporter
Source: "{#ProjectRoot}\..\OpenBoard-Importer\release\OpenBoardImporter.exe"; DestDir: "{app}\Importer"; Flags: ignoreversion
Source: "{#ProjectRoot}\..\OpenBoard-Importer\release\OpenBoardImporter.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "{#QtLibs}\Qt5Core.dll"; DestDir: "{app}"
Source: "{#QtLibs}\Qt5Gui.dll"; DestDir: "{app}"
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -355,6 +355,7 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx
mScene = 0;
UBGraphicsWidgetItem *currentWidget = 0;
bool pageDpiSpecified = true;
saveSceneAfterLoading = false;
mFileVersion = 40100; // default to 4.1.0
......@@ -371,6 +372,7 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx
if (!mScene)
{
mScene = new UBGraphicsScene(mProxy, false);
mScene->setModified(false);
}
// introduced in UB 4.2
......@@ -951,10 +953,11 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene(UBDocumentProx
mScene->addItem(iterator.value());
}
if (mScene)
mScene->setModified(false);
if (mScene) {
mScene->setModified(saveSceneAfterLoading);
mScene->enableUndoRedoStack();
}
mScene->enableUndoRedoStack();
qDebug() << "loadScene() : created scene and read file";
qDebug() << "spent milliseconds: " << time.elapsed();
return mScene;
......@@ -1190,11 +1193,6 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(UBDocumentProxy* proxy,
mXmlWriter.writeStartElement("g");
openStroke = currentStroke;
QMatrix matrix = item->sceneMatrix();
if (!matrix.isIdentity())
mXmlWriter.writeAttribute("transform", toSvgTransform(matrix));
UBGraphicsStroke* stroke = dynamic_cast<UBGraphicsStroke* >(currentStroke);
if (stroke)
......@@ -1215,6 +1213,14 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(UBDocumentProxy* proxy,
mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "uuid", UBStringUtils::toCanonicalUuid(sg->uuid()));
QVariant locked = sg->data(UBGraphicsItemData::ItemLocked);
if (!locked.isNull() && locked.toBool())
mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "locked", xmlTrue);
QMatrix matrix = sg->sceneMatrix();
if (!matrix.isIdentity())
mXmlWriter.writeAttribute("transform", toSvgTransform(matrix));
qDebug() << "Attributes written";
groupHoldsInfo = true;
......@@ -1576,7 +1582,7 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::polygonItemToSvgPolygon(UBGraphicsPo
QString points = pointsToSvgPointsAttribute(polygon);
mXmlWriter.writeAttribute("points", points);
mXmlWriter.writeAttribute("transform",toSvgTransform(polygonItem->sceneMatrix()));
mXmlWriter.writeAttribute("transform",toSvgTransform(polygonItem->matrix()));
mXmlWriter.writeAttribute("fill", polygonItem->brush().color().name());
qreal alpha = polygonItem->brush().color().alphaF();
......@@ -1612,9 +1618,9 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::polygonItemToSvgPolygon(UBGraphicsPo
}
mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "uuid", UBStringUtils::toCanonicalUuid(polygonItem->uuid()));
if (polygonItem->parentItem()) {
mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "parent", UBStringUtils::toCanonicalUuid(UBGraphicsItem::getOwnUuid(polygonItem->parentItem())));
}
UBGraphicsStrokesGroup* sg = polygonItem->strokesGroup();
if (sg)
mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "parent", UBStringUtils::toCanonicalUuid(sg->uuid()));
mXmlWriter.writeEndElement();
}
......@@ -2567,6 +2573,7 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::textItemToSvg(UBGraphicsTextItem* it
mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "width", QString("%1").arg(item->textWidth()));
mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "height", QString("%1").arg(item->textHeight()));
mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "pixels-per-point", QString("%1").arg(item->pixelsPerPoint()));
QColor colorDarkBg = item->colorOnDarkBackground();
QColor colorLightBg = item->colorOnLightBackground();
......@@ -2593,6 +2600,8 @@ UBGraphicsTextItem* UBSvgSubsetAdaptor::UBSvgSubsetReader::textItemFromSvg()
qreal width = mXmlReader.attributes().value("width").toString().toFloat();
qreal height = mXmlReader.attributes().value("height").toString().toFloat();
qreal originalPixelsPerPoint = mXmlReader.attributes().value(mNamespaceUri, "pixels-per-point").toString().toDouble();
UBGraphicsTextItem* textItem = new UBGraphicsTextItem();
graphicsItemFromSvg(textItem);
......@@ -2635,6 +2644,31 @@ UBGraphicsTextItem* UBSvgSubsetAdaptor::UBSvgSubsetReader::textItemFromSvg()
if (mXmlReader.name() == "itemTextContent") {
text = mXmlReader.readElementText();
textItem->setHtml(text);
// Fonts sizes are not displayed the same across platforms: e.g a text item with the same
// font size (in Pts) is displayed smaller on Linux than Windows. This messes up layouts
// when importing documents created on another computer, so if a font is being displayed
// at a different size (relative to the rest of the document) than it was when created,
// we adjust its size.
if (originalPixelsPerPoint != 0) {
qreal pixelsPerPoint = textItem->pixelsPerPoint();
qDebug() << "Pixels per point: original/current" << originalPixelsPerPoint
<< "/" << pixelsPerPoint;
qreal ratio = originalPixelsPerPoint/pixelsPerPoint;
if (ratio != 1) {
qDebug() << "Scaling text by " << ratio;
UBGraphicsTextItemDelegate* textDelegate = dynamic_cast<UBGraphicsTextItemDelegate*>(textItem->Delegate());
if (textDelegate)
textDelegate->scaleTextSize(ratio);
}
}
else
// mark scene as modified so the text item will be saved with a pixelsPerPoint value
saveSceneAfterLoading = true;
textItem->resize(width, height);
if (textItem->toPlainText().isEmpty()) {
delete textItem;
......
......@@ -168,6 +168,8 @@ class UBSvgSubsetAdaptor
qreal mGroupZIndex;
bool mGroupHasInfo;
bool saveSceneAfterLoading;
QString mNamespaceUri;
UBGraphicsScene *mScene;
......
......@@ -555,6 +555,8 @@ Here we determines cases when items should to get mouse press event at pressing
return true;
case UBGraphicsMediaItem::Type:
case UBGraphicsVideoItem::Type:
case UBGraphicsAudioItem::Type:
return false;
case UBGraphicsTextItem::Type:
......@@ -626,6 +628,8 @@ bool UBBoardView::itemShouldReceiveSuspendedMousePressEvent(QGraphicsItem *item)
case DelegateButton::Type:
case UBGraphicsMediaItem::Type:
case UBGraphicsVideoItem::Type:
case UBGraphicsAudioItem::Type:
return true;
}
......@@ -858,6 +862,8 @@ void UBBoardView::moveRubberedItems(QPointF movingVector)
if (item->type() == UBGraphicsW3CWidgetItem::Type
|| item->type() == UBGraphicsPixmapItem::Type
|| item->type() == UBGraphicsMediaItem::Type
|| item->type() == UBGraphicsVideoItem::Type
|| item->type() == UBGraphicsAudioItem::Type
|| item->type() == UBGraphicsSvgItem::Type
|| item->type() == UBGraphicsTextItem::Type
|| item->type() == UBGraphicsStrokesGroup::Type
......@@ -1170,7 +1176,8 @@ void UBBoardView::mouseMoveEvent (QMouseEvent *event)
if (item->type() == UBGraphicsW3CWidgetItem::Type
|| item->type() == UBGraphicsPixmapItem::Type
|| item->type() == UBGraphicsMediaItem::Type
|| item->type() == UBGraphicsVideoItem::Type
|| item->type() == UBGraphicsAudioItem::Type
|| item->type() == UBGraphicsSvgItem::Type
|| item->type() == UBGraphicsTextItem::Type
|| item->type() == UBGraphicsStrokesGroup::Type
......@@ -1328,6 +1335,7 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event)
textItem->setTextInteractionFlags(Qt::TextEditorInteraction);
textItem->setSelected (true);
textItem->setTextWidth(0);
textItem->setFocus();
}
}
......@@ -1597,9 +1605,9 @@ void UBBoardView::drawBackground (QPainter *painter, const QRectF &rect)
QColor bgCrossColor;
if (darkBackground)
bgCrossColor = UBSettings::crossDarkBackground;
bgCrossColor = QColor(UBSettings::settings()->boardCrossColorDarkBackground->get().toString());
else
bgCrossColor = UBSettings::crossLightBackground;
bgCrossColor = QColor(UBSettings::settings()->boardCrossColorLightBackground->get().toString());
if (transform ().m11 () < 1.0)
{
......
......@@ -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()
......@@ -658,7 +642,6 @@ void UBApplicationController::closing()
if (mUninoteController)
{
mUninoteController->hideWindow();
mUninoteController->close();
}
......
......@@ -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_ */
......@@ -56,11 +56,9 @@ void UBOpenSankoreImporter::onProceedClicked()
newProcess.startDetached(qApp->applicationDirPath()+"/importer/OpenBoardImporter");
#elif defined Q_OS_OSX
newProcess.startDetached(qApp->applicationDirPath()+"/../Resources/OpenBoardImporter.app/Contents/MacOS/OpenBoardImporter");
#else
// Windows does not allows to run easily an exe located in a subdirectory when the main
// directory is placed into programs files.
//newProcess.startDetached(qApp->applicationDirPath()+"\\Importer\\OpenBoardImporter.exe");
newProcess.startDetached("C:/OpenBoard/Importer/OpenBoardImporter.exe");
#elif defined Q_OS_WIN
QString importerPath = QDir::toNativeSeparators(qApp->applicationDirPath())+"\\OpenBoardImporter.exe";
newProcess.startDetached("explorer.exe", QStringList() << importerPath);
#endif
qApp->exit(0);
......
......@@ -67,6 +67,7 @@ UBPersistenceManager * UBPersistenceManager::sSingleton = 0;
UBPersistenceManager::UBPersistenceManager(QObject *pParent)
: QObject(pParent)
, mHasPurgedDocuments(false)
, mIsApplicationClosing(false)
, mIsWorkerFinished(false)
{
......@@ -131,8 +132,10 @@ void UBPersistenceManager::destroy()
void UBPersistenceManager::onScenePersisted(UBGraphicsScene* scene)
{
delete scene;
scene = NULL;
if (!mIsApplicationClosing) {
delete scene;
scene = NULL;
}
}
void UBPersistenceManager::onMetadataPersisted(UBDocumentProxy* proxy)
......@@ -147,6 +150,8 @@ void UBPersistenceManager::onWorkerFinished()
UBPersistenceManager::~UBPersistenceManager()
{
mIsApplicationClosing = true;
if(mWorker)
mWorker->applicationWillClose();
......@@ -483,7 +488,7 @@ void UBPersistenceManager::deleteDocumentScenes(UBDocumentProxy* proxy, const QL
foreach(int index, compactedIndexes)
{
UBGraphicsScene *scene = loadDocumentScene(proxy, index);
UBGraphicsScene *scene = loadDocumentScene(proxy, index, false);
if (scene)
{
//scene is about to move into new document
......@@ -727,7 +732,7 @@ void UBPersistenceManager::moveSceneToIndex(UBDocumentProxy* proxy, int source,
}
UBGraphicsScene* UBPersistenceManager::loadDocumentScene(UBDocumentProxy* proxy, int sceneIndex)
UBGraphicsScene* UBPersistenceManager::loadDocumentScene(UBDocumentProxy* proxy, int sceneIndex, bool cacheNeighboringScenes)
{
UBGraphicsScene* scene = NULL;
......@@ -740,11 +745,13 @@ UBGraphicsScene* UBPersistenceManager::loadDocumentScene(UBDocumentProxy* proxy,
mSceneCache.insert(proxy, sceneIndex, scene);
}
if(sceneIndex + 1 < proxy->pageCount() && !mSceneCache.contains(proxy, sceneIndex + 1))
mWorker->readScene(proxy,sceneIndex+1);
if (cacheNeighboringScenes) {
if(sceneIndex + 1 < proxy->pageCount() && !mSceneCache.contains(proxy, sceneIndex + 1))
mWorker->readScene(proxy,sceneIndex+1);
if(sceneIndex - 1 >= 0 && !mSceneCache.contains(proxy, sceneIndex - 1))
mWorker->readScene(proxy,sceneIndex-1);
if(sceneIndex - 1 >= 0 && !mSceneCache.contains(proxy, sceneIndex - 1))
mWorker->readScene(proxy,sceneIndex-1);
}
return scene;
}
......@@ -941,7 +948,6 @@ bool UBPersistenceManager::isEmpty(UBDocumentProxy* pDocumentProxy)
empty = theSoleScene->isEmpty();
if(empty){
mSceneCache.removeScene(pDocumentProxy,0);
delete theSoleScene;
theSoleScene = NULL;
}
else{
......@@ -958,7 +964,6 @@ bool UBPersistenceManager::isEmpty(UBDocumentProxy* pDocumentProxy)
}
if(!usefulItemFound){
mSceneCache.removeScene(pDocumentProxy,0);
delete theSoleScene;
theSoleScene = NULL;
empty = true;
}
......
......@@ -85,7 +85,7 @@ class UBPersistenceManager : public QObject
virtual void moveSceneToIndex(UBDocumentProxy* pDocumentProxy, int source, int target);
virtual UBGraphicsScene* loadDocumentScene(UBDocumentProxy* pDocumentProxy, int sceneIndex);
virtual UBGraphicsScene* loadDocumentScene(UBDocumentProxy* pDocumentProxy, int sceneIndex, bool cacheNeighboringScenes = true);
UBGraphicsScene *getDocumentScene(UBDocumentProxy* pDocumentProxy, int sceneIndex) {return mSceneCache.value(pDocumentProxy, sceneIndex);}
QList<QPointer<UBDocumentProxy> > documentProxies;
......@@ -157,6 +157,8 @@ class UBPersistenceManager : public QObject
QThread* mThread;
bool mIsWorkerFinished;
bool mIsApplicationClosing;
private slots:
void documentRepositoryChanged(const QString& path);
void errorString(QString error);
......
......@@ -73,9 +73,6 @@ const char *UBSettings::sDefaultFontFamily = "Arial";
QString UBSettings::currentFileVersion = "4.8.0";
QColor UBSettings::crossDarkBackground = QColor(44, 44, 44, 200);
QColor UBSettings::crossLightBackground = QColor(165, 225, 255);
QBrush UBSettings::eraserBrushDarkBackground = QBrush(QColor(127, 127, 127, 80));
QBrush UBSettings::eraserBrushLightBackground = QBrush(QColor(255, 255, 255, 30));
......@@ -231,6 +228,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", "");
......@@ -282,6 +280,10 @@ void UBSettings::init()
pageSize = new UBSetting(this, "Board", "DefaultPageSize", documentSizes.value(DocumentSizeRatio::Ratio4_3));
boardCrossColorDarkBackground = new UBSetting(this, "Board", "CrossColorDarkBackground", "#C82C2C2C");
boardCrossColorLightBackground = new UBSetting(this, "Board", "CrossColorLightBackground", "#A5E1FF");
QStringList penLightBackgroundColors;
penLightBackgroundColors << "#000000" << "#FF0000" <<"#004080" << "#008000" << "#FFDD00" << "#C87400" << "#800040" << "#008080" << "#5F2D0A" << "#FFFFFF";
boardPenLightBackgroundColors = new UBColorListSetting(this, "Board", "PenLightBackgroundColors", penLightBackgroundColors, 1.0);
......
......@@ -160,8 +160,6 @@ class UBSettings : public QObject
static int pointerDiameter;
static int boardMargin;
static QColor crossDarkBackground;
static QColor crossLightBackground;
static QColor paletteColor;
static QColor opaquePaletteColor;
......@@ -246,6 +244,7 @@ class UBSettings : public QObject
UBSetting* appToolBarDisplayText;
UBSetting* appEnableAutomaticSoftwareUpdates;
UBSetting* appEnableSoftwareUpdates;
UBSetting* appSoftwareUpdateURI;
UBSetting* appToolBarOrientationVertical;
UBSetting* appPreferredLanguage;
......@@ -286,6 +285,9 @@ class UBSettings : public QObject
UBSetting* featureSliderPosition;
UBSetting* boardCrossColorDarkBackground;
UBSetting* boardCrossColorLightBackground;
UBColorListSetting* boardPenLightBackgroundColors;
UBColorListSetting* boardPenLightBackgroundSelectedColors;
......
......@@ -354,7 +354,10 @@ void UBDesktopAnnotationController::showWindow()
void UBDesktopAnnotationController::close()
{
// NOOP
if (mTransparentDrawingView)
mTransparentDrawingView->hide();
mDesktopPalette->hide();
}
......
......@@ -805,10 +805,12 @@ void UBDocumentController::deleteTreeItem(QTreeWidgetItem * item, bool showConfi
document->parent()->removeChild(document);
UBPersistenceManager::persistenceManager()->deleteDocument(document->proxy());
if (mTrashTi->childCount()==0)
selectDocument(NULL);
else
selectDocument(((UBDocumentProxyTreeItem*)mTrashTi->child(0))->proxy());
if (selectNewDocument) {
if (mTrashTi->childCount()==0)
selectDocument(NULL);
else
selectDocument(((UBDocumentProxyTreeItem*)mTrashTi->child(0))->proxy());
}
reloadThumbnails();
}
......
......@@ -55,6 +55,8 @@ class UBDocumentController : public UBDocumentContainer
{
Q_OBJECT
friend class UBDocumentTreeWidget;
public:
UBDocumentController(UBMainWindow* mainWindow);
virtual ~UBDocumentController();
......@@ -163,5 +165,4 @@ class UBDocumentController : public UBDocumentContainer
};
#endif /* UBDOCUMENTCONTROLLER_H_ */
......@@ -162,7 +162,10 @@ void UBGraphicsGroupContainerItem::removeFromGroup(QGraphicsItem *item)
void UBGraphicsGroupContainerItem::deselectCurrentItem()
{
if (mCurrentItem && mCurrentItem->type() == UBGraphicsMediaItem::Type){
if (mCurrentItem && (mCurrentItem->type() == UBGraphicsMediaItem::Type
|| mCurrentItem->type() == UBGraphicsVideoItem::Type
|| mCurrentItem->type() == UBGraphicsAudioItem::Type))
{
dynamic_cast<UBGraphicsMediaItem*>(mCurrentItem)->Delegate()->getToolBarItem()->hide();
mCurrentItem->setSelected(false);
......
......@@ -252,6 +252,12 @@ void UBGraphicsMediaItem::setMinimumSize(const QSize& size)
this->setSize(width, height);
}
void UBGraphicsMediaItem::setUuid(const QUuid &pUuid)
{
UBItem::setUuid(pUuid);
setData(UBGraphicsItemData::ItemUuid, QVariant(pUuid));
}
void UBGraphicsMediaItem::setMediaFileUrl(QUrl url)
{
mMediaFileUrl = url;
......
......@@ -100,6 +100,7 @@ public:
virtual void setSourceUrl(const QUrl &pSourceUrl);
void setSelected(bool selected);
void setMinimumSize(const QSize& size);
void setUuid(const QUuid &pUuid);
virtual void copyItemParameters(UBItem *copy) const;
......
......@@ -1290,15 +1290,22 @@ UBGraphicsScene* UBGraphicsScene::sceneDeepCopy() const
UBGraphicsGroupContainerItem* groupCloned = group->deepCopyNoChildDuplication();
groupCloned->resetMatrix();
groupCloned->resetTransform();
groupCloned->setMatrix(group->matrix());
groupCloned->setTransform(group->transform());
groupCloned->setPos(0, 0);
bool locked = groupCloned->Delegate()->isLocked();
foreach(QGraphicsItem* eachItem ,group->childItems()){
QGraphicsItem* copiedChild = dynamic_cast<QGraphicsItem*>(dynamic_cast<UBItem*>(eachItem)->deepCopy());
copy->addItem(copiedChild);
groupCloned->addToGroup(copiedChild);
}
if (locked)
groupCloned->setData(UBGraphicsItemData::ItemLocked, QVariant(true));
copy->addItem(groupCloned);
groupCloned->setMatrix(group->matrix());
groupCloned->setTransform(QTransform::fromTranslate(group->pos().x(), group->pos().y()));
groupCloned->setTransform(group->transform(), true);
}
if (ubItem && !stroke && !group && item->isVisible())
......@@ -2503,9 +2510,9 @@ void UBGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect)
QColor bgCrossColor;
if (darkBackground)
bgCrossColor = UBSettings::crossDarkBackground;
bgCrossColor = QColor(UBSettings::settings()->boardCrossColorDarkBackground->get().toString());
else
bgCrossColor = UBSettings::crossLightBackground;
bgCrossColor = QColor(UBSettings::settings()->boardCrossColorLightBackground->get().toString());
if (mZoomFactor < 1.0)
{
int alpha = 255 * mZoomFactor / 2;
......
......@@ -128,10 +128,12 @@ void UBGraphicsStrokesGroup::mousePressEvent(QGraphicsSceneMouseEvent *event)
void UBGraphicsStrokesGroup::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
QGraphicsItemGroup::mouseMoveEvent(event);
if (!isLocked(this)) {
QGraphicsItemGroup::mouseMoveEvent(event);
event->accept();
setSelected(false);
event->accept();
setSelected(false);
}
}
void UBGraphicsStrokesGroup::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
......@@ -173,7 +175,7 @@ UBItem* UBGraphicsStrokesGroup::deepCopy() const
}
}
const_cast<UBGraphicsStrokesGroup*>(this)->setTransform(groupTransform);
copy->setTransform(sceneTransform());
copy->setTransform(groupTransform);
return copy;
}
......@@ -184,6 +186,7 @@ void UBGraphicsStrokesGroup::copyItemParameters(UBItem *copy) const
if(NULL != cp)
{
cp->setTransform(transform());
cp->setPos(pos());
cp->setFlag(QGraphicsItem::ItemIsMovable, true);
cp->setFlag(QGraphicsItem::ItemIsSelectable, true);
......
......@@ -306,8 +306,12 @@ QPainterPath UBGraphicsTextItem::shape() const
void UBGraphicsTextItem::setTextWidth(qreal width)
{
qreal strictMin = 155; // the size of the font customization panel
qreal newWidth = qMax(strictMin, width);
qreal titleBarWidth = 0;
UBGraphicsTextItemDelegate * del = dynamic_cast<UBGraphicsTextItemDelegate*>(Delegate());
if (del)
titleBarWidth = del->titleBarWidth();
qreal newWidth = qMax(titleBarWidth, width);
QGraphicsTextItem::setTextWidth(newWidth);
}
......@@ -328,6 +332,39 @@ qreal UBGraphicsTextItem::textHeight() const
return mTextHeight;
}
/**
* @brief Get the ratio between font size in pixels and points.
* @return The ratio of pixel size to point size of the first character, or 0 if the text item is empty.
*
* Qt may display fonts differently on different platforms -- on the same display,
* the same point size may be displayed at different pixel sizes. This function returns the
* ratio of pixel size to point size, based on the first character in the text item.
*/
qreal UBGraphicsTextItem::pixelsPerPoint() const
{
QTextCursor cursor = textCursor();
if (cursor.isNull())
return 0;
cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
QFont f = cursor.charFormat().font();
qDebug() << "ppp. Font: " << f;
QFontInfo fi(cursor.charFormat().font());
qreal pixelSize = fi.pixelSize();
qreal pointSize = fi.pointSizeF();
//qDebug() << "Pixel size: " << pixelSize;
//qDebug() << "Point size: " << pointSize;
if (pointSize == 0)
return 0;
return pixelSize/pointSize;
}
void UBGraphicsTextItem::contentsChanged()
{
......
......@@ -65,6 +65,7 @@ class UBGraphicsTextItem : public QGraphicsTextItem, public UBItem, public UBRes
void setTextWidth(qreal width);
void setTextHeight(qreal height);
qreal textHeight() const;
qreal pixelsPerPoint() const;
void contentsChanged();
......@@ -101,6 +102,7 @@ class UBGraphicsTextItem : public QGraphicsTextItem, public UBItem, public UBRes
QString mTypeTextHereLabel;
signals:
void textUndoCommandAdded(UBGraphicsTextItem *textItem);
......
......@@ -204,6 +204,31 @@ void UBGraphicsTextItemDelegate::createControls()
}
/**
* @brief Calculate the width of the toolbar containing the text item-related buttons
* @return The space between the left-most and right-most buttons in pixels
*/
qreal UBGraphicsTextItemDelegate::titleBarWidth()
{
if (!mFontButton)
return 0;
// refresh the frame and buttons' positions
positionHandles();
qreal titleBarWidth(0);
qreal frameLeftCoordinate = mFontButton->pos().x();
qreal frameRightCoordinate = frameLeftCoordinate;
foreach(DelegateButton* button, mButtons) {
if (button->getSection() == Qt::TitleBarArea) {
frameLeftCoordinate = qMin(button->pos().x(), frameLeftCoordinate);
frameRightCoordinate = qMax(button->pos().x() + button->boundingRect().width(), frameRightCoordinate);
}
}
return frameRightCoordinate - frameLeftCoordinate;
}
void UBGraphicsTextItemDelegate::freeButtons()
{
......@@ -532,6 +557,9 @@ bool UBGraphicsTextItemDelegate::keyReleaseEvent(QKeyEvent *event)
void UBGraphicsTextItemDelegate::ChangeTextSize(qreal factor, textChangeMode changeMode)
{
// round it to the nearest hundredth
factor = floor(factor*100+0.5)/100.;
if (scaleSize == changeMode)
{
if (1 == factor)
......
......@@ -114,6 +114,7 @@ class UBGraphicsTextItemDelegate : public UBGraphicsItemDelegate
void scaleTextSize(qreal multiplyer);
virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value);
virtual void createControls();
qreal titleBarWidth();
public slots:
void contentsChanged();
......
......@@ -111,9 +111,15 @@ void UBSelectionFrame::setEnclosedItems(const QList<QGraphicsItem*> pGraphicsIte
QRegion resultRegion;
UBGraphicsFlags resultFlags;
mEnclosedtems.clear();
// If at least one of the enclosed items is locked, the entire selection is
// considered to be locked.
mIsLocked = false;
foreach (QGraphicsItem *nextItem, pGraphicsItems) {
UBGraphicsItemDelegate *nextDelegate = UBGraphicsItem::Delegate(nextItem);
if (nextDelegate) {
mIsLocked = (mIsLocked || nextDelegate->isLocked());
mEnclosedtems.append(nextDelegate);
resultRegion |= nextItem->boundingRegion(nextItem->sceneTransform());
resultFlags |= nextDelegate->ubflags();
......@@ -129,6 +135,14 @@ void UBSelectionFrame::setEnclosedItems(const QList<QGraphicsItem*> pGraphicsIte
if (resultRect.isEmpty()) {
hide();
}
if (mIsLocked) {
QColor baseColor = UBSettings::paletteColor;
baseColor.setAlphaF(baseColor.alphaF() / 3);
setLocalBrush(QBrush(baseColor));
}
else
setLocalBrush(QBrush(UBSettings::paletteColor));
}
void UBSelectionFrame::updateRect()
......@@ -168,6 +182,9 @@ void UBSelectionFrame::mousePressEvent(QGraphicsSceneMouseEvent *event)
void UBSelectionFrame::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
if (mIsLocked)
return;
QPointF dp = event->pos() - mPressedPos;
QPointF rotCenter = mapToScene(rect().center());
......
......@@ -103,6 +103,8 @@ private:
QPointF mLastTranslateOffset;
qreal mRotationAngle;
bool mIsLocked;
QList<DelegateButton*> mButtons;
DelegateButton *mDeleteButton;
......
......@@ -188,7 +188,7 @@ QPolygonF UBGeometryUtils::arcToPolygon(const QLineF& startRadius, qreal spanAng
qreal radiusLength = startRadius.length();
qreal angle = 2 * asin(width / (2 * radiusLength)) * 180 / PI;
bool overlap = abs(spanAngleInDegrees) > 360 - angle;
bool overlap = qAbs(spanAngleInDegrees) > 360 - angle;
if (overlap)
spanAngleInDegrees = spanAngleInDegrees < 0 ? -360 : 360;
......
......@@ -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:
......
......@@ -214,79 +214,39 @@ void UBDocumentTreeWidget::focusInEvent(QFocusEvent *event)
QTreeWidget::focusInEvent(event);
}
void UBDocumentTreeWidget::dropEvent(QDropEvent *event)
{
if (mDropTargetProxyTi)
{
if (mDropTargetProxyTi) {
mDropTargetProxyTi->setBackground(0, mBackground);
mDropTargetProxyTi = 0;
}
QTreeWidgetItem* underlyingItem = this->itemAt(event->pos());
UBDocumentGroupTreeItem *groupItem = dynamic_cast<UBDocumentGroupTreeItem*>(underlyingItem);
if (groupItem && mSelectedProxyTi && mSelectedProxyTi->proxy())
{
UBDocumentGroupTreeItem *sourceGroupItem = dynamic_cast<UBDocumentGroupTreeItem*>(mSelectedProxyTi->parent());
bool isTrashItem = sourceGroupItem && sourceGroupItem->isTrashFolder();
if ((isTrashItem && !groupItem->isTrashFolder()) ||
(!isTrashItem && mSelectedProxyTi->proxy()->groupName() != groupItem->groupName()))
{
QString groupName;
if (groupItem->isTrashFolder())
{
QString oldGroupName = mSelectedProxyTi->proxy()->metaData(UBSettings::documentGroupName).toString();
groupName = UBSettings::trashedDocumentGroupNamePrefix + oldGroupName;
}
else
{
if (groupItem->groupName() == UBApplication::app()->documentController->defaultDocumentGroupName())
groupName = "";
else
groupName = groupItem->groupName();
}
mSelectedProxyTi->proxy()->setMetaData(UBSettings::documentGroupName, groupName);
UBPersistenceManager::persistenceManager()->persistDocumentMetadata(mSelectedProxyTi->proxy());
QTreeWidgetItem * underlyingItem = this->itemAt(event->pos());
mSelectedProxyTi->parent()->removeChild(mSelectedProxyTi);
// If the destination is a folder, move the selected document(s) there
UBDocumentGroupTreeItem * destinationFolder = dynamic_cast<UBDocumentGroupTreeItem*>(underlyingItem);
int i = 0;
for (i = 0; i < groupItem->childCount(); i++)
{
QTreeWidgetItem *ti = groupItem->child(i);
UBDocumentProxyTreeItem* pi = dynamic_cast<UBDocumentProxyTreeItem*>(ti);
if (pi)
{
if (mSelectedProxyTi->proxy()->metaData(UBSettings::documentDate).toString() >= pi->proxy()->metaData(UBSettings::documentDate).toString())
{
break;
}
}
}
groupItem->insertChild(i, mSelectedProxyTi);
if (isTrashItem)
mSelectedProxyTi->setFlags(mSelectedProxyTi->flags() | Qt::ItemIsEditable);
if (groupItem->isTrashFolder())
mSelectedProxyTi->setFlags(mSelectedProxyTi->flags() ^ Qt::ItemIsEditable);
expandItem(groupItem);
scrollToItem(mSelectedProxyTi);
if (destinationFolder) {
UBDocumentProxyTreeItem * lastMovedDocument;
foreach(QTreeWidgetItem * item, this->selectedItems()) {
UBDocumentProxyTreeItem * document = dynamic_cast<UBDocumentProxyTreeItem*>(item);
if (document && moveDocument(document, destinationFolder))
lastMovedDocument = document;
}
// disabled, as those 2 calls are buggy on windows, the item disappears if we selected them
//
setCurrentItem(mSelectedProxyTi);
mSelectedProxyTi->setSelected(true);
if (lastMovedDocument) {
expandItem(destinationFolder);
scrollToItem(lastMovedDocument);
setCurrentItem(lastMovedDocument);
lastMovedDocument->setSelected(true);
event->setDropAction(Qt::IgnoreAction);
event->accept();
}
}
else
{
// If the destination is a document and the dropped item is a page, copy the page to that document
else {
QTreeWidgetItem* underlyingTreeItem = this->itemAt(event->pos());
UBDocumentProxyTreeItem *targetProxyTreeItem = dynamic_cast<UBDocumentProxyTreeItem*>(underlyingTreeItem);
......@@ -393,6 +353,67 @@ void UBDocumentTreeWidget::documentUpdated(UBDocumentProxy *pDocument)
}
}
/**
* @brief Move a document to the specified destination folder
* @param document Pointer to the document to move
* @param destinationFolder Pointer to the folder to move the document to
* @return true if document was moved successfully, false otherwise
*/
bool UBDocumentTreeWidget::moveDocument(UBDocumentProxyTreeItem* document, UBDocumentGroupTreeItem* destinationFolder)
{
if (!document || !(document->proxy()) || !destinationFolder)
return false;
UBDocumentGroupTreeItem * sourceFolder = dynamic_cast<UBDocumentGroupTreeItem*>(document->parent());
bool documentIsInTrash = (sourceFolder && sourceFolder->isTrashFolder());
if (documentIsInTrash && destinationFolder->isTrashFolder())
return false;
if (!documentIsInTrash && document->proxy()->groupName() == destinationFolder->groupName())
return false;
QString destinationFolderName;
if (destinationFolder->isTrashFolder()) {
UBApplication::app()->documentController->moveDocumentToTrash(sourceFolder, document, true);
destinationFolderName = document->proxy()->metaData(UBSettings::documentGroupName).toString();
}
else {
if (destinationFolder->groupName() == UBApplication::app()->documentController->defaultDocumentGroupName())
destinationFolderName = "";
else
destinationFolderName = destinationFolder->groupName();
}
// Update the folder name in the document
document->proxy()->setMetaData(UBSettings::documentGroupName, destinationFolderName);
UBPersistenceManager::persistenceManager()->persistDocumentMetadata(document->proxy());
// Remove document from its old folder
document->parent()->removeChild(document);
// Insert document at the right spot in the destination folder (ordered by document date)
int i = 0;
for (i = 0; i < destinationFolder->childCount(); i++) {
QTreeWidgetItem *ti = destinationFolder->child(i);
UBDocumentProxyTreeItem* pi = dynamic_cast<UBDocumentProxyTreeItem*>(ti);
if (pi && document->proxy()->metaData(UBSettings::documentDate).toString() >= pi->proxy()->metaData(UBSettings::documentDate).toString())
break;
}
destinationFolder->insertChild(i, document);
// Update editable status of the document if it was moved to or from the trash
if (documentIsInTrash)
document->setFlags(document->flags() | Qt::ItemIsEditable);
if (destinationFolder->isTrashFolder())
document->setFlags(document->flags() ^ Qt::ItemIsEditable);
return true;
}
UBDocumentProxyTreeItem::UBDocumentProxyTreeItem(QTreeWidgetItem * parent, UBDocumentProxy* proxy, bool isEditable)
: QTreeWidgetItem()
......
......@@ -35,6 +35,7 @@
class UBDocumentProxy;
class UBDocumentProxyTreeItem;
class UBDocumentGroupTreeItem;
class UBDocumentTreeWidget : public QTreeWidget
{
......@@ -60,6 +61,7 @@ class UBDocumentTreeWidget : public QTreeWidget
void autoScroll();
private:
bool moveDocument(UBDocumentProxyTreeItem* document, UBDocumentGroupTreeItem* destinationFolder);
UBDocumentProxyTreeItem *mSelectedProxyTi;
QTreeWidgetItem *mDropTargetProxyTi;
QBrush mBackground;
......
......@@ -125,25 +125,25 @@ class UBGraphicsCompass: public QObject, public QGraphicsRectItem, public UBItem
bool mDrewCenterCross;
// Constants
static const int sNeedleLength = 18;
static const int sNeedleLength = 12;
static const int sNeedleWidth = 3;
static const int sNeedleBaseLength = 12;
static const int sNeedleBaseWidth = 12;
static const int sNeedleBaseLength = 9;
static const int sNeedleBaseWidth = 9;
static const int sNeedleArmLeftWidth = 18;
static const int sNeedleArmRigthWidth = 24;
static const int sNeedleArmLeftWidth = 12;
static const int sNeedleArmRigthWidth = 16;
static const int sPencilLength = 12;
static const int sPencilWidth = 3;
static const int sPencilWidth = 2;
static const int sPencilBaseLength = 18;
static const int sPencilBaseWidth = 12;
static const int sPencilBaseLength = 9;
static const int sPencilBaseWidth = 9;
static const int sPencilArmLeftWidth = 24;
static const int sPencilArmRightWidth = 18;
static const int sPencilArmLeftWidth = 16;
static const int sPencilArmRightWidth = 12;
static const int sCornerRadius = 3;
static const int sCornerRadius = 2;
static const QRect sDefaultRect;
static const int sMinRadius;
......
......@@ -41,6 +41,7 @@
const QRectF UBGraphicsProtractor::sDefaultRect = QRectF(-250, -250, 500, 500);
const qreal UBGraphicsProtractor::minRadius = 70;
UBGraphicsProtractor::UBGraphicsProtractor()
: QGraphicsEllipseItem(sDefaultRect)
......@@ -213,11 +214,13 @@ void UBGraphicsProtractor::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
case Resize :
prepareGeometryChange();
setTransform(QTransform::fromTranslate(rect().center().x(), rect().center().y()), true);
setTransform(QTransform::fromScale(scaleFactor, scaleFactor), true);
setTransform(QTransform::fromTranslate(-rect().center().x(), -rect().center().y()), true);
mScaleFactor *= scaleFactor;
if (radius() * mScaleFactor * scaleFactor > minRadius) {
prepareGeometryChange();
setTransform(QTransform::fromTranslate(rect().center().x(), rect().center().y()), true);
setTransform(QTransform::fromScale(scaleFactor, scaleFactor), true);
setTransform(QTransform::fromTranslate(-rect().center().x(), -rect().center().y()), true);
mScaleFactor *= scaleFactor;
}
break;
case MoveMarker :
......
......@@ -119,6 +119,7 @@ class UBGraphicsProtractor : public UBAbstractDrawRuler, public QGraphicsEllipse
QGraphicsSvgItem* mRotateSvgItem;
static const QRectF sDefaultRect;
static const qreal minRadius;
virtual void rotateAroundCenter(qreal angle);
virtual QPointF rotationCenter() const;
......
......@@ -49,6 +49,7 @@ UBGraphicsTriangle::UBGraphicsTriangle()
, mResizing1(false)
, mResizing2(false)
, mRotating(false)
, mShouldPaintInnerTriangle(true)
{
setRect(sDefaultRect, sDefaultOrientation);
......@@ -224,6 +225,29 @@ void UBGraphicsTriangle::calculatePoints(const QRectF& r)
C2.setX(r.left() + L); C2.setY(r.bottom() - d);
break;
}
bool paintInnerTriangle = true;
switch(mOrientation)
{
case BottomLeft:
if (B2.x() > C2.x() || B2.y() < A2.y())
paintInnerTriangle = false;
break;
case TopLeft:
if (B2.x() > C2.x() || B2.y() > A2.y())
paintInnerTriangle = false;
break;
case TopRight:
if (B2.x() < C2.x() || B2.y() > A2.y())
paintInnerTriangle = false;
break;
case BottomRight:
if (B2.x() < C2.x() || B2.y() < A2.y())
paintInnerTriangle = false;
break;
}
mShouldPaintInnerTriangle = paintInnerTriangle;
W1 = rect().height() * d / C;
H1 = rect().width() * d / C;
......@@ -251,40 +275,54 @@ void UBGraphicsTriangle::paint(QPainter *painter, const QStyleOptionGraphicsItem
QPolygonF polygon;
QLinearGradient gradient1(QPointF(A1.x(), 0), QPointF(A2.x(), 0));
gradient1.setColorAt(0, edgeFillColor());
gradient1.setColorAt(1, middleFillColor());
painter->setBrush(gradient1);
polygon << A1 << A2 << B2 << B1;
painter->drawPolygon(polygon);
polygon.clear();
QLinearGradient gradient2(QPointF(0, B1.y()), QPointF(0, B2.y()));
gradient2.setColorAt(0, edgeFillColor());
gradient2.setColorAt(1, middleFillColor());
painter->setBrush(gradient2);
polygon << B1 << B2 << C2 << C1;
painter->drawPolygon(polygon);
polygon.clear();
QLinearGradient gradient3(CC, C2);
gradient3.setColorAt(0, edgeFillColor());
gradient3.setColorAt(1, middleFillColor());
painter->setBrush(gradient3);
polygon << C1 << C2 << A2 << A1;
painter->drawPolygon(polygon);
polygon.clear();
painter->setBrush(Qt::NoBrush);
painter->setPen(drawColor());
if (mShouldPaintInnerTriangle) {
QLinearGradient gradient1(QPointF(A1.x(), 0), QPointF(A2.x(), 0));
gradient1.setColorAt(0, edgeFillColor());
gradient1.setColorAt(1, middleFillColor());
painter->setBrush(gradient1);
polygon << A1 << A2 << B2 << B1;
painter->drawPolygon(polygon);
polygon.clear();
QLinearGradient gradient2(QPointF(0, B1.y()), QPointF(0, B2.y()));
gradient2.setColorAt(0, edgeFillColor());
gradient2.setColorAt(1, middleFillColor());
painter->setBrush(gradient2);
polygon << B1 << B2 << C2 << C1;
painter->drawPolygon(polygon);
polygon.clear();
QLinearGradient gradient3(CC, C2);
gradient3.setColorAt(0, edgeFillColor());
gradient3.setColorAt(1, middleFillColor());
painter->setBrush(gradient3);
polygon << C1 << C2 << A2 << A1;
painter->drawPolygon(polygon);
polygon.clear();
painter->setBrush(Qt::NoBrush);
painter->setPen(drawColor());
polygon << A1 << B1 << C1;
painter->drawPolygon(polygon);
polygon.clear();
polygon << A2 << B2 << C2;
painter->drawPolygon(polygon);
}
polygon << A1 << B1 << C1;
painter->drawPolygon(polygon);
polygon.clear();
else {
QLinearGradient gradient(QPointF(A1.x(), 0), QPointF(C1.x(), 0));
gradient.setColorAt(0, edgeFillColor());
gradient.setColorAt(1, middleFillColor());
painter->setBrush(gradient);
painter->setPen(drawColor());
polygon << A1 << B1 << C1;
painter->drawPolygon(polygon);
polygon.clear();
}
polygon << A2 << B2 << C2;
painter->drawPolygon(polygon);
paintGraduations(painter);
......@@ -329,9 +367,11 @@ QPainterPath UBGraphicsTriangle::shape() const
tShape.addPolygon(tPolygon);
tPolygon.clear();
tPolygon << A2 << B2 << C2;
tShape.addPolygon(tPolygon);
tPolygon.clear();
if (mShouldPaintInnerTriangle) {
tPolygon << A2 << B2 << C2;
tShape.addPolygon(tPolygon);
tPolygon.clear();
}
//qDebug() << "UBGraphicsTriangle shape()"<<"A1 ="<<A1<<"B1 ="<<B1<<"C1 ="<<C1;
//qDebug() << "UBGraphicsTriangle shape()"<<"A2 ="<<A2<<"B2 ="<<B2<<"C2 ="<<C2;
......@@ -607,19 +647,21 @@ QRectF UBGraphicsTriangle::vFlipRect() const
QRectF UBGraphicsTriangle::rotateRect() const
{
QPointF p(C2);
qreal buttonsX = vFlipRect().left();
switch(mOrientation)
{
case BottomLeft:
p += QPointF(20, 5);
p = QPointF(qMax(p.x() + 20, buttonsX), p.y() + 5);
break;
case TopLeft:
p += QPointF(20, -5 - mRotateSvgItem->boundingRect().height());
p = QPointF(qMax(p.x() + 20, buttonsX), p.y() -5 - mRotateSvgItem->boundingRect().height());
break;
case TopRight:
p += QPointF(-20 - mRotateSvgItem->boundingRect().width(), -5 - mRotateSvgItem->boundingRect().height());
p = QPointF(qMin(p.x() -20 - mRotateSvgItem->boundingRect().width(), buttonsX), p.y() - 5 - mRotateSvgItem->boundingRect().height());
break;
case BottomRight:
p += QPointF(-20 - mRotateSvgItem->boundingRect().width(), 5);
p = QPointF(qMin(p.x() -20 - mRotateSvgItem->boundingRect().width(), buttonsX), p.y() + 5);
break;
}
return QRectF(p, QSizeF(mRotateSvgItem->boundingRect().size()));
......@@ -821,9 +863,9 @@ void UBGraphicsTriangle::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
mShowButtons = true;
mCloseSvgItem->setVisible(true);
mHFlipSvgItem->setVisible(true);
mVFlipSvgItem->setVisible(true);
mRotateSvgItem->setVisible(true);
mHFlipSvgItem->setVisible(contains(hFlipRect()));
mVFlipSvgItem->setVisible(contains(vFlipRect()));
mRotateSvgItem->setVisible(contains(rotateRect()));
if (resize1Polygon().containsPoint(event->pos().toPoint(), Qt::OddEvenFill))
setCursor(resizeCursor1());
......@@ -875,9 +917,9 @@ void UBGraphicsTriangle::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
currentTool == UBStylusTool::Play)
{
mCloseSvgItem->setVisible(mShowButtons);
mVFlipSvgItem->setVisible(mShowButtons);
mHFlipSvgItem->setVisible(mShowButtons);
mRotateSvgItem->setVisible(mShowButtons);
mVFlipSvgItem->setVisible(mShowButtons && contains(vFlipRect()));
mHFlipSvgItem->setVisible(mShowButtons && contains(hFlipRect()));
mRotateSvgItem->setVisible(mShowButtons && contains(rotateRect()));
if (resize1Polygon().containsPoint(event->pos().toPoint(), Qt::OddEvenFill))
setCursor(resizeCursor1());
......@@ -950,6 +992,35 @@ void UBGraphicsTriangle::DrawLine(const QPointF &scenePos, qreal width)
UBDrawingController::drawingController()->stylusTool() != UBStylusTool::Marker);
}
/**
* @brief Check whether a given QRectF is inside the triangle (A1, B1, C1).
*
* Returns true if any corner of the rectangle is within the triangle or, if strict is set to true,
* if all corners of the rectangle are within the triangle.
*/
bool UBGraphicsTriangle::contains(const QRectF &rect, bool strict)
{
QPolygonF poly;
poly << A1 << B1 << C1 << A1;
QPainterPath path;
path.addPolygon(poly);
QList<QPointF> points;
points << rect.bottomRight() << rect.topLeft() << rect.topRight();
bool inside = path.contains(rect.bottomLeft());
foreach(QPointF p, points) {
if (strict)
inside = inside && path.contains(p);
else
inside = inside || path.contains(p);
}
return inside;
}
void UBGraphicsTriangle::EndLine()
{
}
......
......@@ -98,7 +98,7 @@ class UBGraphicsTriangle : public UBAbstractDrawRuler, public QGraphicsPolygonIt
void setRect(const QRectF &rect, UBGraphicsTriangleOrientation orientation)
{
qDebug() << "setRect"<<"rect = "<<rect<<"orientation :"<<orientation;
//qDebug() << "setRect"<<"rect = "<<rect<<"orientation :"<<orientation;
setRect(rect.x(), rect.y(), rect.width(), rect.height(), orientation);
}
......@@ -178,11 +178,15 @@ class UBGraphicsTriangle : public UBAbstractDrawRuler, public QGraphicsPolygonIt
QPointF CC; // Hyp. fillining gradient - top point
void calculatePoints(const QRectF& rect);
bool mShouldPaintInnerTriangle;
static const int d = 70; // width of triangle border
static const int sArrowLength = 30;
static const int sMinWidth = 380;
static const int sMinHeight = 200;
static const int sMinWidth = 240;
static const int sMinHeight = 120;
qreal mStrokeWidth;
bool contains(const QRectF &rect, bool strict = true);
};
#endif /* UBGRAPHICSTRIANGLE_H_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment