From bb08fb652864f75d28c7fe5df6313929a03a295d Mon Sep 17 00:00:00 2001 From: Lasse Holmstedt Date: Thu, 8 Jul 2010 14:00:33 +0200 Subject: [PATCH] added custom qmlviewer to creator This qmlviewer will be also the default one when opening qmlproject files as the runconfiguration was changed too. --- .../qmlprojectrunconfiguration.cpp | 22 +- src/tools/qml/qml.pro | 7 +- src/tools/qml/qmlviewer/Info_mac.plist | 18 + src/tools/qml/qmlviewer/content/Browser.qml | 284 ++++ .../qml/qmlviewer/content/images/folder.png | Bin 0 -> 1841 bytes .../qml/qmlviewer/content/images/titlebar.png | Bin 0 -> 1436 bytes .../qml/qmlviewer/content/images/titlebar.sci | 5 + src/tools/qml/qmlviewer/content/images/up.png | Bin 0 -> 662 bytes src/tools/qml/qmlviewer/deviceorientation.cpp | 75 + src/tools/qml/qmlviewer/deviceorientation.h | 81 + .../qmlviewer/deviceorientation_maemo5.cpp | 127 ++ .../editor/abstractformeditortool.cpp | 193 +++ .../qmlviewer/editor/abstractformeditortool.h | 104 ++ .../editor/boundingrecthighlighter.cpp | 129 ++ .../editor/boundingrecthighlighter.h | 54 + .../qml/qmlviewer/editor/colorpickertool.cpp | 99 ++ .../qml/qmlviewer/editor/colorpickertool.h | 54 + src/tools/qml/qmlviewer/editor/editor.pri | 38 + src/tools/qml/qmlviewer/editor/editor.qrc | 13 + .../qmlviewer/editor/images/color-picker.png | Bin 0 -> 3185 bytes .../qml/qmlviewer/editor/images/from-qml.png | Bin 0 -> 3251 bytes .../qml/qmlviewer/editor/images/pause.png | Bin 0 -> 3110 bytes .../qml/qmlviewer/editor/images/play.png | Bin 0 -> 3367 bytes .../qmlviewer/editor/images/resize_handle.png | Bin 0 -> 160 bytes .../editor/images/select-marquee.png | Bin 0 -> 2878 bytes .../qml/qmlviewer/editor/images/select.png | Bin 0 -> 3359 bytes .../qml/qmlviewer/editor/images/to-qml.png | Bin 0 -> 3271 bytes .../qml/qmlviewer/editor/images/zoom.png | Bin 0 -> 3296 bytes src/tools/qml/qmlviewer/editor/layeritem.cpp | 78 + src/tools/qml/qmlviewer/editor/layeritem.h | 57 + .../qml/qmlviewer/editor/movemanipulator.cpp | 360 +++++ .../qml/qmlviewer/editor/movemanipulator.h | 116 ++ src/tools/qml/qmlviewer/editor/movetool.cpp | 377 +++++ src/tools/qml/qmlviewer/editor/movetool.h | 91 ++ src/tools/qml/qmlviewer/editor/qmltoolbar.cpp | 210 +++ src/tools/qml/qmlviewer/editor/qmltoolbar.h | 73 + .../qml/qmlviewer/editor/qmlviewerconstants.h | 37 + .../qml/qmlviewer/editor/resize_handle.png | Bin 0 -> 160 bytes .../qml/qmlviewer/editor/resizecontroller.cpp | 293 ++++ .../qml/qmlviewer/editor/resizecontroller.h | 106 ++ .../qml/qmlviewer/editor/resizehandleitem.cpp | 126 ++ .../qml/qmlviewer/editor/resizehandleitem.h | 89 + .../qml/qmlviewer/editor/resizeindicator.cpp | 95 ++ .../qml/qmlviewer/editor/resizeindicator.h | 82 + .../qmlviewer/editor/resizemanipulator.cpp | 529 ++++++ .../qml/qmlviewer/editor/resizemanipulator.h | 93 ++ src/tools/qml/qmlviewer/editor/resizetool.cpp | 204 +++ src/tools/qml/qmlviewer/editor/resizetool.h | 82 + .../editor/rubberbandselectionmanipulator.cpp | 143 ++ .../editor/rubberbandselectionmanipulator.h | 82 + .../qmlviewer/editor/selectionindicator.cpp | 114 ++ .../qml/qmlviewer/editor/selectionindicator.h | 61 + .../qmlviewer/editor/selectionrectangle.cpp | 87 + .../qml/qmlviewer/editor/selectionrectangle.h | 62 + .../qml/qmlviewer/editor/selectiontool.cpp | 434 +++++ .../qml/qmlviewer/editor/selectiontool.h | 110 ++ .../editor/singleselectionmanipulator.cpp | 133 ++ .../editor/singleselectionmanipulator.h | 77 + .../qmlviewer/editor/snappinglinecreator.cpp | 188 +++ .../qmlviewer/editor/snappinglinecreator.h | 102 ++ .../editor/subcomponenteditortool.cpp | 227 +++ .../qmlviewer/editor/subcomponenteditortool.h | 71 + .../editor/subcomponentmasklayeritem.cpp | 53 + .../editor/subcomponentmasklayeritem.h | 26 + .../qml/qmlviewer/editor/toolbarcolorbox.cpp | 96 ++ .../qml/qmlviewer/editor/toolbarcolorbox.h | 41 + src/tools/qml/qmlviewer/editor/zoomtool.cpp | 291 ++++ src/tools/qml/qmlviewer/editor/zoomtool.h | 67 + src/tools/qml/qmlviewer/loggerwidget.cpp | 201 +++ src/tools/qml/qmlviewer/loggerwidget.h | 99 ++ src/tools/qml/qmlviewer/main.cpp | 461 ++++++ src/tools/qml/qmlviewer/proxysettings.cpp | 113 ++ src/tools/qml/qmlviewer/proxysettings.h | 75 + src/tools/qml/qmlviewer/proxysettings.ui | 115 ++ .../qml/qmlviewer/proxysettings_maemo5.ui | 177 ++ .../qdeclarativedesigndebugserver.cpp | 92 ++ .../qmlviewer/qdeclarativedesigndebugserver.h | 87 + .../qml/qmlviewer/qdeclarativedesignview.cpp | 465 ++++++ .../qml/qmlviewer/qdeclarativedesignview.h | 118 ++ .../qml/qmlviewer/qdeclarativetester.cpp | 407 +++++ src/tools/qml/qmlviewer/qdeclarativetester.h | 289 ++++ src/tools/qml/qmlviewer/qml.icns | Bin 0 -> 196156 bytes src/tools/qml/qmlviewer/qml.pri | 38 + src/tools/qml/qmlviewer/qmlruntime.cpp | 1434 +++++++++++++++++ src/tools/qml/qmlviewer/qmlruntime.h | 210 +++ src/tools/qml/qmlviewer/qmlruntime.qrc | 9 + src/tools/qml/qmlviewer/qmlviewer.pro | 18 + src/tools/qml/qmlviewer/recopts.ui | 513 ++++++ src/tools/qml/qmlviewer/recopts_maemo5.ui | 254 +++ .../qmlviewer/texteditautoresizer_maemo5.h | 113 ++ 90 files changed, 12147 insertions(+), 7 deletions(-) create mode 100644 src/tools/qml/qmlviewer/Info_mac.plist create mode 100644 src/tools/qml/qmlviewer/content/Browser.qml create mode 100644 src/tools/qml/qmlviewer/content/images/folder.png create mode 100644 src/tools/qml/qmlviewer/content/images/titlebar.png create mode 100644 src/tools/qml/qmlviewer/content/images/titlebar.sci create mode 100644 src/tools/qml/qmlviewer/content/images/up.png create mode 100644 src/tools/qml/qmlviewer/deviceorientation.cpp create mode 100644 src/tools/qml/qmlviewer/deviceorientation.h create mode 100644 src/tools/qml/qmlviewer/deviceorientation_maemo5.cpp create mode 100644 src/tools/qml/qmlviewer/editor/abstractformeditortool.cpp create mode 100644 src/tools/qml/qmlviewer/editor/abstractformeditortool.h create mode 100644 src/tools/qml/qmlviewer/editor/boundingrecthighlighter.cpp create mode 100644 src/tools/qml/qmlviewer/editor/boundingrecthighlighter.h create mode 100644 src/tools/qml/qmlviewer/editor/colorpickertool.cpp create mode 100644 src/tools/qml/qmlviewer/editor/colorpickertool.h create mode 100644 src/tools/qml/qmlviewer/editor/editor.pri create mode 100644 src/tools/qml/qmlviewer/editor/editor.qrc create mode 100644 src/tools/qml/qmlviewer/editor/images/color-picker.png create mode 100644 src/tools/qml/qmlviewer/editor/images/from-qml.png create mode 100644 src/tools/qml/qmlviewer/editor/images/pause.png create mode 100644 src/tools/qml/qmlviewer/editor/images/play.png create mode 100644 src/tools/qml/qmlviewer/editor/images/resize_handle.png create mode 100644 src/tools/qml/qmlviewer/editor/images/select-marquee.png create mode 100644 src/tools/qml/qmlviewer/editor/images/select.png create mode 100644 src/tools/qml/qmlviewer/editor/images/to-qml.png create mode 100644 src/tools/qml/qmlviewer/editor/images/zoom.png create mode 100644 src/tools/qml/qmlviewer/editor/layeritem.cpp create mode 100644 src/tools/qml/qmlviewer/editor/layeritem.h create mode 100644 src/tools/qml/qmlviewer/editor/movemanipulator.cpp create mode 100644 src/tools/qml/qmlviewer/editor/movemanipulator.h create mode 100644 src/tools/qml/qmlviewer/editor/movetool.cpp create mode 100644 src/tools/qml/qmlviewer/editor/movetool.h create mode 100644 src/tools/qml/qmlviewer/editor/qmltoolbar.cpp create mode 100644 src/tools/qml/qmlviewer/editor/qmltoolbar.h create mode 100644 src/tools/qml/qmlviewer/editor/qmlviewerconstants.h create mode 100644 src/tools/qml/qmlviewer/editor/resize_handle.png create mode 100644 src/tools/qml/qmlviewer/editor/resizecontroller.cpp create mode 100644 src/tools/qml/qmlviewer/editor/resizecontroller.h create mode 100644 src/tools/qml/qmlviewer/editor/resizehandleitem.cpp create mode 100644 src/tools/qml/qmlviewer/editor/resizehandleitem.h create mode 100644 src/tools/qml/qmlviewer/editor/resizeindicator.cpp create mode 100644 src/tools/qml/qmlviewer/editor/resizeindicator.h create mode 100644 src/tools/qml/qmlviewer/editor/resizemanipulator.cpp create mode 100644 src/tools/qml/qmlviewer/editor/resizemanipulator.h create mode 100644 src/tools/qml/qmlviewer/editor/resizetool.cpp create mode 100644 src/tools/qml/qmlviewer/editor/resizetool.h create mode 100644 src/tools/qml/qmlviewer/editor/rubberbandselectionmanipulator.cpp create mode 100644 src/tools/qml/qmlviewer/editor/rubberbandselectionmanipulator.h create mode 100644 src/tools/qml/qmlviewer/editor/selectionindicator.cpp create mode 100644 src/tools/qml/qmlviewer/editor/selectionindicator.h create mode 100644 src/tools/qml/qmlviewer/editor/selectionrectangle.cpp create mode 100644 src/tools/qml/qmlviewer/editor/selectionrectangle.h create mode 100644 src/tools/qml/qmlviewer/editor/selectiontool.cpp create mode 100644 src/tools/qml/qmlviewer/editor/selectiontool.h create mode 100644 src/tools/qml/qmlviewer/editor/singleselectionmanipulator.cpp create mode 100644 src/tools/qml/qmlviewer/editor/singleselectionmanipulator.h create mode 100644 src/tools/qml/qmlviewer/editor/snappinglinecreator.cpp create mode 100644 src/tools/qml/qmlviewer/editor/snappinglinecreator.h create mode 100644 src/tools/qml/qmlviewer/editor/subcomponenteditortool.cpp create mode 100644 src/tools/qml/qmlviewer/editor/subcomponenteditortool.h create mode 100644 src/tools/qml/qmlviewer/editor/subcomponentmasklayeritem.cpp create mode 100644 src/tools/qml/qmlviewer/editor/subcomponentmasklayeritem.h create mode 100644 src/tools/qml/qmlviewer/editor/toolbarcolorbox.cpp create mode 100644 src/tools/qml/qmlviewer/editor/toolbarcolorbox.h create mode 100644 src/tools/qml/qmlviewer/editor/zoomtool.cpp create mode 100644 src/tools/qml/qmlviewer/editor/zoomtool.h create mode 100644 src/tools/qml/qmlviewer/loggerwidget.cpp create mode 100644 src/tools/qml/qmlviewer/loggerwidget.h create mode 100644 src/tools/qml/qmlviewer/main.cpp create mode 100644 src/tools/qml/qmlviewer/proxysettings.cpp create mode 100644 src/tools/qml/qmlviewer/proxysettings.h create mode 100644 src/tools/qml/qmlviewer/proxysettings.ui create mode 100644 src/tools/qml/qmlviewer/proxysettings_maemo5.ui create mode 100644 src/tools/qml/qmlviewer/qdeclarativedesigndebugserver.cpp create mode 100644 src/tools/qml/qmlviewer/qdeclarativedesigndebugserver.h create mode 100644 src/tools/qml/qmlviewer/qdeclarativedesignview.cpp create mode 100644 src/tools/qml/qmlviewer/qdeclarativedesignview.h create mode 100644 src/tools/qml/qmlviewer/qdeclarativetester.cpp create mode 100644 src/tools/qml/qmlviewer/qdeclarativetester.h create mode 100644 src/tools/qml/qmlviewer/qml.icns create mode 100644 src/tools/qml/qmlviewer/qml.pri create mode 100644 src/tools/qml/qmlviewer/qmlruntime.cpp create mode 100644 src/tools/qml/qmlviewer/qmlruntime.h create mode 100644 src/tools/qml/qmlviewer/qmlruntime.qrc create mode 100644 src/tools/qml/qmlviewer/qmlviewer.pro create mode 100644 src/tools/qml/qmlviewer/recopts.ui create mode 100644 src/tools/qml/qmlviewer/recopts_maemo5.ui create mode 100644 src/tools/qml/qmlviewer/texteditautoresizer_maemo5.h diff --git a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp index 3b959f83af0..61e1bd0e560 100644 --- a/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp +++ b/src/plugins/qmlprojectmanager/qmlprojectrunconfiguration.cpp @@ -96,18 +96,28 @@ void QmlProjectRunConfiguration::ctor() setDisplayName(tr("QML Viewer", "QMLRunConfiguration display name.")); - // prepend creator/bin dir to search path (only useful for special creator-qml package) - const QString searchPath = QCoreApplication::applicationDirPath() - + Utils::SynchronousProcess::pathSeparator() - + QString(qgetenv("PATH")); - #ifdef Q_OS_MAC const QString qmlViewerName = QLatin1String("QMLViewer"); #else const QString qmlViewerName = QLatin1String("qmlviewer"); #endif - m_qmlViewerDefaultPath = Utils::SynchronousProcess::locateBinary(searchPath, qmlViewerName); + if (m_qmlViewerDefaultPath.isEmpty()) { + QDir qmlviewerExecutable(QCoreApplication::applicationDirPath()); +#ifndef Q_OS_WIN + m_qmlViewerDefaultPath = qmlviewerExecutable.absoluteFilePath(qmlViewerName); +#else + m_qmlViewerDefaultPath = qmlviewerExecutable.absoluteFilePath(QString("%1.exe").arg(qmlViewerName)); +#endif + QFileInfo qmlviewerFileInfo(m_qmlViewerDefaultPath); + if (!qmlviewerFileInfo.exists()) { + qWarning() << "QmlProjectRunConfiguration::ctor(): qmlviewer executable does not exist at" << m_qmlViewerDefaultPath; + m_qmlViewerDefaultPath.clear(); + } else if (!qmlviewerFileInfo.isFile()) { + qWarning() << "QmlProjectRunConfiguration::ctor(): " << m_qmlViewerDefaultPath << " is not a file"; + m_qmlViewerDefaultPath.clear(); + } + } } QmlProjectRunConfiguration::~QmlProjectRunConfiguration() diff --git a/src/tools/qml/qml.pro b/src/tools/qml/qml.pro index fb6d736077a..42a03b117c3 100644 --- a/src/tools/qml/qml.pro +++ b/src/tools/qml/qml.pro @@ -4,7 +4,7 @@ contains(QT_CONFIG, declarative) { include(../../private_headers.pri) exists($${QT_PRIVATE_HEADERS}/QtDeclarative/private/qdeclarativemetatype_p.h) { - SUBDIRS += qmldump + SUBDIRS += qmldump qmlviewer } else { warning() warning("QmlDump utility has been disabled") @@ -12,6 +12,11 @@ contains(QT_CONFIG, declarative) { warning("This means the Qml editor will lack correct completion and type checking.") warning("To enable it, pass 'QT_PRIVATE_HEADERS=$QTDIR/include' to qmake, where $QTDIR is the source directory of qt.") warning() + warning("QmlViewer has been disabled") + warning("This application depends on private headers from QtDeclarative module.") + warning("This means the QML debugging facilities will be limited.") + warning("To enable it, pass 'QT_PRIVATE_HEADERS=$QTDIR/include' to qmake, where $QTDIR is the source directory of qt.") + warning() } } diff --git a/src/tools/qml/qmlviewer/Info_mac.plist b/src/tools/qml/qmlviewer/Info_mac.plist new file mode 100644 index 00000000000..80ca6a35269 --- /dev/null +++ b/src/tools/qml/qmlviewer/Info_mac.plist @@ -0,0 +1,18 @@ + + + + + CFBundleIconFile + @ICON@ + CFBundleIdentifier + com.nokia.qt.qml + CFBundlePackageType + APPL + CFBundleGetInfoString + Created by Qt/QMake + CFBundleSignature + @TYPEINFO@ + CFBundleExecutable + @EXECUTABLE@ + + diff --git a/src/tools/qml/qmlviewer/content/Browser.qml b/src/tools/qml/qmlviewer/content/Browser.qml new file mode 100644 index 00000000000..ff2bb476473 --- /dev/null +++ b/src/tools/qml/qmlviewer/content/Browser.qml @@ -0,0 +1,284 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import Qt 4.7 +import Qt.labs.folderlistmodel 1.0 + +Rectangle { + id: root + property bool keyPressed: false + property variant folders: folders1 + property variant view: view1 + width: 320 + height: 480 + color: palette.window + + FolderListModel { + id: folders1 + nameFilters: [ "*.qml" ] + folder: qmlViewerFolder + } + FolderListModel { + id: folders2 + nameFilters: [ "*.qml" ] + folder: qmlViewerFolder + } + + SystemPalette { id: palette } + + function down(path) { + if (folders == folders1) { + view = view2 + folders = folders2; + view1.state = "exitLeft"; + } else { + view = view1 + folders = folders1; + view2.state = "exitLeft"; + } + view.x = root.width; + view.state = "current"; + view.focus = true; + folders.folder = path; + } + function up() { + var path = folders.parentFolder; + if (folders == folders1) { + view = view2 + folders = folders2; + view1.state = "exitRight"; + } else { + view = view1 + folders = folders1; + view2.state = "exitRight"; + } + view.x = -root.width; + view.state = "current"; + view.focus = true; + folders.folder = path; + } + + Component { + id: folderDelegate + Rectangle { + id: wrapper + function launch() { + if (folders.isFolder(index)) { + down(filePath); + } else { + qmlViewer.launch(filePath); + } + } + width: root.width + height: 52 + color: "transparent" + Rectangle { + id: highlight; visible: false + anchors.fill: parent + gradient: Gradient { + GradientStop { id: t1; position: 0.0; color: palette.highlight } + GradientStop { id: t2; position: 1.0; color: Qt.lighter(palette.highlight) } + } + } + Item { + width: 48; height: 48 + Image { source: "images/folder.png"; anchors.centerIn: parent; visible: folders.isFolder(index)} + } + Text { + id: nameText + anchors.fill: parent; verticalAlignment: Text.AlignVCenter + text: fileName + anchors.leftMargin: 54 + font.pixelSize: 32 + color: (wrapper.ListView.isCurrentItem && root.keyPressed) ? palette.highlightedText : palette.windowText + elide: Text.ElideRight + } + MouseArea { + id: mouseRegion + anchors.fill: parent + onClicked: { if (folders == wrapper.ListView.view.model) launch() } + } + states: [ + State { + name: "pressed" + when: mouseRegion.pressed + PropertyChanges { target: highlight; visible: true } + PropertyChanges { target: nameText; color: palette.highlightedText } + } + ] + } + } + + ListView { + id: view1 + anchors.top: titleBar.bottom + anchors.bottom: parent.bottom + x: 0 + width: parent.width + model: folders1 + delegate: folderDelegate + highlight: Rectangle { color: palette.highlight; visible: root.keyPressed && view1.count != 0 } + highlightMoveSpeed: 1000 + pressDelay: 100 + focus: true + state: "current" + states: [ + State { + name: "current" + PropertyChanges { target: view1; x: 0 } + }, + State { + name: "exitLeft" + PropertyChanges { target: view1; x: -root.width } + }, + State { + name: "exitRight" + PropertyChanges { target: view1; x: root.width } + } + ] + transitions: [ + Transition { + to: "current" + SequentialAnimation { + NumberAnimation { properties: "x"; duration: 250 } + } + }, + Transition { + NumberAnimation { properties: "x"; duration: 250 } + NumberAnimation { properties: "x"; duration: 250 } + } + ] + Keys.onPressed: { root.keyPressed = true; } + } + + ListView { + id: view2 + anchors.top: titleBar.bottom + anchors.bottom: parent.bottom + x: parent.width + width: parent.width + model: folders2 + delegate: folderDelegate + highlight: Rectangle { color: palette.highlight; visible: root.keyPressed && view2.count != 0 } + highlightMoveSpeed: 1000 + pressDelay: 100 + states: [ + State { + name: "current" + PropertyChanges { target: view2; x: 0 } + }, + State { + name: "exitLeft" + PropertyChanges { target: view2; x: -root.width } + }, + State { + name: "exitRight" + PropertyChanges { target: view2; x: root.width } + } + ] + transitions: [ + Transition { + to: "current" + SequentialAnimation { + NumberAnimation { properties: "x"; duration: 250 } + } + }, + Transition { + NumberAnimation { properties: "x"; duration: 250 } + } + ] + Keys.onPressed: { root.keyPressed = true; } + } + + Keys.onPressed: { + root.keyPressed = true; + if (event.key == Qt.Key_Return || event.key == Qt.Key_Select || event.key == Qt.Key_Right) { + view.currentItem.launch(); + event.accepted = true; + } else if (event.key == Qt.Key_Left) { + up(); + } + } + + BorderImage { + source: "images/titlebar.sci"; + width: parent.width; + height: 52 + y: -7 + id: titleBar + + Rectangle { + id: upButton + width: 48 + height: titleBar.height - 7 + color: "transparent" + + Image { anchors.centerIn: parent; source: "images/up.png" } + MouseArea { id: upRegion; anchors.centerIn: parent + width: 56 + height: 56 + onClicked: if (folders.parentFolder != "") up() + } + states: [ + State { + name: "pressed" + when: upRegion.pressed + PropertyChanges { target: upButton; color: palette.highlight } + } + ] + } + Rectangle { + color: "gray" + x: 48 + width: 1 + height: 44 + } + + Text { + anchors.left: upButton.right; anchors.right: parent.right; height: parent.height + anchors.leftMargin: 4; anchors.rightMargin: 4 + text: folders.folder + color: "white" + elide: Text.ElideLeft; horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter + font.pixelSize: 32 + } + } +} diff --git a/src/tools/qml/qmlviewer/content/images/folder.png b/src/tools/qml/qmlviewer/content/images/folder.png new file mode 100644 index 0000000000000000000000000000000000000000..e53e2ad464eb993256a6c3567fc940498e26fc8b GIT binary patch literal 1841 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}EX7WqAsieW95oy%9SjT% zoCO|{#S9Fhbs)^>`s>ep1_lPn64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xh zq!<|3)_J-(hD5aPotBvsa$WTJ|L6P6f7`_!FqXJ2{8-|B^#RRog^b1xizkVhHkkzZ z3ayNu#IKVZtQj-c>6$+Z-qG=fYYRZ*E0<8^_HfGyq9)0}r z%xuZ?MZXW4nWg#IsJ`{Dl3(|(`uX2?me2QU{H@rKy`B*wgd}hsdcdOCQxwGX` z^{*?fV)OM2KISngo?l^}W^(nkgr>lk>IIiP5}4Qxo#OUMN=L1}D%Ja`!qxSkx2+SXL@KIkKzfsa|KL5GKYz`J1j@G>$#pYts!V$NFmYs@EyZiOQ)P>6}pT{f@ zo@nW-e){BT0prbACTO!1%wu3UF_ouCwK*)m>0rddO;MNY!r}_=Uz%4R|F+NISnfjr$0WkWuxH2f9n*8nPG?uw{k>uqT-D)gelA9+P;mPGg2#V_#RFpZa#@%E6Uo|I zbx`T@kt9P4nOckMf5i))9qe0f-6omrwECdU|I>^OoQ5J|k{=(ZOD(**^Wv`yQhPpm zSwH&tGkY#iph)6I9Y>v24h1nR7VOfW`%CL?)mAz(b_i*#_Bnp;?rQ^+Pnxr4zrJ|$ z=FCYg3LFYT0^LUs9y}Oh{`dF4U(eL%O=;@jwApd0OLq75#j9Uy?Ay6akgr|2l#$Qi zT;==H_S42@YD>2WF$Ao#h%&qN;mG8#6^~A?wJ3U0;Kjti&fE}SvFra|VcUmOc$ayc zo{;!F&-&lZzk0WB$vJC?%=#Xu#N^O%ROo@s5e5Yb4*9C@H-2vXAI8AY;kt3*Rt8>Q z?~Uu03hv#z_w&8e9u78kH^1;OSUmrC!e!0xPvXwsA2qlrv1OYb-n{>Z*}VEh@msg! z{q($ZR*DotzUuGqJkuI}q;RIOSUiuNuE)o= z_Z^2&r?tQ5N+ZFqi@!!Mm5_UP^k6f4-t5_$2iNd0I4B6b+VSbBuf_V-2Zg>0R_Eh$ z7rLl1RaAKMo~!@HXl4E1O!>ev))!@sA3t8`-ha3J%jU!F_D`Cb?RdVm8x|=yO_*{^ zJl|~L2Jzc+xkomZ-#f4}IF>8)vLTOQtak}2WbsG%QH`h9^oiIJS z(dXO(^R5f8Tm+V?2~NmM`2AS-#@1x^UAycWHBK#K={Rf4@6)}5AxBZ^)yti~dd^P! zdODPM=`D7-h`zvnj=6Cy_Y|B2#PfuBco!@&k-mHP?sg-GBMv9~o}N@#G*xnDTl3XW z*6-`HS1PV`P{2+3-s|D$T`pVh4(p zjON#rNH>-)=p0>CMpq4M`q1$tzJ0*BNdq{vsi3%kMd9nb=e(wn>gI_Giv- z|F>%8N}u@PV2+(JGu{aA}_nR2D6eY9&i1A=evr5_Yy7T%NGK}qa${e z#hPYb(R%Sksl-h(Wz%g}rH2;(F4Rf6F17se__g{zxyDGPs-;2Sf+By`_TRdGy(=tR z?aHi^YcxWQpIR3F@wQ;UYf--I`)kn|%A5BtIIt`K>npG1(5proB9nPnU+gT1lRy6c z_J6+Zr{BjF2ruJ${)eG~*(GFK#m1G3*R9)7baqx&&}z{O8B+~rZuwAk>}CD5#+?Ea z!?YJXw(1z literal 0 HcmV?d00001 diff --git a/src/tools/qml/qmlviewer/content/images/titlebar.png b/src/tools/qml/qmlviewer/content/images/titlebar.png new file mode 100644 index 0000000000000000000000000000000000000000..51c90082d052a94af34488ca9a13842122f7d7a4 GIT binary patch literal 1436 zcmeAS@N?(olHy`uVBq!ia0y~yU@&B0V9?=UV_;x7b0r{>fq{XsILO_JVcj{ImkbOH zY)RhkE)4%caKYZ?lNlHoI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O_M03MO#0dnWsYrS zU|^6eag8W(&d<$F%`0JWE=o--Nlj5G&n(GMaQE~L2yf&QXJBCY?&;zfl5y|qto?b? z?gGc^H*a6^f+OtGEdvo|y-5suci0Nz4xXQ+lsn5NHp@Kh@ga^o5&|rijlTEZo?CL` z?(V&hCr+AkV2N17oyPLt&u71%JyW%vNrz$P%cWPpw`ZB{lrQBsX;^J_HMEc6gdRiG zI=P5vzSk3$?2_Z|sCvwH#1whGM@^)Q`xUHZQj)K88*_2 zf&!Aa-#tFwzo+*1wDR}&{)##6m~i#glm6-Y^*{ffoUGm=uw&OQr51lpP!wb|LM_D?&^PkEamNL z9{l@XF1!dBd@Qo|M>j*^O)G!!ph2%SzDPF+Z@;u@33MsCwJSdG-ru(mh0B9x3si;`111dA6GvyzQ6z9Rk`m5Yl!Ik+Fjcl zzA$F(vwXgtsY<0WydmSH#3Zws3?;V0X=X`W4p*xt=y`i@p4`O|D;=RD784iu>Bq<9 znx2VgmmU7?ayeXed+;Y)e%cX(Gc)oHH}28gZR=-IEjBBMjVs)nOcA~~*L&%wYKvm^Ey z1g~S(xGl}|>VuW+?aixp9sMy!$iywF=cIa4kL2A48GlV*T~qq4wm(#BALEgIKf5Oe zIfd<#5EfoFtH!DH^em-G8F#+Dc*J9EUi7$fko9%o$DZ*VY^s^mPd^T;z7^f~w`zgUgyzLnil}Dm`~A$nr&O)ZCNL9Ym7feR6&- z6Q#8B*ujmjrqxN`V;jdN(QoYLu)xzW4UdB2b_4lFvZx3}9v ze*b%>MKZ2svZ+UIB<=5Od&(l<8@XM#?rvVhcIi3Ao3H(w^y0H=)WoXqmA%?0o_(oX zldI)uKiws5YyA@6&_dOVZ=I{ZD7+G>kH4iMI9pXMuj*%zA%urD=6n{q%WN zNAvPED<W;!nPQzgs)=Pqy{XUWHl9UiR<#JAFCN3CnVkOP{to zYAKocUQYj3v`s7CkMHdr^QI2NZww)&UoLxooa=o0r1_(aS+>`5vNCrr?g{zVKELkC zK6A#pb#>R`4Mn0~WnEnOTDWxTiq%=d^Beu;epuVzFc69Gn&@hgbN8HD!Y?85$x5f~ zC6CN1y!-Bg&YR@L2A3G6=WBA_{B>DNi#;Xrl-p0oy$qUD7oSUK+tvBCf9W4xDy?SOlNtYo4Aoa(ysz|+wS7uYmYB=k8w?B#44$rjF6*2UngHu! Bp&kGL literal 0 HcmV?d00001 diff --git a/src/tools/qml/qmlviewer/content/images/titlebar.sci b/src/tools/qml/qmlviewer/content/images/titlebar.sci new file mode 100644 index 00000000000..0418d94cd60 --- /dev/null +++ b/src/tools/qml/qmlviewer/content/images/titlebar.sci @@ -0,0 +1,5 @@ +border.left: 10 +border.top: 12 +border.bottom: 12 +border.right: 10 +source: titlebar.png diff --git a/src/tools/qml/qmlviewer/content/images/up.png b/src/tools/qml/qmlviewer/content/images/up.png new file mode 100644 index 0000000000000000000000000000000000000000..b05f8025d0157a5e7b2792b058cdb4553b1d6bff GIT binary patch literal 662 zcmeAS@N?(olHy`uVBq!ia0y~yU=RXf4mJh`hOl#e;S3B6jKx9jP7LeL$-HD>U|>t~ zc6VX;4}uH!E}zW6z`$AH5n0T@z%2~Ij105pNH8!ku$OrHy0YJ77ho_KnaC*7$iToP z=IP=XVsU!!l=Iobjv~kH^V7_4&S3ep*w<%kmmG`W*OaYn&Y?P0A0EgraKGJsW%9i} z+7<85+8_AuARuDn5qMaz8NZI-*PJ!#JWVYenn+9O*trRdz@m0pE;znp@8S4lqJ zo$_hL8;QwzlZD^1y{|cJe&9ZDh|jV&yO*D8-FfP%N>cd8p6(#VC}%zXn|r3rS}n73 z{Rg>i3C#=kuG~_)zGk0^z3t>HR{NTsZw+{qta)MK^G_3`r+22!b^a<}!?cenO`zoI z7oVJmPeRnCy-gbUy#Dw)utb+1G+z=3fp5F~1x`|tQ^wCx(C + +QT_BEGIN_NAMESPACE + +class DeviceOrientationPrivate; +class DeviceOrientation : public QObject +{ + Q_OBJECT + Q_ENUMS(Orientation) +public: + enum Orientation { + UnknownOrientation, + Portrait, + Landscape, + PortraitInverted, + LandscapeInverted + }; + + virtual Orientation orientation() const = 0; + virtual void setOrientation(Orientation) = 0; + + static DeviceOrientation *instance(); + +signals: + void orientationChanged(); + +protected: + DeviceOrientation() {} + +private: + DeviceOrientationPrivate *d_ptr; + friend class DeviceOrientationPrivate; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/tools/qml/qmlviewer/deviceorientation_maemo5.cpp b/src/tools/qml/qmlviewer/deviceorientation_maemo5.cpp new file mode 100644 index 00000000000..e942579b70d --- /dev/null +++ b/src/tools/qml/qmlviewer/deviceorientation_maemo5.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "deviceorientation.h" +#include + +#include +#include + +class MaemoOrientation : public DeviceOrientation +{ + Q_OBJECT +public: + MaemoOrientation() + : o(UnknownOrientation) + { + // enable the orientation sensor + QDBusConnection::systemBus().call( + QDBusMessage::createMethodCall(MCE_SERVICE, MCE_REQUEST_PATH, + MCE_REQUEST_IF, MCE_ACCELEROMETER_ENABLE_REQ)); + + // query the initial orientation + QDBusMessage reply = QDBusConnection::systemBus().call( + QDBusMessage::createMethodCall(MCE_SERVICE, MCE_REQUEST_PATH, + MCE_REQUEST_IF, MCE_DEVICE_ORIENTATION_GET)); + if (reply.type() == QDBusMessage::ErrorMessage) { + qWarning("Unable to retrieve device orientation: %s", qPrintable(reply.errorMessage())); + } else { + o = toOrientation(reply.arguments().value(0).toString()); + } + + // connect to the orientation change signal + QDBusConnection::systemBus().connect(QString(), MCE_SIGNAL_PATH, MCE_SIGNAL_IF, + MCE_DEVICE_ORIENTATION_SIG, + this, + SLOT(deviceOrientationChanged(QString))); + } + + ~MaemoOrientation() + { + // disable the orientation sensor + QDBusConnection::systemBus().call( + QDBusMessage::createMethodCall(MCE_SERVICE, MCE_REQUEST_PATH, + MCE_REQUEST_IF, MCE_ACCELEROMETER_DISABLE_REQ)); + } + + inline Orientation orientation() const + { + return o; + } + + void setOrientation(Orientation o) + { + } + +private Q_SLOTS: + void deviceOrientationChanged(const QString &newOrientation) + { + o = toOrientation(newOrientation); + + emit orientationChanged(); +// printf("%d\n", o); + } + +private: + static Orientation toOrientation(const QString &nativeOrientation) + { + if (nativeOrientation == MCE_ORIENTATION_LANDSCAPE) + return Landscape; + else if (nativeOrientation == MCE_ORIENTATION_LANDSCAPE_INVERTED) + return LandscapeInverted; + else if (nativeOrientation == MCE_ORIENTATION_PORTRAIT) + return Portrait; + else if (nativeOrientation == MCE_ORIENTATION_PORTRAIT_INVERTED) + return PortraitInverted; + return UnknownOrientation; + } + +private: + Orientation o; +}; + +DeviceOrientation* DeviceOrientation::instance() +{ + static MaemoOrientation *o = new MaemoOrientation; + return o; +} + +#include "deviceorientation_maemo5.moc" diff --git a/src/tools/qml/qmlviewer/editor/abstractformeditortool.cpp b/src/tools/qml/qmlviewer/editor/abstractformeditortool.cpp new file mode 100644 index 00000000000..721a3464459 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/abstractformeditortool.cpp @@ -0,0 +1,193 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "abstractformeditortool.h" +#include "qdeclarativedesignview.h" + +#include +#include + +#include +#include +#include + +namespace QmlViewer { + +AbstractFormEditorTool::AbstractFormEditorTool(QDeclarativeDesignView *editorView) + : QObject(editorView), m_view(editorView) +{ +} + + +AbstractFormEditorTool::~AbstractFormEditorTool() +{ + +} + +QDeclarativeDesignView* AbstractFormEditorTool::view() const +{ + return m_view; +} + +QGraphicsScene* AbstractFormEditorTool::scene() const +{ + return view()->scene(); +} + +void AbstractFormEditorTool::setItems(const QList &itemList) +{ + m_itemList = itemList; + selectedItemsChanged(m_itemList); +} + +QList AbstractFormEditorTool::items() const +{ + return m_itemList; +} + +bool AbstractFormEditorTool::topItemIsMovable(const QList & itemList) +{ + QGraphicsItem *firstSelectableItem = topMovableGraphicsItem(itemList); + if (firstSelectableItem == 0) + return false; + + QDeclarativeItem *declarativeItem = dynamic_cast(firstSelectableItem->toGraphicsObject()); + + if (declarativeItem != 0) + return true; + + return false; + +} + +bool AbstractFormEditorTool::topSelectedItemIsMovable(const QList &itemList) +{ + QList selectedItems = view()->selectedItems(); + + foreach (QGraphicsItem *item, itemList) { + QDeclarativeItem *declarativeItem = toQDeclarativeItem(item); + if (declarativeItem + && selectedItems.contains(declarativeItem) + /*&& (declarativeItem->qmlItemNode().hasShowContent() || selectNonContentItems)*/) + return true; + } + + return false; + +} + +bool AbstractFormEditorTool::topItemIsResizeHandle(const QList &/*itemList*/) +{ + return false; +} + +QDeclarativeItem *AbstractFormEditorTool::toQDeclarativeItem(QGraphicsItem *item) +{ + return dynamic_cast(item->toGraphicsObject()); +} + +QGraphicsItem *AbstractFormEditorTool::topMovableGraphicsItem(const QList &itemList) +{ + foreach (QGraphicsItem *item, itemList) { + if (item->flags().testFlag(QGraphicsItem::ItemIsMovable)) + return item; + } + return 0; +} + +QDeclarativeItem *AbstractFormEditorTool::topMovableDeclarativeItem(const QList &itemList) +{ + foreach (QGraphicsItem *item, itemList) { + QDeclarativeItem *declarativeItem = toQDeclarativeItem(item); + if (declarativeItem /*&& (declarativeItem->qmlItemNode().hasShowContent())*/) + return declarativeItem; + } + + return 0; +} + +QList AbstractFormEditorTool::toGraphicsObjectList(const QList &itemList) +{ + QList gfxObjects; + foreach(QGraphicsItem *item, itemList) { + QGraphicsObject *obj = item->toGraphicsObject(); + if (obj) + gfxObjects << obj; + } + + return gfxObjects; +} + +QList AbstractFormEditorTool::toObjectList(const QList &itemList) +{ + QList objects; + foreach(QGraphicsItem *item, itemList) { + QObject *obj = item->toGraphicsObject(); + if (obj) + objects << obj; + } + + return objects; +} + +QString AbstractFormEditorTool::titleForItem(const QGraphicsItem *item) +{ + QString className("QGraphicsItem"); + QString objectStringId; + + const QGraphicsObject *gfxObject = item->toGraphicsObject(); + if (gfxObject) { + className = gfxObject->metaObject()->className(); + className.replace(QRegExp("_QMLTYPE_\\d+"), ""); + + const QDeclarativeItem *declarativeItem = qobject_cast(gfxObject); + if (declarativeItem) { + //QDeclarativeData *ddata = QDeclarativeData::get(declarativeItem); + //ddata->context->findObjectId(declarativeItem); + + QDeclarativeContext *context = QDeclarativeEngine::contextForObject(declarativeItem); + if (context) { + QDeclarativeContextData *cdata = QDeclarativeContextData::get(context); + if (cdata) + objectStringId = cdata->findObjectId(declarativeItem); + } + } + + if (objectStringId.isEmpty()) + objectStringId = gfxObject->objectName(); + + if (!objectStringId.isEmpty()) + return tr("%1 (%2)").arg(objectStringId, className); + } + + return tr("(%1, type %2)").arg(className, QString::number(item->type())); +} + + +} diff --git a/src/tools/qml/qmlviewer/editor/abstractformeditortool.h b/src/tools/qml/qmlviewer/editor/abstractformeditortool.h new file mode 100644 index 00000000000..ae27805ab02 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/abstractformeditortool.h @@ -0,0 +1,104 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef ABSTRACTFORMEDITORTOOL_H +#define ABSTRACTFORMEDITORTOOL_H + +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QMouseEvent; +class QGraphicsItem; +class QDeclarativeItem; +class QKeyEvent; +class QGraphicsScene; +class QGraphicsObject; +class QWheelEvent; +QT_END_NAMESPACE + +namespace QmlViewer { + +class QDeclarativeDesignView; + + +class FormEditorView; + +class AbstractFormEditorTool : public QObject +{ + Q_OBJECT +public: + AbstractFormEditorTool(QDeclarativeDesignView* view); + + virtual ~AbstractFormEditorTool(); + + virtual void mousePressEvent(QMouseEvent *event) = 0; + virtual void mouseMoveEvent(QMouseEvent *event) = 0; + virtual void mouseReleaseEvent(QMouseEvent *event) = 0; + virtual void mouseDoubleClickEvent(QMouseEvent *event) = 0; + + virtual void hoverMoveEvent(QMouseEvent *event) = 0; + virtual void wheelEvent(QWheelEvent *event) = 0; + + virtual void keyPressEvent(QKeyEvent *event) = 0; + virtual void keyReleaseEvent(QKeyEvent *keyEvent) = 0; + virtual void itemsAboutToRemoved(const QList &itemList) = 0; + + virtual void clear() = 0; + virtual void graphicsObjectsChanged(const QList &itemList) = 0; + + void setItems(const QList &itemList); + QList items() const; + + bool topItemIsMovable(const QList &itemList); + bool topItemIsResizeHandle(const QList &itemList); + bool topSelectedItemIsMovable(const QList &itemList); + + static QString titleForItem(const QGraphicsItem *item); + static QList toObjectList(const QList &itemList); + static QList toGraphicsObjectList(const QList &itemList); + static QGraphicsItem* topMovableGraphicsItem(const QList &itemList); + static QDeclarativeItem* topMovableDeclarativeItem(const QList &itemList); + static QDeclarativeItem *toQDeclarativeItem(QGraphicsItem *item); + +protected: + virtual void selectedItemsChanged(const QList &itemList) = 0; + + QDeclarativeDesignView *view() const; + QGraphicsScene* scene() const; + +private: + QDeclarativeDesignView *m_view; + QList m_itemList; +}; + +} + +#endif // ABSTRACTFORMEDITORTOOL_H diff --git a/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.cpp b/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.cpp new file mode 100644 index 00000000000..83be4e4c091 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.cpp @@ -0,0 +1,129 @@ +#include "boundingrecthighlighter.h" +#include "qdeclarativedesignview.h" +#include "qmlviewerconstants.h" + +#include +#include + +#include + +namespace QmlViewer { + +const qreal AnimDelta = 0.025f; +const int AnimInterval = 30; +const int AnimFrames = 10; + +BoundingBoxPolygonItem::BoundingBoxPolygonItem(QGraphicsItem *item) : QGraphicsPolygonItem(item) +{ + QPen pen; + pen.setColor(QColor(108, 141, 221)); + setPen(pen); +} + +int BoundingBoxPolygonItem::type() const +{ + return Constants::EditorItemType; +} + +BoundingRectHighlighter::BoundingRectHighlighter(QDeclarativeDesignView *view) : + LayerItem(view->scene()), + m_view(view), + m_highlightPolygon(0), + m_highlightPolygonEdge(0), + m_animFrame(0) +{ + m_animTimer = new QTimer(this); + m_animTimer->setInterval(AnimInterval); + connect(m_animTimer, SIGNAL(timeout()), SLOT(animTimeout())); +} + +void BoundingRectHighlighter::animTimeout() +{ + ++m_animFrame; + if (m_animFrame == AnimFrames) { + m_animTimer->stop(); + } + + m_highlightPolygon->setPen(QPen(QColor(0, 22, 159))); + m_highlightPolygonEdge->setPen(QPen(QColor(158, 199, 255))); + qreal alpha = m_animFrame / float(AnimFrames); + m_highlightPolygonEdge->setOpacity(alpha); +} + +void BoundingRectHighlighter::clear() +{ + if (m_highlightPolygon) { + m_view->scene()->removeItem(m_highlightPolygon); + delete m_highlightPolygon; + m_highlightPolygon = 0; + delete m_highlightPolygonEdge; + m_highlightPolygonEdge = 0; + m_animTimer->stop(); + + disconnect(m_highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh())); + disconnect(m_highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh())); + disconnect(m_highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh())); + disconnect(m_highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh())); + disconnect(m_highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh())); + + m_highlightedObject.clear(); + } +} + +void BoundingRectHighlighter::highlight(QGraphicsObject* item) +{ + if (!item) + return; + + bool animate = false; + QGraphicsPolygonItem *polygonItem = 0; + QGraphicsPolygonItem *polygonItemEdge = 0; + if (item != m_highlightedObject.data() || !m_highlightPolygon) { + animate = true; + polygonItem = new BoundingBoxPolygonItem(this); + polygonItemEdge = new BoundingBoxPolygonItem(this); + } else { + polygonItem = m_highlightPolygon; + polygonItemEdge = m_highlightPolygonEdge; + } + + QPolygonF boundingRectInSceneSpace(item->mapToScene(item->boundingRect())); + QPolygonF boundingRectInLayerItemSpace = mapFromScene(boundingRectInSceneSpace); + polygonItem->setPolygon(boundingRectInLayerItemSpace); + polygonItem->setFlag(QGraphicsItem::ItemIsSelectable, false); + + QRectF edgeRect = boundingRectInLayerItemSpace.boundingRect(); + edgeRect.adjust(-1, -1, 1, 1); + polygonItemEdge->setPolygon(QPolygonF(edgeRect)); + polygonItemEdge->setFlag(QGraphicsItem::ItemIsSelectable, false); + + if (item != m_highlightedObject.data()) + clear(); + + m_highlightPolygon = polygonItem; + m_highlightPolygonEdge = polygonItemEdge; + m_highlightedObject = item; + + if (item != m_highlightedObject.data()) { + connect(m_highlightedObject.data(), SIGNAL(xChanged()), this, SLOT(refresh())); + connect(m_highlightedObject.data(), SIGNAL(yChanged()), this, SLOT(refresh())); + connect(m_highlightedObject.data(), SIGNAL(widthChanged()), this, SLOT(refresh())); + connect(m_highlightedObject.data(), SIGNAL(heightChanged()), this, SLOT(refresh())); + connect(m_highlightedObject.data(), SIGNAL(rotationChanged()), this, SLOT(refresh())); + } + + if (animate) { + m_highlightPolygonEdge->setOpacity(0); + m_animFrame = 0; + m_animTimer->start(); + } +} + +void BoundingRectHighlighter::refresh() +{ + if (!m_highlightedObject.isNull()) + highlight(m_highlightedObject.data()); +} + + +} // namespace QmlViewer diff --git a/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.h b/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.h new file mode 100644 index 00000000000..81dc84579f2 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/boundingrecthighlighter.h @@ -0,0 +1,54 @@ +#ifndef BOUNDINGRECTHIGHLIGHTER_H +#define BOUNDINGRECTHIGHLIGHTER_H + +#include +#include + +#include "layeritem.h" + +QT_FORWARD_DECLARE_CLASS(QGraphicsItem); +QT_FORWARD_DECLARE_CLASS(QPainter); +QT_FORWARD_DECLARE_CLASS(QWidget); +QT_FORWARD_DECLARE_CLASS(QStyleOptionGraphicsItem); +QT_FORWARD_DECLARE_CLASS(QTimer); + +namespace QmlViewer { + +class QDeclarativeDesignView; + +class BoundingBoxPolygonItem : public QGraphicsPolygonItem +{ +public: + explicit BoundingBoxPolygonItem(QGraphicsItem *item); + int type() const; +}; + +class BoundingRectHighlighter : public LayerItem +{ + Q_OBJECT +public: + explicit BoundingRectHighlighter(QDeclarativeDesignView *view); + void clear(); + void highlight(QGraphicsObject* item); + +private slots: + void refresh(); + void animTimeout(); + +private: + Q_DISABLE_COPY(BoundingRectHighlighter); + + QDeclarativeDesignView *m_view; + QWeakPointer m_highlightedObject; + QGraphicsPolygonItem *m_highlightPolygon; + QGraphicsPolygonItem *m_highlightPolygonEdge; + + QTimer *m_animTimer; + qreal m_animScale; + int m_animFrame; + +}; + +} // namespace QmlViewer + +#endif // BOUNDINGRECTHIGHLIGHTER_H diff --git a/src/tools/qml/qmlviewer/editor/colorpickertool.cpp b/src/tools/qml/qmlviewer/editor/colorpickertool.cpp new file mode 100644 index 00000000000..62d5f3b49c0 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/colorpickertool.cpp @@ -0,0 +1,99 @@ +#include "colorpickertool.h" +#include "qdeclarativedesignview.h" + +#include +#include +#include +#include +#include +#include + +#include + +namespace QmlViewer { + +ColorPickerTool::ColorPickerTool(QDeclarativeDesignView *view) : + AbstractFormEditorTool(view) +{ + m_selectedColor.setRgb(0,0,0); +} + +ColorPickerTool::~ColorPickerTool() +{ + +} + +void ColorPickerTool::mousePressEvent(QMouseEvent */*event*/) +{ + +} + +void ColorPickerTool::mouseMoveEvent(QMouseEvent *event) +{ + pickColor(event->pos()); +} + +void ColorPickerTool::mouseReleaseEvent(QMouseEvent *event) +{ + pickColor(event->pos()); +} + +void ColorPickerTool::mouseDoubleClickEvent(QMouseEvent */*event*/) +{ + +} + + +void ColorPickerTool::hoverMoveEvent(QMouseEvent */*event*/) +{ + +} + +void ColorPickerTool::keyPressEvent(QKeyEvent */*event*/) +{ + +} + +void ColorPickerTool::keyReleaseEvent(QKeyEvent */*keyEvent*/) +{ + +} + +void ColorPickerTool::wheelEvent(QWheelEvent */*event*/) +{ + +} + +void ColorPickerTool::itemsAboutToRemoved(const QList &/*itemList*/) +{ + +} + +void ColorPickerTool::clear() +{ + view()->setCursor(Qt::CrossCursor); +} + +void ColorPickerTool::graphicsObjectsChanged(const QList &/*itemList*/) +{ + +} + +void ColorPickerTool::selectedItemsChanged(const QList &/*itemList*/) +{ + +} + +void ColorPickerTool::pickColor(const QPoint &pos) +{ + QRectF target(0,0, 1, 1); + QRect source(pos.x(), pos.y(), 1, 1); + QImage img(1, 1, QImage::Format_ARGB32); + QPainter painter(&img); + view()->render(&painter, target, source); + m_selectedColor = QColor::fromRgb(img.pixel(0, 0)); + + emit selectedColorChanged(m_selectedColor); +} + +} // namespace QmlViewer diff --git a/src/tools/qml/qmlviewer/editor/colorpickertool.h b/src/tools/qml/qmlviewer/editor/colorpickertool.h new file mode 100644 index 00000000000..24221dce756 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/colorpickertool.h @@ -0,0 +1,54 @@ +#ifndef COLORPICKERTOOL_H +#define COLORPICKERTOOL_H + +#include "abstractformeditortool.h" + +#include + +QT_FORWARD_DECLARE_CLASS(QPoint); + +namespace QmlViewer { + +class ColorPickerTool : public AbstractFormEditorTool +{ + Q_OBJECT +public: + explicit ColorPickerTool(QDeclarativeDesignView *view); + + virtual ~ColorPickerTool(); + + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); + + void hoverMoveEvent(QMouseEvent *event); + + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *keyEvent); + + void wheelEvent(QWheelEvent *event); + + void itemsAboutToRemoved(const QList &itemList); + + void clear(); + void graphicsObjectsChanged(const QList &itemList); + +signals: + void selectedColorChanged(const QColor &color); + +protected: + + void selectedItemsChanged(const QList &itemList); + +private: + void pickColor(const QPoint &pos); + +private: + QColor m_selectedColor; + +}; + +} // namespace QmlViewer + +#endif // COLORPICKERTOOL_H diff --git a/src/tools/qml/qmlviewer/editor/editor.pri b/src/tools/qml/qmlviewer/editor/editor.pri new file mode 100644 index 00000000000..f525315b1ca --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/editor.pri @@ -0,0 +1,38 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/abstractformeditortool.h \ + $$PWD/selectiontool.h \ + $$PWD/layeritem.h \ + $$PWD/singleselectionmanipulator.h \ + $$PWD/rubberbandselectionmanipulator.h \ + $$PWD/selectionrectangle.h \ + $$PWD/selectionindicator.h \ + $$PWD/qmlviewerconstants.h \ + $$PWD/boundingrecthighlighter.h \ + $$PWD/subcomponenteditortool.h \ + $$PWD/subcomponentmasklayeritem.h \ + $$PWD/zoomtool.h \ + $$PWD/colorpickertool.h \ + $$PWD/qmltoolbar.h \ + $$PWD/toolbarcolorbox.h + +SOURCES += \ + $$PWD/abstractformeditortool.cpp \ + $$PWD/selectiontool.cpp \ + $$PWD/layeritem.cpp \ + $$PWD/singleselectionmanipulator.cpp \ + $$PWD/rubberbandselectionmanipulator.cpp \ + $$PWD/selectionrectangle.cpp \ + $$PWD/selectionindicator.cpp \ + $$PWD/boundingrecthighlighter.cpp \ + $$PWD/subcomponenteditortool.cpp \ + $$PWD/subcomponentmasklayeritem.cpp \ + $$PWD/zoomtool.cpp \ + $$PWD/colorpickertool.cpp \ + $$PWD/qmltoolbar.cpp \ + $$PWD/toolbarcolorbox.cpp + +RESOURCES += $$PWD/editor.qrc + +DEFINES += QWEAKPOINTER_ENABLE_ARROW diff --git a/src/tools/qml/qmlviewer/editor/editor.qrc b/src/tools/qml/qmlviewer/editor/editor.qrc new file mode 100644 index 00000000000..6657b325e38 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/editor.qrc @@ -0,0 +1,13 @@ + + + images/resize_handle.png + images/select.png + images/select-marquee.png + images/color-picker.png + images/play.png + images/pause.png + images/from-qml.png + images/zoom.png + images/to-qml.png + + diff --git a/src/tools/qml/qmlviewer/editor/images/color-picker.png b/src/tools/qml/qmlviewer/editor/images/color-picker.png new file mode 100644 index 0000000000000000000000000000000000000000..73d9ae3dfc40995337e3a0762831fa908e390120 GIT binary patch literal 3185 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 Y#g`ktxZ1Xefq{X+)78&qol`;+05S6bPXGV_ literal 0 HcmV?d00001 diff --git a/src/tools/qml/qmlviewer/editor/images/from-qml.png b/src/tools/qml/qmlviewer/editor/images/from-qml.png new file mode 100644 index 0000000000000000000000000000000000000000..e3a6e24c1994c04a9a15513af6f94fd6ee159ee2 GIT binary patch literal 3251 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 literal 0 HcmV?d00001 diff --git a/src/tools/qml/qmlviewer/editor/images/pause.png b/src/tools/qml/qmlviewer/editor/images/pause.png new file mode 100644 index 0000000000000000000000000000000000000000..c5d33a2d04b7ae11b35e88e4ef8033057a809093 GIT binary patch literal 3110 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 literal 0 HcmV?d00001 diff --git a/src/tools/qml/qmlviewer/editor/images/play.png b/src/tools/qml/qmlviewer/editor/images/play.png new file mode 100644 index 0000000000000000000000000000000000000000..af75fcdb6285032ce073ab90bb1648d19d372b3f GIT binary patch literal 3367 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 HDWM4fiL6Gf literal 0 HcmV?d00001 diff --git a/src/tools/qml/qmlviewer/editor/images/resize_handle.png b/src/tools/qml/qmlviewer/editor/images/resize_handle.png new file mode 100644 index 0000000000000000000000000000000000000000..2934f25b7436ea36065f0ef5c249db9e87b04906 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0y~yU|k44ofy`glX=O&z`$AH z5n0T@z%2~Ij105pNH8!kxO%!chHzX@PHA9D-oNa>!MB^fr9C`6JUl)pgp@Y9X>dti zRF#mBkho`KcbwsRr%vOUbf>V+b(00}`pq~3Qrq(*hMOU#MXp56!0;Xe0|SGntDnm{ Hr-UW|5L7M- literal 0 HcmV?d00001 diff --git a/src/tools/qml/qmlviewer/editor/images/select-marquee.png b/src/tools/qml/qmlviewer/editor/images/select-marquee.png new file mode 100644 index 0000000000000000000000000000000000000000..a28381f117653497bff3245a2712acd341b545f9 GIT binary patch literal 2878 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoI14-?iy0WWg+Z8+Vb&Z8 z1_mzwOlRkSfQjkW+Vq$V4?QMNR>)4#kBxMFS5Cy1KGRpIFer+}GF8BO0i~)5Udz{fXkDzUIXp zU8jCOtX`abZO`{-Xa8-zZufl6=ee8DvmfB#ndV^}XxhND(n(J6LG$q=#~wb>b7d=7!LT(K42iz{-6Jq)65vgh8D&HB@->Y zIT}P59IE=9mN7WEF*eMdp%%=rfQ2F9baK*Th5%iL1oir7ml+!7{+LO86pfAMAE#ESTfwuWiapzPxD~du$|$+IRWlX3>-WR27w)| znhY$}3<)Qcl`9xpW-^GleG0evsJ%|$xfTOM#mr4MJ5?-Q8>2aN3)#cN_2e|pd5UX` zm?bhL&T`N@R5?@9sL_P~!RIp!3=1ZT3O;E5{I}v9-@0?>%=)(R#p}M>&-Py_De3XQ zr{`A}I503gEUCNrPe*^VRD(5JL+-yts_$4b;Q;wm;6nz~Hi=QEP*v^p}GYItSQf4zk`k$o(h5ti?&?$RQ^IC$5wR znW6;EHBC+$ZD%*gY9;7jaga4R5SY<6xqwgaQ0NXm+XDVyi5&9|YV2v`WN|#fA)Kgq ztAjDAD?+)CLwsiI5524k8#^I(fR~~ zQPZEcJ?@568aD;nUg6p5ymN)QREygp?h7d;hO_#`7Ra3h?;vuCx`Q)vX>`m;JQ*;!xPqaRn z`{eKw<0sNj6hB3C%}sJBT=FCMkw(y|EHBBY0#8kzvZc;2atvKOE9mZug&~5b{ZUS9 z7j6q$AK1P^*rarp<=JL2Pw%B`7frn^l_8$-J#+nwl3jv#r^@+FzYu=u^h@^_(_b)u zDd*vB6Ky`;k**;*TY_C8U9wza{S2RFl9#(BkB1nT8@`_Ld?x?Q{Ll!kZCW*=6HjqX z^_r?SRa#3wWaX-5tM0Ah4*eW@I;4MPTyX6=w@~BY$16FnOj{kgYHq;mVCmrWmDVfT zSEaAW53yfT7x}l7E%LC>VSnc(feSXqKi+dpfje1pbA^s#Ht*`T(nixGY8%hqtSQsl zJ>#$J?rz&vD;HWi8+#dtZw~rACC#4w@r=SBb4vU;pKC0i{<*H}p2&O6N1D>hOni14 zrp9Einl^n}#A=V#fveqL?=@TZcKO_8dtG-&{%+)RJnp3)qwb#Ge~xwT^WdAocb9W5 z7xT5X`npbURrXTpg}YtK_vbBtH)GzuxQ2N?`OEKB?tT7CrdI!N$lu&w%fGtwM6hk< zQDM8yb56qMsA*xojjaCh+aCj+V-GtxFHM}9IQ?PE#GMyy7GHJib>r{JJQnj<<#Fz@ z++&N?*whr&ynSE!zMB=~yK|Z5GHV}epW|oGoLzMG+Dy~gwuaY@p3i|aQRNZ$$qQnT}wZ_ z;p4WG+g5Iu-0<`U+wFDRa<|ncrYDJ~Z$G;3@Vm)-C)e((?fq-Z&f9*IZ?$ZcY+dn| zA`z=Ft9!G~&3R{Ed-Th+m-^`u=LOE+Fn+vE__XGc%(=m{FT1CUr|&Fo{@l^s>D_c% zZ@Qh{Z0TcnPwai-Rr0kk_F>hfuXAT_o_*-;ireeonZ3(=*M4XI8I$>%^CFFlFC0GM z{2=h@MSJe~Qw_53uc`BQ_HRtz`dnE*S$|^q+Upy(FD+m7J@LJ`-8Z|U`H$@$+nC=o zx)&LL#{9tc6WdSwAI_f_-+JGbFfd-#Ydz*y$+h*x$6a>FL3>iWw)~OjxV<{rQY@6VGMxwFcC^xORa(@mXT`;W{4m z*7nx$Hv7JUjtHrXhSN>UFWzx3zVGtOWtz*q+3AM1Em6GT&vg%l?>N zTI89l5pyFvbG&6N^|aQR<>lEq&E}ym{zJB zHD0RobZ3kD$_aaXczy29wwfn4t4tx+$kuAFVe_Pk6AGPHDf&*{mi{XJSz6iYHL0ze z{vFNh-mWh&l+efI5{&8Kcp zFrV{&{{Oc^hlCzZ+P1XKJ6u;b;@RFcS(ck@3M+4OJr-rvZVO{uW3!`cn^x{s|J859 zr?0Eqt5)Tk-57W9RMWw&jM=ZbL%E)|*1o=T{cWs&gns1xt%<+d=1SX%c6O~3xh+0j zwEl+1orFOT=;tu4Iw!?wKr z`pxyW{`9jNw|6&hbKbdlzs-(4smo8EJ8NwpvLxh7$gdEycbD#NO}zdi@8Ub@>OJ2~ z-dw#Mz32O1yOaBFhcbrxUQN52`rGsO=I{3FI#<2?G3|G5>{`Fv!nennFERgRSLWMx zedm>{vX^W_g8Hv%zjo(4F2C>J-1p_Wyk@+iy>pH|QZ8_*eDd-;=l$<;yjHi$daBnv zWWOw5CYvs+pXD^`(=4~y!LxoxCq?h_KVx_C+N*n2f81}&^UpD{iLCVc9C9-A*2|{L zlhZ$)@0mMwZf%|3&pQdX7j3J4o_y|p7JvTxT>>Q!FS-8jer~a_1KrRSNSyZdEtD@QW)!(h%=ES4z)+>iz|hdl z!0_`w14F}028L1t28LG&3=CE?7#PI!C&eFiV_;y&^mK6yskoK&=l_3uW?e>M=H7!V zSXmgk%^d$T)K{Fzzq4VYU@Q-p#6pv{s3x%o0cSd#HQQWSnmJ~BcQEuQYltRx1|%K$ zFDT-&cx6V#Ql&Ymf@j1%1pPK_I4t#fapjkW+Vq$V4?QMNR>)4#kBxMFS5Cy1KGRpIFer+}GF8BO0i~)5Udz{fXkDzUIXp zU8jCOtX`abZO`{-Xa8-zZufl6=ee8DvmfB#ndV^}XxhND(n(J6LG$q=#~wb>b7d=7!LT(K42iz{-6Jq)65vgh8D&HB@->Y zIT}P59IE=9mN7WEF*eMdp%%=rfQ2F9baK*Th5%iL1oir7ml+!7{+LO86pfAMAE#ESTfwuWiapzPxD~du$|$+IRWlX3>-WR27w)| znhY$}3<)Qcl`9xpW-^GleG0evsJ%|$xfTOM#mr4MJ5?-Q8>2aN3)#cN_2e|pd5UX` zm?bhL&T`N@R5?@9sL_P~!RIp!3=1ZT3O;E5{I}v9-@0?>%=)(R#p}M>&-Py_De3XQ zr{`A}I503gEUCNrPe*^VRD(5JL+-yts_$4b;Q;wm;6nz~Hi=QEP*v^p}GYItSQf4zk`k$o(h5ti?&?$RQ^IC$5wR znW6;EHBC+$ZD%*gY9;7jaga4R5SY<6xqwgaQ0NXm+XDVyi5&9|YV2v`WN|#fA)Kgq ztAjDAD?+)CLwsiI5524k8#^I(fR~~ zQPZEcJ?@568aD;nUg6p5ymN)QREygp?h7d;hO_#`7Ra3h?;vuCx`Q)vX>`m;JQ*;!xPqaRn z`{eKw<0sNj6hB3C%}sJBT=FCMkw(y|EHBBY0#8kzvZc;2atvKOE9mZug&~5b{ZUS9 z7j6q$AK1P^*rarp<=JL2Pw%B`7frn^l_8$-J#+nwl3jv#r^@+FzYu=u^h@^_(_b)u zDd*vB6Ky`;k**;*TY_C8U9wza{S2RFl9#(BkB1nT8@`_Ld?x?Q{Ll!kZCW*=6HjqX z^_r?SRa#3wWaX-5tM0Ah4*eW@I;4MPTyX6=w@~BY$16FnOj{kgYHq;mVCmrWmDVfT zSEaAW53yfT7x}l7E%LC>VSnc(feSXqKi+dpfje1pbA^s#Ht*`T(nixGY8%hqtSQsl zJ>#$J?rz&vD;HWi8+#dtZw~rACC#4w@r=SBb4vU;pKC0i{<*H}p2&O6N1D>hOni14 zrp9Einl^n}#A=V#fveqL?=@TZcKO_8dtG-&{%+)RJnp3)qwb#Ge~xwT^WdAocb9W5 z7xT5X`npbURrXTpg}YtK_vbBtH)GzuxQ2N?`OEKB?tT7CrdI!N$lu&w%fGtwM6hk< zQDM8yb56qMsA*xojjaCh+aCj+V-GtxFHM}9IQ?PE#GMyy7GHJib>r{JJQnj<<#Fz@ z++&N?*whr&ynSE!zMB=~yK|Z5GHV}epW|oGoLzMG+Dy~gwuaY@p3i|aQRNZ$$qQnT}wZ_ z;p4WG+g5Iu-0<`U+wFDRa<|ncrYDJ~Z$G;3@Vm)-C)e((?fq-Z&f9*IZ?$ZcY+dn| zA`z=Ft9!G~&3R{Ed-Th+m-^`u=LOE+Fn+vE__XGc%(=m{FT1CUr|&Fo{@l^s>D_c% zZ@Qh{Z0TcnPwai-Rr0kk_F>hfuXAT_o_*-;ireeonZ3(=*M4XI8I$>%^CFFlFC0GM z{2=h@MSJe~Qw_53uc`BQ_HRtz`dnE*S$|^q+Upy(FD+m7J@LJ`-8Z|U`H$@$+nC=o zx)&LL#{9tc6WdSwAI_f_-+JGbFfd-#Ydz*y$+h*x$6a>FL3>iWw)~OjxV<{rQY@6VGMxwFcC^xORa(@mXT`;W{4m z*7nx$Hv7JUjtHrXhSN>UFWzx3zVGtOWtz*q+3AM1Em6GT&vg%l?>N zTI89l5pyFvbG&6N^|aQR<>lEq&E}ym{zJB zHD0RobZ3kD$_aaXczy29wwfn4t4tx+$kuAFVe_Pk6AGPHDf&*{mi{XJSz6iYHL0ze z{vFNh-mWh&l+efI5{&8Kcp zFrV{&{{Oc^hlCzZ+P1XKJ6u;b;@RFcS(ck@3M+4OJr-rvZVO{uW3!`cn^x{s|J859 zr?0Eqt5)Tk-57W9RMWw&jM=ZbL%E)|*1o=T{cWs&gns1xt%<+d=1SX%c6O~3xh+0j zwEl+1orFOT=;tu4Iw!?wKr z`pxyW{`9jNw|6&hbKbdlzs-(4smo8EJ8NwpvLxh7$gdEycbD#NO}zdi@8Ub@>OJ2~ z-dw#Mz32O1yOaBFhcbrxUQN52`rGsO=I{3FI#<2?G3|G5>{`Fv!nennFERgRSLWMx zedm>{vX^W_g8Hv%zjo(4F2C>J-1p_Wyk@+iy>pH|QZ8_*eDd-;=l$<;yjHi$daBnv zWWOw5CYvs+pXD^`(=4~y!LxoxCq?h_KVx_C+N*n2f81}&^UpD{iLCVc9C9-A*2|{L zlhZ$)@0mMwZf%|3&pQdX7j3J4o_y|p7JvTxT>>Q!FS-8jer~a_1KrRSNSyZdEtD@QW)!(h%=ES4z)+>iz|hdl z!0_`w14F}028L1t28LG&3=CE?7#PI!C&eFiV_;zN@^o|8=~1hl zk{{b|U|Z6>%a((CgFgPWdZ6br=sIh0??f3N-h_geXWWhI{Abb}OLS%XXY z6CYdf9f(ZVN%uRmDgMqnzDFM`Hbm&`n=^CfOjZNN1J6$~3H~)@uwV$D>a{dv{q?I; zr%p|0SjI4?_?ut-G;Rh4HFGnwd*!=h-CV--rvEMG681TAt5ZCh1b* z;u5y`X3m;*>-I4ea35&3zstiVF?as_{o#7kd&_p8?O5UKa=&v$u!hK|jS+7Y8?yK2 zv9T5~EK7~NxB6;UTkh?ijwqKDp^2%p(zNIL?Jv4Bhy4IA7ej;eB8_)4GBOg=QVo@o zTv99+hzZKBT=lCkGc)rNuR)R1$*8VHZ`_n7cI4jv@Uw=&Vb(Iq*RNl{SMmHc;bh7_ zh70U#U%s!NF?;sz^%`E?hG{dFoeT-JP3e)<)6=tKD_Hq`(O#D$j5E%qZLaQhJ3Jw^ z(p-egc4gS=cu`kP7N$n)bJ^c{7#bdY`}XbJzkhX8pZ{cMXj&PPwe#{z6IIVDW`!TG zr&hE2bS&DjXY1CfOa)h0K0SN(?Ah(dk019DXj#s{6c^3Hu=r%krz#5>zAq(pXWoB5 zKh10D`CaQ)U(7IJN;sq4@OoxkuewlY%evS1KmGiZ&G0ymG4ByWOk{L)^_C4A3T~fe zy#D^c{QC!2J}FMx%y{F<`G5cIf6iyF<6&?=J!Qt^Y(q5$1_lOCS3j3^P6jkW+Vq$V4?QMNR>)4#kBxMFS5Cy1KGRpIFer+}GF8BO0i~)5Udz{fXkDzUIXp zU8jCOtX`abZO`{-Xa8-zZufl6=ee8DvmfB#ndV^}XxhND(n(J6LG$q=#~wb>b7d=7!LT(K42iz{-6Jq)65vgh8D&HB@->Y zIT}P59IE=9mN7WEF*eMdp%%=rfQ2F9baK*Th5%iL1oir7ml+!7{+LO86pfAMAE#ESTfwuWiapzPxD~du$|$+IRWlX3>-WR27w)| znhY$}3<)Qcl`9xpW-^GleG0evsJ%|$xfTOM#mr4MJ5?-Q8>2aN3)#cN_2e|pd5UX` zm?bhL&T`N@R5?@9sL_P~!RIp!3=1ZT3O;E5{I}v9-@0?>%=)(R#p}M>&-Py_De3XQ zr{`A}I503gEUCNrPe*^VRD(5JL+-yts_$4b;Q;wm;6nz~Hi=QEP*v^p}GYItSQf4zk`k$o(h5ti?&?$RQ^IC$5wR znW6;EHBC+$ZD%*gY9;7jaga4R5SY<6xqwgaQ0NXm+XDVyi5&9|YV2v`WN|#fA)Kgq ztAjDAD?+)CLwsiI5524k8#^I(fR~~ zQPZEcJ?@568aD;nUg6p5ymN)QREygp?h7d;hO_#`7Ra3h?;vuCx`Q)vX>`m;JQ*;!xPqaRn z`{eKw<0sNj6hB3C%}sJBT=FCMkw(y|EHBBY0#8kzvZc;2atvKOE9mZug&~5b{ZUS9 z7j6q$AK1P^*rarp<=JL2Pw%B`7frn^l_8$-J#+nwl3jv#r^@+FzYu=u^h@^_(_b)u zDd*vB6Ky`;k**;*TY_C8U9wza{S2RFl9#(BkB1nT8@`_Ld?x?Q{Ll!kZCW*=6HjqX z^_r?SRa#3wWaX-5tM0Ah4*eW@I;4MPTyX6=w@~BY$16FnOj{kgYHq;mVCmrWmDVfT zSEaAW53yfT7x}l7E%LC>VSnc(feSXqKi+dpfje1pbA^s#Ht*`T(nixGY8%hqtSQsl zJ>#$J?rz&vD;HWi8+#dtZw~rACC#4w@r=SBb4vU;pKC0i{<*H}p2&O6N1D>hOni14 zrp9Einl^n}#A=V#fveqL?=@TZcKO_8dtG-&{%+)RJnp3)qwb#Ge~xwT^WdAocb9W5 z7xT5X`npbURrXTpg}YtK_vbBtH)GzuxQ2N?`OEKB?tT7CrdI!N$lu&w%fGtwM6hk< zQDM8yb56qMsA*xojjaCh+aCj+V-GtxFHM}9IQ?PE#GMyy7GHJib>r{JJQnj<<#Fz@ z++&N?*whr&ynSE!zMB=~yK|Z5GHV}epW|oGoLzMG+Dy~gwuaY@p3i|aQRNZ$$qQnT}wZ_ z;p4WG+g5Iu-0<`U+wFDRa<|ncrYDJ~Z$G;3@Vm)-C)e((?fq-Z&f9*IZ?$ZcY+dn| zA`z=Ft9!G~&3R{Ed-Th+m-^`u=LOE+Fn+vE__XGc%(=m{FT1CUr|&Fo{@l^s>D_c% zZ@Qh{Z0TcnPwai-Rr0kk_F>hfuXAT_o_*-;ireeonZ3(=*M4XI8I$>%^CFFlFC0GM z{2=h@MSJe~Qw_53uc`BQ_HRtz`dnE*S$|^q+Upy(FD+m7J@LJ`-8Z|U`H$@$+nC=o zx)&LL#{9tc6WdSwAI_f_-+JGbFfd-#Ydz*y$+h*x$6a>FL3>iWw)~OjxV<{rQY@6VGMxwFcC^xORa(@mXT`;W{4m z*7nx$Hv7JUjtHrXhSN>UFWzx3zVGtOWtz*q+3AM1Em6GT&vg%l?>N zTI89l5pyFvbG&6N^|aQR<>lEq&E}ym{zJB zHD0RobZ3kD$_aaXczy29wwfn4t4tx+$kuAFVe_Pk6AGPHDf&*{mi{XJSz6iYHL0ze z{vFNh-mWh&l+efI5{&8Kcp zFrV{&{{Oc^hlCzZ+P1XKJ6u;b;@RFcS(ck@3M+4OJr-rvZVO{uW3!`cn^x{s|J859 zr?0Eqt5)Tk-57W9RMWw&jM=ZbL%E)|*1o=T{cWs&gns1xt%<+d=1SX%c6O~3xh+0j zwEl+1orFOT=;tu4Iw!?wKr z`pxyW{`9jNw|6&hbKbdlzs-(4smo8EJ8NwpvLxh7$gdEycbD#NO}zdi@8Ub@>OJ2~ z-dw#Mz32O1yOaBFhcbrxUQN52`rGsO=I{3FI#<2?G3|G5>{`Fv!nennFERgRSLWMx zedm>{vX^W_g8Hv%zjo(4F2C>J-1p_Wyk@+iy>pH|QZ8_*eDd-;=l$<;yjHi$daBnv zWWOw5CYvs+pXD^`(=4~y!LxoxCq?h_KVx_C+N*n2f81}&^UpD{iLCVc9C9-A*2|{L zlhZ$)@0mMwZf%|3&pQdX7j3J4o_y|p7JvTxT>>Q!FS-8jer~a_1KrRSNSyZdEtD@QW)!(h%=ES4z)+>iz|hdl z!0_`w14F}028L1t28LG&3=CE?7#PI!C&eFiV_;zX*2MgcDOqc}|KP==494ndVV{5gaoC+hL30}s5ZN&9lb?%dry4lf^iuez#LxBvb$8yP<9ZJCdbuDm`=Cdl$aNwD;KV>`2B z8;@FM`LCYyt%|eNX`4%1qD3{k{k8p<|K4Iv$bBOEUftec>5m)hOEjmSHj(OGD6&NP z*-e%Ow(qCi2zjtL+#(`qr$u#V>uT;5t9EI#{>}OI^yZaW&puXgNNtX>lRx~n?0;hL zYNo>mVNC}g*a~Ly%7`9V{Br)j*Nx@JGuN4iCvCj(NkQE5o#XnD&ub?$yo}M?KJjeY z^tJqFGx^)(L~TQ~rdl6pSsb{rJ9C$)?t{rw{eS*X{r8)*j+fz}&YT0RQwmoyFfcH9 My85}Sb4q9e09sfd!vFvP literal 0 HcmV?d00001 diff --git a/src/tools/qml/qmlviewer/editor/images/zoom.png b/src/tools/qml/qmlviewer/editor/images/zoom.png new file mode 100644 index 0000000000000000000000000000000000000000..4abf31444006ba1d80eb508c24e8cd0b0606d8f8 GIT binary patch literal 3296 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 i + +namespace QmlViewer { + +LayerItem::LayerItem(QGraphicsScene* scene) + : QGraphicsObject() +{ + scene->addItem(this); + setZValue(1); + setFlag(QGraphicsItem::ItemIsMovable, false); +} + +LayerItem::~LayerItem() +{ +} + +void LayerItem::paint(QPainter * /*painter*/, const QStyleOptionGraphicsItem * /*option*/, QWidget * /*widget*/) +{ +} + +int LayerItem::type() const +{ + return Constants::EditorItemType; +} + +QRectF LayerItem::boundingRect() const +{ + return childrenBoundingRect(); +} + +QList LayerItem::findAllChildItems() const +{ + return findAllChildItems(this); +} + +QList LayerItem::findAllChildItems(const QGraphicsItem *item) const +{ + QList itemList(item->childItems()); + + foreach (QGraphicsItem *childItem, item->childItems()) + itemList += findAllChildItems(childItem); + + return itemList; +} + +} // namespace QmlViewer diff --git a/src/tools/qml/qmlviewer/editor/layeritem.h b/src/tools/qml/qmlviewer/editor/layeritem.h new file mode 100644 index 00000000000..5ce3c82e56f --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/layeritem.h @@ -0,0 +1,57 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef LAYERITEM_H +#define LAYERITEM_H + +#include +#include + +namespace QmlViewer { + +class FormEditorScene; + +class LayerItem : public QGraphicsObject +{ +public: + LayerItem(QGraphicsScene* scene); + ~LayerItem(); + void paint ( QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0 ); + QRectF boundingRect() const; + int type() const; + + QList findAllChildItems() const; + +protected: + QList findAllChildItems(const QGraphicsItem *item) const; +}; + +} + +#endif // LAYERITEM_H diff --git a/src/tools/qml/qmlviewer/editor/movemanipulator.cpp b/src/tools/qml/qmlviewer/editor/movemanipulator.cpp new file mode 100644 index 00000000000..a9182fad185 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/movemanipulator.cpp @@ -0,0 +1,360 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "movemanipulator.h" +#include "qdeclarativedesignview.h" +//#include "layeritem.h" + +#include +#include +#include +#include +#include + +#include + +namespace QmlViewer { + +MoveManipulator::MoveManipulator(/*LayerItem *layerItem, */QDeclarativeDesignView *view) + : //m_layerItem(layerItem), + m_view(view), + m_isActive(false) +{ +} + +MoveManipulator::~MoveManipulator() +{ + deleteSnapLines(); +} + +QPointF MoveManipulator::beginPoint() const +{ + return m_beginPoint; +} + +QList MoveManipulator::itemList() const +{ + return m_itemList; +} + +void MoveManipulator::setItem(QGraphicsItem* item) +{ + QList itemList; + itemList.append(item); + + setItems(itemList); +} + +void MoveManipulator::setItems(const QList &itemList) +{ + m_itemList = itemList; + + foreach (QGraphicsItem* item, m_itemList) { + //QPointF positionInParentSpace = m_snapper.containerQGraphicsItem()->mapFromScene(m_beginPositionInSceneSpaceHash.value(item)); + //m_beginItemRectHash[item].translate(positionInParentSpace - m_beginPositionHash.value(item)); + qDebug() << item << item->pos(); + m_beginPositionHash.insert(item, item->pos()); + } + +// if (!m_itemList.isEmpty()) { +// if (m_itemList.first()->parentItem()) +// m_snapper.setContainerQGraphicsItem(m_itemList.first()->parentItem()); +// else +// m_snapper.setContainerQGraphicsItem(m_itemList.first()); +// m_snapper.setTransformtionSpaceQGraphicsItem(m_snapper.containerQGraphicsItem()); +// } +} + +void MoveManipulator::updateHashes() +{ +// foreach (QGraphicsItem* item, m_itemList) +// m_beginItemRectHash[item] = item->mapRectToParent(item->qmlItemNode().instanceBoundingRect()); + +// foreach (QGraphicsItem* item, m_itemList) { +// QPointF positionInParentSpace = m_snapper.containerQGraphicsItem()->mapFromScene(m_beginPositionInSceneSpaceHash.value(item)); +// m_beginItemRectHash[item].translate(positionInParentSpace - m_beginPositionHash.value(item)); +// m_beginPositionHash.insert(item, positionInParentSpace); +// } +} + +bool MoveManipulator::itemsCanReparented() const +{ + return true; +} + +void MoveManipulator::begin(const QPointF &beginPoint) +{ + m_isActive = true; + + //m_snapper.updateSnappingLines(m_itemList); + + +// foreach (QGraphicsItem* item, m_itemList) +// m_beginItemRectHash.insert(item, m_snapper.containerQGraphicsItem()->mapRectFromItem(item, item->qmlItemNode().instanceBoundingRect())); + +// foreach (QGraphicsItem* item, m_itemList) { +// QPointF positionInParentSpace(item->qmlItemNode().instancePosition()); +// QPointF positionInScenesSpace = m_snapper.containerQGraphicsItem()->mapToScene(positionInParentSpace); +// m_beginPositionInSceneSpaceHash.insert(item, positionInScenesSpace); +// } + +// foreach (QGraphicsItem* item, m_itemList) { +// QPointF positionInParentSpace = m_snapper.containerQGraphicsItem()->mapFromScene(m_beginPositionInSceneSpaceHash.value(item)); +// m_beginPositionHash.insert(item, positionInParentSpace); + +// QmlAnchors anchors(item->qmlItemNode().anchors()); +// m_beginTopMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Top)); +// m_beginLeftMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Left)); +// m_beginRightMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Right)); +// m_beginBottomMarginHash.insert(item, anchors.instanceMargin(AnchorLine::Bottom)); +// m_beginHorizontalCenterHash.insert(item, anchors.instanceMargin(AnchorLine::HorizontalCenter)); +// m_beginVerticalCenterHash.insert(item, anchors.instanceMargin(AnchorLine::VerticalCenter)); +// } + + m_beginPoint = beginPoint; + +} + +//QPointF MoveManipulator::findSnappingOffset(const QList &boundingRectList) +//{ +// QPointF offset; + +// QMap verticalOffsetMap; +// foreach (const QRectF &boundingRect, boundingRectList) { +// double verticalOffset = m_snapper.snappedVerticalOffset(boundingRect); +// if (verticalOffset < std::numeric_limits::max()) +// verticalOffsetMap.insert(qAbs(verticalOffset), verticalOffset); +// } + + +// if (!verticalOffsetMap.isEmpty()) +// offset.rx() = verticalOffsetMap.begin().value(); + + + +// QMap horizontalOffsetMap; +// foreach (const QRectF &boundingRect, boundingRectList) { +// double horizontalOffset = m_snapper.snappedHorizontalOffset(boundingRect); +// if (horizontalOffset < std::numeric_limits::max()) +// horizontalOffsetMap.insert(qAbs(horizontalOffset), horizontalOffset); +// } + + +// if (!horizontalOffsetMap.isEmpty()) +// offset.ry() = horizontalOffsetMap.begin().value(); + +// return offset; +//} + +//void MoveManipulator::generateSnappingLines(const QList &boundingRectList) +//{ +// m_graphicsLineList = m_snapper.generateSnappingLines(boundingRectList, +// m_layerItem.data(), +// m_snapper.transformtionSpaceQGraphicsItem()->sceneTransform()); +//} + +QList MoveManipulator::translatedBoundingRects(const QList &boundingRectList, const QPointF& offsetVector) +{ + QList translatedBoundingRectList; + foreach (const QRectF &boundingRect, boundingRectList) + translatedBoundingRectList.append(boundingRect.translated(offsetVector)); + + return translatedBoundingRectList; +} + + + +/* + /brief updates the position of the items. +*/ +void MoveManipulator::update(const QPointF& updatePoint, Snapping /*useSnapping*/, State /*stateToBeManipulated*/) +{ + //deleteSnapLines(); //Since they position is changed and the item is moved the snapping lines are + //are obsolete. The new updated snapping lines (color and visibility) will be + //calculated in snapPoint() called in moveNode() later + + if (m_itemList.isEmpty()) { + return; + } else { + //QPointF updatePointInContainerSpace(m_snapper.containerQGraphicsItem()->mapFromScene(updatePoint)); + //QPointF beginPointInContainerSpace(m_snapper.containerQGraphicsItem()->mapFromScene(m_beginPoint)); + + QPointF offsetVector(updatePoint - m_beginPoint); + +// if (useSnapping == UseSnapping || useSnapping == UseSnappingAndAnchoring) { +// offsetVector -= findSnappingOffset(translatedBoundingRects(m_beginItemRectHash.values(), offsetVector)); +// //generateSnappingLines(translatedBoundingRects(m_beginItemRectHash.values(), offsetVector)); +// } + + foreach (QGraphicsItem* item, m_itemList) { + //qDebug() << "offset:" << m_beginPositionHash.value(item) << offsetVector; + QPointF positionInContainerSpace(m_beginPositionHash.value(item) + offsetVector); + + // don't support anchors for base state because it is not needed by the droptool +// if (stateToBeManipulated == UseActualState) { +// QmlAnchors anchors(item->qmlItemNode().anchors()); + +// if (anchors.instanceHasAnchor(AnchorLine::Top)) { +// anchors.setMargin(AnchorLine::Top, m_beginTopMarginHash.value(item) + offsetVector.y()); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Left)) { +// anchors.setMargin(AnchorLine::Left, m_beginLeftMarginHash.value(item) + offsetVector.x()); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { +// anchors.setMargin(AnchorLine::Bottom, m_beginBottomMarginHash.value(item) - offsetVector.y()); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Right)) { +// anchors.setMargin(AnchorLine::Right, m_beginRightMarginHash.value(item) - offsetVector.x()); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// anchors.setMargin(AnchorLine::HorizontalCenter, m_beginHorizontalCenterHash.value(item) + offsetVector.x()); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// anchors.setMargin(AnchorLine::VerticalCenter, m_beginVerticalCenterHash.value(item) + offsetVector.y()); +// } + +// item->setPos(positionInContainerSpace); +// } else { +// item->qmlItemNode().modelNode().variantProperty("x").setValue(qRound(positionInContainerSpace.x())); +// item->qmlItemNode().modelNode().variantProperty("y").setValue(qRound(positionInContainerSpace.y())); +// } + item->setPos(positionInContainerSpace); + } + } +} + +void MoveManipulator::clear() +{ + deleteSnapLines(); + m_beginItemRectHash.clear(); + m_beginPositionHash.clear(); + m_beginPositionInSceneSpaceHash.clear(); + m_itemList.clear(); + + m_beginTopMarginHash.clear(); + m_beginLeftMarginHash.clear(); + m_beginRightMarginHash.clear(); + m_beginBottomMarginHash.clear(); + m_beginHorizontalCenterHash.clear(); + m_beginVerticalCenterHash.clear(); +} + +void MoveManipulator::reparentTo(QGraphicsItem *newParent) +{ + deleteSnapLines(); + + if (!newParent) + return; + + if (!itemsCanReparented()) + return; + +// foreach (QGraphicsItem* item, m_itemList) { +// QmlItemNode parent(newParent->qmlItemNode()); +// if (parent.isValid()) { +// item->qmlItemNode().setParentProperty(parent.nodeAbstractProperty("data")); +// } +// } + +// m_snapper.setContainerQGraphicsItem(newParent); +// m_snapper.setTransformtionSpaceQGraphicsItem(m_snapper.containerQGraphicsItem()); +// m_snapper.updateSnappingLines(m_itemList); + + updateHashes(); +} + + +void MoveManipulator::end(const QPointF &/*endPoint*/) +{ + m_isActive = false; + deleteSnapLines(); + + clear(); +} + +void MoveManipulator::moveBy(double deltaX, double deltaY) +{ + foreach (QGraphicsItem* item, m_itemList) { +// QmlAnchors anchors(item->qmlItemNode().anchors()); + +// if (anchors.instanceHasAnchor(AnchorLine::Top)) { +// anchors.setMargin(AnchorLine::Top, anchors.instanceMargin(AnchorLine::Top) + deltaY); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Left)) { +// anchors.setMargin(AnchorLine::Left, anchors.instanceMargin(AnchorLine::Left) + deltaX); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { +// anchors.setMargin(AnchorLine::Bottom, anchors.instanceMargin(AnchorLine::Bottom) - deltaY); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Right)) { +// anchors.setMargin(AnchorLine::Right, anchors.instanceMargin(AnchorLine::Right) - deltaX); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// anchors.setMargin(AnchorLine::HorizontalCenter, anchors.instanceMargin(AnchorLine::HorizontalCenter) + deltaX); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// anchors.setMargin(AnchorLine::VerticalCenter, anchors.instanceMargin(AnchorLine::VerticalCenter) + deltaY); +// } + + item->moveBy(deltaX, deltaY); + } +} + +void MoveManipulator::setOpacityForAllElements(qreal opacity) +{ + foreach (QGraphicsItem* item, m_itemList) + item->setOpacity(opacity); +} + +void MoveManipulator::deleteSnapLines() +{ +// if (m_layerItem) { +// foreach (QGraphicsItem *item, m_graphicsLineList) +// m_layerItem->scene()->removeItem(item); +// } +// m_graphicsLineList.clear(); +// m_view->scene()->update(); +} + +bool MoveManipulator::isActive() const +{ + return m_isActive; +} + +} diff --git a/src/tools/qml/qmlviewer/editor/movemanipulator.h b/src/tools/qml/qmlviewer/editor/movemanipulator.h new file mode 100644 index 00000000000..f09a7436249 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/movemanipulator.h @@ -0,0 +1,116 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MOVEMANIPULATOR_H +#define MOVEMANIPULATOR_H + +#include +#include +#include +#include +#include +#include + +//#include "snapper.h" +//#include "formeditorview.h" + +namespace QmlViewer { + +class QDeclarativeDesignView; + +class MoveManipulator +{ +public: + enum Snapping { + UseSnapping, + UseSnappingAndAnchoring, + NoSnapping + }; + + enum State { + UseActualState, + UseBaseState + }; + + MoveManipulator(/*LayerItem *layerItem, */QDeclarativeDesignView *view); + ~MoveManipulator(); + QList itemList() const; + void setItems(const QList &itemList); + void setItem(QGraphicsItem* item); + + void begin(const QPointF& beginPoint); + void update(const QPointF& updatePoint, Snapping useSnapping, State stateToBeManipulated = UseActualState); + void reparentTo(QGraphicsItem *newParent); + void end(const QPointF& endPoint); + + void moveBy(double deltaX, double deltaY); + + QPointF beginPoint() const; + + void clear(); + + bool isActive() const; + +protected: + void setOpacityForAllElements(qreal opacity); + + //QPointF findSnappingOffset(const QList &boundingRectList); + void deleteSnapLines(); + + QList translatedBoundingRects(const QList &boundingRectList, const QPointF& offset); + QPointF calculateBoundingRectMovementOffset(const QPointF& updatePoint); + QRectF boundingRect(QGraphicsItem* item, const QPointF& updatePoint); + + //void generateSnappingLines(const QList &boundingRectList); + void updateHashes(); + + bool itemsCanReparented() const; + +private: + //Snapper m_snapper; + //QWeakPointer m_layerItem; + QWeakPointer m_view; + QList m_itemList; + QHash m_beginItemRectHash; + QHash m_beginPositionHash; + QHash m_beginPositionInSceneSpaceHash; + QPointF m_beginPoint; + QHash m_beginTopMarginHash; + QHash m_beginLeftMarginHash; + QHash m_beginRightMarginHash; + QHash m_beginBottomMarginHash; + QHash m_beginHorizontalCenterHash; + QHash m_beginVerticalCenterHash; + QList m_graphicsLineList; + bool m_isActive; +}; + +} + +#endif // MOVEMANIPULATOR_H diff --git a/src/tools/qml/qmlviewer/editor/movetool.cpp b/src/tools/qml/qmlviewer/editor/movetool.cpp new file mode 100644 index 00000000000..20377c10ddb --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/movetool.cpp @@ -0,0 +1,377 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "movetool.h" + +#include "resizehandleitem.h" +#include "qdeclarativedesignview.h" + +#include +#include +#include +#include +#include + +namespace QmlViewer { + +MoveTool::MoveTool(QDeclarativeDesignView *editorView) + : AbstractFormEditorTool(editorView), + m_moving(false), + m_moveManipulator(editorView), + m_selectionIndicator(editorView->manipulatorLayer()), + m_resizeIndicator(editorView->manipulatorLayer()) +{ + +} + + +MoveTool::~MoveTool() +{ + +} + +void MoveTool::clear() +{ + view()->clearHighlightBoundingRect(); + view()->setCursor(Qt::SizeAllCursor); + m_moveManipulator.clear(); + m_movingItems.clear(); + m_resizeIndicator.clear(); + m_selectionIndicator.clear(); +} + +void MoveTool::mousePressEvent(QMouseEvent *event) +{ + QList itemList = view()->selectableItems(event->pos()); + + if (event->buttons() & Qt::LeftButton) { + m_moving = true; + + if (itemList.isEmpty()) { + view()->changeTool(Constants::SelectionToolMode); + return; + } + + m_movingItems = movingItems(items()); + if (m_movingItems.isEmpty()) + return; + + m_moveManipulator.setItems(m_movingItems); + + m_moveManipulator.begin(event->pos()); + } else if (event->buttons() & Qt::RightButton) { + view()->changeTool(Constants::SelectionToolMode); + } + +} + +void MoveTool::mouseMoveEvent(QMouseEvent *event) +{ + if (m_movingItems.isEmpty()) + return; + + if (event->buttons() & Qt::LeftButton) { + + m_selectionIndicator.hide(); + m_resizeIndicator.hide(); + +// QGraphicsItem *containerItem = containerQGraphicsItem(itemList, m_movingItems); +// if (containerItem +// && view()->currentState().isBaseState()) { +// if (containerItem != m_movingItems.first()->parentItem() +// && event->modifiers().testFlag(Qt::ShiftModifier)) { +// m_moveManipulator.reparentTo(containerItem); +// } +// } +// bool shouldSnapping = view()->widget()->snappingAction()->isChecked(); +// bool shouldSnappingAndAnchoring = view()->widget()->snappingAndAnchoringAction()->isChecked(); +// MoveManipulator::Snapping useSnapping = MoveManipulator::NoSnapping; +// if (event->modifiers().testFlag(Qt::ControlModifier) != (shouldSnapping || shouldSnappingAndAnchoring)) { +// if (shouldSnappingAndAnchoring) +// useSnapping = MoveManipulator::UseSnappingAndAnchoring; +// else +// useSnapping = MoveManipulator::UseSnapping; +// } + + m_moveManipulator.update(event->pos(), MoveManipulator::NoSnapping); + } +} + +void MoveTool::mouseReleaseEvent(QMouseEvent *event) +{ + if (m_movingItems.isEmpty()) + return; + + if (m_moving) { + QLineF moveVector(event->pos(), m_moveManipulator.beginPoint()); + if (moveVector.length() < QApplication::startDragDistance()) + { + QPointF beginPoint(m_moveManipulator.beginPoint()); + + m_moveManipulator.end(beginPoint); + + m_selectionIndicator.show(); + m_resizeIndicator.show(); + m_movingItems.clear(); + view()->changeTool(Constants::SelectionToolMode, + Constants::UseCursorPos); + } else { + m_moveManipulator.end(event->pos()); + + m_selectionIndicator.show(); + m_resizeIndicator.show(); + m_movingItems.clear(); + } + qDebug() << "releasing"; + view()->changeTool(Constants::ResizeToolMode); + } + + m_moving = false; + + qDebug() << "released"; +} + + +void MoveTool::hoverMoveEvent(QMouseEvent *event) +{ + QList itemList = view()->items(event->pos()); + + if (itemList.isEmpty()) { + view()->changeTool(Constants::SelectionToolMode); + return; + } + + ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(itemList.first()); + if (resizeHandle) { + view()->changeTool(Constants::ResizeToolMode); + return; + } + + QList selectableItemList = view()->selectableItems(event->pos()); + if (!topSelectedItemIsMovable(selectableItemList)) { + view()->changeTool(Constants::SelectionToolMode); + return; + } +} + +void MoveTool::keyPressEvent(QKeyEvent *event) +{ + switch(event->key()) { + case Qt::Key_Shift: + case Qt::Key_Alt: + case Qt::Key_Control: + case Qt::Key_AltGr: + event->setAccepted(false); + return; + } + + double moveStep = 1.0; + + if (event->modifiers().testFlag(Qt::ShiftModifier)) + moveStep = 10.0; + + if (!event->isAutoRepeat()) { + QList movableItems(movingItems(items())); + if (movableItems.isEmpty()) + return; + + m_moveManipulator.setItems(movableItems); + m_selectionIndicator.hide(); + m_resizeIndicator.hide(); + } + + switch(event->key()) { + case Qt::Key_Left: m_moveManipulator.moveBy(-moveStep, 0.0); break; + case Qt::Key_Right: m_moveManipulator.moveBy(moveStep, 0.0); break; + case Qt::Key_Up: m_moveManipulator.moveBy(0.0, -moveStep); break; + case Qt::Key_Down: m_moveManipulator.moveBy(0.0, moveStep); break; + } + + +} + +void MoveTool::keyReleaseEvent(QKeyEvent *keyEvent) +{ + switch(keyEvent->key()) { + case Qt::Key_Shift: + case Qt::Key_Alt: + case Qt::Key_Control: + case Qt::Key_AltGr: + keyEvent->setAccepted(false); + return; + } + + if (!keyEvent->isAutoRepeat()) { + m_moveManipulator.clear(); + m_selectionIndicator.show(); + m_resizeIndicator.show(); + } +} + +void MoveTool::wheelEvent(QWheelEvent */*event*/) +{ + +} + +void MoveTool::mouseDoubleClickEvent(QMouseEvent * /*event*/) +{ + +} + +void MoveTool::itemsAboutToRemoved(const QList &removedItemList) +{ + foreach (QGraphicsItem* removedItem, removedItemList) + m_movingItems.removeOne(removedItem); +} + +void MoveTool::selectedItemsChanged(const QList &itemList) +{ + m_selectionIndicator.setItems(toGraphicsObjectList(itemList)); + m_resizeIndicator.setItems(toGraphicsObjectList(itemList)); + updateMoveManipulator(); +} + +bool MoveTool::haveSameParent(const QList &itemList) +{ + if (itemList.isEmpty()) + return false; + + QGraphicsItem *firstParent = itemList.first()->parentItem(); + foreach (QGraphicsItem* item, itemList) + { + if (firstParent != item->parentItem()) + return false; + } + + return true; +} + +bool MoveTool::isAncestorOfAllItems(QGraphicsItem* maybeAncestorItem, + const QList &itemList) +{ + foreach (QGraphicsItem* item, itemList) + { + if (!maybeAncestorItem->isAncestorOf(item) && item != maybeAncestorItem) + return false; + } + + return true; +} + + +QGraphicsItem* MoveTool::ancestorIfOtherItemsAreChild(const QList &itemList) +{ + if (itemList.isEmpty()) + return 0; + + + foreach (QGraphicsItem* item, itemList) + { + if (isAncestorOfAllItems(item, itemList)) + return item; + } + + return 0; +} + +void MoveTool::updateMoveManipulator() +{ + if (m_moveManipulator.isActive()) + return; +} + +void MoveTool::beginWithPoint(const QPointF &beginPoint) +{ + m_movingItems = movingItems(items()); + if (m_movingItems.isEmpty()) + return; + + m_moving = true; + m_moveManipulator.setItems(m_movingItems); + m_moveManipulator.begin(beginPoint); +} + +//static bool isNotAncestorOfItemInList(QGraphicsItem *graphicsItem, const QList &itemList) +//{ +// foreach (QGraphicsItem *item, itemList) { +// if (item->qmlItemNode().isAncestorOf(graphicsItem->qmlItemNode())) +// return false; +// } + +// return true; +//} + +//QGraphicsItem* MoveTool::containerQGraphicsItem(const QList &itemUnderMouseList, +// const QList &selectedItemList) +//{ +// Q_ASSERT(!selectedItemList.isEmpty()); + +// foreach (QGraphicsItem* item, itemUnderMouseList) { +// QGraphicsItem *QGraphicsItem = QGraphicsItem::fromQGraphicsItem(item); +// if (QGraphicsItem +// && !selectedItemList.contains(QGraphicsItem) +// && isNotAncestorOfItemInList(QGraphicsItem, selectedItemList)) +// return QGraphicsItem; + +// } + +// return 0; +//} + + +QList MoveTool::movingItems(const QList &selectedItemList) +{ + QGraphicsItem* ancestorItem = ancestorIfOtherItemsAreChild(selectedItemList); + +// if (ancestorItem != 0 && ancestorItem->qmlItemNode().isRootNode()) { +// view()->changeTool(QDeclarativeDesignView::SelectionToolMode); +// return QList(); +// } + + if (ancestorItem != 0 && ancestorItem->parentItem() != 0) { + QList ancestorItemList; + ancestorItemList.append(ancestorItem); + return ancestorItemList; + } + + if (!haveSameParent(selectedItemList)) { + view()->changeTool(Constants::SelectionToolMode); + return QList(); + } + + return selectedItemList; +} + +void MoveTool::graphicsObjectsChanged(const QList &itemList) +{ + m_selectionIndicator.updateItems(itemList); + m_resizeIndicator.updateItems(itemList); +} + +} diff --git a/src/tools/qml/qmlviewer/editor/movetool.h b/src/tools/qml/qmlviewer/editor/movetool.h new file mode 100644 index 00000000000..7514cf68664 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/movetool.h @@ -0,0 +1,91 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MOVETOOL_H +#define MOVETOOL_H + +#include "abstractformeditortool.h" +#include "movemanipulator.h" +#include "resizeindicator.h" +#include "selectionindicator.h" +#include + +namespace QmlViewer { + +class MoveTool : public AbstractFormEditorTool +{ +public: + MoveTool(QDeclarativeDesignView* editorView); + ~MoveTool(); + + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); + void hoverMoveEvent(QMouseEvent *event); + + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *keyEvent); + void wheelEvent(QWheelEvent *event); + + void itemsAboutToRemoved(const QList &itemList); + + void selectedItemsChanged(const QList &itemList); + + void updateMoveManipulator(); + + void beginWithPoint(const QPointF &beginPoint); + + void clear(); + + void graphicsObjectsChanged(const QList &itemList); + +protected: + static bool haveSameParent(const QList &itemList); + + QList movingItems(const QList &selectedItemList); + + static QGraphicsItem* containerFormEditorItem(const QList &itemUnderMouseList, + const QList &selectedItemList); + + static bool isAncestorOfAllItems(QGraphicsItem* maybeAncestorItem, + const QList &itemList); + static QGraphicsItem* ancestorIfOtherItemsAreChild(const QList &itemList); + +private: + bool m_moving; + MoveManipulator m_moveManipulator; + SelectionIndicator m_selectionIndicator; + ResizeIndicator m_resizeIndicator; + QList m_movingItems; +}; + +} + +#endif // MOVETOOL_H diff --git a/src/tools/qml/qmlviewer/editor/qmltoolbar.cpp b/src/tools/qml/qmlviewer/editor/qmltoolbar.cpp new file mode 100644 index 00000000000..9bb1357f84b --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/qmltoolbar.cpp @@ -0,0 +1,210 @@ +#include +#include +#include + +#include "qmltoolbar.h" +#include "toolbarcolorbox.h" + +#include + +namespace QmlViewer { + +QmlToolbar::QmlToolbar(QWidget *parent) : + QToolBar(parent), + m_emitSignals(true), + ui(new Ui) +{ + ui->play = new QAction(QIcon(":/qml/images/play.png"), tr("Play"), this); + ui->pause = new QAction(QIcon(":/qml/images/pause.png"), tr("Pause"), this); + ui->select = new QAction(QIcon(":/qml/images/select.png"), tr("Select"), this); + ui->selectMarquee = new QAction(QIcon(":/qml/images/select-marquee.png"), tr("Select (Marquee)"), this); + ui->zoom = new QAction(QIcon(":/qml/images/zoom.png"), tr("Zoom"), this); + ui->colorPicker = new QAction(QIcon(":/qml/images/color-picker.png"), tr("Color Picker"), this); + ui->toQml = new QAction(QIcon(":/qml/images/to-qml.png"), tr("Apply Changes to QML Viewer"), this); + ui->fromQml = new QAction(QIcon(":/qml/images/from-qml.png"), tr("Apply Changes to Document"), this); + ui->play->setCheckable(true); + ui->play->setChecked(true); + ui->pause->setCheckable(true); + ui->select->setCheckable(true); + ui->selectMarquee->setCheckable(true); + ui->zoom->setCheckable(true); + ui->colorPicker->setCheckable(true); + + setWindowTitle(tr("Tools")); + + addAction(ui->play); + addAction(ui->pause); + addSeparator(); + + addAction(ui->select); + addAction(ui->selectMarquee); + addSeparator(); + addAction(ui->zoom); + addAction(ui->colorPicker); + addAction(ui->fromQml); + + ui->colorBox = new ToolBarColorBox(this); + ui->colorBox->setMinimumSize(24, 24); + ui->colorBox->setMaximumSize(28, 28); + ui->colorBox->setColor(Qt::black); + addWidget(ui->colorBox); + + setWindowFlags(Qt::Tool); + + connect(ui->colorPicker, SIGNAL(triggered()), SLOT(activateColorPickerOnClick())); + + connect(ui->play, SIGNAL(triggered()), SLOT(activatePlayOnClick())); + connect(ui->pause, SIGNAL(triggered()), SLOT(activatePauseOnClick())); + + connect(ui->zoom, SIGNAL(triggered()), SLOT(activateZoomOnClick())); + connect(ui->colorPicker, SIGNAL(triggered()), SLOT(activateColorPickerOnClick())); + connect(ui->select, SIGNAL(triggered()), SLOT(activateSelectToolOnClick())); + connect(ui->selectMarquee, SIGNAL(triggered()), SLOT(activateMarqueeSelectToolOnClick())); + + connect(ui->toQml, SIGNAL(triggered()), SLOT(activateToQml())); + connect(ui->fromQml, SIGNAL(triggered()), SLOT(activateFromQml())); +} + +QmlToolbar::~QmlToolbar() +{ + delete ui; +} + +void QmlToolbar::startExecution() +{ + m_emitSignals = false; + activatePlayOnClick(); + m_emitSignals = true; +} + +void QmlToolbar::pauseExecution() +{ + m_emitSignals = false; + activatePauseOnClick(); + m_emitSignals = true; +} + +void QmlToolbar::activateColorPicker() +{ + m_emitSignals = false; + activateColorPickerOnClick(); + m_emitSignals = true; +} + +void QmlToolbar::activateSelectTool() +{ + m_emitSignals = false; + activateSelectToolOnClick(); + m_emitSignals = true; +} + +void QmlToolbar::activateMarqueeSelectTool() +{ + m_emitSignals = false; + activateMarqueeSelectToolOnClick(); + m_emitSignals = true; +} + +void QmlToolbar::activateZoom() +{ + m_emitSignals = false; + activateZoomOnClick(); + m_emitSignals = true; +} + +void QmlToolbar::setColorBoxColor(const QColor &color) +{ + ui->colorBox->setColor(color); +} + +void QmlToolbar::activatePlayOnClick() +{ + ui->pause->setChecked(false); + if (!m_isRunning) { + ui->play->setChecked(true); + m_isRunning = true; + if (m_emitSignals) + emit executionStarted(); + } +} + +void QmlToolbar::activatePauseOnClick() +{ + ui->play->setChecked(false); + if (m_isRunning) { + m_isRunning = false; + ui->pause->setChecked(true); + if (m_emitSignals) + emit executionPaused(); + } +} + +void QmlToolbar::activateColorPickerOnClick() +{ + ui->zoom->setChecked(false); + ui->select->setChecked(false); + ui->selectMarquee->setChecked(false); + + ui->colorPicker->setChecked(true); + if (m_activeTool != Constants::ColorPickerMode) { + m_activeTool = Constants::ColorPickerMode; + if (m_emitSignals) + emit colorPickerSelected(); + } +} + +void QmlToolbar::activateSelectToolOnClick() +{ + ui->zoom->setChecked(false); + ui->selectMarquee->setChecked(false); + ui->colorPicker->setChecked(false); + + ui->select->setChecked(true); + if (m_activeTool != Constants::SelectionToolMode) { + m_activeTool = Constants::SelectionToolMode; + if (m_emitSignals) + emit selectToolSelected(); + } +} + +void QmlToolbar::activateMarqueeSelectToolOnClick() +{ + ui->zoom->setChecked(false); + ui->select->setChecked(false); + ui->colorPicker->setChecked(false); + + ui->selectMarquee->setChecked(true); + if (m_activeTool != Constants::MarqueeSelectionToolMode) { + m_activeTool = Constants::MarqueeSelectionToolMode; + if (m_emitSignals) + emit marqueeSelectToolSelected(); + } +} + +void QmlToolbar::activateZoomOnClick() +{ + ui->select->setChecked(false); + ui->selectMarquee->setChecked(false); + ui->colorPicker->setChecked(false); + + ui->zoom->setChecked(true); + if (m_activeTool != Constants::ZoomMode) { + m_activeTool = Constants::ZoomMode; + if (m_emitSignals) + emit zoomToolSelected(); + } +} + +void QmlToolbar::activateFromQml() +{ + if (m_emitSignals) + emit applyChangesFromQmlFileSelected(); +} + +void QmlToolbar::activateToQml() +{ + if (m_emitSignals) + emit applyChangesToQmlFileSelected(); +} + +} diff --git a/src/tools/qml/qmlviewer/editor/qmltoolbar.h b/src/tools/qml/qmlviewer/editor/qmltoolbar.h new file mode 100644 index 00000000000..e6a5ec418e0 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/qmltoolbar.h @@ -0,0 +1,73 @@ +#ifndef QMLTOOLBAR_H +#define QMLTOOLBAR_H + +#include +#include "qmlviewerconstants.h" + +namespace QmlViewer { + +class ToolBarColorBox; + +class QmlToolbar : public QToolBar +{ + Q_OBJECT + +public: + explicit QmlToolbar(QWidget *parent = 0); + ~QmlToolbar(); + +public slots: + void setColorBoxColor(const QColor &color); + void startExecution(); + void pauseExecution(); + void activateColorPicker(); + void activateSelectTool(); + void activateMarqueeSelectTool(); + void activateZoom(); + +signals: + void executionStarted(); + void executionPaused(); + + void colorPickerSelected(); + void selectToolSelected(); + void marqueeSelectToolSelected(); + void zoomToolSelected(); + + void applyChangesToQmlFileSelected(); + void applyChangesFromQmlFileSelected(); + +private slots: + void activatePlayOnClick(); + void activatePauseOnClick(); + void activateColorPickerOnClick(); + void activateSelectToolOnClick(); + void activateMarqueeSelectToolOnClick(); + void activateZoomOnClick(); + + void activateFromQml(); + void activateToQml(); + +private: + class Ui { + public: + QAction *play; + QAction *pause; + QAction *select; + QAction *selectMarquee; + QAction *zoom; + QAction *colorPicker; + QAction *toQml; + QAction *fromQml; + ToolBarColorBox *colorBox; + }; + + bool m_emitSignals; + bool m_isRunning; + Constants::DesignTool m_activeTool; + Ui *ui; +}; + +} + +#endif // QMLTOOLBAR_H diff --git a/src/tools/qml/qmlviewer/editor/qmlviewerconstants.h b/src/tools/qml/qmlviewer/editor/qmlviewerconstants.h new file mode 100644 index 00000000000..aa9c1666da8 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/qmlviewerconstants.h @@ -0,0 +1,37 @@ +#ifndef QMLVIEWERCONSTANTS_H +#define QMLVIEWERCONSTANTS_H + +namespace QmlViewer { +namespace Constants { + +enum DesignTool { + NoTool = 0, + SelectionToolMode = 1, + MarqueeSelectionToolMode = 2, + MoveToolMode = 3, + ResizeToolMode = 4, + ColorPickerMode = 5, + ZoomMode = 6 +}; + +enum ToolFlags { + NoToolFlags = 0, + UseCursorPos = 1 +}; + +static const int DragStartTime = 50; + +static const int DragStartDistance = 20; + +static const double ZoomSnapDelta = 0.04; + +enum GraphicsItemTypes { + EditorItemType = 0xEAAA, + ResizeHandleItemType = 0xEAEA +}; + + +} // namespace Constants +} // namespace QmlViewer + +#endif // QMLVIEWERCONSTANTS_H diff --git a/src/tools/qml/qmlviewer/editor/resize_handle.png b/src/tools/qml/qmlviewer/editor/resize_handle.png new file mode 100644 index 0000000000000000000000000000000000000000..2934f25b7436ea36065f0ef5c249db9e87b04906 GIT binary patch literal 160 zcmeAS@N?(olHy`uVBq!ia0y~yU|k44ofy`glX=O&z`$AH z5n0T@z%2~Ij105pNH8!kxO%!chHzX@PHA9D-oNa>!MB^fr9C`6JUl)pgp@Y9X>dti zRF#mBkho`KcbwsRr%vOUbf>V+b(00}`pq~3Qrq(*hMOU#MXp56!0;Xe0|SGntDnm{ Hr-UW|5L7M- literal 0 HcmV?d00001 diff --git a/src/tools/qml/qmlviewer/editor/resizecontroller.cpp b/src/tools/qml/qmlviewer/editor/resizecontroller.cpp new file mode 100644 index 00000000000..27e5daf9176 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/resizecontroller.cpp @@ -0,0 +1,293 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "resizecontroller.h" +#include "layeritem.h" + +#include +#include +#include +#include + +#include + +namespace QmlViewer { + +ResizeControllerData::ResizeControllerData(LayerItem *layerItem, QGraphicsObject *formEditorItem) + : + layerItem(layerItem), + formEditorItem(formEditorItem), + topLeftItem(0), + topRightItem(0), + bottomLeftItem(0), + bottomRightItem(0), + topItem(0), + leftItem(0), + rightItem(0), + bottomItem(0) +{ + +} + +ResizeControllerData::~ResizeControllerData() +{ + clear(); +} + +void ResizeControllerData::clear() +{ + if (!formEditorItem.isNull() && topLeftItem) { + formEditorItem.data()->scene()->removeItem(topLeftItem); + formEditorItem.data()->scene()->removeItem(topRightItem); + formEditorItem.data()->scene()->removeItem(bottomLeftItem); + formEditorItem.data()->scene()->removeItem(bottomRightItem); + formEditorItem.data()->scene()->removeItem(topItem); + formEditorItem.data()->scene()->removeItem(leftItem); + formEditorItem.data()->scene()->removeItem(rightItem); + formEditorItem.data()->scene()->removeItem(bottomItem); + formEditorItem.clear(); + layerItem.clear(); + topLeftItem = 0; + topRightItem = 0; + bottomLeftItem = 0; + bottomRightItem = 0; + topItem = 0; + leftItem = 0; + rightItem = 0; + bottomItem = 0; + } +} + +ResizeController::ResizeController() + : m_data(new ResizeControllerData(0, 0)) +{ + +} + +ResizeController::~ResizeController() +{ + delete m_data; + m_data = 0; +} + +void ResizeController::setItem(LayerItem *layerItem, QGraphicsObject *item) +{ + createFor(layerItem, item); +} + +ResizeController::ResizeController(LayerItem *layerItem, QGraphicsObject *formEditorItem) : + m_data(new ResizeControllerData(layerItem, formEditorItem)) +{ + createFor(layerItem, formEditorItem); +} + +void ResizeController::createFor(LayerItem *layerItem, QGraphicsObject *formEditorItem) +{ + if (m_data) + m_data->clear(); + else + m_data = new ResizeControllerData(layerItem, formEditorItem); + + m_data->formEditorItem = formEditorItem; + m_data->layerItem = layerItem; + + m_data->topLeftItem = new ResizeHandleItem(layerItem, this); + m_data->topLeftItem->setZValue(3020); + m_data->topLeftItem->setCustomCursor(Qt::SizeFDiagCursor); + + m_data->topRightItem = new ResizeHandleItem(layerItem, this); + m_data->topRightItem->setZValue(3010); + m_data->topRightItem->setCustomCursor(Qt::SizeBDiagCursor); + + m_data->bottomLeftItem = new ResizeHandleItem(layerItem, this); + m_data->bottomLeftItem->setZValue(3010); + m_data->bottomLeftItem->setCustomCursor(Qt::SizeBDiagCursor); + + m_data->bottomRightItem = new ResizeHandleItem(layerItem, this); + m_data->bottomRightItem->setZValue(3050); + m_data->bottomRightItem->setCustomCursor(Qt::SizeFDiagCursor); + + m_data->topItem = new ResizeHandleItem(layerItem, this); + m_data->topItem->setZValue(3000); + m_data->topItem->setCustomCursor(Qt::SizeVerCursor); + + m_data->leftItem = new ResizeHandleItem(layerItem, this); + m_data->leftItem->setZValue(3000); + m_data->leftItem->setCustomCursor(Qt::SizeHorCursor); + + m_data->rightItem = new ResizeHandleItem(layerItem, this); + m_data->rightItem->setZValue(3000); + m_data->rightItem->setCustomCursor(Qt::SizeHorCursor); + + m_data->bottomItem = new ResizeHandleItem(layerItem, this); + m_data->bottomItem->setZValue(3000); + m_data->bottomItem->setCustomCursor(Qt::SizeVerCursor); + + updatePosition(); +} + +bool ResizeController::isValid() const +{ + return !m_data->formEditorItem.isNull(); +} + +void ResizeController::show() +{ + updatePosition(); + + m_data->topLeftItem->show(); + m_data->topRightItem->show(); + m_data->bottomLeftItem->show(); + m_data->bottomRightItem->show(); + m_data->topItem->show(); + m_data->leftItem->show(); + m_data->rightItem->show(); + m_data->bottomItem->show(); +} +void ResizeController::hide() +{ + m_data->topLeftItem->hide(); + m_data->topRightItem->hide(); + m_data->bottomLeftItem->hide(); + m_data->bottomRightItem->hide(); + m_data->topItem->hide(); + m_data->leftItem->hide(); + m_data->rightItem->hide(); + m_data->bottomItem->hide(); +} + + +static QPointF topCenter(const QRectF &rect) +{ + return QPointF(rect.center().x(), rect.top()); +} + +static QPointF leftCenter(const QRectF &rect) +{ + return QPointF(rect.left(), rect.center().y()); +} + +static QPointF rightCenter(const QRectF &rect) +{ + return QPointF(rect.right(), rect.center().y()); +} + +static QPointF bottomCenter(const QRectF &rect) +{ + return QPointF(rect.center().x(), rect.bottom()); +} + + +void ResizeController::updatePosition() +{ + QGraphicsItem *formEditorItem = m_data->formEditorItem.data(); + QRectF boundingRect =formEditorItem->boundingRect(); + QPointF topLeftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + boundingRect.topLeft())); + QPointF topRightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + boundingRect.topRight())); + QPointF bottomLeftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + boundingRect.bottomLeft())); + QPointF bottomRightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + boundingRect.bottomRight())); + + QPointF topPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + topCenter(boundingRect))); + QPointF leftPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + leftCenter(boundingRect))); + + QPointF rightPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + rightCenter(boundingRect))); + QPointF bottomPointInLayerSpace(m_data->formEditorItem->mapToItem(m_data->layerItem.data(), + bottomCenter(boundingRect))); + + + m_data->topRightItem->setHandlePosition(topRightPointInLayerSpace, boundingRect.topRight()); + m_data->topLeftItem->setHandlePosition(topLeftPointInLayerSpace, boundingRect.topLeft()); + m_data->bottomLeftItem->setHandlePosition(bottomLeftPointInLayerSpace, boundingRect.bottomLeft()); + m_data->bottomRightItem->setHandlePosition(bottomRightPointInLayerSpace, boundingRect.bottomRight()); + m_data->topItem->setHandlePosition(topPointInLayerSpace, topCenter(boundingRect)); + m_data->leftItem->setHandlePosition(leftPointInLayerSpace, leftCenter(boundingRect)); + m_data->rightItem->setHandlePosition(rightPointInLayerSpace, rightCenter(boundingRect)); + m_data->bottomItem->setHandlePosition(bottomPointInLayerSpace, bottomCenter(boundingRect)); + +} + + +QGraphicsObject* ResizeController::formEditorItem() const +{ + return m_data->formEditorItem.data(); +} + +ResizeControllerData *ResizeController::data() const +{ + return m_data; +} + +bool ResizeController::isTopLeftHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->topLeftItem; +} + +bool ResizeController::isTopRightHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->topRightItem; +} + +bool ResizeController::isBottomLeftHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->bottomLeftItem; +} + +bool ResizeController::isBottomRightHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->bottomRightItem; +} + +bool ResizeController::isTopHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->topItem; +} + +bool ResizeController::isLeftHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->leftItem; +} + +bool ResizeController::isRightHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->rightItem; +} + +bool ResizeController::isBottomHandle(const ResizeHandleItem *handle) const +{ + return handle == m_data->bottomItem; +} + +} diff --git a/src/tools/qml/qmlviewer/editor/resizecontroller.h b/src/tools/qml/qmlviewer/editor/resizecontroller.h new file mode 100644 index 00000000000..6b214195709 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/resizecontroller.h @@ -0,0 +1,106 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef RESIZECONTROLLER_H +#define RESIZECONTROLLER_H + +#include +#include +#include +#include + +namespace QmlViewer { + +class LayerItem; +class ResizeHandleItem; + +class ResizeControllerData +{ +public: + ResizeControllerData(LayerItem *layerItem, + QGraphicsObject *formEditorItem); + //ResizeControllerData(const ResizeControllerData &other); + ~ResizeControllerData(); + void clear(); + + QWeakPointer layerItem; + QWeakPointer formEditorItem; + ResizeHandleItem *topLeftItem; + ResizeHandleItem *topRightItem; + ResizeHandleItem *bottomLeftItem; + ResizeHandleItem *bottomRightItem; + ResizeHandleItem *topItem; + ResizeHandleItem *leftItem; + ResizeHandleItem *rightItem; + ResizeHandleItem *bottomItem; +}; + + + + +class ResizeController +{ +public: + friend class ResizeHandleItem; + + ResizeController(); + ~ResizeController(); + ResizeController(LayerItem *layerItem, QGraphicsObject *formEditorItem); + + void show(); + void hide(); + void setItem(LayerItem *layerItem, QGraphicsObject *item); + + void updatePosition(); + + bool isValid() const; + + QGraphicsObject *formEditorItem() const; + + bool isTopLeftHandle(const ResizeHandleItem *handle) const; + bool isTopRightHandle(const ResizeHandleItem *handle) const; + bool isBottomLeftHandle(const ResizeHandleItem *handle) const; + bool isBottomRightHandle(const ResizeHandleItem *handle) const; + + bool isTopHandle(const ResizeHandleItem *handle) const; + bool isLeftHandle(const ResizeHandleItem *handle) const; + bool isRightHandle(const ResizeHandleItem *handle) const; + bool isBottomHandle(const ResizeHandleItem *handle) const; + +private: // functions + void createFor(LayerItem *layerItem, QGraphicsObject *formEditorItem); + ResizeControllerData *data() const; + +private: // variables + ResizeControllerData *m_data; +}; + +} + +#endif // RESIZECONTROLLER_H diff --git a/src/tools/qml/qmlviewer/editor/resizehandleitem.cpp b/src/tools/qml/qmlviewer/editor/resizehandleitem.cpp new file mode 100644 index 00000000000..88d50b4650c --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/resizehandleitem.cpp @@ -0,0 +1,126 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "resizehandleitem.h" + +#include + +namespace QmlViewer { + +ResizeHandleItem::ResizeHandleItem(QGraphicsItem *parent, ResizeController *resizeController) + : QGraphicsPixmapItem(QPixmap(":/editor/handle/resize_handle.png"), parent), + m_resizeController(resizeController) +{ + setShapeMode(QGraphicsPixmapItem::BoundingRectShape); + setOffset(-pixmap().rect().center()); + setFlag(QGraphicsItem::ItemIsMovable, true); + setFlag(QGraphicsItem::ItemIgnoresTransformations, true); +} + +void ResizeHandleItem::setHandlePosition(const QPointF & globalPosition, const QPointF & itemSpacePosition) +{ + m_itemSpacePosition = itemSpacePosition; + setPos(globalPosition); +} + +QRectF ResizeHandleItem::boundingRect() const +{ + return QGraphicsPixmapItem::boundingRect().adjusted(-1, -1, 1, 1); +} + +QPainterPath ResizeHandleItem::shape() const +{ + return QGraphicsItem::shape(); +} + +ResizeController * ResizeHandleItem::resizeController() const +{ + return m_resizeController; +} + +ResizeHandleItem* ResizeHandleItem::fromGraphicsItem(QGraphicsItem *item) +{ + return qgraphicsitem_cast(item); +} + +bool ResizeHandleItem::isTopLeftHandle() const +{ + return resizeController()->isTopLeftHandle(this); +} + +bool ResizeHandleItem::isTopRightHandle() const +{ + return resizeController()->isTopRightHandle(this); +} + +bool ResizeHandleItem::isBottomLeftHandle() const +{ + return resizeController()->isBottomLeftHandle(this); +} + +bool ResizeHandleItem::isBottomRightHandle() const +{ + return resizeController()->isBottomRightHandle(this); +} + +bool ResizeHandleItem::isTopHandle() const +{ + return resizeController()->isTopHandle(this); +} + +bool ResizeHandleItem::isLeftHandle() const +{ + return resizeController()->isLeftHandle(this); +} + +bool ResizeHandleItem::isRightHandle() const +{ + return resizeController()->isRightHandle(this); +} + +bool ResizeHandleItem::isBottomHandle() const +{ + return resizeController()->isBottomHandle(this); +} + +QPointF ResizeHandleItem::itemSpacePosition() const +{ + return m_itemSpacePosition; +} + +QCursor ResizeHandleItem::customCursor() const +{ + return m_customCursor; +} +void ResizeHandleItem::setCustomCursor(const QCursor &cursor) +{ + m_customCursor = cursor; +} + +} diff --git a/src/tools/qml/qmlviewer/editor/resizehandleitem.h b/src/tools/qml/qmlviewer/editor/resizehandleitem.h new file mode 100644 index 00000000000..a758dc059fd --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/resizehandleitem.h @@ -0,0 +1,89 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef RESIZEHANDLEITEM_H +#define RESIZEHANDLEITEM_H + +#include +#include + +#include "resizecontroller.h" + +namespace QmlViewer { + +class ResizeHandleItem : public QGraphicsPixmapItem +{ +public: + enum + { + Type = 0xEAEA + }; + + + ResizeHandleItem(QGraphicsItem *parent, ResizeController *resizeController); + + void setHandlePosition(const QPointF & globalPosition, const QPointF & itemSpacePosition); + + int type() const; + QRectF boundingRect() const; + QPainterPath shape() const; + + ResizeController * resizeController() const; + + static ResizeHandleItem* fromGraphicsItem(QGraphicsItem *item); + + bool isTopLeftHandle() const; + bool isTopRightHandle() const; + bool isBottomLeftHandle() const; + bool isBottomRightHandle() const; + + bool isTopHandle() const; + bool isLeftHandle() const; + bool isRightHandle() const; + bool isBottomHandle() const; + + QPointF itemSpacePosition() const; + QCursor customCursor() const; + void setCustomCursor(const QCursor &cursor); + +private: + ResizeController *m_resizeController; + QPointF m_itemSpacePosition; + QCursor m_customCursor; + +}; + +inline int ResizeHandleItem::type() const +{ + return Type; +} + +} + +#endif // RESIZEHANDLEITEM_H diff --git a/src/tools/qml/qmlviewer/editor/resizeindicator.cpp b/src/tools/qml/qmlviewer/editor/resizeindicator.cpp new file mode 100644 index 00000000000..62a7eb29cff --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/resizeindicator.cpp @@ -0,0 +1,95 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "resizeindicator.h" +#include "layeritem.h" + +#include + +namespace QmlViewer { + +ResizeIndicator::ResizeIndicator(LayerItem *layerItem) + : m_layerItem(layerItem) +{ + +} + +ResizeIndicator::~ResizeIndicator() +{ + m_itemControllerHash.clear(); +} + +void ResizeIndicator::show() +{ + QHashIterator itemControllerIterator(m_itemControllerHash); + while (itemControllerIterator.hasNext()) { + ResizeController *controller = itemControllerIterator.next().value(); + controller->show(); + } +} +void ResizeIndicator::hide() +{ + QHashIterator itemControllerIterator(m_itemControllerHash); + while (itemControllerIterator.hasNext()) { + ResizeController *controller = itemControllerIterator.next().value(); + controller->hide(); + } +} + +void ResizeIndicator::clear() +{ + QHashIterator itemControllerIterator(m_itemControllerHash); + while(itemControllerIterator.hasNext()) { + itemControllerIterator.next(); + delete itemControllerIterator.value(); + } + m_itemControllerHash.clear(); +} + +void ResizeIndicator::setItems(const QList &itemList) +{ + clear(); + + foreach (QGraphicsObject* item, itemList) { + ResizeController *controller = new ResizeController(m_layerItem.data(), item); + m_itemControllerHash.insert(item, controller); + } +} + +void ResizeIndicator::updateItems(const QList &/*itemList*/) +{ +// foreach (QDeclarativeItem* item, itemList) { +// if (m_itemControllerHash.contains(item)) { +// ResizeController *controller = new ResizeController(m_itemControllerHash.value(item)); +// controller.updatePosition(); +// } +// } +} + +} diff --git a/src/tools/qml/qmlviewer/editor/resizeindicator.h b/src/tools/qml/qmlviewer/editor/resizeindicator.h new file mode 100644 index 00000000000..360dba72b7b --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/resizeindicator.h @@ -0,0 +1,82 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef RESIZEINDICATOR_H +#define RESIZEINDICATOR_H + +#include +#include +#include +#include +#include + +#include "resizecontroller.h" + +QT_FORWARD_DECLARE_CLASS(QGraphicsRectItem); + +namespace QmlViewer { + +class LayerItem; + +class ResizeIndicator +{ +public: + enum Orientation { + Top = 1, + Right = 2, + Bottom = 4, + Left = 8 + }; + + ResizeIndicator(LayerItem *layerItem); + ~ResizeIndicator(); + + void show(); + void hide(); + + void clear(); + + void setItems(const QList &itemList); + void updateItems(const QList &itemList); + +// +// QPair pick(QGraphicsRectItem* pickedItem) const; +// +// void show(); +// void hide(); + +private: + QWeakPointer m_layerItem; + QHash m_itemControllerHash; + +}; + +} + +#endif // SCALEINDICATOR_H diff --git a/src/tools/qml/qmlviewer/editor/resizemanipulator.cpp b/src/tools/qml/qmlviewer/editor/resizemanipulator.cpp new file mode 100644 index 00000000000..329404244d6 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/resizemanipulator.cpp @@ -0,0 +1,529 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "resizemanipulator.h" +#include "resizehandleitem.h" + +#include "mathutils.h" + +#include +#include +#include +#include + +namespace QmlViewer { + +ResizeManipulator::ResizeManipulator(LayerItem *layer, QDeclarativeView *view) + : m_view(view), + m_resizeController(0), + m_beginTopMargin(0.0), + m_beginLeftMargin(0.0), + m_beginRightMargin(0.0), + m_beginBottomMargin(0.0), + m_resizeHandle(0), + m_layerItem(layer) +{ +} + +ResizeManipulator::~ResizeManipulator() +{ + deleteSnapLines(); +} + +void ResizeManipulator::setHandle(ResizeHandleItem *resizeHandle) +{ + Q_ASSERT(resizeHandle); + m_view->setCursor(resizeHandle->customCursor()); + m_resizeHandle = resizeHandle; + m_resizeController = resizeHandle->resizeController(); + //m_snapper.setContainerFormEditorItem(m_resizeController.formEditorItem()->parentItem()); + //m_snapper.setTransformtionSpaceFormEditorItem(m_resizeController.formEditorItem()); + Q_ASSERT(m_resizeController->isValid()); +} + +void ResizeManipulator::removeHandle() +{ + m_resizeController = 0; + m_resizeHandle = 0; +} + +void ResizeManipulator::begin(const QPointF &/*beginPoint*/) +{ + + if (m_resizeController->isValid()) { + m_beginBoundingRect = m_resizeController->formEditorItem()->boundingRect(); + m_beginToSceneTransform = m_resizeController->formEditorItem()->sceneTransform(); + m_beginFromSceneTransform = m_beginToSceneTransform.inverted(); + + if (m_resizeController->formEditorItem()->parentItem()) { + m_beginToParentTransform = m_resizeController->formEditorItem()->itemTransform(m_resizeController->formEditorItem()->parentItem()); + } else { + m_beginToParentTransform = QTransform(); + } + + //m_snapper.updateSnappingLines(m_resizeController.formEditorItem()); + m_beginBottomRightPoint = m_beginToParentTransform.map(m_resizeController->formEditorItem()->boundingRect().bottomRight()); + + //QmlAnchors anchors(m_resizeController.formEditorItem()->qmlItemNode().anchors()); + m_beginTopMargin = 0;//anchors.instanceMargin(AnchorLine::Top); + m_beginLeftMargin = 0;//anchors.instanceMargin(AnchorLine::Left); + m_beginRightMargin = 0;//anchors.instanceMargin(AnchorLine::Right); + m_beginBottomMargin = 0;//anchors.instanceMargin(AnchorLine::Bottom); + } +} + +//static QSizeF mapSizeToParent(const QSizeF &size, QGraphicsItem *item) +//{ +// QPointF sizeAsPoint(size.width(), size.height()); +// sizeAsPoint = item->mapToParent(sizeAsPoint); +// return QSizeF(sizeAsPoint.x(), sizeAsPoint.y()); +//} + +void ResizeManipulator::update(const QPointF& updatePoint, Snapping useSnapping) +{ + if (!m_resizeHandle || !m_resizeController) + return; + + const double minimumWidth = 15.0; + const double minimumHeight = 15.0; + + deleteSnapLines(); + + bool snap = useSnapping == UseSnapping || useSnapping == UseSnappingAndAnchoring; + + if (m_resizeController->isValid()) { + + QDeclarativeItem *formEditorItem = qobject_cast(m_resizeController->formEditorItem()); + + if (!formEditorItem) + return; + + //FormEditorItem *containerItem = m_snapper.containerFormEditorItem(); + +// if (!containerItem) +// return; +// QPointF updatePointInLocalSpace = QPointF(0,0); +// if (formEditorItem->parentItem()) { +// updatePointInLocalSpace = formEditorItem->parentItem()->mapFromScene(updatePoint); +// } else { +// updatePointInLocalSpace = updatePoint; //= m_beginFromSceneTransform.map(updatePoint); +// } + + QPointF updatePointInLocalSpace = m_beginFromSceneTransform.map(updatePoint); + //QmlAnchors anchors(formEditorItem->qmlItemNode().anchors()); + + QRectF boundingRect(m_beginBoundingRect); + if (m_resizeHandle->isBottomRightHandle()) { + boundingRect.setBottomRight(updatePointInLocalSpace); + + if (snap) { +// double rightOffset = m_snapper.snapRightOffset(boundingRect); +// if (rightOffset < std::numeric_limits::max()) +// updatePointInLocalSpace.rx() -= rightOffset; + +// double bottomOffset = m_snapper.snapBottomOffset(boundingRect); +// if (bottomOffset < std::numeric_limits::max()) +// updatePointInLocalSpace.ry() -= bottomOffset; + } + boundingRect.setBottomRight(updatePointInLocalSpace); + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// boundingRect.setLeft(boundingRect.left() - (updatePointInLocalSpace.x() - m_beginBoundingRect.right())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// boundingRect.setTop(boundingRect.top() - (updatePointInLocalSpace.y() - m_beginBoundingRect.bottom())); +// } + + + if (boundingRect.width() < minimumWidth) + boundingRect.setWidth(minimumWidth); + if (boundingRect.height() < minimumHeight) + boundingRect.setHeight(minimumHeight); + + formEditorItem->setSize(boundingRect.size()); + +// if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { +// anchors.setMargin(AnchorLine::Bottom, +// m_beginBottomMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).y()); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Right)) { +// anchors.setMargin(AnchorLine::Right, +// m_beginRightMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).x()); +// } + } else if (m_resizeHandle->isTopLeftHandle()) { + boundingRect.setTopLeft(updatePointInLocalSpace); + + if (snap) { +// double leftOffset = m_snapper.snapLeftOffset(boundingRect); +// if (leftOffset < std::numeric_limits::max()) +// updatePointInLocalSpace.rx() -= leftOffset; + +// double topOffset = m_snapper.snapTopOffset(boundingRect); +// if (topOffset < std::numeric_limits::max()) +// updatePointInLocalSpace.ry() -= topOffset; + } + //boundingRect.setTopLeft(updatePointInLocalSpace); + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// boundingRect.setRight(boundingRect.right() - (updatePointInLocalSpace.x() - m_beginBoundingRect.left())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// boundingRect.setBottom(boundingRect.bottom() - (updatePointInLocalSpace.y() - m_beginBoundingRect.top())); +// } + + + if (boundingRect.width() < minimumWidth) + boundingRect.setLeft(boundingRect.left() - minimumWidth + boundingRect.width()); + if (boundingRect.height() < minimumHeight) + boundingRect.setTop(boundingRect.top() - minimumHeight + boundingRect.height()); + + formEditorItem->setSize(boundingRect.size()); + formEditorItem->setPos(m_beginToParentTransform.map(boundingRect.topLeft())); + + +// if (anchors.instanceHasAnchor(AnchorLine::Top)) { +// anchors.setMargin(AnchorLine::Top, +// m_beginTopMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).y() + m_beginToParentTransform.map(boundingRect.topLeft()).y())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Left)) { +// anchors.setMargin(AnchorLine::Left, +// m_beginLeftMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).x() + m_beginToParentTransform.map(boundingRect.topLeft()).x())); +// } + + } else if (m_resizeHandle->isTopRightHandle()) { + boundingRect.setTopRight(updatePointInLocalSpace); + + if (snap) { +// double rightOffset = m_snapper.snapRightOffset(boundingRect); +// if (rightOffset < std::numeric_limits::max()) +// updatePointInLocalSpace.rx() -= rightOffset; + +// double topOffset = m_snapper.snapTopOffset(boundingRect); +// if (topOffset < std::numeric_limits::max()) +// updatePointInLocalSpace.ry() -= topOffset; + } + boundingRect.setTopRight(updatePointInLocalSpace); + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// boundingRect.setLeft(boundingRect.left() - (updatePointInLocalSpace.x() - m_beginBoundingRect.right())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// boundingRect.setBottom(boundingRect.bottom() - (updatePointInLocalSpace.y() - m_beginBoundingRect.top())); +// } + + if (boundingRect.height() < minimumHeight) + boundingRect.setTop(boundingRect.top() - minimumHeight + boundingRect.height()); + if (boundingRect.width() < minimumWidth) + boundingRect.setWidth(minimumWidth); + + formEditorItem->setSize(boundingRect.size()); + + // was: setPositionWithBorder + formEditorItem->setPos(m_beginToParentTransform.map(boundingRect.topLeft())); + +// if (anchors.instanceHasAnchor(AnchorLine::Top)) { +// anchors.setMargin(AnchorLine::Top, +// m_beginTopMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).y() + m_beginToParentTransform.map(boundingRect.topLeft()).y())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Right)) { +// anchors.setMargin(AnchorLine::Right, +// m_beginRightMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).x()); +// } + } else if (m_resizeHandle->isBottomLeftHandle()) { + boundingRect.setBottomLeft(updatePointInLocalSpace); + + if (snap) { +// double leftOffset = m_snapper.snapLeftOffset(boundingRect); +// if (leftOffset < std::numeric_limits::max()) +// updatePointInLocalSpace.rx() -= leftOffset; + +// double bottomOffset = m_snapper.snapBottomOffset(boundingRect); +// if (bottomOffset < std::numeric_limits::max()) +// updatePointInLocalSpace.ry() -= bottomOffset; + } + + boundingRect.setBottomLeft(updatePointInLocalSpace); + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// boundingRect.setRight(boundingRect.right() - (updatePointInLocalSpace.x() - m_beginBoundingRect.left())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// boundingRect.setTop(boundingRect.top() - (updatePointInLocalSpace.y() - m_beginBoundingRect.bottom())); +// } + + if (boundingRect.height() < minimumHeight) + boundingRect.setHeight(minimumHeight); + if (boundingRect.width() < minimumWidth) + boundingRect.setLeft(boundingRect.left() - minimumWidth + boundingRect.width()); + + formEditorItem->setSize(boundingRect.size()); + formEditorItem->setPos(m_beginToParentTransform.map(boundingRect.topLeft())); + +// if (anchors.instanceHasAnchor(AnchorLine::Left)) { +// anchors.setMargin(AnchorLine::Left, +// m_beginLeftMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).x() + m_beginToParentTransform.map(boundingRect.topLeft()).x())); +// } + +// if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { +// anchors.setMargin(AnchorLine::Bottom, +// m_beginBottomMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).y()); +// } + } else if (m_resizeHandle->isBottomHandle()) { + boundingRect.setBottom(updatePointInLocalSpace.y()); + + if (snap) { +// double bottomOffset = m_snapper.snapBottomOffset(boundingRect); +// if (bottomOffset < std::numeric_limits::max()) +// updatePointInLocalSpace.ry() -= bottomOffset; + } + + boundingRect.setBottom(updatePointInLocalSpace.y()); + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// boundingRect.setTop(boundingRect.top() - (updatePointInLocalSpace.y() - m_beginBoundingRect.bottom())); +// } + + if (boundingRect.height() < minimumHeight) + boundingRect.setHeight(minimumHeight); + + formEditorItem->setSize(boundingRect.size()); + +// if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { +// anchors.setMargin(AnchorLine::Bottom, +// m_beginBottomMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).y()); +// } + } else if (m_resizeHandle->isTopHandle()) { + boundingRect.setTop(updatePointInLocalSpace.y()); + + if (snap) { +// double topOffset = m_snapper.snapTopOffset(boundingRect); +// if (topOffset < std::numeric_limits::max()) +// updatePointInLocalSpace.ry() -= topOffset; + } + + boundingRect.setTop(updatePointInLocalSpace.y()); + +// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +// boundingRect.setBottom(boundingRect.bottom() - (updatePointInLocalSpace.y() - m_beginBoundingRect.top())); +// } + + if (boundingRect.height() < minimumHeight) + boundingRect.setTop(boundingRect.top() - minimumHeight + boundingRect.height()); + + formEditorItem->setSize(boundingRect.size()); + formEditorItem->setPos(m_beginToParentTransform.map(boundingRect.topLeft())); + +// if (anchors.instanceHasAnchor(AnchorLine::Top)) { +// anchors.setMargin(AnchorLine::Top, +// m_beginTopMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).y() + m_beginToParentTransform.map(boundingRect.topLeft()).y())); +// } + } else if (m_resizeHandle->isRightHandle()) { + boundingRect.setRight(updatePointInLocalSpace.x()); + + if (snap) { +// double rightOffset = m_snapper.snapRightOffset(boundingRect); +// if (rightOffset < std::numeric_limits::max()) +// updatePointInLocalSpace.rx() -= rightOffset; + } + + boundingRect.setRight(updatePointInLocalSpace.x()); + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// boundingRect.setLeft(boundingRect.left() - (updatePointInLocalSpace.x() - m_beginBoundingRect.right())); +// } + + if (boundingRect.width() < minimumWidth) + boundingRect.setWidth(minimumWidth); + + formEditorItem->setSize(boundingRect.size()); + + +// if (anchors.instanceHasAnchor(AnchorLine::Right)) { +// anchors.setMargin(AnchorLine::Right, +// m_beginRightMargin - (m_beginToParentTransform.map(boundingRect.bottomRight()) - m_beginBottomRightPoint).x()); +// } + } else if (m_resizeHandle->isLeftHandle()) { + boundingRect.setLeft(updatePointInLocalSpace.x()); + + if (snap) { +// double leftOffset = m_snapper.snapLeftOffset(boundingRect); +// if (leftOffset < std::numeric_limits::max()) +// updatePointInLocalSpace.rx() -= leftOffset; + } + + boundingRect.setLeft(updatePointInLocalSpace.x()); + +// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +// boundingRect.setRight(boundingRect.right() - (updatePointInLocalSpace.x() - m_beginBoundingRect.left())); +// } + + if (boundingRect.width() < minimumWidth) + boundingRect.setLeft(boundingRect.left() - minimumWidth + boundingRect.width()); + + formEditorItem->setSize(boundingRect.size()); + formEditorItem->setPos(m_beginToParentTransform.map(boundingRect.topLeft())); + +// if (anchors.instanceHasAnchor(AnchorLine::Left)) { +// anchors.setMargin(AnchorLine::Left, +// m_beginLeftMargin + (-m_beginToParentTransform.map(m_beginBoundingRect.topLeft()).x() + m_beginToParentTransform.map(boundingRect.topLeft()).x())); +// } + } + +// if (snap) +// m_graphicsLineList = m_snapper.generateSnappingLines(boundingRect, +// m_layerItem.data(), +// m_beginToSceneTransform); + } + m_resizeController->updatePosition(); +} + +void ResizeManipulator::end() +{ + //m_rewriterTransaction.commit(); + clear(); + removeHandle(); +} + +//void ResizeManipulator::moveBy(double deltaX, double deltaY) +//{ +// if (resizeHandle()) { +// //QmlItemNode qmlItemNode(m_resizeController.formEditorItem()->qmlItemNode()); +// //QmlAnchors anchors(qmlItemNode.anchors()); + +// if (m_resizeController.isLeftHandle(resizeHandle()) +// || m_resizeController.isTopLeftHandle(resizeHandle()) +// || m_resizeController.isBottomLeftHandle(resizeHandle())) { +// qmlItemNode.setVariantProperty("x", round((qmlItemNode.instanceValue("x").toDouble() + deltaX), 4)); +// qmlItemNode.setVariantProperty("width", round(qmlItemNode.instanceValue("width").toDouble() - deltaX, 4)); + + +//// if (anchors.instanceHasAnchor(AnchorLine::Left)) { +//// anchors.setMargin(AnchorLine::Left, anchors.instanceMargin(AnchorLine::Left) + deltaX); +//// } + +//// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +//// qmlItemNode.setVariantProperty("width", round(qmlItemNode.instanceValue("width").toDouble() - (deltaX * 2), 4)); +//// } +// } + +// if (m_resizeController.isRightHandle(resizeHandle()) +// || m_resizeController.isTopRightHandle(resizeHandle()) +// || m_resizeController.isBottomRightHandle(resizeHandle())) { +// qmlItemNode.setVariantProperty("width", round(qmlItemNode.instanceValue("width").toDouble() + deltaX, 4)); + +//// if (anchors.instanceHasAnchor(AnchorLine::Right)) { +//// anchors.setMargin(AnchorLine::Right, round(anchors.instanceMargin(AnchorLine::Right) - deltaX, 4)); +//// } + +//// if (anchors.instanceHasAnchor(AnchorLine::HorizontalCenter)) { +//// qmlItemNode.setVariantProperty("width", round(qmlItemNode.instanceValue("width").toDouble() + (deltaX * 2), 4)); +//// } +// } + + +// if (m_resizeController.isTopHandle(resizeHandle()) +// || m_resizeController.isTopLeftHandle(resizeHandle()) +// || m_resizeController.isTopRightHandle(resizeHandle())) { +// qmlItemNode.setVariantProperty("y", round(qmlItemNode.instanceValue("y").toDouble() + deltaY, 4)); +// qmlItemNode.setVariantProperty("height", round(qmlItemNode.instanceValue("height").toDouble() - deltaY, 4)); + +//// if (anchors.instanceHasAnchor(AnchorLine::Top)) { +//// anchors.setMargin(AnchorLine::Top, anchors.instanceMargin(AnchorLine::Top) + deltaY); +//// } + +//// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +//// qmlItemNode.setVariantProperty("height", round(qmlItemNode.instanceValue("height").toDouble() - (deltaY * 2), 4)); +//// } +// } + +// if (m_resizeController.isBottomHandle(resizeHandle()) +// || m_resizeController.isBottomLeftHandle(resizeHandle()) +// || m_resizeController.isBottomRightHandle(resizeHandle())) { +// qmlItemNode.setVariantProperty("height", round(qmlItemNode.instanceValue("height").toDouble() + deltaY, 4)); + +//// if (anchors.instanceHasAnchor(AnchorLine::Bottom)) { +//// anchors.setMargin(AnchorLine::Bottom, anchors.instanceMargin(AnchorLine::Bottom) - deltaY); +//// } + +//// if (anchors.instanceHasAnchor(AnchorLine::VerticalCenter)) { +//// qmlItemNode.setVariantProperty("height", round(qmlItemNode.instanceValue("height").toDouble() + (deltaY * 2), 4)); +//// } +// } + +// } +//} + +bool ResizeManipulator::isInvalidSize(const QSizeF & size) +{ + if (size.width() < 15 || size.height() < 15) + return true; + + return false; +} + +void ResizeManipulator::deleteSnapLines() +{ +// if (m_layerItem) { +// foreach (QGraphicsItem *item, m_graphicsLineList) +// m_layerItem->scene()->removeItem(item); +// } + + m_graphicsLineList.clear(); + m_view->scene()->update(); +} + +ResizeHandleItem *ResizeManipulator::resizeHandle() +{ + return m_resizeHandle; +} + +void ResizeManipulator::clear() +{ + //m_rewriterTransaction.commit(); + + deleteSnapLines(); + m_beginBoundingRect = QRectF(); + m_beginFromSceneTransform = QTransform(); + m_beginToSceneTransform = QTransform(); + m_beginToParentTransform = QTransform(); + m_beginTopMargin = 0.0; + m_beginLeftMargin = 0.0; + m_beginRightMargin = 0.0; + m_beginBottomMargin = 0.0; + removeHandle(); +} + +} diff --git a/src/tools/qml/qmlviewer/editor/resizemanipulator.h b/src/tools/qml/qmlviewer/editor/resizemanipulator.h new file mode 100644 index 00000000000..87bd943be31 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/resizemanipulator.h @@ -0,0 +1,93 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef RESIZEMANIPULATOR_H +#define RESIZEMANIPULATOR_H + +#include +#include "layeritem.h" +#include "resizehandleitem.h" + +#include +#include + +namespace QmlViewer { + +class ResizeHandleItem; +class Model; + +class ResizeManipulator +{ +public: + enum Snapping { + UseSnapping, + UseSnappingAndAnchoring, + NoSnapping + }; + + ResizeManipulator(LayerItem *layer, QDeclarativeView *view); + ~ResizeManipulator(); + + void setHandle(ResizeHandleItem *resizeHandle); + void removeHandle(); + + void begin(const QPointF& beginPoint); + void update(const QPointF& updatePoint, Snapping useSnapping); + void end(); + + void moveBy(double deltaX, double deltaY); + + void clear(); + +protected: + bool isInvalidSize(const QSizeF & size); + void deleteSnapLines(); + ResizeHandleItem *resizeHandle(); + +private: +// Snapper m_snapper; + QWeakPointer m_view; + QList m_graphicsLineList; + ResizeController *m_resizeController; + QTransform m_beginFromSceneTransform; + QTransform m_beginToSceneTransform; + QTransform m_beginToParentTransform; + QRectF m_beginBoundingRect; + QPointF m_beginBottomRightPoint; + double m_beginTopMargin; + double m_beginLeftMargin; + double m_beginRightMargin; + double m_beginBottomMargin; + ResizeHandleItem *m_resizeHandle; + QWeakPointer m_layerItem; +}; + +} + +#endif // RESIZEMANIPULATOR_H diff --git a/src/tools/qml/qmlviewer/editor/resizetool.cpp b/src/tools/qml/qmlviewer/editor/resizetool.cpp new file mode 100644 index 00000000000..d5845be6672 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/resizetool.cpp @@ -0,0 +1,204 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "resizetool.h" +#include "resizehandleitem.h" +#include "qdeclarativedesignview.h" + +#include +#include +#include +#include +#include +#include + +#include + +namespace QmlViewer { + +ResizeTool::ResizeTool(QDeclarativeDesignView *view) + : AbstractFormEditorTool(view), + m_selectionIndicator(view->manipulatorLayer()), + m_resizeManipulator(new ResizeManipulator(view->manipulatorLayer(), view)), + m_resizeIndicator(view->manipulatorLayer()) +{ +} + + +ResizeTool::~ResizeTool() +{ + delete m_resizeManipulator; +} + +void ResizeTool::mousePressEvent(QMouseEvent *event) +{ + QList itemList = view()->items(event->pos()); + + if (itemList.isEmpty()) + return; + + ResizeHandleItem *resizeHandle = ResizeHandleItem::fromGraphicsItem(itemList.first()); + + if (resizeHandle) + qDebug() << resizeHandle->resizeController(); + + if (resizeHandle + && resizeHandle->resizeController() + && resizeHandle->resizeController()->isValid()) + { + m_resizeManipulator->setHandle(resizeHandle); + m_resizeManipulator->begin(view()->mapToScene(event->pos())); + m_resizeIndicator.hide(); + } else { + view()->setCursor(Qt::ArrowCursor); + } +} + +void ResizeTool::mouseMoveEvent(QMouseEvent *event) +{ + + bool shouldSnapping = false; //view()->widget()->snappingAction()->isChecked(); + bool shouldSnappingAndAnchoring = false; //view()->widget()->snappingAndAnchoringAction()->isChecked(); + + ResizeManipulator::Snapping useSnapping = ResizeManipulator::NoSnapping; + if (event->modifiers().testFlag(Qt::ControlModifier) != (shouldSnapping || shouldSnappingAndAnchoring)) { + if (shouldSnappingAndAnchoring) + useSnapping = ResizeManipulator::UseSnappingAndAnchoring; + else + useSnapping = ResizeManipulator::UseSnapping; + } + m_resizeManipulator->update(view()->mapToScene(event->pos()), useSnapping); +} + +void ResizeTool::hoverMoveEvent(QMouseEvent *event) +{ + QList itemList = view()->items(event->pos()); + + if (itemList.isEmpty()) + return; + + ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(itemList.first()); + if (resizeHandle && resizeHandle->resizeController()->isValid()) { + m_resizeManipulator->setHandle(resizeHandle); + } else { + qDebug() << "resize -> selection tool"; + view()->changeTool(Constants::SelectionToolMode); + return; + } +} + +void ResizeTool::mouseReleaseEvent(QMouseEvent *event) +{ + QList itemList = view()->selectableItems(event->pos()); + if (itemList.isEmpty()) + return; + + view()->setCursor(Qt::ArrowCursor); + m_selectionIndicator.show(); + m_resizeIndicator.show(); + m_resizeManipulator->end(); +} + +void ResizeTool::mouseDoubleClickEvent(QMouseEvent * /*event*/) +{ +} + +void ResizeTool::keyPressEvent(QKeyEvent * event) +{ + switch(event->key()) { + case Qt::Key_Shift: + case Qt::Key_Alt: + case Qt::Key_Control: + case Qt::Key_AltGr: + event->setAccepted(false); + return; + } + + double moveStep = 1.0; + + if (event->modifiers().testFlag(Qt::ShiftModifier)) + moveStep = 10.0; + +// switch(event->key()) { +// case Qt::Key_Left: m_resizeManipulator->moveBy(-moveStep, 0.0); break; +// case Qt::Key_Right: m_resizeManipulator->moveBy(moveStep, 0.0); break; +// case Qt::Key_Up: m_resizeManipulator->moveBy(0.0, -moveStep); break; +// case Qt::Key_Down: m_resizeManipulator->moveBy(0.0, moveStep); break; +// } + +} + +void ResizeTool::keyReleaseEvent(QKeyEvent * keyEvent) +{ + switch(keyEvent->key()) { + case Qt::Key_Shift: + case Qt::Key_Alt: + case Qt::Key_Control: + case Qt::Key_AltGr: + keyEvent->setAccepted(false); + return; + } + + if (!keyEvent->isAutoRepeat()) + m_resizeManipulator->clear(); +} + +void ResizeTool::wheelEvent(QWheelEvent */*event*/) +{ + +} + +void ResizeTool::itemsAboutToRemoved(const QList & /*itemList*/) +{ + +} + +void ResizeTool::selectedItemsChanged(const QList & itemList) +{ + m_selectionIndicator.setItems(toGraphicsObjectList(itemList)); + + m_resizeIndicator.setItems(toGraphicsObjectList(itemList)); +} + +void ResizeTool::clear() +{ + view()->clearHighlightBoundingRect(); + view()->setCursor(Qt::ArrowCursor); + m_selectionIndicator.clear(); + m_resizeIndicator.clear(); + m_resizeManipulator->clear(); +} + +void ResizeTool::graphicsObjectsChanged(const QList &itemList) +{ + m_selectionIndicator.updateItems(itemList); + m_resizeIndicator.updateItems(itemList); +} + +} diff --git a/src/tools/qml/qmlviewer/editor/resizetool.h b/src/tools/qml/qmlviewer/editor/resizetool.h new file mode 100644 index 00000000000..250441a4e5c --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/resizetool.h @@ -0,0 +1,82 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef RESIZETOOL_H +#define RESIZETOOL_H + +#include +#include +#include + +#include "resizeindicator.h" + +#include "resizemanipulator.h" +#include "abstractformeditortool.h" +#include "selectionindicator.h" + +#include "resizeindicator.h" + +namespace QmlViewer { + +class QDeclarativeDesignView; + +class ResizeTool : public AbstractFormEditorTool +{ +public: + ResizeTool(QDeclarativeDesignView *view); + ~ResizeTool(); + + bool isActive() const; + + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); + + void hoverMoveEvent(QMouseEvent *event); + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *keyEvent); + void wheelEvent(QWheelEvent *event); + + void itemsAboutToRemoved(const QList &itemList); + + void selectedItemsChanged(const QList &itemList); + + void clear(); + void graphicsObjectsChanged(const QList &itemList); + +private: + SelectionIndicator m_selectionIndicator; + ResizeManipulator *m_resizeManipulator; + ResizeIndicator m_resizeIndicator; +}; + +} + +#endif // RESIZETOOL_H diff --git a/src/tools/qml/qmlviewer/editor/rubberbandselectionmanipulator.cpp b/src/tools/qml/qmlviewer/editor/rubberbandselectionmanipulator.cpp new file mode 100644 index 00000000000..3783a09c404 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/rubberbandselectionmanipulator.cpp @@ -0,0 +1,143 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "rubberbandselectionmanipulator.h" +#include "qdeclarativedesignview.h" + +#include + +namespace QmlViewer { + +RubberBandSelectionManipulator::RubberBandSelectionManipulator(LayerItem *layerItem, QDeclarativeDesignView *editorView) + : m_selectionRectangleElement(layerItem), + m_editorView(editorView), + m_beginFormEditorItem(0), + m_isActive(false) +{ + m_selectionRectangleElement.hide(); +} + +void RubberBandSelectionManipulator::clear() +{ + m_selectionRectangleElement.clear(); + m_isActive = false; + m_beginPoint = QPointF(); + m_itemList.clear(); + m_oldSelectionList.clear(); +} + +QGraphicsItem *RubberBandSelectionManipulator::topFormEditorItem(const QList &itemList) +{ + if (itemList.isEmpty()) + return 0; + + return itemList.first(); +} + +void RubberBandSelectionManipulator::begin(const QPointF& beginPoint) +{ + m_beginPoint = beginPoint; + m_selectionRectangleElement.setRect(m_beginPoint, m_beginPoint); + m_selectionRectangleElement.show(); + m_isActive = true; + m_beginFormEditorItem = topFormEditorItem(m_editorView->selectableItems(beginPoint)); + m_oldSelectionList = m_editorView->selectedItems(); +} + +void RubberBandSelectionManipulator::update(const QPointF& updatePoint) +{ + m_selectionRectangleElement.setRect(m_beginPoint, updatePoint); +} + +void RubberBandSelectionManipulator::end() +{ + m_oldSelectionList.clear(); + m_selectionRectangleElement.hide(); + m_isActive = false; +} + +void RubberBandSelectionManipulator::select(SelectionType selectionType) +{ + QList itemList = m_editorView->selectableItems(m_selectionRectangleElement.rect(), + Qt::IntersectsItemShape); + QList newSelectionList; + + foreach (QGraphicsItem* item, itemList) { + if (item + && item->parentItem() + //&& m_beginFormEditorItem->childItems().contains(item) // TODO activate this test + ) + { + newSelectionList.append(item); + } + } + + if (newSelectionList.isEmpty() && m_beginFormEditorItem) + newSelectionList.append(m_beginFormEditorItem); + + QList resultList; + + switch(selectionType) { + case AddToSelection: { + resultList.append(m_oldSelectionList); + resultList.append(newSelectionList); + } + break; + case ReplaceSelection: { + resultList.append(newSelectionList); + } + break; + case RemoveFromSelection: { + QSet oldSelectionSet(m_oldSelectionList.toSet()); + QSet newSelectionSet(newSelectionList.toSet()); + resultList.append(oldSelectionSet.subtract(newSelectionSet).toList()); + } + } + + m_editorView->setSelectedItems(resultList); +} + + +void RubberBandSelectionManipulator::setItems(const QList &itemList) +{ + m_itemList = itemList; +} + +QPointF RubberBandSelectionManipulator::beginPoint() const +{ + return m_beginPoint; +} + +bool RubberBandSelectionManipulator::isActive() const +{ + return m_isActive; + +} + +} diff --git a/src/tools/qml/qmlviewer/editor/rubberbandselectionmanipulator.h b/src/tools/qml/qmlviewer/editor/rubberbandselectionmanipulator.h new file mode 100644 index 00000000000..c2a4486cf31 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/rubberbandselectionmanipulator.h @@ -0,0 +1,82 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef RUBBERBANDSELECTIONMANIPULATOR_H +#define RUBBERBANDSELECTIONMANIPULATOR_H + + +#include "selectionrectangle.h" + +namespace QmlViewer { + +class QDeclarativeDesignView; + +class RubberBandSelectionManipulator +{ +public: + enum SelectionType { + ReplaceSelection, + AddToSelection, + RemoveFromSelection + }; + + + RubberBandSelectionManipulator(LayerItem *layerItem, QDeclarativeDesignView *editorView); + + void setItems(const QList &itemList); + + void begin(const QPointF& beginPoint); + void update(const QPointF& updatePoint); + void end(); + + void clear(); + + void select(SelectionType selectionType); + + QPointF beginPoint() const; + + bool isActive() const; + +protected: + QGraphicsItem *topFormEditorItem(const QList &itemList); + + +private: + QList m_itemList; + QList m_oldSelectionList; + SelectionRectangle m_selectionRectangleElement; + QPointF m_beginPoint; + QDeclarativeDesignView *m_editorView; + QGraphicsItem *m_beginFormEditorItem; + bool m_isActive; +}; + +} + +#endif // RUBBERBANDSELECTIONMANIPULATOR_H diff --git a/src/tools/qml/qmlviewer/editor/selectionindicator.cpp b/src/tools/qml/qmlviewer/editor/selectionindicator.cpp new file mode 100644 index 00000000000..e16a0a1e600 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/selectionindicator.cpp @@ -0,0 +1,114 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "selectionindicator.h" + +#include +#include +#include + +namespace QmlViewer { + +SelectionIndicator::SelectionIndicator(LayerItem *layerItem) + : m_layerItem(layerItem) +{ +} + +SelectionIndicator::~SelectionIndicator() +{ + clear(); +} + +void SelectionIndicator::show() +{ + foreach (QGraphicsPolygonItem *item, m_indicatorShapeHash.values()) + item->show(); +} + +void SelectionIndicator::hide() +{ + foreach (QGraphicsPolygonItem *item, m_indicatorShapeHash.values()) + item->hide(); +} + +void SelectionIndicator::clear() +{ + if (m_layerItem) { + foreach (QGraphicsItem *item, m_indicatorShapeHash.values()) + m_layerItem->scene()->removeItem(item); + } + m_indicatorShapeHash.clear(); +} + +//static void alignVertices(QPolygonF &polygon, double factor) +//{ +// QMutableVectorIterator iterator(polygon); +// while (iterator.hasNext()) { +// QPointF &vertex = iterator.next(); +// vertex.setX(std::floor(vertex.x()) + factor); +// vertex.setY(std::floor(vertex.y()) + factor); +// } +// +//} + +void SelectionIndicator::setItems(const QList &itemList) +{ + clear(); + + foreach (QGraphicsItem *item, itemList) { + QGraphicsPolygonItem *newSelectionIndicatorGraphicsItem = new QGraphicsPolygonItem(m_layerItem.data()); + m_indicatorShapeHash.insert(item, newSelectionIndicatorGraphicsItem); + QPolygonF boundingRectInSceneSpace(item->mapToScene(item->boundingRect())); + + QPolygonF boundingRectInLayerItemSpace = m_layerItem->mapFromScene(boundingRectInSceneSpace); + newSelectionIndicatorGraphicsItem->setPolygon(boundingRectInLayerItemSpace); + newSelectionIndicatorGraphicsItem->setFlag(QGraphicsItem::ItemIsSelectable, false); + + QPen pen; + pen.setColor(QColor(108, 141, 221)); + newSelectionIndicatorGraphicsItem->setPen(pen); + } +} + + + +void SelectionIndicator::updateItems(const QList &itemList) +{ + foreach (QGraphicsItem *item, itemList) { + if (m_indicatorShapeHash.contains(item)) { + QGraphicsPolygonItem *indicatorGraphicsItem = m_indicatorShapeHash.value(item); + QPolygonF boundingRectInSceneSpace(item->mapToScene(item->boundingRect())); + QPolygonF boundingRectInLayerItemSpace = m_layerItem->mapFromScene(boundingRectInSceneSpace); + indicatorGraphicsItem->setPolygon(boundingRectInLayerItemSpace); + } + } +} + +} //namespace QmlViewer + diff --git a/src/tools/qml/qmlviewer/editor/selectionindicator.h b/src/tools/qml/qmlviewer/editor/selectionindicator.h new file mode 100644 index 00000000000..5eac8ad83e7 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/selectionindicator.h @@ -0,0 +1,61 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef SELECTIONINDICATOR_H +#define SELECTIONINDICATOR_H + +#include +#include +#include "layeritem.h" + +namespace QmlViewer { + +class SelectionIndicator +{ +public: + SelectionIndicator(LayerItem *layerItem); + ~SelectionIndicator(); + + void show(); + void hide(); + + void clear(); + + void setItems(const QList &itemList); + void updateItems(const QList &itemList); + +private: + QHash m_indicatorShapeHash; + QWeakPointer m_layerItem; + +}; + +} + +#endif // SELECTIONINDICATOR_H diff --git a/src/tools/qml/qmlviewer/editor/selectionrectangle.cpp b/src/tools/qml/qmlviewer/editor/selectionrectangle.cpp new file mode 100644 index 00000000000..74a308e0c1c --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/selectionrectangle.cpp @@ -0,0 +1,87 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "selectionrectangle.h" + +#include +#include +#include +#include +#include + +namespace QmlViewer { + +SelectionRectangle::SelectionRectangle(LayerItem *layerItem) + : m_controlShape(new QGraphicsRectItem(layerItem)), + m_layerItem(layerItem) +{ + m_controlShape->setPen(QPen(Qt::black)); + m_controlShape->setBrush(QColor(128, 128, 128, 50)); +} + +SelectionRectangle::~SelectionRectangle() +{ + if (m_layerItem) + m_layerItem->scene()->removeItem(m_controlShape); +} + +void SelectionRectangle::clear() +{ + hide(); +} +void SelectionRectangle::show() +{ + m_controlShape->show(); +} + +void SelectionRectangle::hide() +{ + m_controlShape->hide(); +} + +QRectF SelectionRectangle::rect() const +{ + return m_controlShape->mapFromScene(m_controlShape->rect()).boundingRect(); +} + +void SelectionRectangle::setRect(const QPointF &firstPoint, + const QPointF &secondPoint) +{ + double firstX = std::floor(firstPoint.x()) + 0.5; + double firstY = std::floor(firstPoint.y()) + 0.5; + double secondX = std::floor(secondPoint.x()) + 0.5; + double secondY = std::floor(secondPoint.y()) + 0.5; + QPointF topLeftPoint(firstX < secondX ? firstX : secondX, firstY < secondY ? firstY : secondY); + QPointF bottomRightPoint(firstX > secondX ? firstX : secondX, firstY > secondY ? firstY : secondY); + + QRectF rect(topLeftPoint, bottomRightPoint); + m_controlShape->setRect(rect); +} + +} diff --git a/src/tools/qml/qmlviewer/editor/selectionrectangle.h b/src/tools/qml/qmlviewer/editor/selectionrectangle.h new file mode 100644 index 00000000000..372a8ebd3e8 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/selectionrectangle.h @@ -0,0 +1,62 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef SELECTIONRECTANGLE_H +#define SELECTIONRECTANGLE_H + +#include +#include +#include "layeritem.h" + +namespace QmlViewer { + +class SelectionRectangle +{ +public: + SelectionRectangle(LayerItem *layerItem); + ~SelectionRectangle(); + + void show(); + void hide(); + + void clear(); + + void setRect(const QPointF &firstPoint, + const QPointF &secondPoint); + + QRectF rect() const; + +private: + QGraphicsRectItem *m_controlShape; + QWeakPointer m_layerItem; +}; + +} + +#endif // SELECTIONRECTANGLE_H diff --git a/src/tools/qml/qmlviewer/editor/selectiontool.cpp b/src/tools/qml/qmlviewer/editor/selectiontool.cpp new file mode 100644 index 00000000000..c2f4dac8d7d --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/selectiontool.cpp @@ -0,0 +1,434 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "selectiontool.h" + +//#include "resizehandleitem.h" +#include "qdeclarativedesignview.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace QmlViewer { + +SelectionTool::SelectionTool(QDeclarativeDesignView *editorView) + : AbstractFormEditorTool(editorView), + m_rubberbandSelectionMode(false), + m_rubberbandSelectionManipulator(editorView->manipulatorLayer(), editorView), + m_singleSelectionManipulator(editorView), + m_selectionIndicator(editorView->manipulatorLayer()), + //m_resizeIndicator(editorView->manipulatorLayer()), + m_selectOnlyContentItems(true) +{ + +} + +SelectionTool::~SelectionTool() +{ +} + +void SelectionTool::setRubberbandSelectionMode(bool value) +{ + m_rubberbandSelectionMode = value; +} + +SingleSelectionManipulator::SelectionType SelectionTool::getSelectionType(Qt::KeyboardModifiers modifiers) +{ + SingleSelectionManipulator::SelectionType selectionType = SingleSelectionManipulator::ReplaceSelection; + if (modifiers.testFlag(Qt::ControlModifier)) { + selectionType = SingleSelectionManipulator::RemoveFromSelection; + } else if (modifiers.testFlag(Qt::ShiftModifier)) { + selectionType = SingleSelectionManipulator::AddToSelection; + } + return selectionType; +} + +bool SelectionTool::alreadySelected(const QList &itemList) const +{ + const QList selectedItems = view()->selectedItems(); + + if (selectedItems.isEmpty()) + return false; + + foreach(QGraphicsItem *item, itemList) { + if (selectedItems.contains(item)) { + return true; + } + } + + return false; +} + +void SelectionTool::mousePressEvent(QMouseEvent *event) +{ + QList itemList = view()->selectableItems(event->pos()); + SingleSelectionManipulator::SelectionType selectionType = getSelectionType(event->modifiers()); + + if (event->buttons() & Qt::LeftButton) { + m_mousePressTimer.start(); + + if (m_rubberbandSelectionMode) { + m_rubberbandSelectionManipulator.begin(event->pos()); + } else { + + if (itemList.isEmpty()) { + view()->setSelectedItems(itemList); + return; + } + + if ((selectionType == SingleSelectionManipulator::InvertSelection + || selectionType == SingleSelectionManipulator::ReplaceSelection) + && alreadySelected(itemList)) + { + //view()->changeToMoveTool(event->pos()); + return; + } + + QGraphicsItem* item = itemList.first(); + + if (item->children().isEmpty()) { + m_singleSelectionManipulator.begin(event->pos()); + m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems); + } else { + m_mousePressTimer.start(); + + if (itemList.isEmpty()) { + view()->setSelectedItems(itemList); + return; + } + + if (item->children().isEmpty()) { + m_singleSelectionManipulator.begin(event->pos()); + m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems); + } else { + m_singleSelectionManipulator.begin(event->pos()); + m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems); + m_singleSelectionManipulator.end(event->pos()); + //view()->changeToMoveTool(event->pos()); + } + + m_singleSelectionManipulator.begin(event->pos()); + m_singleSelectionManipulator.select(selectionType, m_selectOnlyContentItems); + m_singleSelectionManipulator.end(event->pos()); + //view()->changeToMoveTool(event->pos()); + + } + } + + } else if (event->buttons() & Qt::RightButton) { + createContextMenu(itemList, event->globalPos()); + } +} + +void SelectionTool::createContextMenu(QList itemList, QPoint globalPos) +{ + if (!view()->mouseInsideContextItem()) + return; + + QMenu contextMenu; + connect(&contextMenu, SIGNAL(hovered(QAction*)), this, SLOT(contextMenuElementHovered(QAction*))); + +// QList sortedList; +// for(int i = itemList.length(); i>= 0; i--) { +// } + + m_contextMenuItemList = itemList; + + contextMenu.addAction("Items"); + contextMenu.addSeparator(); + int shortcutKey = Qt::Key_1; + bool addKeySequence = true; + int i = 0; + + foreach(QGraphicsItem * const item, itemList) { + QString itemTitle = titleForItem(item); + QAction *elementAction = contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected())); + + if (view()->selectedItems().contains(item)) { + QFont boldFont = elementAction->font(); + boldFont.setBold(true); + elementAction->setFont(boldFont); + } + + elementAction->setData(i); + if (addKeySequence) + elementAction->setShortcut(QKeySequence(shortcutKey)); + + shortcutKey++; + if (shortcutKey > Qt::Key_9) + addKeySequence = false; + + ++i; + } + // add root item separately + QString itemTitle = QString(tr("%1 (root)")).arg(titleForItem(view()->currentRootItem())); + contextMenu.addAction(itemTitle, this, SLOT(contextMenuElementSelected())); + m_contextMenuItemList.append(view()->currentRootItem()); + + contextMenu.exec(globalPos); + m_contextMenuItemList.clear(); +} + +void SelectionTool::contextMenuElementSelected() +{ + QAction *senderAction = static_cast(sender()); + int itemListIndex = senderAction->data().toInt(); + if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) { + + QPointF updatePt(0, 0); + m_singleSelectionManipulator.begin(updatePt); + m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection, + QList() << m_contextMenuItemList.at(itemListIndex), + false); + m_singleSelectionManipulator.end(updatePt); + } +} + +void SelectionTool::contextMenuElementHovered(QAction *action) +{ + int itemListIndex = action->data().toInt(); + if (itemListIndex >= 0 && itemListIndex < m_contextMenuItemList.length()) { + view()->highlightBoundingRect(m_contextMenuItemList.at(itemListIndex)); + } +} + +void SelectionTool::mouseMoveEvent(QMouseEvent *event) +{ + if (m_singleSelectionManipulator.isActive()) { + QPointF mouseMovementVector = m_singleSelectionManipulator.beginPoint() - event->pos(); + + if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance) + && (m_mousePressTimer.elapsed() > Constants::DragStartTime)) + { + m_singleSelectionManipulator.end(event->pos()); + //view()->changeToMoveTool(m_singleSelectionManipulator.beginPoint()); + return; + } + } else if (m_rubberbandSelectionManipulator.isActive()) { + QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos(); + + if ((mouseMovementVector.toPoint().manhattanLength() > Constants::DragStartDistance) + && (m_mousePressTimer.elapsed() > Constants::DragStartTime)) { + m_rubberbandSelectionManipulator.update(event->pos()); + + if (event->modifiers().testFlag(Qt::ControlModifier)) + m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::RemoveFromSelection); + else if (event->modifiers().testFlag(Qt::ShiftModifier)) + m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::AddToSelection); + else + m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::ReplaceSelection); + } + } +} + +void SelectionTool::hoverMoveEvent(QMouseEvent * event) +{ + QList itemList = view()->items(event->pos()); + if (!itemList.isEmpty() && !m_rubberbandSelectionMode) { + +// foreach(QGraphicsItem *item, itemList) { +// if (item->type() == Constants::ResizeHandleItemType) { +// ResizeHandleItem* resizeHandle = ResizeHandleItem::fromGraphicsItem(item); +// if (resizeHandle) +// view()->changeTool(Constants::ResizeToolMode); +// return; +// } +// } +// if (topSelectedItemIsMovable(itemList)) +// view()->changeTool(Constants::MoveToolMode); + } + + QList selectableItemList = view()->selectableItems(event->pos()); + if (!selectableItemList.isEmpty()) { + QGraphicsItem *topSelectableItem = 0; + foreach(QGraphicsItem* item, selectableItemList) + { + if (item + && item->type() != Constants::EditorItemType + /*&& !item->qmlItemNode().isRootNode() + && (QGraphicsItem->qmlItemNode().hasShowContent() || !m_selectOnlyContentItems)*/) + { + topSelectableItem = item; + break; + } + } + + view()->highlightBoundingRect(topSelectableItem); + } +} + +void SelectionTool::mouseReleaseEvent(QMouseEvent *event) +{ + if (m_singleSelectionManipulator.isActive()) { + m_singleSelectionManipulator.end(event->pos()); + } + else if (m_rubberbandSelectionManipulator.isActive()) { + + QPointF mouseMovementVector = m_rubberbandSelectionManipulator.beginPoint() - event->pos(); + if (mouseMovementVector.toPoint().manhattanLength() < Constants::DragStartDistance) { + m_singleSelectionManipulator.begin(event->pos()); + + if (event->modifiers().testFlag(Qt::ControlModifier)) + m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection, m_selectOnlyContentItems); + else if (event->modifiers().testFlag(Qt::ShiftModifier)) + m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection, m_selectOnlyContentItems); + else + m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection, m_selectOnlyContentItems); + + m_singleSelectionManipulator.end(event->pos()); + } else { + m_rubberbandSelectionManipulator.update(event->pos()); + + if (event->modifiers().testFlag(Qt::ControlModifier)) + m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::RemoveFromSelection); + else if (event->modifiers().testFlag(Qt::ShiftModifier)) + m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::AddToSelection); + else + m_rubberbandSelectionManipulator.select(RubberBandSelectionManipulator::ReplaceSelection); + + m_rubberbandSelectionManipulator.end(); + } + } +} + +void SelectionTool::mouseDoubleClickEvent(QMouseEvent * /*event*/) +{ + +} + +void SelectionTool::keyPressEvent(QKeyEvent *event) +{ + switch(event->key()) { + case Qt::Key_Left: + case Qt::Key_Right: + case Qt::Key_Up: + case Qt::Key_Down: + view()->changeTool(Constants::MoveToolMode); + view()->currentTool()->keyPressEvent(event); + break; + } +} + +void SelectionTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/) +{ + +} + +void SelectionTool::wheelEvent(QWheelEvent *event) +{ + if (event->orientation() == Qt::Horizontal || m_rubberbandSelectionMode) + return; + + QList itemList = view()->selectableItems(event->pos()); + + int selectedIdx = 0; + if (!view()->selectedItems().isEmpty()) { + selectedIdx = itemList.indexOf(view()->selectedItems().first()); + if (selectedIdx >= 0) { + if (event->delta() > 0) { + selectedIdx++; + if (selectedIdx == itemList.length()) + selectedIdx = 0; + } else if (event->delta() < 0) { + selectedIdx--; + if (selectedIdx == -1) + selectedIdx = itemList.length() - 1; + } + } else { + selectedIdx = 0; + } + } + + QPointF updatePt(0, 0); + m_singleSelectionManipulator.begin(updatePt); + m_singleSelectionManipulator.select(SingleSelectionManipulator::ReplaceSelection, + QList() << itemList.at(selectedIdx), + false); + m_singleSelectionManipulator.end(updatePt); + +} + +void SelectionTool::setSelectOnlyContentItems(bool selectOnlyContentItems) +{ + m_selectOnlyContentItems = selectOnlyContentItems; +} + +void SelectionTool::itemsAboutToRemoved(const QList &/*itemList*/) +{ + +} + +void SelectionTool::clear() +{ + view()->setCursor(Qt::ArrowCursor); + m_rubberbandSelectionManipulator.clear(), + m_singleSelectionManipulator.clear(); + m_selectionIndicator.clear(); + //m_resizeIndicator.clear(); +} + +void SelectionTool::selectedItemsChanged(const QList &itemList) +{ + m_selectionIndicator.setItems(toGraphicsObjectList(itemList)); + //m_resizeIndicator.setItems(toGraphicsObjectList(itemList)); +} + +void SelectionTool::graphicsObjectsChanged(const QList &itemList) +{ + m_selectionIndicator.updateItems(itemList); + //m_resizeIndicator.updateItems(itemList); +} + +void SelectionTool::selectUnderPoint(QMouseEvent *event) +{ + m_singleSelectionManipulator.begin(event->pos()); + + if (event->modifiers().testFlag(Qt::ControlModifier)) + m_singleSelectionManipulator.select(SingleSelectionManipulator::RemoveFromSelection, m_selectOnlyContentItems); + else if (event->modifiers().testFlag(Qt::ShiftModifier)) + m_singleSelectionManipulator.select(SingleSelectionManipulator::AddToSelection, m_selectOnlyContentItems); + else + m_singleSelectionManipulator.select(SingleSelectionManipulator::InvertSelection, m_selectOnlyContentItems); + + m_singleSelectionManipulator.end(event->pos()); +} + +} diff --git a/src/tools/qml/qmlviewer/editor/selectiontool.h b/src/tools/qml/qmlviewer/editor/selectiontool.h new file mode 100644 index 00000000000..0dc01c41227 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/selectiontool.h @@ -0,0 +1,110 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef SELECTIONTOOL_H +#define SELECTIONTOOL_H + + +#include "abstractformeditortool.h" +#include "movemanipulator.h" +#include "rubberbandselectionmanipulator.h" +#include "singleselectionmanipulator.h" +#include "selectionindicator.h" +#include "resizeindicator.h" + +#include +#include +#include + +QT_FORWARD_DECLARE_CLASS(QGraphicsItem); +QT_FORWARD_DECLARE_CLASS(QMouseEvent); +QT_FORWARD_DECLARE_CLASS(QKeyEvent); + +namespace QmlViewer { + +class SelectionTool : public AbstractFormEditorTool +{ + Q_OBJECT + +public: + SelectionTool(QDeclarativeDesignView* editorView); + ~SelectionTool(); + + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); + void hoverMoveEvent(QMouseEvent *event); + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *keyEvent); + void wheelEvent(QWheelEvent *event); + + void itemsAboutToRemoved(const QList &itemList); + // QVariant itemChange(const QList &itemList, +// QGraphicsItem::GraphicsItemChange change, +// const QVariant &value ); + +// void update(); + + void clear(); + + void selectedItemsChanged(const QList &itemList); + + void graphicsObjectsChanged(const QList &itemList); + + void selectUnderPoint(QMouseEvent *event); + + void setSelectOnlyContentItems(bool selectOnlyContentItems); + + void setRubberbandSelectionMode(bool value); + +private slots: + void contextMenuElementSelected(); + void contextMenuElementHovered(QAction *action); + +private: + void createContextMenu(QList itemList, QPoint globalPos); + SingleSelectionManipulator::SelectionType getSelectionType(Qt::KeyboardModifiers modifiers); + bool alreadySelected(const QList &itemList) const; + +private: + bool m_rubberbandSelectionMode; + RubberBandSelectionManipulator m_rubberbandSelectionManipulator; + SingleSelectionManipulator m_singleSelectionManipulator; + SelectionIndicator m_selectionIndicator; + //ResizeIndicator m_resizeIndicator; + QTime m_mousePressTimer; + bool m_selectOnlyContentItems; + + QList m_contextMenuItemList; +}; + +} + +#endif // SELECTIONTOOL_H diff --git a/src/tools/qml/qmlviewer/editor/singleselectionmanipulator.cpp b/src/tools/qml/qmlviewer/editor/singleselectionmanipulator.cpp new file mode 100644 index 00000000000..c585618c76f --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/singleselectionmanipulator.cpp @@ -0,0 +1,133 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "singleselectionmanipulator.h" +#include "qdeclarativedesignview.h" +#include + +namespace QmlViewer { + +SingleSelectionManipulator::SingleSelectionManipulator(QDeclarativeDesignView *editorView) + : m_editorView(editorView), + m_isActive(false) +{ +} + + +void SingleSelectionManipulator::begin(const QPointF &beginPoint) +{ + m_beginPoint = beginPoint; + m_isActive = true; + m_oldSelectionList = m_editorView->selectedItems(); +} + +void SingleSelectionManipulator::update(const QPointF &/*updatePoint*/) +{ + m_oldSelectionList.clear(); +} + +void SingleSelectionManipulator::clear() +{ + m_beginPoint = QPointF(); + m_oldSelectionList.clear(); +} + + +void SingleSelectionManipulator::end(const QPointF &/*updatePoint*/) +{ + m_oldSelectionList.clear(); + m_isActive = false; +} + +void SingleSelectionManipulator::select(SelectionType selectionType, const QList &items, bool /*selectOnlyContentItems*/) +{ + QGraphicsItem *selectedItem = 0; + + foreach(QGraphicsItem* item, items) + { + //FormEditorItem *formEditorItem = FormEditorItem::fromQGraphicsItem(item); + if (item + /*&& !formEditorItem->qmlItemNode().isRootNode() + && (formEditorItem->qmlItemNode().hasShowContent() || !selectOnlyContentItems)*/) + { + selectedItem = item; + break; + } + } + + QList resultList; + + switch(selectionType) { + case AddToSelection: { + resultList.append(m_oldSelectionList); + if (selectedItem && !m_oldSelectionList.contains(selectedItem)) + resultList.append(selectedItem); + } + break; + case ReplaceSelection: { + if (selectedItem) + resultList.append(selectedItem); + } + break; + case RemoveFromSelection: { + resultList.append(m_oldSelectionList); + if (selectedItem) + resultList.removeAll(selectedItem); + } + break; + case InvertSelection: { + if (selectedItem + && !m_oldSelectionList.contains(selectedItem)) + { + resultList.append(selectedItem); + } + } + } + + m_editorView->setSelectedItems(resultList); +} + +void SingleSelectionManipulator::select(SelectionType selectionType, bool selectOnlyContentItems) +{ + QList itemList = m_editorView->selectableItems(m_beginPoint); + select(selectionType, itemList, selectOnlyContentItems); +} + + +bool SingleSelectionManipulator::isActive() const +{ + return m_isActive; +} + +QPointF SingleSelectionManipulator::beginPoint() const +{ + return m_beginPoint; +} + +} diff --git a/src/tools/qml/qmlviewer/editor/singleselectionmanipulator.h b/src/tools/qml/qmlviewer/editor/singleselectionmanipulator.h new file mode 100644 index 00000000000..eeecc8a4455 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/singleselectionmanipulator.h @@ -0,0 +1,77 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef SINGLESELECTIONMANIPULATOR_H +#define SINGLESELECTIONMANIPULATOR_H + +#include "selectionrectangle.h" +#include +#include + +QT_FORWARD_DECLARE_CLASS(QGraphicsItem); + +namespace QmlViewer { + +class QDeclarativeDesignView; + +class SingleSelectionManipulator +{ +public: + SingleSelectionManipulator(QDeclarativeDesignView *editorView); + + enum SelectionType { + ReplaceSelection, + AddToSelection, + RemoveFromSelection, + InvertSelection + }; + + void begin(const QPointF& beginPoint); + void update(const QPointF& updatePoint); + void end(const QPointF& updatePoint); + + void select(SelectionType selectionType, const QList &items, bool selectOnlyContentItems); + void select(SelectionType selectionType, bool selectOnlyContentItems); + + void clear(); + + QPointF beginPoint() const; + + bool isActive() const; + +private: + QList m_oldSelectionList; + QPointF m_beginPoint; + QDeclarativeDesignView *m_editorView; + bool m_isActive; +}; + +} + +#endif // SINGLESELECTIONMANIPULATOR_H diff --git a/src/tools/qml/qmlviewer/editor/snappinglinecreator.cpp b/src/tools/qml/qmlviewer/editor/snappinglinecreator.cpp new file mode 100644 index 00000000000..4a0e3498376 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/snappinglinecreator.cpp @@ -0,0 +1,188 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "snappinglinecreator.h" + +#include +#include "formeditoritem.h" + +namespace QmlDesigner { + +SnappingLineCreator::SnappingLineCreator(FormEditorItem *formEditorItem) + : m_formEditorItem(formEditorItem), + m_topOffset(formEditorItem->formEditorView()->spacing()), + m_bottomOffset(formEditorItem->formEditorView()->spacing()), + m_leftOffset(formEditorItem->formEditorView()->spacing()), + m_rightOffset(formEditorItem->formEditorView()->spacing()), + m_topMargin(formEditorItem->formEditorView()->margins()), + m_bottomMargin(formEditorItem->formEditorView()->margins()), + m_leftMargin(formEditorItem->formEditorView()->margins()), + m_rightMargin(formEditorItem->formEditorView()->margins()) +{ + Q_ASSERT(m_formEditorItem); +} + +void SnappingLineCreator::clearLines() +{ + m_topLineMap.clear(); + m_bottomLineMap.clear(); + m_leftLineMap.clear(); + m_rightLineMap.clear(); + m_horizontalCenterLineMap.clear(); + m_verticalCenterLineMap.clear(); + + m_topOffsetMap.clear(); + m_bottomOffsetMap.clear(); + m_leftOffsetMap.clear(); + m_rightOffsetMap.clear(); + +} + +void SnappingLineCreator::addLines(const QRectF &rectInSceneSpace, FormEditorItem *item) +{ + m_topLineMap.insert(rectInSceneSpace.top(), qMakePair(rectInSceneSpace, item)); + m_bottomLineMap.insert(rectInSceneSpace.bottom(), qMakePair(rectInSceneSpace, item)); + m_leftLineMap.insert(rectInSceneSpace.left(), qMakePair(rectInSceneSpace, item)); + m_rightLineMap.insert(rectInSceneSpace.right(), qMakePair(rectInSceneSpace, item)); + QPointF centerPoint(rectInSceneSpace.center()); + m_horizontalCenterLineMap.insert(centerPoint.y(), qMakePair(rectInSceneSpace, item)); + m_verticalCenterLineMap.insert(centerPoint.x(), qMakePair(rectInSceneSpace, item)); +} + +void SnappingLineCreator::addOffsets(const QRectF &rectInSceneSpace, FormEditorItem *item) +{ + m_topOffsetMap.insert(rectInSceneSpace.top() - m_topOffset, qMakePair(rectInSceneSpace, item)); + m_bottomOffsetMap.insert(rectInSceneSpace.bottom() + m_bottomOffset, qMakePair(rectInSceneSpace, item)); + m_leftOffsetMap.insert(rectInSceneSpace.left() - m_leftOffset, qMakePair(rectInSceneSpace, item)); + m_rightOffsetMap.insert(rectInSceneSpace.right() + m_rightOffset, qMakePair(rectInSceneSpace, item)); +} + +void SnappingLineCreator::generateLines(const QList &exceptionList, + FormEditorItem *transformationSpaceItem) +{ + Q_ASSERT(transformationSpaceItem); + { + QRectF containerBoundingRectInTransformationSpace = m_formEditorItem->mapRectToItem(transformationSpaceItem, + m_formEditorItem->qmlItemNode().instanceBoundingRect()); + + addLines(containerBoundingRectInTransformationSpace, m_formEditorItem); + containerBoundingRectInTransformationSpace.adjust(m_leftMargin, m_topMargin, -m_rightMargin, -m_rightMargin); + addLines(containerBoundingRectInTransformationSpace, m_formEditorItem); + } + + foreach (FormEditorItem *item, m_formEditorItem->childFormEditorItems()) { + if (exceptionList.contains(item)) + continue; + QRectF boundingRectInContainerSpace; + + boundingRectInContainerSpace = item->mapRectToItem(transformationSpaceItem, item->qmlItemNode().instanceBoundingRect()); + + boundingRectInContainerSpace = boundingRectInContainerSpace.toRect(); // round to integer + + addLines(boundingRectInContainerSpace, item); + addOffsets(boundingRectInContainerSpace, item); + } +} + +void SnappingLineCreator::setMargins(double margin) +{ + m_topMargin = margin; + m_bottomMargin = margin; + m_leftMargin = margin; + m_rightMargin = margin; +} + +void SnappingLineCreator::setSpacing(double spacing) +{ + m_topOffset = spacing; + m_bottomOffset = spacing; + m_leftOffset = spacing; + m_rightOffset = spacing; +} + +void SnappingLineCreator::update(const QList &exceptionList, + FormEditorItem *transformationSpaceItem) +{ + clearLines(); + setMargins(m_formEditorItem->formEditorView()->margins()); + setSpacing(m_formEditorItem->formEditorView()->spacing()); + generateLines(exceptionList, transformationSpaceItem); +} + +SnapLineMap SnappingLineCreator::topLines() const +{ + return m_topLineMap; +} + +SnapLineMap SnappingLineCreator::bottomLines() const +{ + return m_bottomLineMap; +} + +SnapLineMap SnappingLineCreator::leftLines() const +{ + return m_leftLineMap; +} + +SnapLineMap SnappingLineCreator::rightLines() const +{ + return m_rightLineMap; +} + +SnapLineMap SnappingLineCreator::horizontalCenterLines() const +{ + return m_horizontalCenterLineMap; +} + +SnapLineMap SnappingLineCreator::verticalCenterLines() const +{ + return m_verticalCenterLineMap; +} + +SnapLineMap SnappingLineCreator::topOffsets() const +{ + return m_topOffsetMap; +} + +SnapLineMap SnappingLineCreator::bottomOffsets() const +{ + return m_bottomOffsetMap; +} + +SnapLineMap SnappingLineCreator::leftOffsets() const +{ + return m_leftOffsetMap; +} + +SnapLineMap SnappingLineCreator::rightOffsets() const +{ + return m_rightOffsetMap; +} + +} diff --git a/src/tools/qml/qmlviewer/editor/snappinglinecreator.h b/src/tools/qml/qmlviewer/editor/snappinglinecreator.h new file mode 100644 index 00000000000..dd4f38eeeed --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/snappinglinecreator.h @@ -0,0 +1,102 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef SNAPPINGLINECREATOR_H +#define SNAPPINGLINECREATOR_H + +#include "layeritem.h" +#include + +namespace QmlDesigner { + +class FormEditorItem; + +typedef QMultiMap > SnapLineMap; +typedef QMapIterator > SnapLineMapIterator; + +class FormEditorItem; + +class SnappingLineCreator +{ +public: + SnappingLineCreator(FormEditorItem *formEditorItem); + + void update(const QList &exceptionList, + FormEditorItem *transformationSpaceItem); + + + SnapLineMap topLines() const; + SnapLineMap bottomLines() const; + SnapLineMap leftLines() const; + SnapLineMap rightLines() const; + SnapLineMap horizontalCenterLines() const; + SnapLineMap verticalCenterLines() const; + + SnapLineMap topOffsets() const; + SnapLineMap bottomOffsets() const; + SnapLineMap leftOffsets() const; + SnapLineMap rightOffsets() const; + + void setMargins(double margin); + void setSpacing(double spacing); + +protected: + void addLines(const QRectF &rectInSceneSpace, FormEditorItem *item); + void addOffsets(const QRectF &rectInSceneSpace, FormEditorItem *item); + + void clearLines(); + void generateLines(const QList &exceptionList, + FormEditorItem *transformationSpaceItem); + +private: + SnapLineMap m_topLineMap; + SnapLineMap m_bottomLineMap; + SnapLineMap m_leftLineMap; + SnapLineMap m_rightLineMap; + SnapLineMap m_horizontalCenterLineMap; + SnapLineMap m_verticalCenterLineMap; + + SnapLineMap m_topOffsetMap; + SnapLineMap m_bottomOffsetMap; + SnapLineMap m_leftOffsetMap; + SnapLineMap m_rightOffsetMap; + + FormEditorItem *m_formEditorItem; + double m_topOffset; + double m_bottomOffset; + double m_leftOffset; + double m_rightOffset; + double m_topMargin; + double m_bottomMargin; + double m_leftMargin; + double m_rightMargin; +}; + +} +#endif // SNAPPINGLINECREATOR_H diff --git a/src/tools/qml/qmlviewer/editor/subcomponenteditortool.cpp b/src/tools/qml/qmlviewer/editor/subcomponenteditortool.cpp new file mode 100644 index 00000000000..01cdc17e372 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/subcomponenteditortool.cpp @@ -0,0 +1,227 @@ +#include "subcomponenteditortool.h" +#include "qdeclarativedesignview.h" +#include "subcomponentmasklayeritem.h" +#include "layeritem.h" + +#include +#include +#include +#include +#include + +#include + + +namespace QmlViewer { + +SubcomponentEditorTool::SubcomponentEditorTool(QDeclarativeDesignView *view) + : AbstractFormEditorTool(view), + m_animIncrement(0.05f), + m_animTimer(new QTimer(this)) +{ + m_mask = new SubcomponentMaskLayerItem(view, view->manipulatorLayer()); + connect(m_animTimer, SIGNAL(timeout()), SLOT(animate())); + m_animTimer->setInterval(20); +} + +SubcomponentEditorTool::~SubcomponentEditorTool() +{ + +} + +void SubcomponentEditorTool::mousePressEvent(QMouseEvent */*event*/) +{ + +} + +void SubcomponentEditorTool::mouseMoveEvent(QMouseEvent */*event*/) +{ + +} + +bool SubcomponentEditorTool::containsCursor(const QPoint &mousePos) const +{ + if (!m_currentContext.size()) + return false; + + qDebug() << __FUNCTION__ << m_currentContext.top(); + + QPointF scenePos = view()->mapToScene(mousePos); + QRectF itemRect = m_currentContext.top()->boundingRect() | m_currentContext.top()->childrenBoundingRect(); + QRectF polyRect = m_currentContext.top()->mapToScene(itemRect).boundingRect(); + + return polyRect.contains(scenePos); +} + +void SubcomponentEditorTool::mouseReleaseEvent(QMouseEvent */*event*/) +{ + +} + +void SubcomponentEditorTool::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (event->buttons() & Qt::LeftButton + && !containsCursor(event->pos()) + && m_currentContext.size() > 1) + { + aboutToPopContext(); + } +} + +void SubcomponentEditorTool::hoverMoveEvent(QMouseEvent *event) +{ + if (!containsCursor(event->pos()) && m_currentContext.size() > 1) { + view()->clearHighlightBoundingRect(); + } +} + +void SubcomponentEditorTool::wheelEvent(QWheelEvent */*event*/) +{ + +} + +void SubcomponentEditorTool::keyPressEvent(QKeyEvent */*event*/) +{ + +} + +void SubcomponentEditorTool::keyReleaseEvent(QKeyEvent */*keyEvent*/) +{ + +} + +void SubcomponentEditorTool::itemsAboutToRemoved(const QList &/*itemList*/) +{ + +} + +void SubcomponentEditorTool::animate() +{ + if (m_animIncrement > 0) { + if (m_mask->opacity() + m_animIncrement < 0.5f) { + m_mask->setOpacity(m_mask->opacity() + m_animIncrement); + } else { + m_animTimer->stop(); + m_mask->setOpacity(0.5f); + } + } else { + if (m_mask->opacity() + m_animIncrement > 0) { + m_mask->setOpacity(m_mask->opacity() + m_animIncrement); + } else { + m_animTimer->stop(); + m_mask->setOpacity(0); + popContext(); + } + } + +} + +void SubcomponentEditorTool::clear() +{ + m_currentContext.clear(); + m_mask->setCurrentItem(0); + m_animTimer->stop(); + m_mask->hide(); +} + +void SubcomponentEditorTool::graphicsObjectsChanged(const QList &/*itemList*/) +{ + +} + +void SubcomponentEditorTool::selectedItemsChanged(const QList &/*itemList*/) +{ + +} + +void SubcomponentEditorTool::setCurrentItem(QGraphicsItem* contextItem) +{ + if (!contextItem) + return; + + QGraphicsObject *gfxObject = contextItem->toGraphicsObject(); + if (!gfxObject) + return; + + //QString parentClassName = gfxObject->metaObject()->className(); + //if (parentClassName.contains(QRegExp("_QMLTYPE_\\d+"))) + + bool containsSelectableItems = false; + foreach(QGraphicsItem *item, gfxObject->childItems()) { + if (item->type() == Constants::EditorItemType + || item->type() == Constants::ResizeHandleItemType) + { + continue; + } + containsSelectableItems = true; + break; + } + + if (containsSelectableItems) { + m_mask->setCurrentItem(gfxObject); + m_mask->setOpacity(0); + m_mask->show(); + m_animIncrement = 0.05f; + m_animTimer->start(); + + view()->clearHighlightBoundingRect(); + view()->setSelectedItems(QList()); + + pushContext(gfxObject); + } +} + +bool SubcomponentEditorTool::isDirectChildOfContext(QGraphicsItem *item) const +{ + return (item->parentItem() == m_currentContext.top()); +} + +bool SubcomponentEditorTool::itemIsChildOfQmlSubComponent(QGraphicsItem *item) const +{ + if (item->parentItem() && item->parentItem() != m_currentContext.top()) { + QGraphicsObject *parent = item->parentItem()->toGraphicsObject(); + QString parentClassName = parent->metaObject()->className(); + + if (parentClassName.contains(QRegExp("_QMLTYPE_\\d+"))) { + return true; + } else { + return itemIsChildOfQmlSubComponent(parent); + } + } + + return false; +} + +void SubcomponentEditorTool::pushContext(QGraphicsObject *contextItem) +{ + m_currentContext.push(contextItem); +} + +void SubcomponentEditorTool::aboutToPopContext() +{ + if (m_currentContext.size() > 2) { + popContext(); + } else { + m_animIncrement = -0.05f; + m_animTimer->start(); + } +} + +QGraphicsObject *SubcomponentEditorTool::popContext() +{ + QGraphicsObject *popped = m_currentContext.pop(); + if (m_currentContext.size() > 1) { + m_mask->setCurrentItem(m_currentContext.top()); + m_mask->setOpacity(0.5f); + m_mask->setVisible(true); + } + + return popped; +} + +QGraphicsObject *SubcomponentEditorTool::currentRootItem() const +{ + return m_currentContext.top(); +} + +} // namespace QmlViewer diff --git a/src/tools/qml/qmlviewer/editor/subcomponenteditortool.h b/src/tools/qml/qmlviewer/editor/subcomponenteditortool.h new file mode 100644 index 00000000000..5ba821649b4 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/subcomponenteditortool.h @@ -0,0 +1,71 @@ +#ifndef SUBCOMPONENTEDITORTOOL_H +#define SUBCOMPONENTEDITORTOOL_H + +#include "abstractformeditortool.h" +#include + +QT_FORWARD_DECLARE_CLASS(QGraphicsObject) +QT_FORWARD_DECLARE_CLASS(QPoint) +QT_FORWARD_DECLARE_CLASS(QTimer) + +namespace QmlViewer { + +class SubcomponentMaskLayerItem; + +class SubcomponentEditorTool : public AbstractFormEditorTool +{ + Q_OBJECT + +public: + SubcomponentEditorTool(QDeclarativeDesignView *view); + ~SubcomponentEditorTool(); + + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); + + void hoverMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *keyEvent); + void itemsAboutToRemoved(const QList &itemList); + + void clear(); + void graphicsObjectsChanged(const QList &itemList); + + bool containsCursor(const QPoint &mousePos) const; + bool itemIsChildOfQmlSubComponent(QGraphicsItem *item) const; + bool isDirectChildOfContext(QGraphicsItem *item) const; + + void setCurrentItem(QGraphicsItem *contextObject); + + void pushContext(QGraphicsObject *contextItem); + QGraphicsObject *popContext(); + QGraphicsObject *currentRootItem() const; + +signals: + void exitContextRequested(); + +protected: + void selectedItemsChanged(const QList &itemList); + +private slots: + void animate(); + +private: + void aboutToPopContext(); + +private: + QStack m_currentContext; + + qreal m_animIncrement; + SubcomponentMaskLayerItem *m_mask; + QTimer *m_animTimer; + +}; + +} // namespace QmlViewer + +#endif // SUBCOMPONENTEDITORTOOL_H diff --git a/src/tools/qml/qmlviewer/editor/subcomponentmasklayeritem.cpp b/src/tools/qml/qmlviewer/editor/subcomponentmasklayeritem.cpp new file mode 100644 index 00000000000..5ce1a10cf80 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/subcomponentmasklayeritem.cpp @@ -0,0 +1,53 @@ +#include "subcomponentmasklayeritem.h" +#include "qmlviewerconstants.h" +#include "qdeclarativedesignview.h" +#include + +namespace QmlViewer { + +SubcomponentMaskLayerItem::SubcomponentMaskLayerItem(QDeclarativeDesignView *view, QGraphicsItem *parentItem) : + QGraphicsPolygonItem(parentItem), + m_view(view), + m_currentItem(0), + m_borderRect(new QGraphicsRectItem(this)) +{ + m_borderRect->setRect(0,0,0,0); + m_borderRect->setPen(QPen(QColor(60, 60, 60), 1)); + + setBrush(QBrush(Qt::black)); + setPen(Qt::NoPen); +} + +int SubcomponentMaskLayerItem::type() const +{ + return Constants::EditorItemType; +} + +void SubcomponentMaskLayerItem::setCurrentItem(QGraphicsItem *item) +{ + m_currentItem = item; + + if (!m_currentItem) + return; + + QPolygonF viewPoly(QRectF(m_view->rect())); + viewPoly = m_view->mapToScene(viewPoly.toPolygon()); + + QRectF itemRect = item->boundingRect() | item->childrenBoundingRect(); + QPolygonF itemPoly(itemRect); + itemPoly = item->mapToScene(itemPoly); + + QRectF borderRect = itemPoly.boundingRect(); + borderRect.adjust(-1, -1, 1, 1); + m_borderRect->setRect(borderRect); + + itemPoly = viewPoly.subtracted(QPolygonF(itemPoly.boundingRect())); + setPolygon(itemPoly); +} + +QGraphicsItem *SubcomponentMaskLayerItem::currentItem() const +{ + return m_currentItem; +} + +} // namespace QmlViewer diff --git a/src/tools/qml/qmlviewer/editor/subcomponentmasklayeritem.h b/src/tools/qml/qmlviewer/editor/subcomponentmasklayeritem.h new file mode 100644 index 00000000000..1cbc9e6abf0 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/subcomponentmasklayeritem.h @@ -0,0 +1,26 @@ +#ifndef SUBCOMPONENTMASKLAYERITEM_H +#define SUBCOMPONENTMASKLAYERITEM_H + +#include + +namespace QmlViewer { + +class QDeclarativeDesignView; + +class SubcomponentMaskLayerItem : public QGraphicsPolygonItem +{ +public: + explicit SubcomponentMaskLayerItem(QDeclarativeDesignView *view, QGraphicsItem *parentItem = 0); + int type() const; + void setCurrentItem(QGraphicsItem *item); + QGraphicsItem *currentItem() const; +private: + QDeclarativeDesignView *m_view; + QGraphicsItem *m_currentItem; + QGraphicsRectItem *m_borderRect; + +}; + +} // namespace QmlViewer + +#endif // SUBCOMPONENTMASKLAYERITEM_H diff --git a/src/tools/qml/qmlviewer/editor/toolbarcolorbox.cpp b/src/tools/qml/qmlviewer/editor/toolbarcolorbox.cpp new file mode 100644 index 00000000000..c4d4d4e0fe1 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/toolbarcolorbox.cpp @@ -0,0 +1,96 @@ +#include "toolbarcolorbox.h" +#include "qmlviewerconstants.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace QmlViewer { + +ToolBarColorBox::ToolBarColorBox(QWidget *parent) : + QLabel(parent) +{ + m_copyHexColor = new QAction(tr("Copy"), this); + connect(m_copyHexColor, SIGNAL(triggered()), SLOT(copyColorToClipboard())); + setScaledContents(false); +} + +void ToolBarColorBox::setColor(const QColor &color) +{ + m_color = color; + + QPixmap pix = createDragPixmap(width()); + setPixmap(pix); + update(); +} + +void ToolBarColorBox::mousePressEvent(QMouseEvent *event) +{ + m_dragBeginPoint = event->pos(); + m_dragStarted = false; +} + +void ToolBarColorBox::mouseMoveEvent(QMouseEvent *event) +{ + if (event->buttons() & Qt::LeftButton + && QPoint(event->pos() - m_dragBeginPoint).manhattanLength() > Constants::DragStartDistance + && !m_dragStarted) + { + m_dragStarted = true; + QDrag *drag = new QDrag(this); + QMimeData *mimeData = new QMimeData; + + mimeData->setText(m_color.name()); + drag->setMimeData(mimeData); + drag->setPixmap(createDragPixmap()); + + drag->exec(); + } +} + +QPixmap ToolBarColorBox::createDragPixmap(int size) const +{ + QPixmap pix(size, size); + QPainter p(&pix); + + QColor borderColor1 = QColor(143, 143 ,143); + QColor borderColor2 = Qt::white; + + p.setBrush(QBrush(m_color)); + p.setPen(QPen(QBrush(borderColor2),1)); + + p.fillRect(0, 0, size, size, borderColor1); + p.drawRect(1,1, size - 3, size - 3); + return pix; +} + +void ToolBarColorBox::contextMenuEvent(QContextMenuEvent *ev) +{ + QMenu contextMenu; + contextMenu.addAction(m_copyHexColor); + contextMenu.exec(ev->globalPos()); +} + +void ToolBarColorBox::mouseDoubleClickEvent(QMouseEvent *) +{ + QColorDialog dialog(m_color); + dialog.show(); +} + +void ToolBarColorBox::copyColorToClipboard() +{ + QClipboard *clipboard = QApplication::clipboard(); + clipboard->setText(m_color.name()); +} + + +} // namespace QmlViewer diff --git a/src/tools/qml/qmlviewer/editor/toolbarcolorbox.h b/src/tools/qml/qmlviewer/editor/toolbarcolorbox.h new file mode 100644 index 00000000000..f3d3afea697 --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/toolbarcolorbox.h @@ -0,0 +1,41 @@ +#ifndef ToolBarColorBox_H +#define ToolBarColorBox_H + +#include +#include +#include + +QT_FORWARD_DECLARE_CLASS(QContextMenuEvent); +QT_FORWARD_DECLARE_CLASS(QAction); + +namespace QmlViewer { + +class ToolBarColorBox : public QLabel +{ + Q_OBJECT +public: + explicit ToolBarColorBox(QWidget *parent = 0); + void setColor(const QColor &color); + +protected: + void contextMenuEvent(QContextMenuEvent *ev); + void mouseDoubleClickEvent(QMouseEvent *); + void mousePressEvent(QMouseEvent *ev); + void mouseMoveEvent(QMouseEvent *ev); +private slots: + void copyColorToClipboard(); + +private: + QPixmap createDragPixmap(int size = 24) const; + +private: + bool m_dragStarted; + QPoint m_dragBeginPoint; + QAction *m_copyHexColor; + QColor m_color; + +}; + +} // namespace QmlViewer + +#endif // ToolBarColorBox_H diff --git a/src/tools/qml/qmlviewer/editor/zoomtool.cpp b/src/tools/qml/qmlviewer/editor/zoomtool.cpp new file mode 100644 index 00000000000..d6a6086f5ee --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/zoomtool.cpp @@ -0,0 +1,291 @@ +#include "zoomtool.h" +#include "qdeclarativedesignview.h" + +#include +#include +#include +#include +#include +#include + +#include + +namespace QmlViewer { + +ZoomTool::ZoomTool(QDeclarativeDesignView *view) : + AbstractFormEditorTool(view), + m_rubberbandManipulator(view->manipulatorLayer(), view), + m_smoothZoomMultiplier(0.05f), + m_currentScale(1.0f) +{ + m_zoomTo100Action = new QAction(tr("Zoom to &100%"), this); + m_zoomInAction = new QAction(tr("Zoom In"), this); + m_zoomOutAction = new QAction(tr("Zoom Out"), this); + m_zoomInAction->setShortcut(QKeySequence(Qt::Key_Plus)); + m_zoomOutAction->setShortcut(QKeySequence(Qt::Key_Minus)); + + connect(m_zoomTo100Action, SIGNAL(triggered()), SLOT(zoomTo100())); + connect(m_zoomInAction, SIGNAL(triggered()), SLOT(zoomIn())); + connect(m_zoomOutAction, SIGNAL(triggered()), SLOT(zoomOut())); +} + +ZoomTool::~ZoomTool() +{ + +} + +void ZoomTool::mousePressEvent(QMouseEvent *event) +{ + m_mousePos = event->pos(); + + QPointF scenePos = view()->mapToScene(event->pos()); + + if (event->buttons() & Qt::RightButton) { + QMenu contextMenu; + contextMenu.addAction(m_zoomTo100Action); + contextMenu.addSeparator(); + contextMenu.addAction(m_zoomInAction); + contextMenu.addAction(m_zoomOutAction); + contextMenu.exec(event->globalPos()); + } else if (event->buttons() & Qt::LeftButton) { + m_dragBeginPos = scenePos; + m_dragStarted = false; + } +} + +void ZoomTool::mouseMoveEvent(QMouseEvent *event) +{ + m_mousePos = event->pos(); + + QPointF scenePos = view()->mapToScene(event->pos()); + + if (event->buttons() & Qt::LeftButton + && QPointF(scenePos - m_dragBeginPos).manhattanLength() > Constants::DragStartDistance / 3 + && !m_dragStarted) + { + m_dragStarted = true; + m_rubberbandManipulator.begin(m_dragBeginPos); + return; + } + + if (m_dragStarted) + m_rubberbandManipulator.update(scenePos); + +} + +void ZoomTool::mouseReleaseEvent(QMouseEvent *event) +{ + m_mousePos = event->pos(); + QPointF scenePos = view()->mapToScene(event->pos()); + + if (m_dragStarted) { + m_rubberbandManipulator.end(); + + int x1 = qMin(scenePos.x(), m_rubberbandManipulator.beginPoint().x()); + int x2 = qMax(scenePos.x(), m_rubberbandManipulator.beginPoint().x()); + int y1 = qMin(scenePos.y(), m_rubberbandManipulator.beginPoint().y()); + int y2 = qMax(scenePos.y(), m_rubberbandManipulator.beginPoint().y()); + + QPointF scenePosTopLeft = QPoint(x1, y1); + QPointF scenePosBottomRight = QPoint(x2, y2); + + QRectF sceneArea(scenePosTopLeft, scenePosBottomRight); + + m_currentScale = qMin(view()->rect().width() / sceneArea.width(), + view()->rect().height() / sceneArea.height()); + + + QTransform transform; + transform.scale(m_currentScale, m_currentScale); + + view()->setTransform(transform); + view()->setSceneRect(sceneArea); + } else { + Qt::KeyboardModifier modifierKey = Qt::ControlModifier; +#ifdef Q_WS_MAC + modifierKey = Qt::AltModifier; +#endif + if (event->modifiers() & modifierKey) { + zoomOut(); + } else { + zoomIn(); + } + } +} + +void ZoomTool::zoomIn() +{ + m_currentScale = nextZoomScale(ZoomIn); + scaleView(view()->mapToScene(m_mousePos)); +} + +void ZoomTool::zoomOut() +{ + m_currentScale = nextZoomScale(ZoomOut); + scaleView(view()->mapToScene(m_mousePos)); +} + +void ZoomTool::mouseDoubleClickEvent(QMouseEvent *event) +{ + m_mousePos = event->pos(); +} + + +void ZoomTool::hoverMoveEvent(QMouseEvent *event) +{ + m_mousePos = event->pos(); +} + + +void ZoomTool::keyPressEvent(QKeyEvent */*event*/) +{ +} + +void ZoomTool::wheelEvent(QWheelEvent *event) +{ + if (event->orientation() != Qt::Vertical) + return; + + Qt::KeyboardModifier smoothZoomModifier = Qt::ControlModifier; + if (event->modifiers() & smoothZoomModifier) { + int numDegrees = event->delta() / 8; + m_currentScale += m_smoothZoomMultiplier * (numDegrees / 15.0f); + + scaleView(view()->mapToScene(m_mousePos)); + + } else if (!event->modifiers()) { + if (event->delta() > 0) { + m_currentScale = nextZoomScale(ZoomIn); + } else if (event->delta() < 0) { + m_currentScale = nextZoomScale(ZoomOut); + } + scaleView(view()->mapToScene(m_mousePos)); + } +} + +void ZoomTool::keyReleaseEvent(QKeyEvent *event) +{ + switch(event->key()) { + case Qt::Key_Plus: + zoomIn(); + break; + case Qt::Key_Minus: + zoomOut(); + break; + case Qt::Key_1: + case Qt::Key_2: + case Qt::Key_3: + case Qt::Key_4: + case Qt::Key_5: + case Qt::Key_6: + case Qt::Key_7: + case Qt::Key_8: + case Qt::Key_9: + { + m_currentScale = ((event->key() - Qt::Key_0) * 1.0f); + scaleView(view()->mapToScene(m_mousePos)); // view()->mapToScene(view()->rect().center()) + break; + } + + default: + break; + } + +} + +void ZoomTool::itemsAboutToRemoved(const QList &/*itemList*/) +{ +} + +void ZoomTool::clear() +{ + view()->setCursor(Qt::ArrowCursor); +} + +void ZoomTool::graphicsObjectsChanged(const QList &/*itemList*/) +{ +} + +void ZoomTool::selectedItemsChanged(const QList &/*itemList*/) +{ +} + +void ZoomTool::scaleView(const QPointF ¢erPos) +{ + + QTransform transform; + transform.scale(m_currentScale, m_currentScale); + view()->setTransform(transform); + + QPointF adjustedCenterPos = centerPos; + QSize rectSize(view()->rect().width() / m_currentScale, + view()->rect().height() / m_currentScale); + + QRectF sceneRect; + if (qAbs(m_currentScale - 1.0f) < Constants::ZoomSnapDelta) { + adjustedCenterPos.rx() = rectSize.width() / 2; + adjustedCenterPos.ry() = rectSize.height() / 2; + } + + if (m_currentScale < 1.0f) { + adjustedCenterPos.rx() = rectSize.width() / 2; + adjustedCenterPos.ry() = rectSize.height() / 2; + sceneRect.setRect(view()->rect().width() / 2 -rectSize.width() / 2, + view()->rect().height() / 2 -rectSize.height() / 2, + rectSize.width(), + rectSize.height()); + } else { + sceneRect.setRect(adjustedCenterPos.x() - rectSize.width() / 2, + adjustedCenterPos.y() - rectSize.height() / 2, + rectSize.width(), + rectSize.height()); + } + + view()->setSceneRect(sceneRect); +} + +void ZoomTool::zoomTo100() +{ + m_currentScale = 1.0f; + scaleView(view()->mapToScene(view()->rect().center())); +} + +qreal ZoomTool::nextZoomScale(ZoomDirection direction) const +{ + static QList zoomScales = + QList() + << 0.125f + << 1.0f / 6.0f + << 0.25f + << 1.0f / 3.0f + << 0.5f + << 2.0f / 3.0f + << 1.0f + << 2.0f + << 3.0f + << 4.0f + << 5.0f + << 6.0f + << 7.0f + << 8.0f + << 12.0f + << 16.0f + << 32.0f + << 48.0f; + + if (direction == ZoomIn) { + for(int i = 0; i < zoomScales.length(); ++i) { + if (zoomScales[i] > m_currentScale || i == zoomScales.length() - 1) + return zoomScales[i]; + } + } else { + for(int i = zoomScales.length() - 1; i >= 0; --i) { + if (zoomScales[i] < m_currentScale || i == 0) + return zoomScales[i]; + } + } + + return 1.0f; +} + +} // namespace QmlViewer diff --git a/src/tools/qml/qmlviewer/editor/zoomtool.h b/src/tools/qml/qmlviewer/editor/zoomtool.h new file mode 100644 index 00000000000..099f956f30e --- /dev/null +++ b/src/tools/qml/qmlviewer/editor/zoomtool.h @@ -0,0 +1,67 @@ +#ifndef ZOOMTOOL_H +#define ZOOMTOOL_H + +#include "abstractformeditortool.h" +#include "rubberbandselectionmanipulator.h" + +QT_FORWARD_DECLARE_CLASS(QAction); + +namespace QmlViewer { + +class ZoomTool : public AbstractFormEditorTool +{ + Q_OBJECT +public: + enum ZoomDirection { + ZoomIn, + ZoomOut + }; + + explicit ZoomTool(QDeclarativeDesignView *view); + + virtual ~ZoomTool(); + + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); + + void hoverMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + + void keyPressEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *keyEvent); + void itemsAboutToRemoved(const QList &itemList); + + void clear(); + void graphicsObjectsChanged(const QList &itemList); + +protected: + void selectedItemsChanged(const QList &itemList); + +private slots: + void zoomTo100(); + void zoomIn(); + void zoomOut(); + +private: + qreal nextZoomScale(ZoomDirection direction) const; + void scaleView(const QPointF ¢erPos); + +private: + bool m_dragStarted; + QPoint m_mousePos; // in view coords + QPointF m_dragBeginPos; + QAction *m_zoomTo100Action; + QAction *m_zoomInAction; + QAction *m_zoomOutAction; + RubberBandSelectionManipulator m_rubberbandManipulator; + + qreal m_smoothZoomMultiplier; + qreal m_currentScale; + +}; + +} // namespace QmlViewer + +#endif // ZOOMTOOL_H diff --git a/src/tools/qml/qmlviewer/loggerwidget.cpp b/src/tools/qml/qmlviewer/loggerwidget.cpp new file mode 100644 index 00000000000..8aa029f3d00 --- /dev/null +++ b/src/tools/qml/qmlviewer/loggerwidget.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#ifdef Q_WS_MAEMO_5 +# include +# include +# include "texteditautoresizer_maemo5.h" +#endif + +#include "loggerwidget.h" + +QT_BEGIN_NAMESPACE + +LoggerWidget::LoggerWidget(QWidget *parent) : + QMainWindow(parent), + m_visibilityOrigin(SettingsOrigin) +{ + setAttribute(Qt::WA_QuitOnClose, false); + setWindowTitle(tr("Warnings")); + + m_plainTextEdit = new QPlainTextEdit(); + +#ifdef Q_WS_MAEMO_5 + new TextEditAutoResizer(m_plainTextEdit); + setAttribute(Qt::WA_Maemo5StackedWindow); + QScrollArea *area = new QScrollArea(); + area->setWidget(m_plainTextEdit); + area->setWidgetResizable(true); + setCentralWidget(area); +#else + setCentralWidget(m_plainTextEdit); +#endif + readSettings(); + setupPreferencesMenu(); +} + +void LoggerWidget::append(const QString &msg) +{ + m_plainTextEdit->appendPlainText(msg); + + if (!isVisible() && (defaultVisibility() == AutoShowWarnings)) + setVisible(true); +} + +LoggerWidget::Visibility LoggerWidget::defaultVisibility() const +{ + return m_visibility; +} + +void LoggerWidget::setDefaultVisibility(LoggerWidget::Visibility visibility) +{ + if (m_visibility == visibility) + return; + + m_visibility = visibility; + m_visibilityOrigin = CommandLineOrigin; + + m_preferencesMenu->setEnabled(m_visibilityOrigin == SettingsOrigin); +} + +QMenu *LoggerWidget::preferencesMenu() +{ + return m_preferencesMenu; +} + +QAction *LoggerWidget::showAction() +{ + return m_showWidgetAction; +} + +void LoggerWidget::readSettings() +{ + QSettings settings; + QString warningsPreferences = settings.value("warnings", "hide").toString(); + if (warningsPreferences == "show") { + m_visibility = ShowWarnings; + } else if (warningsPreferences == "hide") { + m_visibility = HideWarnings; + } else { + m_visibility = AutoShowWarnings; + } +} + +void LoggerWidget::saveSettings() +{ + if (m_visibilityOrigin != SettingsOrigin) + return; + + QString value = "autoShow"; + if (defaultVisibility() == ShowWarnings) { + value = "show"; + } else if (defaultVisibility() == HideWarnings) { + value = "hide"; + } + + QSettings settings; + settings.setValue("warnings", value); +} + +void LoggerWidget::warningsPreferenceChanged(QAction *action) +{ + Visibility newSetting = static_cast(action->data().toInt()); + m_visibility = newSetting; + saveSettings(); +} + +void LoggerWidget::showEvent(QShowEvent *event) +{ + QWidget::showEvent(event); + emit opened(); +} + +void LoggerWidget::closeEvent(QCloseEvent *event) +{ + QWidget::closeEvent(event); + emit closed(); +} + +void LoggerWidget::setupPreferencesMenu() +{ + m_preferencesMenu = new QMenu(tr("Warnings")); + QActionGroup *warnings = new QActionGroup(m_preferencesMenu); + warnings->setExclusive(true); + + connect(warnings, SIGNAL(triggered(QAction*)), this, SLOT(warningsPreferenceChanged(QAction*))); + + QAction *showWarningsPreference = new QAction(tr("Show by default"), m_preferencesMenu); + showWarningsPreference->setCheckable(true); + showWarningsPreference->setData(LoggerWidget::ShowWarnings); + warnings->addAction(showWarningsPreference); + m_preferencesMenu->addAction(showWarningsPreference); + + QAction *hideWarningsPreference = new QAction(tr("Hide by default"), m_preferencesMenu); + hideWarningsPreference->setCheckable(true); + hideWarningsPreference->setData(LoggerWidget::HideWarnings); + warnings->addAction(hideWarningsPreference); + m_preferencesMenu->addAction(hideWarningsPreference); + + QAction *autoWarningsPreference = new QAction(tr("Show for first warning"), m_preferencesMenu); + autoWarningsPreference->setCheckable(true); + autoWarningsPreference->setData(LoggerWidget::AutoShowWarnings); + warnings->addAction(autoWarningsPreference); + m_preferencesMenu->addAction(autoWarningsPreference); + + switch (defaultVisibility()) { + case LoggerWidget::ShowWarnings: + showWarningsPreference->setChecked(true); + break; + case LoggerWidget::HideWarnings: + hideWarningsPreference->setChecked(true); + break; + default: + autoWarningsPreference->setChecked(true); + } +} + +QT_END_NAMESPACE diff --git a/src/tools/qml/qmlviewer/loggerwidget.h b/src/tools/qml/qmlviewer/loggerwidget.h new file mode 100644 index 00000000000..13c319f91af --- /dev/null +++ b/src/tools/qml/qmlviewer/loggerwidget.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LOGGERWIDGET_H +#define LOGGERWIDGET_H + +#include +#include + +QT_BEGIN_NAMESPACE + +class QPlainTextEdit; +class QMenu; +class QAction; + +class LoggerWidget : public QMainWindow { + Q_OBJECT +public: + LoggerWidget(QWidget *parent=0); + + enum Visibility { ShowWarnings, HideWarnings, AutoShowWarnings }; + + Visibility defaultVisibility() const; + void setDefaultVisibility(Visibility visibility); + + QMenu *preferencesMenu(); + QAction *showAction(); + +public slots: + void append(const QString &msg); + +private slots: + void warningsPreferenceChanged(QAction *action); + void readSettings(); + void saveSettings(); + +protected: + void showEvent(QShowEvent *event); + void closeEvent(QCloseEvent *event); + +signals: + void opened(); + void closed(); + +private: + void setupPreferencesMenu(); + + QMenu *m_preferencesMenu; + QAction *m_showWidgetAction; + QPlainTextEdit *m_plainTextEdit; + + enum ConfigOrigin { CommandLineOrigin, SettingsOrigin }; + ConfigOrigin m_visibilityOrigin; + Visibility m_visibility; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(LoggerWidget::Visibility) + +#endif // LOGGERWIDGET_H diff --git a/src/tools/qml/qmlviewer/main.cpp b/src/tools/qml/qmlviewer/main.cpp new file mode 100644 index 00000000000..4c410eeb312 --- /dev/null +++ b/src/tools/qml/qmlviewer/main.cpp @@ -0,0 +1,461 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarative.h" +#include "qmlruntime.h" +#include "qdeclarativeengine.h" +#include "loggerwidget.h" +#include +#include +#include +#include +#include +#include +#include "qdeclarativetester.h" + +QT_USE_NAMESPACE + +QtMsgHandler systemMsgOutput = 0; + +#if defined (Q_OS_SYMBIAN) +#include +#include +#include +#include + +void myMessageOutput(QtMsgType type, const char *msg) +{ + static int fd = -1; + if (fd == -1) + fd = ::open("E:\\qml.log", O_WRONLY | O_CREAT); + + ::write(fd, msg, strlen(msg)); + ::write(fd, "\n", 1); + ::fsync(fd); + + switch (type) { + case QtFatalMsg: + abort(); + } +} + +#else // !defined (Q_OS_SYMBIAN) + +QWeakPointer logger; + +QString warnings; +void showWarnings() +{ + if (!warnings.isEmpty()) { + QMessageBox::warning(0, QApplication::tr("Qt QML Viewer"), warnings); + } +} + +void myMessageOutput(QtMsgType type, const char *msg) +{ + if (!logger.isNull()) { + QString strMsg = QString::fromAscii(msg); + QMetaObject::invokeMethod(logger.data(), "append", Q_ARG(QString, strMsg)); + } else { + warnings += msg; + warnings += QLatin1Char('\n'); + } + if (systemMsgOutput) { // Windows + systemMsgOutput(type, msg); + } else { // Unix + fprintf(stderr, "%s\n",msg); + fflush(stderr); + } +} + +#endif + +void usage() +{ + qWarning("Usage: qmlviewer [options] "); + qWarning(" "); + qWarning(" options:"); + qWarning(" -v, -version ............................. display version"); + qWarning(" -frameless ............................... run with no window frame"); + qWarning(" -maximized................................ run maximized"); + qWarning(" -fullscreen............................... run fullscreen"); + qWarning(" -stayontop................................ keep viewer window on top"); + qWarning(" -sizeviewtorootobject .................... the view resizes to the changes in the content"); + qWarning(" -sizerootobjecttoview .................... the content resizes to the changes in the view (default)"); + qWarning(" -qmlbrowser .............................. use a QML-based file browser"); + qWarning(" -warnings [show|hide]..................... show warnings in a separate log window"); + qWarning(" -recordfile ..................... set video recording file"); + qWarning(" - ImageMagick 'convert' for GIF)"); + qWarning(" - png file for raw frames"); + qWarning(" - 'ffmpeg' for other formats"); + qWarning(" -recorddither ordered|threshold|floyd .... set GIF dither recording mode"); + qWarning(" -recordrate ........................ set recording frame rate"); + qWarning(" -record arg .............................. add a recording process argument"); + qWarning(" -autorecord [from-] ...... set recording to start and stop"); + qWarning(" -devicekeys .............................. use numeric keys (see F1)"); + qWarning(" -dragthreshold .................... set mouse drag threshold size"); + qWarning(" -netcache ......................... set disk cache to size bytes"); + qWarning(" -translation ........... set the language to run in"); + qWarning(" -I ........................... prepend to the module import search path,"); + qWarning(" display path if is empty"); + qWarning(" -P ........................... prepend to the plugin search path"); + qWarning(" -opengl .................................. use a QGLWidget for the viewport"); + qWarning(" -script ........................... set the script to use"); + qWarning(" -scriptopts |help ............... set the script options to use"); + + qWarning(" "); + qWarning(" Press F1 for interactive help"); + exit(1); +} + +void scriptOptsUsage() +{ + qWarning("Usage: qmlviewer -scriptopts