forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.10'
Conflicts: src/libs/utils/consoleprocess.h Change-Id: I771630cb4dc60a9e87e9d30d6295040c27348d8c
This commit is contained in:
46
README.md
46
README.md
@@ -155,8 +155,6 @@ For detailed information on the supported compilers, see
|
|||||||
* Before you launch Qt Creator you may prepend the PATH with
|
* Before you launch Qt Creator you may prepend the PATH with
|
||||||
the location of libclang.dll/.so that you want to be used.
|
the location of libclang.dll/.so that you want to be used.
|
||||||
See more info in the section "Prebuilt LLVM/Clang packages".
|
See more info in the section "Prebuilt LLVM/Clang packages".
|
||||||
* When you launch Qt Creator, activate the Clang Code Model plugin as
|
|
||||||
described in doc/src/editors/creator-only/creator-clang-codemodel.qdoc.
|
|
||||||
|
|
||||||
11. You are now ready to configure and build Qt and Qt Creator.
|
11. You are now ready to configure and build Qt and Qt Creator.
|
||||||
Please see <https://wiki.qt.io/Building_Qt_5_from_Git> for
|
Please see <https://wiki.qt.io/Building_Qt_5_from_Git> for
|
||||||
@@ -237,9 +235,10 @@ Prebuilt packages of LLVM/Clang can be downloaded from
|
|||||||
https://download.qt.io/development_releases/prebuilt/libclang/
|
https://download.qt.io/development_releases/prebuilt/libclang/
|
||||||
|
|
||||||
This should be your preferred option because you will use the version that is
|
This should be your preferred option because you will use the version that is
|
||||||
shipped together with Qt Creator. In addition, MinGW packages for Windows are
|
shipped together with Qt Creator (with backported/additional patches). In
|
||||||
faster due to profile-guided optimization. If the prebuilt packages do not
|
addition, MinGW packages for Windows are faster due to profile-guided
|
||||||
match your configuration, you need to build LLVM/Clang manually.
|
optimization. If the prebuilt packages do not match your configuration, you
|
||||||
|
need to build LLVM/Clang manually.
|
||||||
|
|
||||||
If you use the MSVC compiler to build Qt Creator the suggested way is:
|
If you use the MSVC compiler to build Qt Creator the suggested way is:
|
||||||
1. Download both MSVC and MinGW packages of libclang.
|
1. Download both MSVC and MinGW packages of libclang.
|
||||||
@@ -247,23 +246,6 @@ If you use the MSVC compiler to build Qt Creator the suggested way is:
|
|||||||
3. Prepend PATH variable used for the run time with the location of MinGW version of libclang.dll.
|
3. Prepend PATH variable used for the run time with the location of MinGW version of libclang.dll.
|
||||||
4. Launch Qt Creator.
|
4. Launch Qt Creator.
|
||||||
|
|
||||||
If you use GCC 5 or higher on Linux, please do not use our LLVM package, but get
|
|
||||||
the package for your distribution. Our LLVM package is compiled with GCC 4, so
|
|
||||||
you get linking errors, because GCC 5 is using a C++ 11 conforming string
|
|
||||||
implementation, which is not used by GCC 4. To sum it up, do not mix GCC 5 and
|
|
||||||
GCC 4 binaries. On Ubuntu, you can download the package from
|
|
||||||
http://apt.llvm.org/ with:
|
|
||||||
|
|
||||||
wget -O - http://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
|
||||||
sudo apt-add-repository "deb http://apt.llvm.org/`lsb_release -cs`/ llvm-toolchain-`lsb_release -cs`-8.0 main"
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install llvm-8.0 libclang-8.0-dev
|
|
||||||
|
|
||||||
There is a workaround to set _GLIBCXX_USE_CXX11_ABI to 1 or 0, but we recommend
|
|
||||||
to download the package from http://apt.llvm.org/.
|
|
||||||
|
|
||||||
https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
|
|
||||||
|
|
||||||
### Building LLVM/Clang manually
|
### Building LLVM/Clang manually
|
||||||
|
|
||||||
You need to install CMake in order to build LLVM/Clang.
|
You need to install CMake in order to build LLVM/Clang.
|
||||||
@@ -271,9 +253,9 @@ You need to install CMake in order to build LLVM/Clang.
|
|||||||
Build LLVM/Clang by roughly following the instructions at
|
Build LLVM/Clang by roughly following the instructions at
|
||||||
http://llvm.org/docs/GettingStarted.html#git-mirror:
|
http://llvm.org/docs/GettingStarted.html#git-mirror:
|
||||||
|
|
||||||
1. Clone LLVM and checkout a suitable branch
|
1. Clone LLVM/Clang and checkout a suitable branch
|
||||||
|
|
||||||
git clone -b release_80-based --recursive https://code.qt.io/clang/llvm
|
git clone -b release_80-based --recursive https://code.qt.io/clang/llvm-project.git
|
||||||
|
|
||||||
2. Build and install LLVM/Clang
|
2. Build and install LLVM/Clang
|
||||||
|
|
||||||
@@ -282,12 +264,12 @@ http://llvm.org/docs/GettingStarted.html#git-mirror:
|
|||||||
|
|
||||||
For Linux/macOS:
|
For Linux/macOS:
|
||||||
|
|
||||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=<installation location> -DLLVM_ENABLE_RTTI=ON ../llvm
|
cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DCMAKE_INSTALL_PREFIX=<installation location> ../llvm-project/llvm
|
||||||
make install
|
make install
|
||||||
|
|
||||||
For Windows:
|
For Windows:
|
||||||
|
|
||||||
cmake -G "NMake Makefiles JOM" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=<installation location> -DLLVM_ENABLE_RTTI=ON ..\llvm
|
cmake -G "NMake Makefiles JOM" -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_RTTI=ON -DLLVM_ENABLE_PROJECTS="clang;clang-tools-extra" -DCMAKE_INSTALL_PREFIX=<installation location> ..\llvm-project\llvm
|
||||||
jom install
|
jom install
|
||||||
|
|
||||||
## Third-party Components
|
## Third-party Components
|
||||||
@@ -346,18 +328,14 @@ we thank the authors who made this possible:
|
|||||||
|
|
||||||
### LLVM/Clang
|
### LLVM/Clang
|
||||||
|
|
||||||
http://llvm.org/svn/llvm-project/llvm
|
https://github.com/llvm/llvm-project.git
|
||||||
http://llvm.org/svn/llvm-project/cfe/trunk
|
|
||||||
http://llvm.org/svn/llvm-project/clang-tools-extra/trunk
|
|
||||||
|
|
||||||
Copyright (C) 2003-2018 LLVM Team
|
Copyright (C) 2003-2019 LLVM Team
|
||||||
|
|
||||||
Distributed under the University of Illinois/NCSA Open Source License (NCSA),
|
Distributed under the University of Illinois/NCSA Open Source License (NCSA),
|
||||||
see https://github.com/llvm-mirror/llvm/blob/master/LICENSE.TXT
|
see https://github.com/llvm/llvm-project/blob/master/llvm/LICENSE.TXT
|
||||||
|
|
||||||
With backported/additional patches from
|
With backported/additional patches from https://code.qt.io/clang/llvm-project.git
|
||||||
http://code.qt.io/cgit/clang/llvm.git/
|
|
||||||
http://code.qt.io/cgit/clang/clang.git/
|
|
||||||
|
|
||||||
### Reference implementation for std::experimental::optional
|
### Reference implementation for std::experimental::optional
|
||||||
|
|
||||||
|
2
dist/changes-4.10.0.md
vendored
2
dist/changes-4.10.0.md
vendored
@@ -22,7 +22,7 @@ you can check out from the public Git repository. For example:
|
|||||||
* Added support for `workspace/workspaceFolders` server request
|
* Added support for `workspace/workspaceFolders` server request
|
||||||
* Added Locator filter for current document (`.`)
|
* Added Locator filter for current document (`.`)
|
||||||
* Added Locator filters for symbols in workspace (`:`, `c`, and `m`) (QTCREATORBUG-21915)
|
* Added Locator filters for symbols in workspace (`:`, `c`, and `m`) (QTCREATORBUG-21915)
|
||||||
* Added hover information
|
* Added support for showing tooltip information from server
|
||||||
* Made client settings expand variables for executable and arguments
|
* Made client settings expand variables for executable and arguments
|
||||||
* Improved completion item tooltip (QTCREATORBUG-22429)
|
* Improved completion item tooltip (QTCREATORBUG-22429)
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@ int main(int argc, char *argv[])
|
|||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
QQuickView view;
|
QQuickView view;
|
||||||
|
view.engine->addImportPath("qrc:/qml/imports");
|
||||||
view.setSource(QUrl("qrc:/qml/ProgressBar.ui.qml"));
|
view.setSource(QUrl("qrc:/qml/ProgressBar.ui.qml"));
|
||||||
if (!view.errors().isEmpty())
|
if (!view.errors().isEmpty())
|
||||||
return -1;
|
return -1;
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
\contentspage index.html
|
\contentspage index.html
|
||||||
\page creator-keyboard-shortcuts.html
|
\page creator-keyboard-shortcuts.html
|
||||||
\if defined(qtdesignstudio)
|
\if defined(qtdesignstudio)
|
||||||
\previouspage studio-advanced.html
|
\previouspage studio-platforms.html
|
||||||
\nextpage creator-coding.html
|
\nextpage creator-coding.html
|
||||||
\else
|
\else
|
||||||
\previouspage creator-cli.html
|
\previouspage creator-cli.html
|
||||||
|
@@ -79,8 +79,9 @@
|
|||||||
subproject.
|
subproject.
|
||||||
|
|
||||||
To remove all build artifacts, select \uicontrol Build > \uicontrol {Clean All} or
|
To remove all build artifacts, select \uicontrol Build > \uicontrol {Clean All} or
|
||||||
\uicontrol {Clean Project}. To clean the build directory and then build the
|
\uicontrol {Clean Project}. To clean the build directory, run qmake, and
|
||||||
project, select \uicontrol Build > \uicontrol {Rebuild All} or \uicontrol {Rebuild Project}.
|
then build the project, select \uicontrol Build > \uicontrol {Rebuild All}
|
||||||
|
or \uicontrol {Rebuild Project}.
|
||||||
|
|
||||||
To build and clean projects without dependencies, select the
|
To build and clean projects without dependencies, select the
|
||||||
\uicontrol {Build Without Dependencies},
|
\uicontrol {Build Without Dependencies},
|
||||||
@@ -88,6 +89,10 @@
|
|||||||
\uicontrol {Clean Without Dependencies} options in the context menu in the
|
\uicontrol {Clean Without Dependencies} options in the context menu in the
|
||||||
\uicontrol Projects view.
|
\uicontrol Projects view.
|
||||||
|
|
||||||
To run qmake to generate new Makefiles, select \uicontrol Build > \uicontrol qmake.
|
To run qmake to generate new Makefiles, select \uicontrol Build >
|
||||||
|
\uicontrol qmake. To prevent failures on incremental builds, it might make
|
||||||
|
sense to always run qmake before building, even though it means that
|
||||||
|
building will take more time. To enable this option, select \uicontrol Tools
|
||||||
|
> \uicontrol Options > \uicontrol {Build & Run} > \uicontrol qmake >
|
||||||
|
\uicontrol {Run qmake on every build}.
|
||||||
*/
|
*/
|
||||||
|
@@ -472,8 +472,10 @@
|
|||||||
and the subproject that you add as a value of the \l{Variables#subdirs}
|
and the subproject that you add as a value of the \l{Variables#subdirs}
|
||||||
{SUBDIRS variable}. It also adds all the necessary files for the subproject.
|
{SUBDIRS variable}. It also adds all the necessary files for the subproject.
|
||||||
|
|
||||||
To add more subprojects, right-click the project name in the \uicontrol Projects
|
To create more subprojects, right-click the project name in the
|
||||||
pane, and select \uicontrol {New Subproject} in the context menu.
|
\uicontrol Projects pane, and select \uicontrol {New Subproject} in the
|
||||||
|
context menu. To add an existing project as a subproject, select
|
||||||
|
\uicontrol {Add Existing Projects}.
|
||||||
|
|
||||||
To remove subprojects, right-click the project name in the \uicontrol Projects
|
To remove subprojects, right-click the project name in the \uicontrol Projects
|
||||||
pane, and select \uicontrol {Remove Subproject} in the context menu.
|
pane, and select \uicontrol {Remove Subproject} in the context menu.
|
||||||
|
@@ -99,8 +99,9 @@
|
|||||||
\quotefromfile progressbar/main.cpp
|
\quotefromfile progressbar/main.cpp
|
||||||
\skipto QQuickView view;
|
\skipto QQuickView view;
|
||||||
\printuntil view.show()
|
\printuntil view.show()
|
||||||
Where \c {qml\main.qml} is the path to and the name of the main QML
|
Where \c {qrc:/qml/imports} is the import path and
|
||||||
file in the Qt Quick UI project.
|
\c {qrc:qml/ProgressBar.ui.qml} is the path to and the
|
||||||
|
name of the main QML file in the Qt Quick UI project.
|
||||||
\li Select \uicontrol Build > \uicontrol Run to build and run your
|
\li Select \uicontrol Build > \uicontrol Run to build and run your
|
||||||
project.
|
project.
|
||||||
\endlist
|
\endlist
|
||||||
|
@@ -1895,10 +1895,14 @@ class DumperBase:
|
|||||||
|
|
||||||
if qobjectPtr:
|
if qobjectPtr:
|
||||||
qobjectType = self.createType('QObject')
|
qobjectType = self.createType('QObject')
|
||||||
qobjectPtrType = self.createType('QObject') # FIXME.
|
|
||||||
with SubItem(self, '[parent]'):
|
with SubItem(self, '[parent]'):
|
||||||
self.putField('sortgroup', 9)
|
self.putField('sortgroup', 9)
|
||||||
self.putItem(self.createValue(parentPtr, qobjectPtrType))
|
if parentPtr:
|
||||||
|
self.putItem(self.createValue(parentPtr, qobjectType))
|
||||||
|
else:
|
||||||
|
self.putValue('0x0')
|
||||||
|
self.putType('QObject *')
|
||||||
|
self.putNumChild(0)
|
||||||
with SubItem(self, '[children]'):
|
with SubItem(self, '[children]'):
|
||||||
self.putField('sortgroup', 8)
|
self.putField('sortgroup', 8)
|
||||||
base = self.extractPointer(dd + 3 * ptrSize) # It's a QList<QObject *>
|
base = self.extractPointer(dd + 3 * ptrSize) # It's a QList<QObject *>
|
||||||
|
@@ -67,19 +67,28 @@ Rectangle {
|
|||||||
SecondColumnLayout {
|
SecondColumnLayout {
|
||||||
LineEdit {
|
LineEdit {
|
||||||
id: lineEdit
|
id: lineEdit
|
||||||
enabled: isBaseState
|
|
||||||
backendValue: backendValues.id
|
backendValue: backendValues.id
|
||||||
placeholderText: qsTr("id")
|
placeholderText: qsTr("id")
|
||||||
text: backendValues.id.value
|
text: backendValues.id.value
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
width: 240
|
||||||
showTranslateCheckBox: false
|
showTranslateCheckBox: false
|
||||||
showExtendedFunctionButton: false
|
showExtendedFunctionButton: false
|
||||||
|
enabled: !modelNodeBackend.multiSelection
|
||||||
}
|
}
|
||||||
// workaround: without this item the lineedit does not shrink to the
|
|
||||||
// right size after resizing to a wider width
|
Image {
|
||||||
Item {
|
visible: !modelNodeBackend.multiSelection
|
||||||
width: 0
|
Layout.preferredWidth: 16
|
||||||
height: 1
|
Layout.preferredHeight: 16
|
||||||
|
source: hasAliasExport ? "image://icons/alias-export-checked" : "image://icons/alias-export-unchecked"
|
||||||
|
ToolTipArea {
|
||||||
|
enabled: !modelNodeBackend.multiSelection
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: toogleExportAlias()
|
||||||
|
tooltip: qsTr("Toggles whether this item is exported as an alias property of the root item.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -47,32 +47,32 @@ Menu {
|
|||||||
MenuSeparator {
|
MenuSeparator {
|
||||||
}
|
}
|
||||||
|
|
||||||
Controls2.Action {
|
Controls2.MenuItem {
|
||||||
text: "Copy"
|
text: "Copy"
|
||||||
enabled: myTextEdit.selectedText !== ""
|
enabled: myTextEdit.selectedText !== ""
|
||||||
onTriggered: myTextEdit.copy()
|
onTriggered: myTextEdit.copy()
|
||||||
/* shortcut: StandardKey.Copy Shortcuts in QQC2 seem to override global shortcuts */
|
/* shortcut: StandardKey.Copy Shortcuts in QQC2 seem to override global shortcuts */
|
||||||
}
|
}
|
||||||
Controls2.Action {
|
Controls2.MenuItem {
|
||||||
text: "Cut"
|
text: "Cut"
|
||||||
enabled: myTextEdit.selectedText !== "" && !myTextEdit.readOnly
|
enabled: myTextEdit.selectedText !== "" && !myTextEdit.readOnly
|
||||||
onTriggered: myTextEdit.cut()
|
onTriggered: myTextEdit.cut()
|
||||||
/* shortcut: StandardKey.Cut Shortcuts in QQC2 seem to override global shortcuts */
|
/* shortcut: StandardKey.Cut Shortcuts in QQC2 seem to override global shortcuts */
|
||||||
}
|
}
|
||||||
Controls2.Action {
|
Controls2.MenuItem {
|
||||||
text: "Paste"
|
text: "Paste"
|
||||||
enabled: myTextEdit.canPaste
|
enabled: myTextEdit.canPaste
|
||||||
onTriggered: myTextEdit.paste()
|
onTriggered: myTextEdit.paste()
|
||||||
/* shortcut: StandardKey.Paste Shortcuts in QQC2 seem to override global shortcuts */
|
/* shortcut: StandardKey.Paste Shortcuts in QQC2 seem to override global shortcuts */
|
||||||
}
|
}
|
||||||
Controls2.Action {
|
Controls2.MenuItem {
|
||||||
text: "Delete"
|
text: "Delete"
|
||||||
enabled: myTextEdit.selectedText !== ""
|
enabled: myTextEdit.selectedText !== ""
|
||||||
onTriggered: myTextEdit.remove(myTextEdit.selectionStart,
|
onTriggered: myTextEdit.remove(myTextEdit.selectionStart,
|
||||||
myTextEdit.selectionEnd)
|
myTextEdit.selectionEnd)
|
||||||
/* shortcut: StandardKey.Delete Shortcuts in QQC2 seem to override global shortcuts */
|
/* shortcut: StandardKey.Delete Shortcuts in QQC2 seem to override global shortcuts */
|
||||||
}
|
}
|
||||||
Controls2.Action {
|
Controls2.MenuItem {
|
||||||
text: "Clear"
|
text: "Clear"
|
||||||
enabled: myTextEdit.text !== ""
|
enabled: myTextEdit.text !== ""
|
||||||
onTriggered: myTextEdit.clear()
|
onTriggered: myTextEdit.clear()
|
||||||
|
@@ -116,6 +116,7 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode)
|
|||||||
_tokenText.reserve(1024);
|
_tokenText.reserve(1024);
|
||||||
_errorMessage.clear();
|
_errorMessage.clear();
|
||||||
_tokenSpell = QStringRef();
|
_tokenSpell = QStringRef();
|
||||||
|
_rawString = QStringRef();
|
||||||
|
|
||||||
_codePtr = code.unicode();
|
_codePtr = code.unicode();
|
||||||
_endPtr = _codePtr + code.length();
|
_endPtr = _codePtr + code.length();
|
||||||
@@ -149,13 +150,20 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode)
|
|||||||
|
|
||||||
void Lexer::scanChar()
|
void Lexer::scanChar()
|
||||||
{
|
{
|
||||||
unsigned sequenceLength = isLineTerminatorSequence();
|
if (_skipLinefeed) {
|
||||||
|
Q_ASSERT(*_codePtr == QLatin1Char('\n'));
|
||||||
|
++_codePtr;
|
||||||
|
_skipLinefeed = false;
|
||||||
|
}
|
||||||
_char = *_codePtr++;
|
_char = *_codePtr++;
|
||||||
if (sequenceLength == 2)
|
|
||||||
_char = *_codePtr++;
|
|
||||||
|
|
||||||
++_currentColumnNumber;
|
++_currentColumnNumber;
|
||||||
|
|
||||||
if (isLineTerminator()) {
|
if (isLineTerminator()) {
|
||||||
|
if (_char == QLatin1Char('\r')) {
|
||||||
|
if (_codePtr < _endPtr && *_codePtr == QLatin1Char('\n'))
|
||||||
|
_skipLinefeed = true;
|
||||||
|
_char = QLatin1Char('\n');
|
||||||
|
}
|
||||||
++_currentLineNumber;
|
++_currentLineNumber;
|
||||||
_currentColumnNumber = 0;
|
_currentColumnNumber = 0;
|
||||||
}
|
}
|
||||||
@@ -232,6 +240,7 @@ int Lexer::lex()
|
|||||||
|
|
||||||
again:
|
again:
|
||||||
_tokenSpell = QStringRef();
|
_tokenSpell = QStringRef();
|
||||||
|
_rawString = QStringRef();
|
||||||
_tokenKind = scanToken();
|
_tokenKind = scanToken();
|
||||||
_tokenLength = _codePtr - _tokenStartPtr - 1;
|
_tokenLength = _codePtr - _tokenStartPtr - 1;
|
||||||
|
|
||||||
@@ -807,12 +816,15 @@ int Lexer::scanString(ScanStringMode mode)
|
|||||||
QChar quote = (mode == TemplateContinuation) ? QChar(TemplateHead) : QChar(mode);
|
QChar quote = (mode == TemplateContinuation) ? QChar(TemplateHead) : QChar(mode);
|
||||||
bool multilineStringLiteral = false;
|
bool multilineStringLiteral = false;
|
||||||
|
|
||||||
const QChar *startCode = _codePtr;
|
const QChar *startCode = _codePtr - 1;
|
||||||
|
// in case we just parsed a \r, we need to reset this flag to get things working
|
||||||
|
// correctly in the loop below and afterwards
|
||||||
|
_skipLinefeed = false;
|
||||||
|
|
||||||
if (_engine) {
|
if (_engine) {
|
||||||
while (_codePtr <= _endPtr) {
|
while (_codePtr <= _endPtr) {
|
||||||
if (isLineTerminator() && quote != QLatin1Char('`')) {
|
if (isLineTerminator()) {
|
||||||
if (qmlMode())
|
if ((quote == QLatin1Char('`') || qmlMode()))
|
||||||
break;
|
break;
|
||||||
_errorCode = IllegalCharacter;
|
_errorCode = IllegalCharacter;
|
||||||
_errorMessage = QCoreApplication::translate("QmlParser", "Stray newline in string literal");
|
_errorMessage = QCoreApplication::translate("QmlParser", "Stray newline in string literal");
|
||||||
@@ -822,7 +834,8 @@ int Lexer::scanString(ScanStringMode mode)
|
|||||||
} else if (_char == '$' && quote == QLatin1Char('`')) {
|
} else if (_char == '$' && quote == QLatin1Char('`')) {
|
||||||
break;
|
break;
|
||||||
} else if (_char == quote) {
|
} else if (_char == quote) {
|
||||||
_tokenSpell = _engine->midRef(startCode - _code.unicode() - 1, _codePtr - startCode);
|
_tokenSpell = _engine->midRef(startCode - _code.unicode(), _codePtr - startCode - 1);
|
||||||
|
_rawString = _tokenSpell;
|
||||||
scanChar();
|
scanChar();
|
||||||
|
|
||||||
if (quote == QLatin1Char('`'))
|
if (quote == QLatin1Char('`'))
|
||||||
@@ -835,28 +848,36 @@ int Lexer::scanString(ScanStringMode mode)
|
|||||||
else
|
else
|
||||||
return T_STRING_LITERAL;
|
return T_STRING_LITERAL;
|
||||||
}
|
}
|
||||||
scanChar();
|
// don't use scanChar() here, that would transform \r sequences and the midRef() call would create the wrong result
|
||||||
|
_char = *_codePtr++;
|
||||||
|
++_currentColumnNumber;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rewind by one char, so things gets scanned correctly
|
||||||
|
--_codePtr;
|
||||||
|
|
||||||
_validTokenText = true;
|
_validTokenText = true;
|
||||||
_tokenText.resize(0);
|
_tokenText = QString(startCode, _codePtr - startCode);
|
||||||
startCode--;
|
|
||||||
while (startCode != _codePtr - 1)
|
auto setRawString = [&](const QChar *end) {
|
||||||
_tokenText += *startCode++;
|
QString raw(startCode, end - startCode - 1);
|
||||||
|
raw.replace(QLatin1String("\r\n"), QLatin1String("\n"));
|
||||||
|
raw.replace(QLatin1Char('\r'), QLatin1Char('\n'));
|
||||||
|
_rawString = _engine->newStringRef(raw);
|
||||||
|
};
|
||||||
|
|
||||||
|
scanChar();
|
||||||
|
|
||||||
while (_codePtr <= _endPtr) {
|
while (_codePtr <= _endPtr) {
|
||||||
if (unsigned sequenceLength = isLineTerminatorSequence()) {
|
if (_char == quote) {
|
||||||
multilineStringLiteral = true;
|
|
||||||
_tokenText += _char;
|
|
||||||
if (sequenceLength == 2)
|
|
||||||
_tokenText += *_codePtr;
|
|
||||||
scanChar();
|
|
||||||
} else if (_char == mode) {
|
|
||||||
scanChar();
|
scanChar();
|
||||||
|
|
||||||
if (_engine)
|
if (_engine) {
|
||||||
_tokenSpell = _engine->newStringRef(_tokenText);
|
_tokenSpell = _engine->newStringRef(_tokenText);
|
||||||
|
if (quote == QLatin1Char('`'))
|
||||||
|
setRawString(_codePtr - 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (quote == QLatin1Char('`'))
|
if (quote == QLatin1Char('`'))
|
||||||
_bracesCount = _outerTemplateBraceCount.pop();
|
_bracesCount = _outerTemplateBraceCount.pop();
|
||||||
@@ -871,8 +892,10 @@ int Lexer::scanString(ScanStringMode mode)
|
|||||||
scanChar();
|
scanChar();
|
||||||
scanChar();
|
scanChar();
|
||||||
_bracesCount = 1;
|
_bracesCount = 1;
|
||||||
if (_engine)
|
if (_engine) {
|
||||||
_tokenSpell = _engine->newStringRef(_tokenText);
|
_tokenSpell = _engine->newStringRef(_tokenText);
|
||||||
|
setRawString(_codePtr - 2);
|
||||||
|
}
|
||||||
|
|
||||||
return (mode == TemplateHead ? T_TEMPLATE_HEAD : T_TEMPLATE_MIDDLE);
|
return (mode == TemplateHead ? T_TEMPLATE_HEAD : T_TEMPLATE_MIDDLE);
|
||||||
} else if (_char == QLatin1Char('\\')) {
|
} else if (_char == QLatin1Char('\\')) {
|
||||||
|
@@ -146,6 +146,7 @@ public:
|
|||||||
int tokenStartColumn() const { return _tokenColumn; }
|
int tokenStartColumn() const { return _tokenColumn; }
|
||||||
|
|
||||||
inline QStringRef tokenSpell() const { return _tokenSpell; }
|
inline QStringRef tokenSpell() const { return _tokenSpell; }
|
||||||
|
inline QStringRef rawString() const { return _rawString; }
|
||||||
double tokenValue() const { return _tokenValue; }
|
double tokenValue() const { return _tokenValue; }
|
||||||
QString tokenText() const;
|
QString tokenText() const;
|
||||||
|
|
||||||
@@ -198,6 +199,7 @@ private:
|
|||||||
QString _tokenText;
|
QString _tokenText;
|
||||||
QString _errorMessage;
|
QString _errorMessage;
|
||||||
QStringRef _tokenSpell;
|
QStringRef _tokenSpell;
|
||||||
|
QStringRef _rawString;
|
||||||
|
|
||||||
const QChar *_codePtr;
|
const QChar *_codePtr;
|
||||||
const QChar *_endPtr;
|
const QChar *_endPtr;
|
||||||
@@ -233,6 +235,7 @@ private:
|
|||||||
bool _followsClosingBrace;
|
bool _followsClosingBrace;
|
||||||
bool _delimited;
|
bool _delimited;
|
||||||
bool _qmlMode;
|
bool _qmlMode;
|
||||||
|
bool _skipLinefeed = false;
|
||||||
int _generatorLevel = 0;
|
int _generatorLevel = 0;
|
||||||
bool _staticIsKeyword = false;
|
bool _staticIsKeyword = false;
|
||||||
};
|
};
|
||||||
|
@@ -633,10 +633,10 @@ protected:
|
|||||||
if (!ast->typeModifier.isNull()) {
|
if (!ast->typeModifier.isNull()) {
|
||||||
out(ast->typeModifierToken);
|
out(ast->typeModifierToken);
|
||||||
out("<");
|
out("<");
|
||||||
out(ast->typeToken);
|
accept(ast->memberType);
|
||||||
out(">");
|
out(">");
|
||||||
} else {
|
} else {
|
||||||
out(ast->typeToken);
|
accept(ast->memberType);
|
||||||
}
|
}
|
||||||
out(" ");
|
out(" ");
|
||||||
if (ast->statement) {
|
if (ast->statement) {
|
||||||
@@ -1329,9 +1329,8 @@ protected:
|
|||||||
{
|
{
|
||||||
for (FormalParameterList *it = ast; it; it = it->next) {
|
for (FormalParameterList *it = ast; it; it = it->next) {
|
||||||
out(it->element->bindingIdentifier.toString()); // TODO
|
out(it->element->bindingIdentifier.toString()); // TODO
|
||||||
if (it->next) {
|
if (it->next)
|
||||||
out(", ");
|
out(", ");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -83,6 +83,8 @@ struct SftpSession::SftpSessionPrivate
|
|||||||
|
|
||||||
SftpJobId queueCommand(CommandType command, const QStringList &paths)
|
SftpJobId queueCommand(CommandType command, const QStringList &paths)
|
||||||
{
|
{
|
||||||
|
qCDebug(sshLog) << "queueing command" << int(command) << paths;
|
||||||
|
|
||||||
const SftpJobId jobId = nextJobId++;
|
const SftpJobId jobId = nextJobId++;
|
||||||
pendingCommands.enqueue(Command(command, paths, jobId));
|
pendingCommands.enqueue(Command(command, paths, jobId));
|
||||||
runNextCommand();
|
runNextCommand();
|
||||||
@@ -111,6 +113,7 @@ SftpSession::SftpSession(const QStringList &connectionArgs) : d(new SftpSessionP
|
|||||||
{
|
{
|
||||||
d->connectionArgs = connectionArgs;
|
d->connectionArgs = connectionArgs;
|
||||||
connect(&d->sftpProc, &QProcess::started, [this] {
|
connect(&d->sftpProc, &QProcess::started, [this] {
|
||||||
|
qCDebug(sshLog) << "sftp process started";
|
||||||
d->sftpProc.write("\n"); // Force initial prompt.
|
d->sftpProc.write("\n"); // Force initial prompt.
|
||||||
});
|
});
|
||||||
connect(&d->sftpProc, &QProcess::errorOccurred, [this](QProcess::ProcessError error) {
|
connect(&d->sftpProc, &QProcess::errorOccurred, [this](QProcess::ProcessError error) {
|
||||||
@@ -120,6 +123,8 @@ SftpSession::SftpSession(const QStringList &connectionArgs) : d(new SftpSessionP
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(&d->sftpProc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [this] {
|
connect(&d->sftpProc, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), [this] {
|
||||||
|
qCDebug(sshLog) << "sftp process finished";
|
||||||
|
|
||||||
d->state = State::Inactive;
|
d->state = State::Inactive;
|
||||||
if (d->sftpProc.exitStatus() != QProcess::NormalExit) {
|
if (d->sftpProc.exitStatus() != QProcess::NormalExit) {
|
||||||
emit done(tr("sftp crashed."));
|
emit done(tr("sftp crashed."));
|
||||||
@@ -269,6 +274,8 @@ void SftpSession::start()
|
|||||||
|
|
||||||
void SftpSession::quit()
|
void SftpSession::quit()
|
||||||
{
|
{
|
||||||
|
qCDebug(sshLog) << "quitting sftp session, current state is" << int(state());
|
||||||
|
|
||||||
switch (state()) {
|
switch (state()) {
|
||||||
case State::Starting:
|
case State::Starting:
|
||||||
case State::Closing:
|
case State::Closing:
|
||||||
|
@@ -138,7 +138,7 @@ public:
|
|||||||
explicit CommandLine(const FilePath &executable);
|
explicit CommandLine(const FilePath &executable);
|
||||||
CommandLine(const FilePath &exe,
|
CommandLine(const FilePath &exe,
|
||||||
const QStringList &args,
|
const QStringList &args,
|
||||||
MetaCharMode metaCharMode = MetaCharMode::Ignore);
|
MetaCharMode metaCharMode = MetaCharMode::Abort);
|
||||||
CommandLine(const FilePath &exe, const QString &unparsedArgs, RawType);
|
CommandLine(const FilePath &exe, const QString &unparsedArgs, RawType);
|
||||||
|
|
||||||
void addArg(const QString &arg, OsType osType = HostOsInfo::hostOs());
|
void addArg(const QString &arg, OsType osType = HostOsInfo::hostOs());
|
||||||
|
@@ -74,8 +74,9 @@ const char ANDROID_PACKAGE_SOURCE_DIR[] = "AndroidPackageSourceDir";
|
|||||||
const char ANDROID_EXTRA_LIBS[] = "AndroidExtraLibs";
|
const char ANDROID_EXTRA_LIBS[] = "AndroidExtraLibs";
|
||||||
|
|
||||||
const char ANDROID_PACKAGENAME[] = "Android.PackageName";
|
const char ANDROID_PACKAGENAME[] = "Android.PackageName";
|
||||||
const char ANDROID_PACKAGE_INSTALLATION_STEP_ID[] = "Android.PackageInstallationStep";
|
const char ANDROID_PACKAGE_INSTALLATION_STEP_ID[]
|
||||||
const char ANDROID_BUILD_APK_ID[] = "Android.BuildApkStep";
|
= "Qt4ProjectManager.AndroidPackageInstallationStep";
|
||||||
|
const char ANDROID_BUILD_APK_ID[] = "QmakeProjectManager.AndroidBuildApkStep";
|
||||||
|
|
||||||
const char AndroidPackageSourceDir[] = "AndroidPackageSourceDir"; // QString
|
const char AndroidPackageSourceDir[] = "AndroidPackageSourceDir"; // QString
|
||||||
const char AndroidDeploySettingsFile[] = "AndroidDeploySettingsFile"; // QString
|
const char AndroidDeploySettingsFile[] = "AndroidDeploySettingsFile"; // QString
|
||||||
|
@@ -62,6 +62,7 @@
|
|||||||
#include <projectexplorer/projectmacro.h>
|
#include <projectexplorer/projectmacro.h>
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
#include <utils/hostosinfo.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
@@ -513,6 +514,10 @@ CppModelManager::CppModelManager()
|
|||||||
d->m_indexingSupporter = nullptr;
|
d->m_indexingSupporter = nullptr;
|
||||||
d->m_enableGC = true;
|
d->m_enableGC = true;
|
||||||
|
|
||||||
|
// Visual C++ has 1MiB, macOSX has 512KiB
|
||||||
|
if (Utils::HostOsInfo::isWindowsHost() || Utils::HostOsInfo::isMacHost())
|
||||||
|
d->m_threadPool.setStackSize(2 * 1024 * 1024);
|
||||||
|
|
||||||
qRegisterMetaType<QSet<QString> >();
|
qRegisterMetaType<QSet<QString> >();
|
||||||
connect(this, &CppModelManager::sourceFilesRefreshed,
|
connect(this, &CppModelManager::sourceFilesRefreshed,
|
||||||
this, &CppModelManager::onSourceFilesRefreshed);
|
this, &CppModelManager::onSourceFilesRefreshed);
|
||||||
|
@@ -327,7 +327,6 @@ bool fileSizeExceedsLimit(const QFileInfo &fileInfo, int sizeLimitInMb)
|
|||||||
Core::MessageManager::write(msg, Core::MessageManager::Silent);
|
Core::MessageManager::write(msg, Core::MessageManager::Silent);
|
||||||
});
|
});
|
||||||
|
|
||||||
qWarning().noquote() << msg;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -499,8 +499,13 @@ void JsonWizard::openProjectForNode(Node *node)
|
|||||||
{
|
{
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
ProjectNode *projNode = node->asProjectNode() ? node->asProjectNode() : node->parentProjectNode();
|
const ProjectNode *projNode = node->asProjectNode();
|
||||||
|
if (!projNode) {
|
||||||
|
if (ContainerNode * const cn = node->asContainerNode())
|
||||||
|
projNode = cn->rootProjectNode();
|
||||||
|
else
|
||||||
|
projNode = node->parentProjectNode();
|
||||||
|
}
|
||||||
QTC_ASSERT(projNode, return);
|
QTC_ASSERT(projNode, return);
|
||||||
|
|
||||||
Utils::optional<FilePath> projFilePath = projNode->visibleAfterAddFileAction();
|
Utils::optional<FilePath> projFilePath = projNode->visibleAfterAddFileAction();
|
||||||
|
@@ -385,6 +385,7 @@ bool BaseBoolAspect::defaultValue() const
|
|||||||
void BaseBoolAspect::setDefaultValue(bool defaultValue)
|
void BaseBoolAspect::setDefaultValue(bool defaultValue)
|
||||||
{
|
{
|
||||||
d->m_defaultValue = defaultValue;
|
d->m_defaultValue = defaultValue;
|
||||||
|
d->m_value = defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BaseBoolAspect::value() const
|
bool BaseBoolAspect::value() const
|
||||||
|
@@ -161,6 +161,9 @@ TargetSetupPageWrapper::TargetSetupPageWrapper(Project *project)
|
|||||||
|
|
||||||
void TargetSetupPageWrapper::updateNoteText()
|
void TargetSetupPageWrapper::updateNoteText()
|
||||||
{
|
{
|
||||||
|
if (!m_targetSetupPage)
|
||||||
|
return;
|
||||||
|
|
||||||
Kit *k = KitManager::defaultKit();
|
Kit *k = KitManager::defaultKit();
|
||||||
|
|
||||||
QString text;
|
QString text;
|
||||||
|
@@ -25,7 +25,7 @@ add_qtc_plugin(QmlDesigner
|
|||||||
switchsplittabwidget.cpp switchsplittabwidget.h
|
switchsplittabwidget.cpp switchsplittabwidget.h
|
||||||
EXPLICIT_MOC
|
EXPLICIT_MOC
|
||||||
components/propertyeditor/propertyeditorvalue.h
|
components/propertyeditor/propertyeditorvalue.h
|
||||||
qmldesignerextension/connectioneditor/connectionviewwidget.h
|
components/connectioneditor/connectionviewwidget.h
|
||||||
SKIP_DEBUG_CMAKE_FILE_CHECK
|
SKIP_DEBUG_CMAKE_FILE_CHECK
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -499,12 +499,12 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
)
|
)
|
||||||
|
|
||||||
extend_qtc_plugin(QmlDesigner
|
extend_qtc_plugin(QmlDesigner
|
||||||
SOURCES_PREFIX qmldesignerextension/colortool
|
SOURCES_PREFIX components/colortool
|
||||||
SOURCES colortool.cpp colortool.h
|
SOURCES colortool.cpp colortool.h
|
||||||
)
|
)
|
||||||
|
|
||||||
extend_qtc_plugin(QmlDesigner
|
extend_qtc_plugin(QmlDesigner
|
||||||
SOURCES_PREFIX qmldesignerextension/connectioneditor
|
SOURCES_PREFIX components/connectioneditor
|
||||||
SOURCES
|
SOURCES
|
||||||
addnewbackenddialog.cpp addnewbackenddialog.h addnewbackenddialog.ui
|
addnewbackenddialog.cpp addnewbackenddialog.h addnewbackenddialog.ui
|
||||||
backendmodel.cpp backendmodel.h
|
backendmodel.cpp backendmodel.h
|
||||||
@@ -518,7 +518,7 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
)
|
)
|
||||||
|
|
||||||
extend_qtc_plugin(QmlDesigner
|
extend_qtc_plugin(QmlDesigner
|
||||||
SOURCES_PREFIX qmldesignerextension
|
SOURCES_PREFIX components
|
||||||
SOURCES
|
SOURCES
|
||||||
pathtool/controlpoint.cpp pathtool/controlpoint.h
|
pathtool/controlpoint.cpp pathtool/controlpoint.h
|
||||||
pathtool/cubicsegment.cpp pathtool/cubicsegment.h
|
pathtool/cubicsegment.cpp pathtool/cubicsegment.h
|
||||||
@@ -527,9 +527,6 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
pathtool/pathtool.cpp pathtool/pathtool.h
|
pathtool/pathtool.cpp pathtool/pathtool.h
|
||||||
pathtool/pathtoolview.cpp pathtool/pathtoolview.h
|
pathtool/pathtoolview.cpp pathtool/pathtoolview.h
|
||||||
|
|
||||||
qmldesignerextensionconstants.h
|
|
||||||
qmldesignerextension_global.h
|
|
||||||
|
|
||||||
sourcetool/sourcetool.cpp sourcetool/sourcetool.h
|
sourcetool/sourcetool.cpp sourcetool/sourcetool.h
|
||||||
|
|
||||||
texttool/textedititem.cpp texttool/textedititem.h
|
texttool/textedititem.cpp texttool/textedititem.h
|
||||||
@@ -538,7 +535,7 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
)
|
)
|
||||||
|
|
||||||
extend_qtc_plugin(QmlDesigner
|
extend_qtc_plugin(QmlDesigner
|
||||||
SOURCES_PREFIX qmldesignerextension/timelineeditor
|
SOURCES_PREFIX components/timelineeditor
|
||||||
SOURCES
|
SOURCES
|
||||||
canvas.cpp canvas.h
|
canvas.cpp canvas.h
|
||||||
canvasstyledialog.cpp canvasstyledialog.h
|
canvasstyledialog.cpp canvasstyledialog.h
|
||||||
@@ -576,6 +573,33 @@ extend_qtc_plugin(QmlDesigner
|
|||||||
timelinewidget.cpp timelinewidget.h
|
timelinewidget.cpp timelinewidget.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
extend_qtc_plugin(QmlDesigner
|
||||||
|
SOURCES_PREFIX components/curveeditor
|
||||||
|
SOURCES
|
||||||
|
animationcurve.cpp animationcurve.h
|
||||||
|
curveeditor.cpp curveeditor.h
|
||||||
|
curveeditormodel.cpp curveeditormodel.h
|
||||||
|
curveeditorstyle.h
|
||||||
|
keyframe.cpp keyframe.h
|
||||||
|
treeitem.cpp treeitem.h
|
||||||
|
detail/colorcontrol.cpp detail/colorcontrol.h
|
||||||
|
detail/curveeditorstyledialog.cpp detail/curveeditorstyledialog.h
|
||||||
|
detail/curveitem.cpp detail/curveitem.h
|
||||||
|
detail/curvesegment.cpp detail/curvesegment.h
|
||||||
|
detail/graphicsscene.cpp detail/graphicsscene.h
|
||||||
|
detail/graphicsview.cpp detail/graphicsview.h
|
||||||
|
detail/handleitem.cpp detail/handleitem.h
|
||||||
|
detail/keyframeitem.cpp detail/keyframeitem.h
|
||||||
|
detail/playhead.cpp detail/playhead.h
|
||||||
|
detail/selectableitem.cpp detail/selectableitem.h
|
||||||
|
detail/selector.cpp detail/selector.h
|
||||||
|
detail/shortcut.cpp detail/shortcut.h
|
||||||
|
detail/treeitemdelegate.cpp detail/treeitemdelegate.h
|
||||||
|
detail/treemodel.cpp detail/treemodel.h
|
||||||
|
detail/treeview.cpp detail/treeview.h
|
||||||
|
detail/utils.cpp detail/utils.h
|
||||||
|
)
|
||||||
|
|
||||||
# Do the file comparison at the end, due to all the extend_qtc_plugin calls
|
# Do the file comparison at the end, due to all the extend_qtc_plugin calls
|
||||||
if (WITH_DEBUG_CMAKE)
|
if (WITH_DEBUG_CMAKE)
|
||||||
foreach(plugin QmlDesigner componentsplugin qtquickplugin)
|
foreach(plugin QmlDesigner componentsplugin qtquickplugin)
|
||||||
|
@@ -0,0 +1,187 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "animationcurve.h"
|
||||||
|
#include "detail/curvesegment.h"
|
||||||
|
|
||||||
|
#include <QLineF>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
AnimationCurve::AnimationCurve()
|
||||||
|
: m_frames()
|
||||||
|
{}
|
||||||
|
|
||||||
|
AnimationCurve::AnimationCurve(const std::vector<Keyframe> &frames)
|
||||||
|
: m_frames(frames)
|
||||||
|
, m_minY(std::numeric_limits<double>::max())
|
||||||
|
, m_maxY(std::numeric_limits<double>::lowest())
|
||||||
|
{
|
||||||
|
if (isValid()) {
|
||||||
|
|
||||||
|
for (auto e : extrema()) {
|
||||||
|
|
||||||
|
if (m_minY > e.y())
|
||||||
|
m_minY = e.y();
|
||||||
|
|
||||||
|
if (m_maxY < e.y())
|
||||||
|
m_maxY = e.y();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &frame : qAsConst(m_frames)) {
|
||||||
|
if (frame.position().y() < m_minY)
|
||||||
|
m_minY = frame.position().y();
|
||||||
|
|
||||||
|
if (frame.position().y() > m_maxY)
|
||||||
|
m_maxY = frame.position().y();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AnimationCurve::isValid() const
|
||||||
|
{
|
||||||
|
return m_frames.size() >= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
double AnimationCurve::minimumTime() const
|
||||||
|
{
|
||||||
|
if (!m_frames.empty())
|
||||||
|
return m_frames.front().position().x();
|
||||||
|
|
||||||
|
return std::numeric_limits<double>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
double AnimationCurve::maximumTime() const
|
||||||
|
{
|
||||||
|
if (!m_frames.empty())
|
||||||
|
return m_frames.back().position().x();
|
||||||
|
|
||||||
|
return std::numeric_limits<double>::lowest();
|
||||||
|
}
|
||||||
|
|
||||||
|
double AnimationCurve::minimumValue() const
|
||||||
|
{
|
||||||
|
return m_minY;
|
||||||
|
}
|
||||||
|
|
||||||
|
double AnimationCurve::maximumValue() const
|
||||||
|
{
|
||||||
|
return m_maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Keyframe> AnimationCurve::keyframes() const
|
||||||
|
{
|
||||||
|
return m_frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<QPointF> AnimationCurve::extrema() const
|
||||||
|
{
|
||||||
|
std::vector<QPointF> out;
|
||||||
|
|
||||||
|
CurveSegment segment;
|
||||||
|
segment.setLeft(m_frames.at(0));
|
||||||
|
|
||||||
|
for (size_t i = 1; i < m_frames.size(); ++i) {
|
||||||
|
|
||||||
|
segment.setRight(m_frames[i]);
|
||||||
|
|
||||||
|
const auto es = segment.extrema();
|
||||||
|
out.insert(std::end(out), std::begin(es), std::end(es));
|
||||||
|
|
||||||
|
segment.setLeft(m_frames[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> AnimationCurve::yForX(double x) const
|
||||||
|
{
|
||||||
|
if (m_frames.front().position().x() > x)
|
||||||
|
return std::vector<double>();
|
||||||
|
|
||||||
|
CurveSegment segment;
|
||||||
|
for (auto &frame : m_frames) {
|
||||||
|
if (frame.position().x() > x) {
|
||||||
|
segment.setRight(frame);
|
||||||
|
return segment.yForX(x);
|
||||||
|
}
|
||||||
|
segment.setLeft(frame);
|
||||||
|
}
|
||||||
|
return std::vector<double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> AnimationCurve::xForY(double y, uint segment) const
|
||||||
|
{
|
||||||
|
if (m_frames.size() > segment + 1) {
|
||||||
|
CurveSegment seg(m_frames[segment], m_frames[segment + 1]);
|
||||||
|
return seg.xForY(y);
|
||||||
|
}
|
||||||
|
return std::vector<double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AnimationCurve::intersects(const QPointF &coord, double radius)
|
||||||
|
{
|
||||||
|
if (m_frames.size() < 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::vector<CurveSegment> influencer;
|
||||||
|
|
||||||
|
CurveSegment current;
|
||||||
|
current.setLeft(m_frames.at(0));
|
||||||
|
|
||||||
|
for (size_t i = 1; i < m_frames.size(); ++i) {
|
||||||
|
Keyframe &frame = m_frames.at(i);
|
||||||
|
|
||||||
|
current.setRight(frame);
|
||||||
|
|
||||||
|
if (current.containsX(coord.x() - radius) ||
|
||||||
|
current.containsX(coord.x()) ||
|
||||||
|
current.containsX(coord.x() + radius)) {
|
||||||
|
influencer.push_back(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frame.position().x() > coord.x() + radius)
|
||||||
|
break;
|
||||||
|
|
||||||
|
current.setLeft(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &segment : influencer) {
|
||||||
|
for (auto &y : segment.yForX(coord.x())) {
|
||||||
|
QLineF line(coord.x(), y, coord.x(), coord.y());
|
||||||
|
if (line.length() < radius)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &x : segment.xForY(coord.y())) {
|
||||||
|
QLineF line(x, coord.y(), coord.x(), coord.y());
|
||||||
|
if (line.length() < radius)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,69 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "keyframe.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class AnimationCurve
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AnimationCurve();
|
||||||
|
|
||||||
|
AnimationCurve(const std::vector<Keyframe> &frames);
|
||||||
|
|
||||||
|
bool isValid() const;
|
||||||
|
|
||||||
|
double minimumTime() const;
|
||||||
|
|
||||||
|
double maximumTime() const;
|
||||||
|
|
||||||
|
double minimumValue() const;
|
||||||
|
|
||||||
|
double maximumValue() const;
|
||||||
|
|
||||||
|
std::vector<Keyframe> keyframes() const;
|
||||||
|
|
||||||
|
std::vector<QPointF> extrema() const;
|
||||||
|
|
||||||
|
std::vector<double> yForX(double x) const;
|
||||||
|
|
||||||
|
std::vector<double> xForY(double y, uint segment) const;
|
||||||
|
|
||||||
|
bool intersects(const QPointF &coord, double radius);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Keyframe> m_frames;
|
||||||
|
|
||||||
|
double m_minY;
|
||||||
|
|
||||||
|
double m_maxY;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,64 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "curveeditor.h"
|
||||||
|
#include "curveeditormodel.h"
|
||||||
|
#include "detail/curveitem.h"
|
||||||
|
#include "detail/graphicsview.h"
|
||||||
|
#include "detail/treeview.h"
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QSplitter>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
CurveEditor::CurveEditor(CurveEditorModel *model, QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
, m_tree(new TreeView(model, this))
|
||||||
|
, m_view(new GraphicsView(model))
|
||||||
|
{
|
||||||
|
QSplitter *splitter = new QSplitter;
|
||||||
|
splitter->addWidget(m_tree);
|
||||||
|
splitter->addWidget(m_view);
|
||||||
|
splitter->setStretchFactor(1, 2);
|
||||||
|
|
||||||
|
QHBoxLayout *box = new QHBoxLayout;
|
||||||
|
box->addWidget(splitter);
|
||||||
|
setLayout(box);
|
||||||
|
|
||||||
|
connect(m_tree, &TreeView::curvesSelected, m_view, &GraphicsView::reset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditor::zoomX(double zoom)
|
||||||
|
{
|
||||||
|
m_view->setZoomX(zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditor::zoomY(double zoom)
|
||||||
|
{
|
||||||
|
m_view->setZoomY(zoom);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -1,9 +1,9 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of Qt Creator.
|
** This file is part of the Qt Design Tooling
|
||||||
**
|
**
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
@@ -25,11 +25,29 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace QmlDesignerExtension {
|
#include <QWidget>
|
||||||
namespace Constants {
|
|
||||||
|
|
||||||
const char ACTION_ID[] = "QmlDesignerExtension.Action";
|
namespace DesignTools {
|
||||||
const char MENU_ID[] = "QmlDesignerExtension.Menu";
|
|
||||||
|
|
||||||
} // namespace QmlDesignerExtension
|
class CurveEditorModel;
|
||||||
} // namespace Constants
|
class GraphicsView;
|
||||||
|
class TreeView;
|
||||||
|
|
||||||
|
class CurveEditor : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
CurveEditor(CurveEditorModel *model, QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
void zoomX(double zoom);
|
||||||
|
|
||||||
|
void zoomY(double zoom);
|
||||||
|
|
||||||
|
private:
|
||||||
|
TreeView *m_tree;
|
||||||
|
|
||||||
|
GraphicsView *m_view;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,46 @@
|
|||||||
|
INCLUDEPATH += $$PWD
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
$$PWD/animationcurve.h \
|
||||||
|
$$PWD/curveeditor.h \
|
||||||
|
$$PWD/curveeditormodel.h \
|
||||||
|
$$PWD/detail/colorcontrol.h \
|
||||||
|
$$PWD/detail/curveeditorstyledialog.h \
|
||||||
|
$$PWD/detail/curveitem.h \
|
||||||
|
$$PWD/detail/curvesegment.h \
|
||||||
|
$$PWD/detail/graphicsscene.h \
|
||||||
|
$$PWD/detail/graphicsview.h \
|
||||||
|
$$PWD/detail/handleitem.h \
|
||||||
|
$$PWD/detail/keyframeitem.h \
|
||||||
|
$$PWD/detail/playhead.h \
|
||||||
|
$$PWD/detail/selectableitem.h \
|
||||||
|
$$PWD/detail/selector.h \
|
||||||
|
$$PWD/detail/shortcut.h \
|
||||||
|
$$PWD/detail/treeitemdelegate.h \
|
||||||
|
$$PWD/detail/treemodel.h \
|
||||||
|
$$PWD/detail/treeview.h \
|
||||||
|
$$PWD/keyframe.h \
|
||||||
|
$$PWD/treeitem.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
$$PWD/animationcurve.cpp \
|
||||||
|
$$PWD/curveeditor.cpp \
|
||||||
|
$$PWD/curveeditormodel.cpp \
|
||||||
|
$$PWD/detail/colorcontrol.cpp \
|
||||||
|
$$PWD/detail/curveeditorstyledialog.cpp \
|
||||||
|
$$PWD/detail/curveitem.cpp \
|
||||||
|
$$PWD/detail/curvesegment.cpp \
|
||||||
|
$$PWD/detail/graphicsscene.cpp \
|
||||||
|
$$PWD/detail/graphicsview.cpp \
|
||||||
|
$$PWD/detail/handleitem.cpp \
|
||||||
|
$$PWD/detail/keyframeitem.cpp \
|
||||||
|
$$PWD/detail/playhead.cpp \
|
||||||
|
$$PWD/detail/selectableitem.cpp \
|
||||||
|
$$PWD/detail/selector.cpp \
|
||||||
|
$$PWD/detail/shortcut.cpp \
|
||||||
|
$$PWD/detail/treeitemdelegate.cpp \
|
||||||
|
$$PWD/detail/treemodel.cpp \
|
||||||
|
$$PWD/detail/treeview.cpp \
|
||||||
|
$$PWD/detail/utils.cpp \
|
||||||
|
$$PWD/keyframe.cpp \
|
||||||
|
$$PWD/treeitem.cpp
|
@@ -0,0 +1,70 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "curveeditormodel.h"
|
||||||
|
#include "treeitem.h"
|
||||||
|
#include "detail/graphicsview.h"
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
CurveEditorModel::CurveEditorModel(QObject *parent)
|
||||||
|
: TreeModel(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
CurveEditorModel::~CurveEditorModel() {}
|
||||||
|
|
||||||
|
|
||||||
|
void CurveEditorModel::setCurrentFrame(int frame)
|
||||||
|
{
|
||||||
|
if (graphicsView())
|
||||||
|
graphicsView()->setCurrentFrame(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorModel::setCurve(unsigned int id, const AnimationCurve &curve)
|
||||||
|
{
|
||||||
|
if (TreeItem *item = find(id)) {
|
||||||
|
if (PropertyTreeItem *propertyItem = item->asPropertyItem()) {
|
||||||
|
propertyItem->setCurve(curve);
|
||||||
|
emit curveChanged(propertyItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorModel::reset(const std::vector<TreeItem *> &items)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
|
||||||
|
initialize();
|
||||||
|
|
||||||
|
unsigned int counter = 0;
|
||||||
|
for (auto *item : items) {
|
||||||
|
item->setId(++counter);
|
||||||
|
root()->addChild(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,72 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "detail/treemodel.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QPointF;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
struct CurveEditorStyle;
|
||||||
|
|
||||||
|
class AnimationCurve;
|
||||||
|
class PropertyTreeItem;
|
||||||
|
class TreeItem;
|
||||||
|
|
||||||
|
class CurveEditorModel : public TreeModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void currentFrameChanged(int frame);
|
||||||
|
|
||||||
|
void curveChanged(PropertyTreeItem *item);
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual double minimumTime() const = 0;
|
||||||
|
|
||||||
|
virtual double maximumTime() const = 0;
|
||||||
|
|
||||||
|
virtual CurveEditorStyle style() const = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CurveEditorModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
~CurveEditorModel() override;
|
||||||
|
|
||||||
|
void setCurrentFrame(int frame);
|
||||||
|
|
||||||
|
void setCurve(unsigned int id, const AnimationCurve &curve);
|
||||||
|
|
||||||
|
void reset(const std::vector<TreeItem *> &items);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,125 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "detail/shortcut.h"
|
||||||
|
|
||||||
|
#include <QBitmap>
|
||||||
|
#include <QBrush>
|
||||||
|
#include <QColor>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QKeySequence>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
struct TreeItemStyleOption
|
||||||
|
{
|
||||||
|
double margins;
|
||||||
|
QIcon pinnedIcon = QIcon(":/ICON_PINNED");
|
||||||
|
QIcon unpinnedIcon = QIcon(":/ICON_UNPINNED");
|
||||||
|
QIcon lockedIcon = QIcon(":/ICON_LOCKED");
|
||||||
|
QIcon unlockedIcon = QIcon(":/ICON_UNLOCKED");
|
||||||
|
};
|
||||||
|
|
||||||
|
struct HandleItemStyleOption
|
||||||
|
{
|
||||||
|
double size = 10.0;
|
||||||
|
double lineWidth = 1.0;
|
||||||
|
QColor color = QColor(200, 0, 0);
|
||||||
|
QColor selectionColor = QColor(200, 200, 200);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KeyframeItemStyleOption
|
||||||
|
{
|
||||||
|
double size = 10.0;
|
||||||
|
QColor color = QColor(200, 200, 0);
|
||||||
|
QColor selectionColor = QColor(200, 200, 200);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CurveItemStyleOption
|
||||||
|
{
|
||||||
|
double width = 1.0;
|
||||||
|
QColor color = QColor(0, 200, 0);
|
||||||
|
QColor selectionColor = QColor(200, 200, 200);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PlayheadStyleOption
|
||||||
|
{
|
||||||
|
double width = 20.0;
|
||||||
|
double radius = 4.0;
|
||||||
|
QColor color = QColor(200, 200, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Shortcuts
|
||||||
|
{
|
||||||
|
Shortcut newSelection = Shortcut(Qt::LeftButton);
|
||||||
|
Shortcut addToSelection = Shortcut(Qt::LeftButton, Qt::ControlModifier | Qt::ShiftModifier);
|
||||||
|
Shortcut removeFromSelection = Shortcut(Qt::LeftButton, Qt::ShiftModifier);
|
||||||
|
Shortcut toggleSelection = Shortcut(Qt::LeftButton, Qt::ControlModifier);
|
||||||
|
|
||||||
|
Shortcut zoom = Shortcut(Qt::RightButton, Qt::AltModifier);
|
||||||
|
Shortcut pan = Shortcut(Qt::MiddleButton, Qt::AltModifier);
|
||||||
|
Shortcut frameAll = Shortcut(Qt::NoModifier, Qt::Key_A);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CurveEditorStyle
|
||||||
|
{
|
||||||
|
Shortcuts shortcuts;
|
||||||
|
|
||||||
|
QBrush backgroundBrush = QBrush(QColor(5, 0, 100));
|
||||||
|
QBrush backgroundAlternateBrush = QBrush(QColor(0, 0, 50));
|
||||||
|
QColor fontColor = QColor(200, 200, 200);
|
||||||
|
QColor gridColor = QColor(128, 128, 128);
|
||||||
|
double canvasMargin = 5.0;
|
||||||
|
int zoomInWidth = 100;
|
||||||
|
int zoomInHeight = 100;
|
||||||
|
double timeAxisHeight = 40.0;
|
||||||
|
double timeOffsetLeft = 10.0;
|
||||||
|
double timeOffsetRight = 10.0;
|
||||||
|
QColor rangeBarColor = QColor(128, 128, 128);
|
||||||
|
QColor rangeBarCapsColor = QColor(50, 50, 255);
|
||||||
|
double valueAxisWidth = 60.0;
|
||||||
|
double valueOffsetTop = 10.0;
|
||||||
|
double valueOffsetBottom = 10.0;
|
||||||
|
|
||||||
|
HandleItemStyleOption handleStyle;
|
||||||
|
KeyframeItemStyleOption keyframeStyle;
|
||||||
|
CurveItemStyleOption curveStyle;
|
||||||
|
TreeItemStyleOption treeItemStyle;
|
||||||
|
PlayheadStyleOption playhead;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QPixmap pixmapFromIcon(const QIcon &icon, const QSize &size, const QColor &color)
|
||||||
|
{
|
||||||
|
QPixmap pixmap = icon.pixmap(size);
|
||||||
|
QPixmap mask(pixmap.size());
|
||||||
|
mask.fill(color);
|
||||||
|
mask.setMask(pixmap.createMaskFromColor(Qt::transparent));
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,101 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#include "colorcontrol.h"
|
||||||
|
|
||||||
|
#include <QColorDialog>
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QHelpEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QToolTip>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
ColorControl::ColorControl()
|
||||||
|
: QWidget(nullptr)
|
||||||
|
, m_color(Qt::black)
|
||||||
|
{
|
||||||
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
setFixedHeight(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorControl::ColorControl(const QColor &color, QWidget *parent)
|
||||||
|
: QWidget(parent)
|
||||||
|
, m_color(color)
|
||||||
|
{
|
||||||
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||||
|
setFixedHeight(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorControl::~ColorControl() = default;
|
||||||
|
|
||||||
|
QColor ColorControl::value() const
|
||||||
|
{
|
||||||
|
return m_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorControl::setValue(const QColor &val)
|
||||||
|
{
|
||||||
|
m_color = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ColorControl::event(QEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::ToolTip) {
|
||||||
|
if (auto helpEvent = static_cast<const QHelpEvent *>(event)) {
|
||||||
|
QToolTip::showText(helpEvent->globalPos(), m_color.name());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QWidget::event(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorControl::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
QPainter painter(this);
|
||||||
|
painter.fillRect(event->rect(), m_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorControl::mouseReleaseEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
QColor color = QColorDialog::getColor(m_color, this);
|
||||||
|
|
||||||
|
event->accept();
|
||||||
|
|
||||||
|
if (color != m_color) {
|
||||||
|
m_color = color;
|
||||||
|
update();
|
||||||
|
emit valueChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorControl::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
// Required if embedded in a QGraphicsProxywidget
|
||||||
|
// in order to call mouseRelease properly.
|
||||||
|
QWidget::mousePressEvent(event);
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,63 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class ColorControl : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ColorControl();
|
||||||
|
|
||||||
|
ColorControl(const QColor &color, QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
~ColorControl() override;
|
||||||
|
|
||||||
|
QColor value() const;
|
||||||
|
|
||||||
|
void setValue(const QColor &val);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool event(QEvent *event) override;
|
||||||
|
|
||||||
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
|
||||||
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void valueChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QColor m_color;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,267 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#include "curveeditorstyledialog.h"
|
||||||
|
#include "colorcontrol.h"
|
||||||
|
#include "curveeditorstyle.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDoubleSpinBox>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
QHBoxLayout *createRow(const QString &title, QWidget *widget)
|
||||||
|
{
|
||||||
|
auto *label = new QLabel(title);
|
||||||
|
label->setFixedWidth(200);
|
||||||
|
label->setAlignment(Qt::AlignRight);
|
||||||
|
|
||||||
|
auto *box = new QHBoxLayout;
|
||||||
|
box->addWidget(label);
|
||||||
|
box->addWidget(widget);
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurveEditorStyleDialog::CurveEditorStyleDialog(CurveEditorStyle &style, QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, m_printButton(new QPushButton("Print"))
|
||||||
|
, m_background(new ColorControl(style.backgroundBrush.color()))
|
||||||
|
, m_backgroundAlternate(new ColorControl(style.backgroundAlternateBrush.color()))
|
||||||
|
, m_fontColor(new ColorControl(style.fontColor))
|
||||||
|
, m_gridColor(new ColorControl(style.gridColor))
|
||||||
|
, m_canvasMargin(new QDoubleSpinBox())
|
||||||
|
, m_zoomInWidth(new QSpinBox())
|
||||||
|
, m_zoomInHeight(new QSpinBox())
|
||||||
|
, m_timeAxisHeight(new QDoubleSpinBox())
|
||||||
|
, m_timeOffsetLeft(new QDoubleSpinBox())
|
||||||
|
, m_timeOffsetRight(new QDoubleSpinBox())
|
||||||
|
, m_rangeBarColor(new ColorControl(style.rangeBarCapsColor))
|
||||||
|
, m_rangeBarCapsColor(new ColorControl(style.rangeBarCapsColor))
|
||||||
|
, m_valueAxisWidth(new QDoubleSpinBox())
|
||||||
|
, m_valueOffsetTop(new QDoubleSpinBox())
|
||||||
|
, m_valueOffsetBottom(new QDoubleSpinBox())
|
||||||
|
, m_handleSize(new QDoubleSpinBox())
|
||||||
|
, m_handleLineWidth(new QDoubleSpinBox())
|
||||||
|
, m_handleColor(new ColorControl(style.handleStyle.color))
|
||||||
|
, m_handleSelectionColor(new ColorControl(style.handleStyle.selectionColor))
|
||||||
|
, m_keyframeSize(new QDoubleSpinBox())
|
||||||
|
, m_keyframeColor(new ColorControl(style.keyframeStyle.color))
|
||||||
|
, m_keyframeSelectionColor(new ColorControl(style.keyframeStyle.selectionColor))
|
||||||
|
, m_curveWidth(new QDoubleSpinBox())
|
||||||
|
, m_curveColor(new ColorControl(style.curveStyle.color))
|
||||||
|
, m_curveSelectionColor(new ColorControl(style.curveStyle.selectionColor))
|
||||||
|
, m_treeMargins(new QDoubleSpinBox())
|
||||||
|
, m_playheadWidth(new QDoubleSpinBox())
|
||||||
|
, m_playheadRadius(new QDoubleSpinBox())
|
||||||
|
, m_playheadColor(new ColorControl(style.playhead.color))
|
||||||
|
|
||||||
|
{
|
||||||
|
m_canvasMargin->setValue(style.canvasMargin);
|
||||||
|
m_zoomInWidth->setValue(style.zoomInWidth);
|
||||||
|
m_zoomInHeight->setValue(style.zoomInHeight);
|
||||||
|
m_zoomInHeight->setMaximum(9000);
|
||||||
|
|
||||||
|
m_timeAxisHeight->setValue(style.timeAxisHeight);
|
||||||
|
m_timeOffsetLeft->setValue(style.timeOffsetLeft);
|
||||||
|
m_timeOffsetRight->setValue(style.timeOffsetRight);
|
||||||
|
m_valueAxisWidth->setValue(style.valueAxisWidth);
|
||||||
|
m_valueOffsetTop->setValue(style.valueOffsetTop);
|
||||||
|
m_valueOffsetBottom->setValue(style.valueOffsetBottom);
|
||||||
|
m_handleSize->setValue(style.handleStyle.size);
|
||||||
|
m_handleLineWidth->setValue(style.handleStyle.lineWidth);
|
||||||
|
m_keyframeSize->setValue(style.keyframeStyle.size);
|
||||||
|
m_curveWidth->setValue(style.curveStyle.width);
|
||||||
|
m_treeMargins->setValue(style.treeItemStyle.margins);
|
||||||
|
m_playheadWidth->setValue(style.playhead.width);
|
||||||
|
m_playheadRadius->setValue(style.playhead.radius);
|
||||||
|
|
||||||
|
connect(m_printButton, &QPushButton::released, this, &CurveEditorStyleDialog::printStyle);
|
||||||
|
|
||||||
|
auto intChanged = [this](int) { emitStyleChanged(); };
|
||||||
|
auto doubleChanged = [this](double) { emitStyleChanged(); };
|
||||||
|
auto colorChanged = [this]() { emitStyleChanged(); };
|
||||||
|
|
||||||
|
auto intSignal = static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged);
|
||||||
|
auto doubleSignal = static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged);
|
||||||
|
|
||||||
|
connect(m_background, &ColorControl::valueChanged, colorChanged);
|
||||||
|
connect(m_backgroundAlternate, &ColorControl::valueChanged, colorChanged);
|
||||||
|
connect(m_fontColor, &ColorControl::valueChanged, colorChanged);
|
||||||
|
connect(m_gridColor, &ColorControl::valueChanged, colorChanged);
|
||||||
|
connect(m_canvasMargin, doubleSignal, doubleChanged);
|
||||||
|
connect(m_zoomInWidth, intSignal, intChanged);
|
||||||
|
connect(m_zoomInHeight, intSignal, intChanged);
|
||||||
|
connect(m_timeAxisHeight, doubleSignal, doubleChanged);
|
||||||
|
connect(m_timeOffsetLeft, doubleSignal, doubleChanged);
|
||||||
|
connect(m_timeOffsetRight, doubleSignal, doubleChanged);
|
||||||
|
connect(m_rangeBarColor, &ColorControl::valueChanged, colorChanged);
|
||||||
|
connect(m_rangeBarCapsColor, &ColorControl::valueChanged, colorChanged);
|
||||||
|
connect(m_valueAxisWidth, doubleSignal, doubleChanged);
|
||||||
|
connect(m_valueOffsetTop, doubleSignal, doubleChanged);
|
||||||
|
connect(m_valueOffsetBottom, doubleSignal, doubleChanged);
|
||||||
|
connect(m_handleSize, doubleSignal, doubleChanged);
|
||||||
|
connect(m_handleLineWidth, doubleSignal, doubleChanged);
|
||||||
|
connect(m_handleColor, &ColorControl::valueChanged, colorChanged);
|
||||||
|
connect(m_handleSelectionColor, &ColorControl::valueChanged, colorChanged);
|
||||||
|
connect(m_keyframeSize, doubleSignal, doubleChanged);
|
||||||
|
connect(m_keyframeColor, &ColorControl::valueChanged, colorChanged);
|
||||||
|
connect(m_keyframeSelectionColor, &ColorControl::valueChanged, colorChanged);
|
||||||
|
connect(m_curveWidth, doubleSignal, doubleChanged);
|
||||||
|
connect(m_curveColor, &ColorControl::valueChanged, colorChanged);
|
||||||
|
connect(m_curveSelectionColor, &ColorControl::valueChanged, colorChanged);
|
||||||
|
connect(m_treeMargins, doubleSignal, doubleChanged);
|
||||||
|
connect(m_playheadWidth, doubleSignal, doubleChanged);
|
||||||
|
connect(m_playheadRadius, doubleSignal, doubleChanged);
|
||||||
|
connect(m_playheadColor, &ColorControl::valueChanged, colorChanged);
|
||||||
|
|
||||||
|
auto *box = new QVBoxLayout;
|
||||||
|
box->addLayout(createRow("Background Color", m_background));
|
||||||
|
box->addLayout(createRow("Alternate Background Color", m_backgroundAlternate));
|
||||||
|
box->addLayout(createRow("Font Color", m_fontColor));
|
||||||
|
box->addLayout(createRow("Grid Color", m_gridColor));
|
||||||
|
box->addLayout(createRow("Canvas Margin", m_canvasMargin));
|
||||||
|
box->addLayout(createRow("Zoom In Width", m_zoomInWidth));
|
||||||
|
box->addLayout(createRow("Zoom In Height", m_zoomInHeight));
|
||||||
|
box->addLayout(createRow("Time Axis Height", m_timeAxisHeight));
|
||||||
|
box->addLayout(createRow("Time Axis Left Offset", m_timeOffsetLeft));
|
||||||
|
box->addLayout(createRow("Time Axis Right Offset", m_timeOffsetRight));
|
||||||
|
box->addLayout(createRow("Range Bar Color", m_rangeBarColor));
|
||||||
|
box->addLayout(createRow("Range Bar Caps Color", m_rangeBarCapsColor));
|
||||||
|
box->addLayout(createRow("Value Axis Width", m_valueAxisWidth));
|
||||||
|
box->addLayout(createRow("Value Axis Top Offset", m_valueOffsetTop));
|
||||||
|
box->addLayout(createRow("Value Axis Bottom Offset", m_valueOffsetBottom));
|
||||||
|
box->addLayout(createRow("Handle Size", m_handleSize));
|
||||||
|
box->addLayout(createRow("Handle Line Width", m_handleLineWidth));
|
||||||
|
box->addLayout(createRow("Handle Color", m_handleColor));
|
||||||
|
box->addLayout(createRow("Handle Selection Color", m_handleSelectionColor));
|
||||||
|
box->addLayout(createRow("Keyframe Size", m_keyframeSize));
|
||||||
|
box->addLayout(createRow("Keyframe Color", m_keyframeColor));
|
||||||
|
box->addLayout(createRow("Keyframe Selection Color", m_keyframeSelectionColor));
|
||||||
|
box->addLayout(createRow("Curve Width", m_curveWidth));
|
||||||
|
box->addLayout(createRow("Curve Color", m_curveColor));
|
||||||
|
box->addLayout(createRow("Curve Selection Color", m_curveSelectionColor));
|
||||||
|
box->addLayout(createRow("Treeview margins", m_treeMargins));
|
||||||
|
box->addLayout(createRow("Playhead width", m_playheadWidth));
|
||||||
|
box->addLayout(createRow("Playhead radius", m_playheadRadius));
|
||||||
|
box->addLayout(createRow("Playhead color", m_playheadColor));
|
||||||
|
|
||||||
|
box->addWidget(m_printButton);
|
||||||
|
setLayout(box);
|
||||||
|
}
|
||||||
|
|
||||||
|
CurveEditorStyle CurveEditorStyleDialog::style() const
|
||||||
|
{
|
||||||
|
CurveEditorStyle style;
|
||||||
|
style.backgroundBrush = QBrush(m_background->value());
|
||||||
|
style.backgroundAlternateBrush = QBrush(m_backgroundAlternate->value());
|
||||||
|
style.fontColor = m_fontColor->value();
|
||||||
|
style.gridColor = m_gridColor->value();
|
||||||
|
style.canvasMargin = m_canvasMargin->value();
|
||||||
|
style.zoomInWidth = m_zoomInWidth->value();
|
||||||
|
style.zoomInHeight = m_zoomInHeight->value();
|
||||||
|
style.timeAxisHeight = m_timeAxisHeight->value();
|
||||||
|
style.timeOffsetLeft = m_timeOffsetLeft->value();
|
||||||
|
style.timeOffsetRight = m_timeOffsetRight->value();
|
||||||
|
style.rangeBarColor = m_rangeBarColor->value();
|
||||||
|
style.rangeBarCapsColor = m_rangeBarCapsColor->value();
|
||||||
|
style.valueAxisWidth = m_valueAxisWidth->value();
|
||||||
|
style.valueOffsetTop = m_valueOffsetTop->value();
|
||||||
|
style.valueOffsetBottom = m_valueOffsetBottom->value();
|
||||||
|
style.handleStyle.size = m_handleSize->value();
|
||||||
|
style.handleStyle.lineWidth = m_handleLineWidth->value();
|
||||||
|
style.handleStyle.color = m_handleColor->value();
|
||||||
|
style.handleStyle.selectionColor = m_handleSelectionColor->value();
|
||||||
|
style.keyframeStyle.size = m_keyframeSize->value();
|
||||||
|
style.keyframeStyle.color = m_keyframeColor->value();
|
||||||
|
style.keyframeStyle.selectionColor = m_keyframeSelectionColor->value();
|
||||||
|
style.curveStyle.width = m_curveWidth->value();
|
||||||
|
style.curveStyle.color = m_curveColor->value();
|
||||||
|
style.curveStyle.selectionColor = m_curveSelectionColor->value();
|
||||||
|
style.treeItemStyle.margins = m_treeMargins->value();
|
||||||
|
style.playhead.width = m_playheadWidth->value();
|
||||||
|
style.playhead.radius = m_playheadRadius->value();
|
||||||
|
style.playhead.color = m_playheadColor->value();
|
||||||
|
|
||||||
|
return style;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorStyleDialog::emitStyleChanged()
|
||||||
|
{
|
||||||
|
emit styleChanged(style());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveEditorStyleDialog::printStyle()
|
||||||
|
{
|
||||||
|
auto toString = [](const QColor &color) {
|
||||||
|
QString tmp
|
||||||
|
= QString("QColor(%1, %2, %3)").arg(color.red()).arg(color.green()).arg(color.blue());
|
||||||
|
return qPrintable(tmp);
|
||||||
|
};
|
||||||
|
|
||||||
|
CurveEditorStyle s = style();
|
||||||
|
qDebug() << "";
|
||||||
|
qDebug().nospace() << "CurveEditorStyle out;";
|
||||||
|
qDebug().nospace() << "out.backgroundBrush = QBrush(" << toString(s.backgroundBrush.color())
|
||||||
|
<< ");";
|
||||||
|
qDebug().nospace() << "out.backgroundAlternateBrush = QBrush("
|
||||||
|
<< toString(s.backgroundAlternateBrush.color()) << ");";
|
||||||
|
qDebug().nospace() << "out.fontColor = " << toString(s.fontColor) << ";";
|
||||||
|
qDebug().nospace() << "out.gridColor = " << toString(s.gridColor) << ";";
|
||||||
|
qDebug().nospace() << "out.canvasMargin = " << s.canvasMargin << ";";
|
||||||
|
qDebug().nospace() << "out.zoomInWidth = " << s.zoomInWidth << ";";
|
||||||
|
qDebug().nospace() << "out.zoomInHeight = " << s.zoomInHeight << ";";
|
||||||
|
qDebug().nospace() << "out.timeAxisHeight = " << s.timeAxisHeight << ";";
|
||||||
|
qDebug().nospace() << "out.timeOffsetLeft = " << s.timeOffsetLeft << ";";
|
||||||
|
qDebug().nospace() << "out.timeOffsetRight = " << s.timeOffsetRight << ";";
|
||||||
|
qDebug().nospace() << "out.rangeBarColor = " << toString(s.rangeBarColor) << ";";
|
||||||
|
qDebug().nospace() << "out.rangeBarCapsColor = " << toString(s.rangeBarCapsColor) << ";";
|
||||||
|
qDebug().nospace() << "out.valueAxisWidth = " << s.valueAxisWidth << ";";
|
||||||
|
qDebug().nospace() << "out.valueOffsetTop = " << s.valueOffsetTop << ";";
|
||||||
|
qDebug().nospace() << "out.valueOffsetBottom = " << s.valueOffsetBottom << ";";
|
||||||
|
qDebug().nospace() << "out.handleStyle.size = " << s.handleStyle.size << ";";
|
||||||
|
qDebug().nospace() << "out.handleStyle.lineWidth = " << s.handleStyle.lineWidth << ";";
|
||||||
|
qDebug().nospace() << "out.handleStyle.color = " << toString(s.handleStyle.color) << ";";
|
||||||
|
qDebug().nospace() << "out.handleStyle.selectionColor = "
|
||||||
|
<< toString(s.handleStyle.selectionColor) << ";";
|
||||||
|
qDebug().nospace() << "out.keyframeStyle.size = " << s.keyframeStyle.size << ";";
|
||||||
|
qDebug().nospace() << "out.keyframeStyle.color = " << toString(s.keyframeStyle.color) << ";";
|
||||||
|
qDebug().nospace() << "out.keyframeStyle.selectionColor = "
|
||||||
|
<< toString(s.keyframeStyle.selectionColor) << ";";
|
||||||
|
qDebug().nospace() << "out.curveStyle.width = " << s.curveStyle.width << ";";
|
||||||
|
qDebug().nospace() << "out.curveStyle.color = " << toString(s.curveStyle.color) << ";";
|
||||||
|
qDebug().nospace() << "out.curveStyle.selectionColor = "
|
||||||
|
<< toString(s.curveStyle.selectionColor) << ";";
|
||||||
|
qDebug().nospace() << "out.treeItemStyle.margins = " << s.treeItemStyle.margins << ";";
|
||||||
|
qDebug().nospace() << "out.playheadStyle.width = " << s.playhead.width << ";";
|
||||||
|
qDebug().nospace() << "out.playheadStyle.radius = " << s.playhead.radius << ";";
|
||||||
|
qDebug().nospace() << "out.playheadStyle.color = " << toString(s.playhead.color) << ";";
|
||||||
|
qDebug().nospace() << "return out;";
|
||||||
|
qDebug() << "";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,127 @@
|
|||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QPushButton;
|
||||||
|
class QSpinBox;
|
||||||
|
class QDoubleSpinBox;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class ColorControl;
|
||||||
|
|
||||||
|
struct CurveEditorStyle;
|
||||||
|
|
||||||
|
class CurveEditorStyleDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void styleChanged(const CurveEditorStyle &style);
|
||||||
|
|
||||||
|
public:
|
||||||
|
CurveEditorStyleDialog(CurveEditorStyle &style, QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
CurveEditorStyle style() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void emitStyleChanged();
|
||||||
|
|
||||||
|
void printStyle();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPushButton *m_printButton;
|
||||||
|
|
||||||
|
ColorControl *m_background;
|
||||||
|
|
||||||
|
ColorControl *m_backgroundAlternate;
|
||||||
|
|
||||||
|
ColorControl *m_fontColor;
|
||||||
|
|
||||||
|
ColorControl *m_gridColor;
|
||||||
|
|
||||||
|
QDoubleSpinBox *m_canvasMargin;
|
||||||
|
|
||||||
|
QSpinBox *m_zoomInWidth;
|
||||||
|
|
||||||
|
QSpinBox *m_zoomInHeight;
|
||||||
|
|
||||||
|
QDoubleSpinBox *m_timeAxisHeight;
|
||||||
|
|
||||||
|
QDoubleSpinBox *m_timeOffsetLeft;
|
||||||
|
|
||||||
|
QDoubleSpinBox *m_timeOffsetRight;
|
||||||
|
|
||||||
|
ColorControl *m_rangeBarColor;
|
||||||
|
|
||||||
|
ColorControl *m_rangeBarCapsColor;
|
||||||
|
|
||||||
|
QDoubleSpinBox *m_valueAxisWidth;
|
||||||
|
|
||||||
|
QDoubleSpinBox *m_valueOffsetTop;
|
||||||
|
|
||||||
|
QDoubleSpinBox *m_valueOffsetBottom;
|
||||||
|
|
||||||
|
// HandleItem
|
||||||
|
QDoubleSpinBox *m_handleSize;
|
||||||
|
|
||||||
|
QDoubleSpinBox *m_handleLineWidth;
|
||||||
|
|
||||||
|
ColorControl *m_handleColor;
|
||||||
|
|
||||||
|
ColorControl *m_handleSelectionColor;
|
||||||
|
|
||||||
|
// KeyframeItem
|
||||||
|
QDoubleSpinBox *m_keyframeSize;
|
||||||
|
|
||||||
|
ColorControl *m_keyframeColor;
|
||||||
|
|
||||||
|
ColorControl *m_keyframeSelectionColor;
|
||||||
|
|
||||||
|
// CurveItem
|
||||||
|
QDoubleSpinBox *m_curveWidth;
|
||||||
|
|
||||||
|
ColorControl *m_curveColor;
|
||||||
|
|
||||||
|
ColorControl *m_curveSelectionColor;
|
||||||
|
|
||||||
|
// TreeItem
|
||||||
|
QDoubleSpinBox *m_treeMargins;
|
||||||
|
|
||||||
|
// Playhead
|
||||||
|
QDoubleSpinBox *m_playheadWidth;
|
||||||
|
|
||||||
|
QDoubleSpinBox *m_playheadRadius;
|
||||||
|
|
||||||
|
ColorControl *m_playheadColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,226 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#include "curveitem.h"
|
||||||
|
#include "animationcurve.h"
|
||||||
|
#include "graphicsscene.h"
|
||||||
|
#include "keyframeitem.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPainterPath>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
CurveItem::CurveItem(QGraphicsItem *parent)
|
||||||
|
: QGraphicsObject(parent)
|
||||||
|
, m_id(0)
|
||||||
|
, m_style()
|
||||||
|
, m_transform()
|
||||||
|
, m_keyframes()
|
||||||
|
, m_underMouse(false)
|
||||||
|
, m_itemDirty(false)
|
||||||
|
, m_pathDirty(true)
|
||||||
|
{}
|
||||||
|
|
||||||
|
CurveItem::CurveItem(unsigned int id, const AnimationCurve &curve, QGraphicsItem *parent)
|
||||||
|
: QGraphicsObject(parent)
|
||||||
|
, m_id(id)
|
||||||
|
, m_style()
|
||||||
|
, m_transform()
|
||||||
|
, m_keyframes()
|
||||||
|
, m_underMouse(false)
|
||||||
|
, m_itemDirty(false)
|
||||||
|
, m_pathDirty(true)
|
||||||
|
{
|
||||||
|
setAcceptHoverEvents(true);
|
||||||
|
|
||||||
|
setFlag(QGraphicsItem::ItemIsMovable, false);
|
||||||
|
|
||||||
|
auto emitCurveChanged = [this]() {
|
||||||
|
m_itemDirty = true;
|
||||||
|
m_pathDirty = true;
|
||||||
|
update();
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto frame : curve.keyframes()) {
|
||||||
|
auto *item = new KeyframeItem(frame, this);
|
||||||
|
QObject::connect(item, &KeyframeItem::redrawCurve, emitCurveChanged);
|
||||||
|
m_keyframes.push_back(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CurveItem::~CurveItem() {}
|
||||||
|
|
||||||
|
int CurveItem::type() const
|
||||||
|
{
|
||||||
|
return Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF CurveItem::boundingRect() const
|
||||||
|
{
|
||||||
|
auto bbox = [](QRectF &bounds, const Keyframe &frame) {
|
||||||
|
grow(bounds, frame.position());
|
||||||
|
grow(bounds, frame.leftHandle());
|
||||||
|
grow(bounds, frame.rightHandle());
|
||||||
|
};
|
||||||
|
|
||||||
|
QRectF bounds;
|
||||||
|
for (auto *item : m_keyframes)
|
||||||
|
bbox(bounds, item->keyframe());
|
||||||
|
|
||||||
|
return m_transform.mapRect(bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CurveItem::contains(const QPointF &point) const
|
||||||
|
{
|
||||||
|
bool valid = false;
|
||||||
|
QPointF transformed(m_transform.inverted(&valid).map(point));
|
||||||
|
|
||||||
|
double width = std::abs(20.0 / scaleY(m_transform));
|
||||||
|
|
||||||
|
if (valid)
|
||||||
|
return curve().intersects(transformed, width);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
|
||||||
|
{
|
||||||
|
if (m_keyframes.size() > 1) {
|
||||||
|
QPen pen = painter->pen();
|
||||||
|
QColor col = m_underMouse ? Qt::red : m_style.color;
|
||||||
|
|
||||||
|
pen.setWidthF(m_style.width);
|
||||||
|
pen.setColor(hasSelection() ? m_style.selectionColor : col);
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
painter->setPen(pen);
|
||||||
|
painter->drawPath(path());
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CurveItem::isDirty() const
|
||||||
|
{
|
||||||
|
return m_itemDirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CurveItem::hasSelection() const
|
||||||
|
{
|
||||||
|
for (auto *frame : m_keyframes) {
|
||||||
|
if (frame->selected())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int CurveItem::id() const
|
||||||
|
{
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPainterPath CurveItem::path() const
|
||||||
|
{
|
||||||
|
if (m_pathDirty) {
|
||||||
|
Keyframe previous = m_keyframes.front()->keyframe();
|
||||||
|
Keyframe current;
|
||||||
|
|
||||||
|
m_path = QPainterPath(m_transform.map(previous.position()));
|
||||||
|
for (size_t i = 1; i < m_keyframes.size(); ++i) {
|
||||||
|
current = m_keyframes[i]->keyframe();
|
||||||
|
|
||||||
|
if (previous.rightHandle().isNull() || current.leftHandle().isNull()) {
|
||||||
|
m_path.lineTo(m_transform.map(current.position()));
|
||||||
|
} else {
|
||||||
|
m_path.cubicTo(
|
||||||
|
m_transform.map(previous.rightHandle()),
|
||||||
|
m_transform.map(current.leftHandle()),
|
||||||
|
m_transform.map(current.position()));
|
||||||
|
}
|
||||||
|
|
||||||
|
previous = current;
|
||||||
|
}
|
||||||
|
m_pathDirty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimationCurve CurveItem::curve() const
|
||||||
|
{
|
||||||
|
std::vector<Keyframe> out;
|
||||||
|
out.reserve(m_keyframes.size());
|
||||||
|
for (auto item : m_keyframes)
|
||||||
|
out.push_back(item->keyframe());
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveItem::setDirty(bool dirty)
|
||||||
|
{
|
||||||
|
m_itemDirty = dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF CurveItem::setComponentTransform(const QTransform &transform)
|
||||||
|
{
|
||||||
|
m_pathDirty = true;
|
||||||
|
|
||||||
|
prepareGeometryChange();
|
||||||
|
m_transform = transform;
|
||||||
|
for (auto frame : m_keyframes)
|
||||||
|
frame->setComponentTransform(transform);
|
||||||
|
|
||||||
|
return boundingRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveItem::setStyle(const CurveEditorStyle &style)
|
||||||
|
{
|
||||||
|
m_style = style.curveStyle;
|
||||||
|
|
||||||
|
for (auto *frame : m_keyframes)
|
||||||
|
frame->setStyle(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveItem::connect(GraphicsScene *scene)
|
||||||
|
{
|
||||||
|
for (auto *frame : m_keyframes) {
|
||||||
|
QObject::connect(frame, &KeyframeItem::keyframeMoved, scene, &GraphicsScene::keyframeMoved);
|
||||||
|
QObject::connect(frame, &KeyframeItem::handleMoved, scene, &GraphicsScene::handleMoved);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveItem::setIsUnderMouse(bool under)
|
||||||
|
{
|
||||||
|
if (under != m_underMouse) {
|
||||||
|
m_underMouse = under;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,98 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "curveeditorstyle.h"
|
||||||
|
#include "selectableitem.h"
|
||||||
|
|
||||||
|
#include <QGraphicsObject>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class AnimationCurve;
|
||||||
|
class KeyframeItem;
|
||||||
|
class GraphicsScene;
|
||||||
|
|
||||||
|
class CurveItem : public QGraphicsObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
CurveItem(QGraphicsItem *parent = nullptr);
|
||||||
|
|
||||||
|
CurveItem(unsigned int id, const AnimationCurve &curve, QGraphicsItem *parent = nullptr);
|
||||||
|
|
||||||
|
~CurveItem() override;
|
||||||
|
|
||||||
|
enum { Type = ItemTypeCurve };
|
||||||
|
|
||||||
|
int type() const override;
|
||||||
|
|
||||||
|
QRectF boundingRect() const override;
|
||||||
|
|
||||||
|
bool contains(const QPointF &point) const override;
|
||||||
|
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||||
|
|
||||||
|
bool isDirty() const;
|
||||||
|
|
||||||
|
bool hasSelection() const;
|
||||||
|
|
||||||
|
unsigned int id() const;
|
||||||
|
|
||||||
|
AnimationCurve curve() const;
|
||||||
|
|
||||||
|
void setDirty(bool dirty);
|
||||||
|
|
||||||
|
QRectF setComponentTransform(const QTransform &transform);
|
||||||
|
|
||||||
|
void setStyle(const CurveEditorStyle &style);
|
||||||
|
|
||||||
|
void connect(GraphicsScene *scene);
|
||||||
|
|
||||||
|
void setIsUnderMouse(bool under);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPainterPath path() const;
|
||||||
|
|
||||||
|
unsigned int m_id;
|
||||||
|
|
||||||
|
CurveItemStyleOption m_style;
|
||||||
|
|
||||||
|
QTransform m_transform;
|
||||||
|
|
||||||
|
std::vector<KeyframeItem *> m_keyframes;
|
||||||
|
|
||||||
|
bool m_underMouse;
|
||||||
|
|
||||||
|
bool m_itemDirty;
|
||||||
|
|
||||||
|
mutable bool m_pathDirty;
|
||||||
|
|
||||||
|
mutable QPainterPath m_path;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,277 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "curvesegment.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <qmath.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class CubicPolynomial
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CubicPolynomial(double p0, double p1, double p2, double p3);
|
||||||
|
|
||||||
|
std::vector<double> extrema() const;
|
||||||
|
|
||||||
|
std::vector<double> roots() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_a;
|
||||||
|
double m_b;
|
||||||
|
double m_c;
|
||||||
|
double m_d;
|
||||||
|
};
|
||||||
|
|
||||||
|
CubicPolynomial::CubicPolynomial(double p0, double p1, double p2, double p3)
|
||||||
|
: m_a(p3 - 3.0 * p2 + 3.0 * p1 - p0)
|
||||||
|
, m_b(3.0 * p2 - 6.0 * p1 + 3.0 * p0)
|
||||||
|
, m_c(3.0 * p1 - 3.0 * p0)
|
||||||
|
, m_d(p0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::vector<double> CubicPolynomial::extrema() const
|
||||||
|
{
|
||||||
|
std::vector<double> out;
|
||||||
|
|
||||||
|
auto addValidValue = [&out](double value) {
|
||||||
|
if (!std::isnan(value) && !std::isinf(value))
|
||||||
|
out.push_back(clamp(value, 0.0, 1.0));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find the roots of the first derivative of y.
|
||||||
|
auto pd2 = (2.0 * m_b) / (3.0 * m_a) / 2.0;
|
||||||
|
auto q = m_c / (3.0 * m_a);
|
||||||
|
|
||||||
|
auto radi = std::pow(pd2, 2.0) - q;
|
||||||
|
|
||||||
|
auto x1 = -pd2 + std::sqrt(radi);
|
||||||
|
auto x2 = -pd2 - std::sqrt(radi);
|
||||||
|
|
||||||
|
addValidValue(x1);
|
||||||
|
addValidValue(x2);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> CubicPolynomial::roots() const
|
||||||
|
{
|
||||||
|
std::vector<double> out;
|
||||||
|
|
||||||
|
auto addValidValue = [&out](double value) {
|
||||||
|
if (!(std::isnan(value) || std::isinf(value)))
|
||||||
|
out.push_back(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_a == 0.0) {
|
||||||
|
// Linear
|
||||||
|
if (m_b == 0.0) {
|
||||||
|
if (m_c != 0.0)
|
||||||
|
out.push_back(-m_d / m_c);
|
||||||
|
// Quadratic
|
||||||
|
} else {
|
||||||
|
const double p = m_c / m_b / 2.0;
|
||||||
|
const double q = m_d / m_b;
|
||||||
|
addValidValue(-p + std::sqrt(std::pow(p, 2.0) - q));
|
||||||
|
addValidValue(-p - std::sqrt(std::pow(p, 2.0) - q));
|
||||||
|
}
|
||||||
|
// Cubic
|
||||||
|
} else {
|
||||||
|
const double p = 3.0 * m_a * m_c - std::pow(m_b, 2.0);
|
||||||
|
const double q = 2.0 * std::pow(m_b, 3.0) - 9.0 * m_a * m_b * m_c
|
||||||
|
+ 27.0 * std::pow(m_a, 2.0) * m_d;
|
||||||
|
|
||||||
|
auto disc = std::pow(q, 2.0) + 4.0 * std::pow(p, 3.0);
|
||||||
|
|
||||||
|
auto toX = [&](double y) { return (y - m_b) / (3.0 * m_a); };
|
||||||
|
|
||||||
|
// One real solution.
|
||||||
|
if (disc >= 0) {
|
||||||
|
auto u = (1.0 / 2.0)
|
||||||
|
* std::cbrt(-4.0 * q
|
||||||
|
+ 4.0 * std::sqrt(std::pow(q, 2.0) + 4.0 * std::pow(p, 3.0)));
|
||||||
|
auto v = (1.0 / 2.0)
|
||||||
|
* std::cbrt(-4.0 * q
|
||||||
|
- 4.0 * std::sqrt(std::pow(q, 2.0) + 4.0 * std::pow(p, 3.0)));
|
||||||
|
|
||||||
|
addValidValue(toX(u + v));
|
||||||
|
// Three real solutions.
|
||||||
|
} else {
|
||||||
|
auto phi = acos(-q / (2 * std::sqrt(-std::pow(p, 3.0))));
|
||||||
|
auto y1 = std::sqrt(-p) * 2.0 * cos(phi / 3.0);
|
||||||
|
auto y2 = std::sqrt(-p) * 2.0 * cos((phi / 3.0) + (2.0 * M_PI / 3.0));
|
||||||
|
auto y3 = std::sqrt(-p) * 2.0 * cos((phi / 3.0) + (4.0 * M_PI / 3.0));
|
||||||
|
|
||||||
|
addValidValue(toX(y1));
|
||||||
|
addValidValue(toX(y2));
|
||||||
|
addValidValue(toX(y3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurveSegment::CurveSegment()
|
||||||
|
: m_left()
|
||||||
|
, m_right()
|
||||||
|
{}
|
||||||
|
|
||||||
|
CurveSegment::CurveSegment(const Keyframe &left, const Keyframe &right)
|
||||||
|
: m_left(left)
|
||||||
|
, m_right(right)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool CurveSegment::containsX(double x) const
|
||||||
|
{
|
||||||
|
return m_left.position().x() <= x && m_right.position().x() >= x;
|
||||||
|
}
|
||||||
|
|
||||||
|
double evaluateForT(double t, double p0, double p1, double p2, double p3)
|
||||||
|
{
|
||||||
|
assert(t >= 0. && t <= 1.);
|
||||||
|
|
||||||
|
const double it = 1.0 - t;
|
||||||
|
|
||||||
|
return p0 * std::pow(it, 3.0) + p1 * 3.0 * std::pow(it, 2.0) * t
|
||||||
|
+ p2 * 3.0 * it * std::pow(t, 2.0) + p3 * std::pow(t, 3.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF CurveSegment::evaluate(double t) const
|
||||||
|
{
|
||||||
|
const double x = evaluateForT(
|
||||||
|
t,
|
||||||
|
m_left.position().x(),
|
||||||
|
m_left.rightHandle().x(),
|
||||||
|
m_right.leftHandle().x(),
|
||||||
|
m_right.position().x());
|
||||||
|
|
||||||
|
const double y = evaluateForT(
|
||||||
|
t,
|
||||||
|
m_left.position().y(),
|
||||||
|
m_left.rightHandle().y(),
|
||||||
|
m_right.leftHandle().y(),
|
||||||
|
m_right.position().y());
|
||||||
|
|
||||||
|
return QPointF(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<QPointF> CurveSegment::extrema() const
|
||||||
|
{
|
||||||
|
std::vector<QPointF> out;
|
||||||
|
|
||||||
|
auto polynomial = CubicPolynomial(
|
||||||
|
m_left.position().y(),
|
||||||
|
m_left.rightHandle().y(),
|
||||||
|
m_right.leftHandle().y(),
|
||||||
|
m_right.position().y());
|
||||||
|
|
||||||
|
for (double t : polynomial.extrema()) {
|
||||||
|
|
||||||
|
const double x = evaluateForT(
|
||||||
|
t,
|
||||||
|
m_left.position().x(),
|
||||||
|
m_left.rightHandle().x(),
|
||||||
|
m_right.leftHandle().x(),
|
||||||
|
m_right.position().x());
|
||||||
|
|
||||||
|
const double y = evaluateForT(
|
||||||
|
t,
|
||||||
|
m_left.position().y(),
|
||||||
|
m_left.rightHandle().y(),
|
||||||
|
m_right.leftHandle().y(),
|
||||||
|
m_right.position().y());
|
||||||
|
|
||||||
|
out.push_back(QPointF(x, y));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> CurveSegment::yForX(double x) const
|
||||||
|
{
|
||||||
|
std::vector<double> out;
|
||||||
|
|
||||||
|
auto polynomial = CubicPolynomial(
|
||||||
|
m_left.position().x() - x,
|
||||||
|
m_left.rightHandle().x() - x,
|
||||||
|
m_right.leftHandle().x() - x,
|
||||||
|
m_right.position().x() - x);
|
||||||
|
|
||||||
|
for (double t : polynomial.roots()) {
|
||||||
|
if (t < 0.0 || t > 1.0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const double y = evaluateForT(
|
||||||
|
t,
|
||||||
|
m_left.position().y(),
|
||||||
|
m_left.rightHandle().y(),
|
||||||
|
m_right.leftHandle().y(),
|
||||||
|
m_right.position().y());
|
||||||
|
|
||||||
|
out.push_back(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> CurveSegment::xForY(double y) const
|
||||||
|
{
|
||||||
|
std::vector<double> out;
|
||||||
|
|
||||||
|
auto polynomial = CubicPolynomial(
|
||||||
|
m_left.position().y() - y,
|
||||||
|
m_left.rightHandle().y() - y,
|
||||||
|
m_right.leftHandle().y() - y,
|
||||||
|
m_right.position().y() - y);
|
||||||
|
|
||||||
|
for (double t : polynomial.roots()) {
|
||||||
|
if (t < 0.0 || t > 1.0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const double x = evaluateForT(
|
||||||
|
t,
|
||||||
|
m_left.position().x(),
|
||||||
|
m_left.rightHandle().x(),
|
||||||
|
m_right.leftHandle().x(),
|
||||||
|
m_right.position().x());
|
||||||
|
|
||||||
|
out.push_back(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveSegment::setLeft(const Keyframe &frame)
|
||||||
|
{
|
||||||
|
m_left = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CurveSegment::setRight(const Keyframe &frame)
|
||||||
|
{
|
||||||
|
m_right = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,65 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "keyframe.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QPointF;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class CurveSegment
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CurveSegment();
|
||||||
|
|
||||||
|
CurveSegment(const Keyframe &first, const Keyframe &last);
|
||||||
|
|
||||||
|
bool containsX(double x) const;
|
||||||
|
|
||||||
|
QPointF evaluate(double t) const;
|
||||||
|
|
||||||
|
std::vector<QPointF> extrema() const;
|
||||||
|
|
||||||
|
std::vector<double> yForX(double x) const;
|
||||||
|
|
||||||
|
std::vector<double> xForY(double y) const;
|
||||||
|
|
||||||
|
void setLeft(const Keyframe &frame);
|
||||||
|
|
||||||
|
void setRight(const Keyframe &frame);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Keyframe m_left;
|
||||||
|
|
||||||
|
Keyframe m_right;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,225 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "graphicsscene.h"
|
||||||
|
#include "animationcurve.h"
|
||||||
|
#include "curveitem.h"
|
||||||
|
#include "graphicsview.h"
|
||||||
|
#include "handleitem.h"
|
||||||
|
|
||||||
|
#include <QGraphicsSceneMouseEvent>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
GraphicsScene::GraphicsScene(QObject *parent)
|
||||||
|
: QGraphicsScene(parent)
|
||||||
|
, m_dirty(true)
|
||||||
|
, m_limits()
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool GraphicsScene::empty() const
|
||||||
|
{
|
||||||
|
return items().empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsScene::minimumTime() const
|
||||||
|
{
|
||||||
|
return limits().left();
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsScene::maximumTime() const
|
||||||
|
{
|
||||||
|
return limits().right();
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsScene::minimumValue() const
|
||||||
|
{
|
||||||
|
return limits().bottom();
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsScene::maximumValue() const
|
||||||
|
{
|
||||||
|
return limits().top();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsScene::addCurveItem(CurveItem *item)
|
||||||
|
{
|
||||||
|
m_dirty = true;
|
||||||
|
addItem(item);
|
||||||
|
item->connect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsScene::setComponentTransform(const QTransform &transform)
|
||||||
|
{
|
||||||
|
QRectF bounds;
|
||||||
|
const auto itemList = items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item))
|
||||||
|
bounds = bounds.united(curveItem->setComponentTransform(transform));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bounds.isNull()) {
|
||||||
|
if (GraphicsView *gview = graphicsView())
|
||||||
|
bounds = gview->defaultRasterRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bounds.isValid())
|
||||||
|
setSceneRect(bounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsScene::keyframeMoved(KeyframeItem *movedItem, const QPointF &direction)
|
||||||
|
{
|
||||||
|
const auto itemList = items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (item == movedItem)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||||
|
if (frameItem->selected())
|
||||||
|
frameItem->moveKeyframe(direction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsScene::handleMoved(KeyframeItem *frame,
|
||||||
|
HandleSlot handle,
|
||||||
|
double angle,
|
||||||
|
double deltaLength)
|
||||||
|
{
|
||||||
|
const auto itemList = items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (item == frame)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||||
|
if (frameItem->selected())
|
||||||
|
frameItem->moveHandle(handle, angle, deltaLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
|
||||||
|
{
|
||||||
|
QGraphicsScene::mouseMoveEvent(mouseEvent);
|
||||||
|
|
||||||
|
if (hasActiveItem())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto itemList = items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item))
|
||||||
|
curveItem->setIsUnderMouse(curveItem->contains(mouseEvent->scenePos()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
|
||||||
|
{
|
||||||
|
QGraphicsScene::mouseReleaseEvent(mouseEvent);
|
||||||
|
|
||||||
|
const auto itemList = items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
|
||||||
|
if (curveItem->contains(mouseEvent->scenePos()))
|
||||||
|
curveItem->setSelected(true);
|
||||||
|
|
||||||
|
if (curveItem->isDirty()) {
|
||||||
|
emit curveChanged(curveItem->id(), curveItem->curve());
|
||||||
|
curveItem->setDirty(false);
|
||||||
|
m_dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsScene::hasActiveKeyframe() const
|
||||||
|
{
|
||||||
|
const auto itemList = items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *kitem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||||
|
if (kitem->activated())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsScene::hasActiveHandle() const
|
||||||
|
{
|
||||||
|
const auto itemList = items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *hitem = qgraphicsitem_cast<HandleItem *>(item)) {
|
||||||
|
if (hitem->activated())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsScene::hasActiveItem() const
|
||||||
|
{
|
||||||
|
return hasActiveKeyframe() || hasActiveHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsView *GraphicsScene::graphicsView() const
|
||||||
|
{
|
||||||
|
const QList<QGraphicsView *> viewList = views();
|
||||||
|
for (auto &&view : viewList) {
|
||||||
|
if (GraphicsView *gview = qobject_cast<GraphicsView *>(view))
|
||||||
|
return gview;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF GraphicsScene::limits() const
|
||||||
|
{
|
||||||
|
if (m_dirty) {
|
||||||
|
QPointF min(std::numeric_limits<double>::max(), std::numeric_limits<double>::max());
|
||||||
|
QPointF max(std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest());
|
||||||
|
|
||||||
|
const auto itemList = items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item)) {
|
||||||
|
auto curve = curveItem->curve();
|
||||||
|
if (min.x() > curve.minimumTime())
|
||||||
|
min.rx() = curve.minimumTime();
|
||||||
|
|
||||||
|
if (min.y() > curve.minimumValue())
|
||||||
|
min.ry() = curve.minimumValue();
|
||||||
|
|
||||||
|
if (max.x() < curve.maximumTime())
|
||||||
|
max.rx() = curve.maximumTime();
|
||||||
|
|
||||||
|
if (max.y() < curve.maximumValue())
|
||||||
|
max.ry() = curve.maximumValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_limits = QRectF(QPointF(min.x(), max.y()), QPointF(max.x(), min.y()));
|
||||||
|
m_dirty = false;
|
||||||
|
}
|
||||||
|
return m_limits;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,89 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "keyframeitem.h"
|
||||||
|
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class AnimationCurve;
|
||||||
|
class CurveItem;
|
||||||
|
class GraphicsView;
|
||||||
|
|
||||||
|
class GraphicsScene : public QGraphicsScene
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void curveChanged(unsigned int id, const AnimationCurve &curve);
|
||||||
|
|
||||||
|
public:
|
||||||
|
GraphicsScene(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
bool empty() const;
|
||||||
|
|
||||||
|
bool hasActiveKeyframe() const;
|
||||||
|
|
||||||
|
bool hasActiveHandle() const;
|
||||||
|
|
||||||
|
bool hasActiveItem() const;
|
||||||
|
|
||||||
|
double minimumTime() const;
|
||||||
|
|
||||||
|
double maximumTime() const;
|
||||||
|
|
||||||
|
double minimumValue() const;
|
||||||
|
|
||||||
|
double maximumValue() const;
|
||||||
|
|
||||||
|
void addCurveItem(CurveItem *item);
|
||||||
|
|
||||||
|
void setComponentTransform(const QTransform &transform);
|
||||||
|
|
||||||
|
void keyframeMoved(KeyframeItem *item, const QPointF &direction);
|
||||||
|
|
||||||
|
void handleMoved(KeyframeItem *frame, HandleSlot handle, double angle, double deltaLength);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
|
||||||
|
|
||||||
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
using QGraphicsScene::addItem;
|
||||||
|
|
||||||
|
GraphicsView *graphicsView() const;
|
||||||
|
|
||||||
|
QRectF limits() const;
|
||||||
|
|
||||||
|
mutable bool m_dirty;
|
||||||
|
|
||||||
|
mutable QRectF m_limits;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,523 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "graphicsview.h"
|
||||||
|
#include "curveeditormodel.h"
|
||||||
|
#include "curveitem.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QResizeEvent>
|
||||||
|
#include <QScrollBar>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
GraphicsView::GraphicsView(CurveEditorModel *model, QWidget *parent)
|
||||||
|
: QGraphicsView(parent)
|
||||||
|
, m_zoomX(0.0)
|
||||||
|
, m_zoomY(0.0)
|
||||||
|
, m_transform()
|
||||||
|
, m_scene()
|
||||||
|
, m_model(model)
|
||||||
|
, m_playhead(this)
|
||||||
|
, m_selector()
|
||||||
|
, m_style(model->style())
|
||||||
|
, m_dialog(m_style)
|
||||||
|
{
|
||||||
|
model->setGraphicsView(this);
|
||||||
|
|
||||||
|
setScene(&m_scene);
|
||||||
|
setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
|
||||||
|
setResizeAnchor(QGraphicsView::NoAnchor);
|
||||||
|
setTransformationAnchor(QGraphicsView::NoAnchor);
|
||||||
|
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||||
|
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||||
|
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
||||||
|
|
||||||
|
connect(&m_dialog, &CurveEditorStyleDialog::styleChanged, this, &GraphicsView::setStyle);
|
||||||
|
|
||||||
|
auto itemSlot = [this](unsigned int id, const AnimationCurve &curve) {
|
||||||
|
applyZoom(m_zoomX, m_zoomY);
|
||||||
|
m_model->setCurve(id, curve);
|
||||||
|
};
|
||||||
|
|
||||||
|
connect(&m_scene, &GraphicsScene::curveChanged, itemSlot);
|
||||||
|
|
||||||
|
applyZoom(m_zoomX, m_zoomY);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
CurveEditorModel *GraphicsView::model() const
|
||||||
|
{
|
||||||
|
return m_model;
|
||||||
|
}
|
||||||
|
|
||||||
|
CurveEditorStyle GraphicsView::editorStyle() const
|
||||||
|
{
|
||||||
|
return m_style;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsView::hasActiveItem() const
|
||||||
|
{
|
||||||
|
return m_scene.hasActiveItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GraphicsView::hasActiveHandle() const
|
||||||
|
{
|
||||||
|
return m_scene.hasActiveHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsView::minimumTime() const
|
||||||
|
{
|
||||||
|
bool check = m_model->minimumTime() < m_scene.minimumTime();
|
||||||
|
return check ? m_model->minimumTime() : m_scene.minimumTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsView::maximumTime() const
|
||||||
|
{
|
||||||
|
bool check = m_model->maximumTime() > m_scene.maximumTime();
|
||||||
|
return check ? m_model->maximumTime() : m_scene.maximumTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsView::minimumValue() const
|
||||||
|
{
|
||||||
|
return m_scene.empty() ? -1.0 : m_scene.minimumValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsView::maximumValue() const
|
||||||
|
{
|
||||||
|
return m_scene.empty() ? 1.0 : m_scene.maximumValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsView::zoomX() const
|
||||||
|
{
|
||||||
|
return m_zoomX;
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsView::zoomY() const
|
||||||
|
{
|
||||||
|
return m_zoomY;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF GraphicsView::canvasRect() const
|
||||||
|
{
|
||||||
|
QRect r = viewport()->rect().adjusted(
|
||||||
|
m_style.valueAxisWidth + m_style.canvasMargin,
|
||||||
|
m_style.timeAxisHeight + m_style.canvasMargin,
|
||||||
|
-m_style.canvasMargin,
|
||||||
|
-m_style.canvasMargin);
|
||||||
|
|
||||||
|
return mapToScene(r).boundingRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF GraphicsView::timeScaleRect() const
|
||||||
|
{
|
||||||
|
QRect vp(viewport()->rect());
|
||||||
|
QPoint tl = vp.topLeft() + QPoint(m_style.valueAxisWidth, 0);
|
||||||
|
QPoint br = vp.topRight() + QPoint(0, m_style.timeAxisHeight);
|
||||||
|
return mapToScene(QRect(tl, br)).boundingRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF GraphicsView::valueScaleRect() const
|
||||||
|
{
|
||||||
|
QRect vp(viewport()->rect());
|
||||||
|
QPoint tl = vp.topLeft() + QPoint(0, m_style.timeAxisHeight);
|
||||||
|
QPoint br = vp.bottomLeft() + QPoint(m_style.valueAxisWidth, 0);
|
||||||
|
return mapToScene(QRect(tl, br)).boundingRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF GraphicsView::defaultRasterRect() const
|
||||||
|
{
|
||||||
|
QPointF topLeft(mapTimeToX(minimumTime()), mapValueToY(maximumValue()));
|
||||||
|
QPointF bottomRight(mapTimeToX(maximumTime()), mapValueToY(minimumValue()));
|
||||||
|
return QRectF(topLeft, bottomRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::setStyle(const CurveEditorStyle &style)
|
||||||
|
{
|
||||||
|
m_style = style;
|
||||||
|
|
||||||
|
const auto itemList = items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *curveItem = qgraphicsitem_cast<CurveItem *>(item))
|
||||||
|
curveItem->setStyle(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
applyZoom(m_zoomX, m_zoomY);
|
||||||
|
viewport()->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::setZoomX(double zoom, const QPoint &pivot)
|
||||||
|
{
|
||||||
|
applyZoom(zoom, m_zoomY, pivot);
|
||||||
|
viewport()->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::setZoomY(double zoom, const QPoint &pivot)
|
||||||
|
{
|
||||||
|
applyZoom(m_zoomX, zoom, pivot);
|
||||||
|
viewport()->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::setCurrentFrame(int frame)
|
||||||
|
{
|
||||||
|
int clampedFrame = clamp(frame, m_model->minimumTime(), m_model->maximumTime());
|
||||||
|
m_playhead.moveToFrame(clampedFrame, this);
|
||||||
|
viewport()->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::scrollContent(double x, double y)
|
||||||
|
{
|
||||||
|
QScrollBar *hs = horizontalScrollBar();
|
||||||
|
QScrollBar *vs = verticalScrollBar();
|
||||||
|
hs->setValue(hs->value() + x);
|
||||||
|
vs->setValue(vs->value() + y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::reset(const std::vector<CurveItem *> &items)
|
||||||
|
{
|
||||||
|
m_scene.clear();
|
||||||
|
for (auto *item : items)
|
||||||
|
m_scene.addCurveItem(item);
|
||||||
|
|
||||||
|
applyZoom(m_zoomX, m_zoomY);
|
||||||
|
viewport()->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::resizeEvent(QResizeEvent *event)
|
||||||
|
{
|
||||||
|
QGraphicsView::resizeEvent(event);
|
||||||
|
applyZoom(m_zoomX, m_zoomY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::keyPressEvent(QKeyEvent *event)
|
||||||
|
{
|
||||||
|
Shortcut shortcut(event->modifiers(), static_cast<Qt::Key>(event->key()));
|
||||||
|
if (shortcut == m_style.shortcuts.frameAll)
|
||||||
|
applyZoom(0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (m_playhead.mousePress(globalToScene(event->globalPos())))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Shortcut shortcut(event);
|
||||||
|
if (shortcut == Shortcut(Qt::LeftButton)) {
|
||||||
|
QPointF pos = mapToScene(event->pos());
|
||||||
|
if (timeScaleRect().contains(pos)) {
|
||||||
|
setCurrentFrame(std::round(mapXtoTime(pos.x())));
|
||||||
|
event->accept();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QGraphicsView::mousePressEvent(event);
|
||||||
|
|
||||||
|
m_selector.mousePress(event, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::mouseMoveEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (m_playhead.mouseMove(globalToScene(event->globalPos()), this))
|
||||||
|
return;
|
||||||
|
|
||||||
|
QGraphicsView::mouseMoveEvent(event);
|
||||||
|
|
||||||
|
m_selector.mouseMove(event, this, m_playhead);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::mouseReleaseEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
QGraphicsView::mouseReleaseEvent(event);
|
||||||
|
|
||||||
|
m_playhead.mouseRelease(this);
|
||||||
|
m_selector.mouseRelease(event, this);
|
||||||
|
this->viewport()->update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::wheelEvent(QWheelEvent *event)
|
||||||
|
{
|
||||||
|
if (event->modifiers().testFlag(Qt::AltModifier))
|
||||||
|
return;
|
||||||
|
|
||||||
|
QGraphicsView::wheelEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::contextMenuEvent(QContextMenuEvent *event)
|
||||||
|
{
|
||||||
|
if (event->modifiers() != Qt::NoModifier)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto openStyleEditor = [this]() { m_dialog.show(); };
|
||||||
|
|
||||||
|
QMenu menu;
|
||||||
|
QAction *openEditorAction = menu.addAction(tr("Open Style Editor"));
|
||||||
|
connect(openEditorAction, &QAction::triggered, openStyleEditor);
|
||||||
|
|
||||||
|
menu.exec(event->globalPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::drawForeground(QPainter *painter, const QRectF &rect)
|
||||||
|
{
|
||||||
|
QRectF abscissa = timeScaleRect();
|
||||||
|
if (abscissa.isValid())
|
||||||
|
drawTimeScale(painter, abscissa);
|
||||||
|
|
||||||
|
auto ordinate = valueScaleRect();
|
||||||
|
if (ordinate.isValid())
|
||||||
|
drawValueScale(painter, ordinate);
|
||||||
|
|
||||||
|
m_playhead.paint(painter, this);
|
||||||
|
|
||||||
|
painter->fillRect(QRectF(rect.topLeft(), abscissa.bottomLeft()),
|
||||||
|
m_style.backgroundAlternateBrush);
|
||||||
|
|
||||||
|
m_selector.paint(painter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::drawBackground(QPainter *painter, const QRectF &rect)
|
||||||
|
{
|
||||||
|
painter->fillRect(rect, m_style.backgroundBrush);
|
||||||
|
painter->fillRect(scene()->sceneRect(), m_style.backgroundAlternateBrush);
|
||||||
|
|
||||||
|
drawGrid(painter, rect);
|
||||||
|
drawExtremaX(painter, rect);
|
||||||
|
drawExtremaY(painter, rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GraphicsView::mapTimeToX(double time) const
|
||||||
|
{
|
||||||
|
return std::round(time * scaleX(m_transform));
|
||||||
|
}
|
||||||
|
|
||||||
|
int GraphicsView::mapValueToY(double y) const
|
||||||
|
{
|
||||||
|
return std::round(y * scaleY(m_transform));
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsView::mapXtoTime(int x) const
|
||||||
|
{
|
||||||
|
return static_cast<double>(x) / scaleX(m_transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsView::mapYtoValue(int y) const
|
||||||
|
{
|
||||||
|
return static_cast<double>(y) / scaleY(m_transform);
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF GraphicsView::globalToScene(const QPoint &point) const
|
||||||
|
{
|
||||||
|
return mapToScene(viewport()->mapFromGlobal(point));
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF GraphicsView::globalToRaster(const QPoint &point) const
|
||||||
|
{
|
||||||
|
QPointF scene = globalToScene(point);
|
||||||
|
return QPointF(mapXtoTime(scene.x()), mapYtoValue(scene.y()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::applyZoom(double x, double y, const QPoint &pivot)
|
||||||
|
{
|
||||||
|
QPointF pivotRaster(globalToRaster(pivot));
|
||||||
|
|
||||||
|
m_zoomX = clamp(x, 0.0, 1.0);
|
||||||
|
m_zoomY = clamp(y, 0.0, 1.0);
|
||||||
|
|
||||||
|
double minTime = minimumTime();
|
||||||
|
double maxTime = maximumTime();
|
||||||
|
|
||||||
|
double minValue = minimumValue();
|
||||||
|
double maxValue = maximumValue();
|
||||||
|
|
||||||
|
QRectF canvas = canvasRect();
|
||||||
|
|
||||||
|
double xZoomedOut = canvas.width() / (maxTime - minTime);
|
||||||
|
double xZoomedIn = m_style.zoomInWidth;
|
||||||
|
double scaleX = lerp(clamp(m_zoomX, 0.0, 1.0), xZoomedOut, xZoomedIn);
|
||||||
|
|
||||||
|
double yZoomedOut = canvas.height() / (maxValue - minValue);
|
||||||
|
double yZoomedIn = m_style.zoomInHeight;
|
||||||
|
double scaleY = lerp(clamp(m_zoomY, 0.0, 1.0), -yZoomedOut, -yZoomedIn);
|
||||||
|
|
||||||
|
m_transform = QTransform::fromScale(scaleX, scaleY);
|
||||||
|
|
||||||
|
m_scene.setComponentTransform(m_transform);
|
||||||
|
|
||||||
|
QRectF sr = m_scene.sceneRect().adjusted(
|
||||||
|
-m_style.valueAxisWidth - m_style.canvasMargin,
|
||||||
|
-m_style.timeAxisHeight - m_style.canvasMargin,
|
||||||
|
m_style.canvasMargin,
|
||||||
|
m_style.canvasMargin);
|
||||||
|
|
||||||
|
setSceneRect(sr);
|
||||||
|
|
||||||
|
m_playhead.resize(this);
|
||||||
|
|
||||||
|
if (!pivot.isNull()) {
|
||||||
|
QPointF deltaTransformed = pivotRaster - globalToRaster(pivot);
|
||||||
|
scrollContent(mapTimeToX(deltaTransformed.x()), mapValueToY(deltaTransformed.y()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::drawGrid(QPainter *painter, const QRectF &rect)
|
||||||
|
{
|
||||||
|
QRectF gridRect = rect.adjusted(
|
||||||
|
m_style.valueAxisWidth + m_style.canvasMargin,
|
||||||
|
m_style.timeAxisHeight + m_style.canvasMargin,
|
||||||
|
-m_style.canvasMargin,
|
||||||
|
-m_style.canvasMargin);
|
||||||
|
|
||||||
|
if (!gridRect.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto drawVerticalLine = [painter, gridRect](double position) {
|
||||||
|
painter->drawLine(position, gridRect.top(), position, gridRect.bottom());
|
||||||
|
};
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
painter->setPen(m_style.gridColor);
|
||||||
|
|
||||||
|
double timeIncrement = timeLabelInterval(painter, m_model->maximumTime());
|
||||||
|
for (double i = minimumTime(); i <= maximumTime(); i += timeIncrement)
|
||||||
|
drawVerticalLine(mapTimeToX(i));
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::drawExtremaX(QPainter *painter, const QRectF &rect)
|
||||||
|
{
|
||||||
|
auto drawVerticalLine = [rect, painter](double position) {
|
||||||
|
painter->drawLine(position, rect.top(), position, rect.bottom());
|
||||||
|
};
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
painter->setPen(Qt::red);
|
||||||
|
drawVerticalLine(mapTimeToX(m_model->minimumTime()));
|
||||||
|
drawVerticalLine(mapTimeToX(m_model->maximumTime()));
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::drawExtremaY(QPainter *painter, const QRectF &rect)
|
||||||
|
{
|
||||||
|
if (m_scene.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto drawHorizontalLine = [rect, painter](double position) {
|
||||||
|
painter->drawLine(rect.left(), position, rect.right(), position);
|
||||||
|
};
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
painter->setPen(Qt::blue);
|
||||||
|
drawHorizontalLine(mapValueToY(m_scene.minimumValue()));
|
||||||
|
drawHorizontalLine(mapValueToY(m_scene.maximumValue()));
|
||||||
|
|
||||||
|
drawHorizontalLine(mapValueToY(0.0));
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::drawTimeScale(QPainter *painter, const QRectF &rect)
|
||||||
|
{
|
||||||
|
painter->save();
|
||||||
|
painter->setPen(m_style.fontColor);
|
||||||
|
painter->fillRect(rect, m_style.backgroundAlternateBrush);
|
||||||
|
|
||||||
|
QFontMetrics fm(painter->font());
|
||||||
|
|
||||||
|
auto paintLabeledTick = [this, painter, rect, fm](double time) {
|
||||||
|
QString timeText = QString("%1").arg(time);
|
||||||
|
|
||||||
|
int position = mapTimeToX(time);
|
||||||
|
|
||||||
|
QRect textRect = fm.boundingRect(timeText);
|
||||||
|
textRect.moveCenter(QPoint(position, rect.center().y()));
|
||||||
|
|
||||||
|
painter->drawText(textRect, Qt::AlignCenter, timeText);
|
||||||
|
painter->drawLine(position, rect.bottom() - 2, position, textRect.bottom() + 2);
|
||||||
|
};
|
||||||
|
|
||||||
|
double timeIncrement = timeLabelInterval(painter, maximumTime());
|
||||||
|
for (double i = minimumTime(); i <= maximumTime(); i += timeIncrement)
|
||||||
|
paintLabeledTick(i);
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GraphicsView::drawValueScale(QPainter *painter, const QRectF &rect)
|
||||||
|
{
|
||||||
|
painter->save();
|
||||||
|
painter->setPen(m_style.fontColor);
|
||||||
|
painter->fillRect(rect, m_style.backgroundAlternateBrush);
|
||||||
|
|
||||||
|
QFontMetrics fm(painter->font());
|
||||||
|
auto paintLabeledTick = [this, painter, rect, fm](double value) {
|
||||||
|
QString valueText = QString("%1").arg(value);
|
||||||
|
|
||||||
|
int position = mapValueToY(value);
|
||||||
|
|
||||||
|
QRect textRect = fm.boundingRect(valueText);
|
||||||
|
textRect.moveCenter(QPoint(rect.center().x(), position));
|
||||||
|
painter->drawText(textRect, Qt::AlignCenter, valueText);
|
||||||
|
};
|
||||||
|
|
||||||
|
paintLabeledTick(minimumValue());
|
||||||
|
paintLabeledTick(maximumValue());
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
double GraphicsView::timeLabelInterval(QPainter *painter, double maxTime)
|
||||||
|
{
|
||||||
|
QFontMetrics fm(painter->font());
|
||||||
|
int minTextSpacing = fm.width(QString("X%1X").arg(maxTime));
|
||||||
|
|
||||||
|
int deltaTime = 1;
|
||||||
|
int nextFactor = 5;
|
||||||
|
|
||||||
|
double tickDistance = mapTimeToX(deltaTime);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (tickDistance == 0 && deltaTime > maxTime)
|
||||||
|
return maxTime;
|
||||||
|
|
||||||
|
if (tickDistance > minTextSpacing)
|
||||||
|
break;
|
||||||
|
|
||||||
|
deltaTime *= nextFactor;
|
||||||
|
tickDistance = mapTimeToX(deltaTime);
|
||||||
|
|
||||||
|
if (nextFactor == 5)
|
||||||
|
nextFactor = 2;
|
||||||
|
else
|
||||||
|
nextFactor = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
return deltaTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,157 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "curveeditorstyle.h"
|
||||||
|
#include "curveeditorstyledialog.h"
|
||||||
|
#include "graphicsscene.h"
|
||||||
|
#include "playhead.h"
|
||||||
|
#include "selector.h"
|
||||||
|
|
||||||
|
#include <QGraphicsView>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class CurveItem;
|
||||||
|
class CurveEditorModel;
|
||||||
|
class Playhead;
|
||||||
|
|
||||||
|
class GraphicsView : public QGraphicsView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend class Playhead;
|
||||||
|
|
||||||
|
public:
|
||||||
|
GraphicsView(CurveEditorModel *model, QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
CurveEditorModel *model() const;
|
||||||
|
|
||||||
|
CurveEditorStyle editorStyle() const;
|
||||||
|
|
||||||
|
bool hasActiveItem() const;
|
||||||
|
|
||||||
|
bool hasActiveHandle() const;
|
||||||
|
|
||||||
|
int mapTimeToX(double time) const;
|
||||||
|
|
||||||
|
int mapValueToY(double value) const;
|
||||||
|
|
||||||
|
double mapXtoTime(int x) const;
|
||||||
|
|
||||||
|
double mapYtoValue(int y) const;
|
||||||
|
|
||||||
|
QPointF globalToScene(const QPoint &point) const;
|
||||||
|
|
||||||
|
QPointF globalToRaster(const QPoint &point) const;
|
||||||
|
|
||||||
|
double minimumTime() const;
|
||||||
|
|
||||||
|
double maximumTime() const;
|
||||||
|
|
||||||
|
double minimumValue() const;
|
||||||
|
|
||||||
|
double maximumValue() const;
|
||||||
|
|
||||||
|
double zoomX() const;
|
||||||
|
|
||||||
|
double zoomY() const;
|
||||||
|
|
||||||
|
QRectF canvasRect() const;
|
||||||
|
|
||||||
|
QRectF timeScaleRect() const;
|
||||||
|
|
||||||
|
QRectF valueScaleRect() const;
|
||||||
|
|
||||||
|
QRectF defaultRasterRect() const;
|
||||||
|
|
||||||
|
void setStyle(const CurveEditorStyle &style);
|
||||||
|
|
||||||
|
void setZoomX(double zoom, const QPoint &pivot = QPoint());
|
||||||
|
|
||||||
|
void setZoomY(double zoom, const QPoint &pivot = QPoint());
|
||||||
|
|
||||||
|
void setCurrentFrame(int frame);
|
||||||
|
|
||||||
|
void scrollContent(double x, double y);
|
||||||
|
|
||||||
|
void reset(const std::vector<CurveItem *> &items);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
||||||
|
void keyPressEvent(QKeyEvent *event) override;
|
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
|
void mouseMoveEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
|
void wheelEvent(QWheelEvent *event) override;
|
||||||
|
|
||||||
|
void contextMenuEvent(QContextMenuEvent *event) override;
|
||||||
|
|
||||||
|
void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||||
|
|
||||||
|
void drawBackground(QPainter *painter, const QRectF &rect) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void applyZoom(double x, double y, const QPoint &pivot = QPoint());
|
||||||
|
|
||||||
|
void drawGrid(QPainter *painter, const QRectF &rect);
|
||||||
|
|
||||||
|
void drawExtremaX(QPainter *painter, const QRectF &rect);
|
||||||
|
|
||||||
|
void drawExtremaY(QPainter *painter, const QRectF &rect);
|
||||||
|
|
||||||
|
void drawTimeScale(QPainter *painter, const QRectF &rect);
|
||||||
|
|
||||||
|
void drawValueScale(QPainter *painter, const QRectF &rect);
|
||||||
|
|
||||||
|
double timeLabelInterval(QPainter *painter, double maxTime);
|
||||||
|
|
||||||
|
private:
|
||||||
|
double m_zoomX;
|
||||||
|
|
||||||
|
double m_zoomY;
|
||||||
|
|
||||||
|
QTransform m_transform;
|
||||||
|
|
||||||
|
GraphicsScene m_scene;
|
||||||
|
|
||||||
|
CurveEditorModel *m_model;
|
||||||
|
|
||||||
|
Playhead m_playhead;
|
||||||
|
|
||||||
|
Selector m_selector;
|
||||||
|
|
||||||
|
CurveEditorStyle m_style;
|
||||||
|
|
||||||
|
CurveEditorStyleDialog m_dialog;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,104 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "handleitem.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
struct HandleGeometry
|
||||||
|
{
|
||||||
|
HandleGeometry(const QPointF &pos, const HandleItemStyleOption &style)
|
||||||
|
{
|
||||||
|
QPointF topLeft(-style.size / 2.0, -style.size / 2.0);
|
||||||
|
handle = QRectF(topLeft, -topLeft);
|
||||||
|
toKeyframe = QLineF(QPointF(0.0, 0.0), -pos);
|
||||||
|
angle = -toKeyframe.angle() + 45.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF handle;
|
||||||
|
|
||||||
|
QLineF toKeyframe;
|
||||||
|
|
||||||
|
double angle;
|
||||||
|
};
|
||||||
|
|
||||||
|
HandleItem::HandleItem(QGraphicsItem *parent)
|
||||||
|
: SelectableItem(parent)
|
||||||
|
, m_style()
|
||||||
|
{
|
||||||
|
setFlag(QGraphicsItem::ItemStacksBehindParent, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleItem::~HandleItem() {}
|
||||||
|
|
||||||
|
int HandleItem::type() const
|
||||||
|
{
|
||||||
|
return Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF HandleItem::boundingRect() const
|
||||||
|
{
|
||||||
|
HandleGeometry geom(pos(), m_style);
|
||||||
|
|
||||||
|
QTransform transform;
|
||||||
|
transform.rotate(geom.angle);
|
||||||
|
|
||||||
|
QRectF bounds = bbox(geom.handle, transform);
|
||||||
|
grow(bounds, -pos());
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
Q_UNUSED(option);
|
||||||
|
Q_UNUSED(widget);
|
||||||
|
|
||||||
|
QColor handleColor(isSelected() ? m_style.selectionColor : m_style.color);
|
||||||
|
|
||||||
|
HandleGeometry geom(pos(), m_style);
|
||||||
|
|
||||||
|
QPen pen = painter->pen();
|
||||||
|
pen.setWidthF(m_style.lineWidth);
|
||||||
|
pen.setColor(handleColor);
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
painter->setPen(pen);
|
||||||
|
|
||||||
|
painter->drawLine(geom.toKeyframe);
|
||||||
|
painter->rotate(geom.angle);
|
||||||
|
painter->fillRect(geom.handle, handleColor);
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleItem::setStyle(const CurveEditorStyle &style)
|
||||||
|
{
|
||||||
|
m_style = style.handleStyle;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,56 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "curveeditorstyle.h"
|
||||||
|
#include "selectableitem.h"
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class HandleItem : public SelectableItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
HandleItem(QGraphicsItem *parent);
|
||||||
|
|
||||||
|
~HandleItem() override;
|
||||||
|
|
||||||
|
enum { Type = ItemTypeHandle };
|
||||||
|
|
||||||
|
int type() const override;
|
||||||
|
|
||||||
|
QRectF boundingRect() const override;
|
||||||
|
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||||
|
|
||||||
|
void setStyle(const CurveEditorStyle &style);
|
||||||
|
|
||||||
|
private:
|
||||||
|
HandleItemStyleOption m_style;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,251 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "keyframeitem.h"
|
||||||
|
#include "handleitem.h"
|
||||||
|
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
KeyframeItem::KeyframeItem(QGraphicsItem *parent)
|
||||||
|
: SelectableItem(parent)
|
||||||
|
, m_frame()
|
||||||
|
{}
|
||||||
|
|
||||||
|
KeyframeItem::KeyframeItem(const Keyframe &keyframe, QGraphicsItem *parent)
|
||||||
|
: SelectableItem(parent)
|
||||||
|
, m_transform()
|
||||||
|
, m_frame(keyframe)
|
||||||
|
, m_left(keyframe.hasLeftHandle() ? new HandleItem(this) : nullptr)
|
||||||
|
, m_right(keyframe.hasRightHandle() ? new HandleItem(this) : nullptr)
|
||||||
|
{
|
||||||
|
auto updatePosition = [this]() { this->updatePosition(true); };
|
||||||
|
connect(this, &QGraphicsObject::xChanged, updatePosition);
|
||||||
|
connect(this, &QGraphicsObject::yChanged, updatePosition);
|
||||||
|
|
||||||
|
if (m_left) {
|
||||||
|
m_left->setPos(m_frame.leftHandle() - m_frame.position());
|
||||||
|
auto updateLeftHandle = [this]() { updateHandle(m_left); };
|
||||||
|
connect(m_left, &QGraphicsObject::xChanged, updateLeftHandle);
|
||||||
|
connect(m_left, &QGraphicsObject::yChanged, updateLeftHandle);
|
||||||
|
m_left->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_right) {
|
||||||
|
m_right->setPos(m_frame.rightHandle() - m_frame.position());
|
||||||
|
auto updateRightHandle = [this]() { updateHandle(m_right); };
|
||||||
|
connect(m_right, &QGraphicsObject::xChanged, updateRightHandle);
|
||||||
|
connect(m_right, &QGraphicsObject::yChanged, updateRightHandle);
|
||||||
|
m_right->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
setPos(m_frame.position());
|
||||||
|
}
|
||||||
|
|
||||||
|
int KeyframeItem::type() const
|
||||||
|
{
|
||||||
|
return Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF KeyframeItem::boundingRect() const
|
||||||
|
{
|
||||||
|
QPointF topLeft(-m_style.size / 2.0, -m_style.size / 2.0);
|
||||||
|
return QRectF(topLeft, -topLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyframeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||||
|
{
|
||||||
|
Q_UNUSED(option);
|
||||||
|
Q_UNUSED(widget);
|
||||||
|
|
||||||
|
QPen pen = painter->pen();
|
||||||
|
pen.setColor(Qt::black);
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
painter->setPen(pen);
|
||||||
|
painter->setBrush(selected() ? Qt::red : m_style.color);
|
||||||
|
painter->drawEllipse(boundingRect());
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyframeItem::~KeyframeItem() {}
|
||||||
|
|
||||||
|
Keyframe KeyframeItem::keyframe() const
|
||||||
|
{
|
||||||
|
return m_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyframeItem::setComponentTransform(const QTransform &transform)
|
||||||
|
{
|
||||||
|
m_transform = transform;
|
||||||
|
|
||||||
|
if (m_left)
|
||||||
|
m_left->setPos(m_transform.map(m_frame.leftHandle() - m_frame.position()));
|
||||||
|
|
||||||
|
if (m_right)
|
||||||
|
m_right->setPos(m_transform.map(m_frame.rightHandle() - m_frame.position()));
|
||||||
|
|
||||||
|
setPos(m_transform.map(m_frame.position()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyframeItem::setStyle(const CurveEditorStyle &style)
|
||||||
|
{
|
||||||
|
m_style = style.keyframeStyle;
|
||||||
|
|
||||||
|
if (m_left)
|
||||||
|
m_left->setStyle(style);
|
||||||
|
|
||||||
|
if (m_right)
|
||||||
|
m_right->setStyle(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyframeItem::updatePosition(bool update)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
QPointF position = m_transform.inverted(&ok).map(pos());
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPointF oldPosition = m_frame.position();
|
||||||
|
m_frame.setPosition(position);
|
||||||
|
|
||||||
|
if (m_left)
|
||||||
|
updateHandle(m_left, false);
|
||||||
|
|
||||||
|
if (m_right)
|
||||||
|
updateHandle(m_right, false);
|
||||||
|
|
||||||
|
if (update) {
|
||||||
|
emit redrawCurve();
|
||||||
|
emit keyframeMoved(this, position - oldPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyframeItem::moveKeyframe(const QPointF &direction)
|
||||||
|
{
|
||||||
|
this->blockSignals(true);
|
||||||
|
setPos(m_transform.map(m_frame.position() + direction));
|
||||||
|
updatePosition(false);
|
||||||
|
this->blockSignals(false);
|
||||||
|
emit redrawCurve();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyframeItem::moveHandle(HandleSlot handle, double deltaAngle, double deltaLength)
|
||||||
|
{
|
||||||
|
auto move = [this, deltaAngle, deltaLength](HandleItem *item) {
|
||||||
|
QLineF current(QPointF(0.0, 0.0), item->pos());
|
||||||
|
current.setAngle(current.angle() + deltaAngle);
|
||||||
|
current.setLength(current.length() + deltaLength);
|
||||||
|
item->setPos(current.p2());
|
||||||
|
updateHandle(item, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
this->blockSignals(true);
|
||||||
|
|
||||||
|
if (handle == HandleSlot::Left)
|
||||||
|
move(m_left);
|
||||||
|
else if (handle == HandleSlot::Right)
|
||||||
|
move(m_right);
|
||||||
|
|
||||||
|
this->blockSignals(false);
|
||||||
|
|
||||||
|
emit redrawCurve();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyframeItem::updateHandle(HandleItem *handle, bool emitChanged)
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
QPointF handlePosition = m_transform.inverted(&ok).map(handle->pos());
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPointF oldPosition;
|
||||||
|
QPointF newPosition;
|
||||||
|
HandleSlot slot = HandleSlot::Undefined;
|
||||||
|
if (handle == m_left) {
|
||||||
|
slot = HandleSlot::Left;
|
||||||
|
oldPosition = m_frame.leftHandle();
|
||||||
|
m_frame.setLeftHandle(m_frame.position() + handlePosition);
|
||||||
|
newPosition = m_frame.leftHandle();
|
||||||
|
} else {
|
||||||
|
slot = HandleSlot::Right;
|
||||||
|
oldPosition = m_frame.rightHandle();
|
||||||
|
m_frame.setRightHandle(m_frame.position() + handlePosition);
|
||||||
|
newPosition = m_frame.rightHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emitChanged) {
|
||||||
|
QLineF oldLine(m_frame.position(), oldPosition);
|
||||||
|
QLineF newLine(m_frame.position(), newPosition);
|
||||||
|
|
||||||
|
QLineF mappedOld = m_transform.map(oldLine);
|
||||||
|
QLineF mappedNew = m_transform.map(newLine);
|
||||||
|
|
||||||
|
auto angle = mappedOld.angleTo(mappedNew);
|
||||||
|
auto deltaLength = mappedNew.length() - mappedOld.length();
|
||||||
|
|
||||||
|
emit redrawCurve();
|
||||||
|
emit handleMoved(this, slot, angle, deltaLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant KeyframeItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value)
|
||||||
|
{
|
||||||
|
if (change == ItemPositionChange) {
|
||||||
|
bool ok;
|
||||||
|
QPointF position = m_transform.inverted(&ok).map(value.toPointF());
|
||||||
|
if (ok) {
|
||||||
|
position.setX(std::round(position.x()));
|
||||||
|
return QVariant(m_transform.map(position));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QGraphicsItem::itemChange(change, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyframeItem::selectionCallback()
|
||||||
|
{
|
||||||
|
auto setHandleVisibility = [](HandleItem *handle, bool visible) {
|
||||||
|
if (handle)
|
||||||
|
handle->setVisible(visible);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (selected()) {
|
||||||
|
setHandleVisibility(m_left, true);
|
||||||
|
setHandleVisibility(m_right, true);
|
||||||
|
} else {
|
||||||
|
setHandleVisibility(m_left, false);
|
||||||
|
setHandleVisibility(m_right, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,98 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "curveeditorstyle.h"
|
||||||
|
#include "keyframe.h"
|
||||||
|
#include "selectableitem.h"
|
||||||
|
|
||||||
|
#include <QGraphicsObject>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class HandleItem;
|
||||||
|
|
||||||
|
enum class HandleSlot { Undefined, Left, Right };
|
||||||
|
|
||||||
|
class KeyframeItem : public SelectableItem
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void redrawCurve();
|
||||||
|
|
||||||
|
void keyframeMoved(KeyframeItem *item, const QPointF &direction);
|
||||||
|
|
||||||
|
void handleMoved(KeyframeItem *frame, HandleSlot handle, double angle, double deltaLength);
|
||||||
|
|
||||||
|
public:
|
||||||
|
KeyframeItem(QGraphicsItem *parent = nullptr);
|
||||||
|
|
||||||
|
KeyframeItem(const Keyframe &keyframe, QGraphicsItem *parent = nullptr);
|
||||||
|
|
||||||
|
~KeyframeItem() override;
|
||||||
|
|
||||||
|
enum { Type = ItemTypeKeyframe };
|
||||||
|
|
||||||
|
int type() const override;
|
||||||
|
|
||||||
|
QRectF boundingRect() const override;
|
||||||
|
|
||||||
|
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override;
|
||||||
|
|
||||||
|
Keyframe keyframe() const;
|
||||||
|
|
||||||
|
void setComponentTransform(const QTransform &transform);
|
||||||
|
|
||||||
|
void setStyle(const CurveEditorStyle &style);
|
||||||
|
|
||||||
|
void moveKeyframe(const QPointF &direction);
|
||||||
|
|
||||||
|
void moveHandle(HandleSlot handle, double deltaAngle, double deltaLength);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
|
||||||
|
|
||||||
|
void selectionCallback() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updatePosition(bool emit = true);
|
||||||
|
|
||||||
|
void updateHandle(HandleItem *handle, bool emit = true);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTransform m_transform;
|
||||||
|
|
||||||
|
KeyframeItemStyleOption m_style;
|
||||||
|
|
||||||
|
Keyframe m_frame;
|
||||||
|
|
||||||
|
HandleItem *m_left;
|
||||||
|
|
||||||
|
HandleItem *m_right;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,187 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "playhead.h"
|
||||||
|
#include "curveeditormodel.h"
|
||||||
|
#include "graphicsview.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QGraphicsScene>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
constexpr double g_playheadMargin = 5.0;
|
||||||
|
|
||||||
|
Playhead::Playhead(GraphicsView *view)
|
||||||
|
: m_frame(0)
|
||||||
|
, m_moving(false)
|
||||||
|
, m_rect()
|
||||||
|
, m_timer()
|
||||||
|
{
|
||||||
|
m_timer.setSingleShot(true);
|
||||||
|
m_timer.setInterval(30);
|
||||||
|
QObject::connect(&m_timer, &QTimer::timeout, view, [this, view]() {
|
||||||
|
if (QApplication::mouseButtons() == Qt::LeftButton)
|
||||||
|
mouseMoveOutOfBounds(view);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int Playhead::currentFrame() const
|
||||||
|
{
|
||||||
|
return m_frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playhead::moveToFrame(int frame, GraphicsView *view)
|
||||||
|
{
|
||||||
|
m_frame = frame;
|
||||||
|
m_rect.moveCenter(QPointF(view->mapTimeToX(m_frame), m_rect.center().y()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playhead::resize(GraphicsView *view)
|
||||||
|
{
|
||||||
|
QRectF viewRect = view->mapToScene(view->viewport()->rect()).boundingRect();
|
||||||
|
|
||||||
|
CurveEditorStyle style = view->editorStyle();
|
||||||
|
|
||||||
|
QPointF tlr(style.valueAxisWidth, style.timeAxisHeight - style.playhead.width);
|
||||||
|
QPointF brr(style.valueAxisWidth + style.playhead.width, -g_playheadMargin);
|
||||||
|
|
||||||
|
QPointF tl = viewRect.topLeft() + tlr;
|
||||||
|
QPointF br = viewRect.bottomLeft() + brr;
|
||||||
|
|
||||||
|
m_rect = QRectF(tl, br);
|
||||||
|
|
||||||
|
moveToFrame(m_frame, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Playhead::mousePress(const QPointF &pos)
|
||||||
|
{
|
||||||
|
QRectF hitRect = m_rect;
|
||||||
|
hitRect.setBottom(hitRect.top() + hitRect.width());
|
||||||
|
|
||||||
|
m_moving = hitRect.contains(pos);
|
||||||
|
|
||||||
|
return m_moving;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Playhead::mouseMove(const QPointF &pos, GraphicsView *view)
|
||||||
|
{
|
||||||
|
if (m_moving) {
|
||||||
|
CurveEditorStyle style = view->editorStyle();
|
||||||
|
|
||||||
|
QRectF canvas = view->canvasRect().adjusted(0.0, -style.timeAxisHeight, 0.0, 0.0);
|
||||||
|
|
||||||
|
if (canvas.contains(pos))
|
||||||
|
view->setCurrentFrame(std::round(view->mapXtoTime(pos.x())));
|
||||||
|
else if (!m_timer.isActive())
|
||||||
|
m_timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_moving;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playhead::mouseMoveOutOfBounds(GraphicsView *view)
|
||||||
|
{
|
||||||
|
if (QApplication::mouseButtons() != Qt::LeftButton)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CurveEditorStyle style = view->editorStyle();
|
||||||
|
QRectF canvas = view->canvasRect();
|
||||||
|
QPointF pos = view->globalToScene(QCursor::pos());
|
||||||
|
|
||||||
|
if (pos.x() > canvas.right()) {
|
||||||
|
double speed = (pos.x() - canvas.right());
|
||||||
|
double nextCenter = m_rect.center().x() + speed;
|
||||||
|
double frame = std::round(view->mapXtoTime(nextCenter));
|
||||||
|
view->setCurrentFrame(frame);
|
||||||
|
|
||||||
|
double framePosition = view->mapTimeToX(frame);
|
||||||
|
double rightSideOut = framePosition + style.playhead.width / 2.0 + style.canvasMargin;
|
||||||
|
double overshoot = rightSideOut - canvas.right();
|
||||||
|
view->scrollContent(overshoot, 0.0);
|
||||||
|
|
||||||
|
} else if (pos.x() < canvas.left()) {
|
||||||
|
double speed = (canvas.left() - pos.x());
|
||||||
|
double nextCenter = m_rect.center().x() - speed;
|
||||||
|
double frame = std::round(view->mapXtoTime(nextCenter));
|
||||||
|
view->setCurrentFrame(frame);
|
||||||
|
|
||||||
|
double framePosition = view->mapTimeToX(frame);
|
||||||
|
double leftSideOut = framePosition - style.playhead.width / 2.0 - style.canvasMargin;
|
||||||
|
double undershoot = canvas.left() - leftSideOut;
|
||||||
|
view->scrollContent(-undershoot, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_timer.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playhead::mouseRelease(GraphicsView *view)
|
||||||
|
{
|
||||||
|
if (m_moving)
|
||||||
|
emit view->model()->currentFrameChanged(m_frame);
|
||||||
|
|
||||||
|
m_moving = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Playhead::paint(QPainter *painter, GraphicsView *view) const
|
||||||
|
{
|
||||||
|
CurveEditorStyle style = view->editorStyle();
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
painter->setPen(style.playhead.color);
|
||||||
|
painter->setRenderHint(QPainter::Antialiasing, true);
|
||||||
|
|
||||||
|
QRectF rect = m_rect;
|
||||||
|
rect.setBottom(m_rect.top() + m_rect.width());
|
||||||
|
|
||||||
|
QPointF top(rect.center().x(), rect.top());
|
||||||
|
QPointF right(rect.right(), rect.top());
|
||||||
|
QPointF bottom(rect.center().x(), rect.bottom());
|
||||||
|
QPointF left(rect.left(), rect.top());
|
||||||
|
|
||||||
|
QLineF rightToBottom(right, bottom);
|
||||||
|
rightToBottom.setLength(style.playhead.radius);
|
||||||
|
|
||||||
|
QLineF leftToBottom(left, bottom);
|
||||||
|
leftToBottom.setLength(style.playhead.radius);
|
||||||
|
|
||||||
|
QPainterPath path(top);
|
||||||
|
path.lineTo(right - QPointF(style.playhead.radius, 0.));
|
||||||
|
path.quadTo(right, rightToBottom.p2());
|
||||||
|
path.lineTo(bottom);
|
||||||
|
path.lineTo(leftToBottom.p2());
|
||||||
|
path.quadTo(left, left + QPointF(style.playhead.radius, 0.));
|
||||||
|
path.closeSubpath();
|
||||||
|
|
||||||
|
painter->fillPath(path, style.playhead.color);
|
||||||
|
painter->drawLine(top + QPointF(0., 5.), QPointF(m_rect.center().x(), m_rect.bottom()));
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,72 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QRectF>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QPainter;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class GraphicsView;
|
||||||
|
|
||||||
|
class Playhead
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Playhead(GraphicsView *view);
|
||||||
|
|
||||||
|
int currentFrame() const;
|
||||||
|
|
||||||
|
void paint(QPainter *painter, GraphicsView *view) const;
|
||||||
|
|
||||||
|
void moveToFrame(int frame, GraphicsView *view);
|
||||||
|
|
||||||
|
void resize(GraphicsView *view);
|
||||||
|
|
||||||
|
bool mousePress(const QPointF &pos);
|
||||||
|
|
||||||
|
bool mouseMove(const QPointF &pos, GraphicsView *view);
|
||||||
|
|
||||||
|
void mouseRelease(GraphicsView *view);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void mouseMoveOutOfBounds(GraphicsView *view);
|
||||||
|
|
||||||
|
int m_frame;
|
||||||
|
|
||||||
|
bool m_moving;
|
||||||
|
|
||||||
|
QRectF m_rect;
|
||||||
|
|
||||||
|
QTimer m_timer;
|
||||||
|
|
||||||
|
GraphicsView *m_view;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,112 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "selectableitem.h"
|
||||||
|
#include "keyframeitem.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
SelectableItem::SelectableItem(QGraphicsItem *parent)
|
||||||
|
: QGraphicsObject(parent)
|
||||||
|
, m_active(false)
|
||||||
|
, m_selected(false)
|
||||||
|
, m_preSelected(SelectionMode::Undefined)
|
||||||
|
{
|
||||||
|
setFlag(QGraphicsItem::ItemIsSelectable, false);
|
||||||
|
|
||||||
|
setFlag(QGraphicsItem::ItemIsMovable, true);
|
||||||
|
setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
|
||||||
|
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectableItem::~SelectableItem() {}
|
||||||
|
|
||||||
|
bool SelectableItem::activated() const
|
||||||
|
{
|
||||||
|
return m_active;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SelectableItem::selected() const
|
||||||
|
{
|
||||||
|
switch (m_preSelected) {
|
||||||
|
case SelectionMode::Clear:
|
||||||
|
return false;
|
||||||
|
case SelectionMode::New:
|
||||||
|
return true;
|
||||||
|
case SelectionMode::Add:
|
||||||
|
return true;
|
||||||
|
case SelectionMode::Remove:
|
||||||
|
return false;
|
||||||
|
case SelectionMode::Toggle:
|
||||||
|
return !m_selected;
|
||||||
|
default:
|
||||||
|
return m_selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableItem::setActivated(bool active)
|
||||||
|
{
|
||||||
|
m_active = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableItem::setPreselected(SelectionMode mode)
|
||||||
|
{
|
||||||
|
m_preSelected = mode;
|
||||||
|
selectionCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableItem::applyPreselection()
|
||||||
|
{
|
||||||
|
m_selected = selected();
|
||||||
|
m_preSelected = SelectionMode::Undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableItem::selectionCallback() {}
|
||||||
|
|
||||||
|
void SelectableItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
m_active = true;
|
||||||
|
QGraphicsObject::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (type() == KeyframeItem::Type && !selected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QGraphicsObject::mouseMoveEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectableItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
|
||||||
|
{
|
||||||
|
m_active = false;
|
||||||
|
QGraphicsObject::mouseReleaseEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,85 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QGraphicsObject>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
enum ItemType
|
||||||
|
{
|
||||||
|
ItemTypeKeyframe = QGraphicsItem::UserType + 1,
|
||||||
|
ItemTypeHandle = QGraphicsItem::UserType + 2,
|
||||||
|
ItemTypeCurve = QGraphicsItem::UserType + 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SelectionMode : unsigned int
|
||||||
|
{
|
||||||
|
Undefined,
|
||||||
|
Clear,
|
||||||
|
New,
|
||||||
|
Add,
|
||||||
|
Remove,
|
||||||
|
Toggle
|
||||||
|
};
|
||||||
|
|
||||||
|
class SelectableItem : public QGraphicsObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
SelectableItem(QGraphicsItem *parent = nullptr);
|
||||||
|
|
||||||
|
~SelectableItem() override;
|
||||||
|
|
||||||
|
bool activated() const;
|
||||||
|
|
||||||
|
bool selected() const;
|
||||||
|
|
||||||
|
void setActivated(bool active);
|
||||||
|
|
||||||
|
void setPreselected(SelectionMode mode);
|
||||||
|
|
||||||
|
void applyPreselection();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void selectionCallback();
|
||||||
|
|
||||||
|
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||||
|
|
||||||
|
void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
|
||||||
|
|
||||||
|
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_active;
|
||||||
|
|
||||||
|
bool m_selected;
|
||||||
|
|
||||||
|
SelectionMode m_preSelected;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,221 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#include "selector.h"
|
||||||
|
#include "graphicsview.h"
|
||||||
|
#include "keyframeitem.h"
|
||||||
|
#include "playhead.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
Selector::Selector() {}
|
||||||
|
|
||||||
|
void Selector::paint(QPainter *painter)
|
||||||
|
{
|
||||||
|
QPen pen(Qt::white);
|
||||||
|
|
||||||
|
painter->save();
|
||||||
|
painter->setPen(pen);
|
||||||
|
|
||||||
|
if (!m_lasso.isEmpty())
|
||||||
|
painter->drawPath(m_lasso);
|
||||||
|
|
||||||
|
if (!m_rect.isNull())
|
||||||
|
painter->drawRect(m_rect);
|
||||||
|
|
||||||
|
painter->restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Selector::mousePress(QMouseEvent *event, GraphicsView *view)
|
||||||
|
{
|
||||||
|
m_shortcut = Shortcut(event);
|
||||||
|
|
||||||
|
if (view->hasActiveHandle())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (select(SelectionTool::Undefined, view->globalToScene(event->globalPos()), view))
|
||||||
|
applyPreSelection(view);
|
||||||
|
|
||||||
|
m_mouseInit = event->globalPos();
|
||||||
|
m_mouseCurr = event->globalPos();
|
||||||
|
|
||||||
|
QPointF click = view->globalToScene(m_mouseInit);
|
||||||
|
|
||||||
|
m_lasso = QPainterPath(click);
|
||||||
|
m_lasso.closeSubpath();
|
||||||
|
|
||||||
|
m_rect = QRectF(click, click);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Selector::mouseMove(QMouseEvent *event, GraphicsView *view, Playhead &playhead)
|
||||||
|
{
|
||||||
|
if (m_mouseInit.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QPointF delta = event->globalPos() - m_mouseInit;
|
||||||
|
if (delta.manhattanLength() < QApplication::startDragDistance())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_shortcut == m_shortcuts.newSelection || m_shortcut == m_shortcuts.addToSelection
|
||||||
|
|| m_shortcut == m_shortcuts.removeFromSelection
|
||||||
|
|| m_shortcut == m_shortcuts.toggleSelection) {
|
||||||
|
if (view->hasActiveItem())
|
||||||
|
return;
|
||||||
|
|
||||||
|
select(m_tool, view->globalToScene(event->globalPos()), view);
|
||||||
|
|
||||||
|
event->accept();
|
||||||
|
view->viewport()->update();
|
||||||
|
|
||||||
|
} else if (m_shortcut == m_shortcuts.zoom) {
|
||||||
|
double bigger = std::abs(delta.x()) > std::abs(delta.y()) ? delta.x() : delta.y();
|
||||||
|
double factor = bigger / view->width();
|
||||||
|
view->setZoomX(view->zoomX() + factor, m_mouseInit);
|
||||||
|
m_mouseCurr = event->globalPos();
|
||||||
|
event->accept();
|
||||||
|
|
||||||
|
} else if (m_shortcut == m_shortcuts.pan) {
|
||||||
|
view->scrollContent(-delta.x(), -delta.y());
|
||||||
|
playhead.resize(view);
|
||||||
|
m_mouseCurr = event->globalPos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Selector::mouseRelease(QMouseEvent *event, GraphicsView *view)
|
||||||
|
{
|
||||||
|
Q_UNUSED(event);
|
||||||
|
|
||||||
|
applyPreSelection(view);
|
||||||
|
|
||||||
|
m_shortcut = Shortcut();
|
||||||
|
m_mouseInit = QPoint();
|
||||||
|
m_mouseCurr = QPoint();
|
||||||
|
m_lasso = QPainterPath();
|
||||||
|
m_rect = QRectF();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Selector::select(const SelectionTool &tool, const QPointF &pos, GraphicsView *view)
|
||||||
|
{
|
||||||
|
auto selectWidthTool = [this, tool](SelectionMode mode, const QPointF &pos, GraphicsView *view) {
|
||||||
|
switch (tool) {
|
||||||
|
case SelectionTool::Lasso:
|
||||||
|
return lassoSelection(mode, pos, view);
|
||||||
|
case SelectionTool::Rectangle:
|
||||||
|
return rectangleSelection(mode, pos, view);
|
||||||
|
default:
|
||||||
|
return pressSelection(mode, pos, view);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (m_shortcut == m_shortcuts.newSelection) {
|
||||||
|
clearSelection(view);
|
||||||
|
return selectWidthTool(SelectionMode::New, pos, view);
|
||||||
|
} else if (m_shortcut == m_shortcuts.addToSelection) {
|
||||||
|
return selectWidthTool(SelectionMode::Add, pos, view);
|
||||||
|
} else if (m_shortcut == m_shortcuts.removeFromSelection) {
|
||||||
|
return selectWidthTool(SelectionMode::Remove, pos, view);
|
||||||
|
} else if (m_shortcut == m_shortcuts.toggleSelection) {
|
||||||
|
return selectWidthTool(SelectionMode::Toggle, pos, view);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Selector::pressSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view)
|
||||||
|
{
|
||||||
|
bool out = false;
|
||||||
|
const auto itemList = view->items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *frame = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||||
|
QRectF itemRect = frame->mapRectToScene(frame->boundingRect());
|
||||||
|
if (itemRect.contains(pos)) {
|
||||||
|
frame->setPreselected(mode);
|
||||||
|
out = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Selector::rectangleSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view)
|
||||||
|
{
|
||||||
|
bool out = false;
|
||||||
|
m_rect.setBottomRight(pos);
|
||||||
|
const auto itemList = view->items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||||
|
if (m_rect.contains(keyframeItem->pos())) {
|
||||||
|
keyframeItem->setPreselected(mode);
|
||||||
|
out = true;
|
||||||
|
} else {
|
||||||
|
keyframeItem->setPreselected(SelectionMode::Undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Selector::lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view)
|
||||||
|
{
|
||||||
|
bool out = false;
|
||||||
|
m_lasso.lineTo(pos);
|
||||||
|
const auto itemList = view->items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||||
|
if (m_lasso.contains(keyframeItem->pos())) {
|
||||||
|
keyframeItem->setPreselected(mode);
|
||||||
|
out = true;
|
||||||
|
} else {
|
||||||
|
keyframeItem->setPreselected(SelectionMode::Undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Selector::clearSelection(GraphicsView *view)
|
||||||
|
{
|
||||||
|
const auto itemList = view->items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *frameItem = qgraphicsitem_cast<KeyframeItem *>(item)) {
|
||||||
|
frameItem->setPreselected(SelectionMode::Clear);
|
||||||
|
frameItem->applyPreselection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Selector::applyPreSelection(GraphicsView *view)
|
||||||
|
{
|
||||||
|
const auto itemList = view->items();
|
||||||
|
for (auto *item : itemList) {
|
||||||
|
if (auto *keyframeItem = qgraphicsitem_cast<KeyframeItem *>(item))
|
||||||
|
keyframeItem->applyPreselection();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,86 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "curveeditorstyle.h"
|
||||||
|
#include "selectableitem.h"
|
||||||
|
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QPainterPath>
|
||||||
|
#include <QPoint>
|
||||||
|
#include <QRectF>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class GraphicsView;
|
||||||
|
class Playhead;
|
||||||
|
|
||||||
|
enum class SelectionTool { Undefined, Lasso, Rectangle };
|
||||||
|
|
||||||
|
class Selector
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Selector();
|
||||||
|
|
||||||
|
void paint(QPainter *painter);
|
||||||
|
|
||||||
|
void mousePress(QMouseEvent *event, GraphicsView *view);
|
||||||
|
|
||||||
|
void mouseMove(QMouseEvent *event, GraphicsView *view, Playhead &playhead);
|
||||||
|
|
||||||
|
void mouseRelease(QMouseEvent *event, GraphicsView *view);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool select(const SelectionTool &tool, const QPointF &pos, GraphicsView *view);
|
||||||
|
|
||||||
|
bool pressSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view);
|
||||||
|
|
||||||
|
bool rectangleSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view);
|
||||||
|
|
||||||
|
bool lassoSelection(SelectionMode mode, const QPointF &pos, GraphicsView *view);
|
||||||
|
|
||||||
|
void clearSelection(GraphicsView *view);
|
||||||
|
|
||||||
|
void applyPreSelection(GraphicsView *view);
|
||||||
|
|
||||||
|
Shortcuts m_shortcuts = Shortcuts();
|
||||||
|
|
||||||
|
Shortcut m_shortcut;
|
||||||
|
|
||||||
|
SelectionMode m_mode = SelectionMode::Undefined;
|
||||||
|
|
||||||
|
SelectionTool m_tool = SelectionTool::Rectangle;
|
||||||
|
|
||||||
|
QPoint m_mouseInit = QPoint();
|
||||||
|
|
||||||
|
QPoint m_mouseCurr = QPoint();
|
||||||
|
|
||||||
|
QPainterPath m_lasso = QPainterPath();
|
||||||
|
|
||||||
|
QRectF m_rect = QRectF();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,81 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#include "shortcut.h"
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
Shortcut::Shortcut()
|
||||||
|
: m_key()
|
||||||
|
, m_buttons()
|
||||||
|
, m_modifiers()
|
||||||
|
{}
|
||||||
|
|
||||||
|
Shortcut::Shortcut(QMouseEvent *event)
|
||||||
|
: m_key()
|
||||||
|
, m_buttons(event->buttons())
|
||||||
|
, m_modifiers(event->modifiers())
|
||||||
|
{}
|
||||||
|
|
||||||
|
Shortcut::Shortcut(const Qt::KeyboardModifiers &mods, const Qt::Key &key)
|
||||||
|
: m_key(key)
|
||||||
|
, m_buttons()
|
||||||
|
, m_modifiers(mods)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Shortcut::Shortcut(const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &mods)
|
||||||
|
: m_key()
|
||||||
|
, m_buttons(buttons)
|
||||||
|
, m_modifiers(mods)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Shortcut::Shortcut(const Qt::MouseButtons &buttons,
|
||||||
|
const Qt::KeyboardModifiers &mods,
|
||||||
|
const Qt::Key &key)
|
||||||
|
: m_key(key)
|
||||||
|
, m_buttons(buttons)
|
||||||
|
, m_modifiers(mods)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool Shortcut::exactMatch(const Qt::Key &key) const
|
||||||
|
{
|
||||||
|
return m_key == key;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shortcut::exactMatch(const Qt::MouseButton &button) const
|
||||||
|
{
|
||||||
|
return static_cast<int>(m_buttons) == static_cast<int>(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shortcut::exactMatch(const Qt::KeyboardModifier &modifier) const
|
||||||
|
{
|
||||||
|
return static_cast<int>(m_modifiers) == static_cast<int>(modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shortcut::operator==(const Shortcut &other) const
|
||||||
|
{
|
||||||
|
return m_key == other.m_key && m_buttons == other.m_buttons && m_modifiers == other.m_modifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,61 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QMouseEvent>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class Shortcut
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Shortcut();
|
||||||
|
|
||||||
|
Shortcut(QMouseEvent *event);
|
||||||
|
|
||||||
|
Shortcut(const Qt::KeyboardModifiers &mods, const Qt::Key &key);
|
||||||
|
|
||||||
|
Shortcut(const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &mods = Qt::NoModifier);
|
||||||
|
|
||||||
|
Shortcut(const Qt::MouseButtons &buttons, const Qt::KeyboardModifiers &mods, const Qt::Key &key);
|
||||||
|
|
||||||
|
bool exactMatch(const Qt::Key &key) const;
|
||||||
|
|
||||||
|
bool exactMatch(const Qt::MouseButton &button) const;
|
||||||
|
|
||||||
|
bool exactMatch(const Qt::KeyboardModifier &modifier) const;
|
||||||
|
|
||||||
|
bool operator==(const Shortcut &other) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Qt::Key m_key;
|
||||||
|
|
||||||
|
Qt::MouseButtons m_buttons;
|
||||||
|
|
||||||
|
Qt::KeyboardModifiers m_modifiers;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,146 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#include "treeitemdelegate.h"
|
||||||
|
#include "treeitem.h"
|
||||||
|
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
TreeItemDelegate::TreeItemDelegate(const CurveEditorStyle &style, QObject *parent)
|
||||||
|
: QStyledItemDelegate(parent)
|
||||||
|
, m_style(style)
|
||||||
|
{}
|
||||||
|
|
||||||
|
QSize TreeItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
return QStyledItemDelegate::sizeHint(option, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeItemDelegate::paint(QPainter *painter,
|
||||||
|
const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (index.column() == 1 || index.column() == 2) {
|
||||||
|
|
||||||
|
int height = option.rect.size().height();
|
||||||
|
QRect iconRect(QPoint(0, 0), QSize(height, height));
|
||||||
|
iconRect.moveCenter(option.rect.center());
|
||||||
|
|
||||||
|
auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
|
||||||
|
if (option.state & QStyle::State_MouseOver && iconRect.contains(m_mousePos)) {
|
||||||
|
|
||||||
|
painter->fillRect(option.rect, option.backgroundBrush);
|
||||||
|
|
||||||
|
if (index.column() == 1) {
|
||||||
|
|
||||||
|
if (treeItem->locked()) {
|
||||||
|
|
||||||
|
QPixmap pixmap = pixmapFromIcon(
|
||||||
|
m_style.treeItemStyle.unlockedIcon,
|
||||||
|
iconRect.size(),
|
||||||
|
m_style.fontColor);
|
||||||
|
|
||||||
|
painter->drawPixmap(iconRect, pixmap);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
QPixmap pixmap = pixmapFromIcon(
|
||||||
|
m_style.treeItemStyle.lockedIcon,
|
||||||
|
iconRect.size(),
|
||||||
|
m_style.fontColor);
|
||||||
|
|
||||||
|
painter->drawPixmap(iconRect, pixmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (index.column() == 2) {
|
||||||
|
|
||||||
|
if (treeItem->pinned()) {
|
||||||
|
|
||||||
|
QPixmap pixmap = pixmapFromIcon(
|
||||||
|
m_style.treeItemStyle.unpinnedIcon,
|
||||||
|
iconRect.size(),
|
||||||
|
m_style.fontColor);
|
||||||
|
|
||||||
|
painter->drawPixmap(iconRect, pixmap);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
QPixmap pixmap = pixmapFromIcon(
|
||||||
|
m_style.treeItemStyle.pinnedIcon,
|
||||||
|
iconRect.size(),
|
||||||
|
m_style.fontColor);
|
||||||
|
|
||||||
|
painter->drawPixmap(iconRect, pixmap);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (treeItem->locked() && index.column() == 1) {
|
||||||
|
|
||||||
|
QPixmap pixmap = pixmapFromIcon(
|
||||||
|
m_style.treeItemStyle.lockedIcon,
|
||||||
|
iconRect.size(),
|
||||||
|
m_style.fontColor);
|
||||||
|
|
||||||
|
painter->drawPixmap(iconRect, pixmap);
|
||||||
|
|
||||||
|
} else if (treeItem->pinned() && index.column() == 2) {
|
||||||
|
|
||||||
|
QPixmap pixmap = pixmapFromIcon(
|
||||||
|
m_style.treeItemStyle.pinnedIcon,
|
||||||
|
iconRect.size(),
|
||||||
|
m_style.fontColor);
|
||||||
|
|
||||||
|
painter->drawPixmap(iconRect, pixmap);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QStyledItemDelegate::paint(painter, option, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeItemDelegate::setStyle(const CurveEditorStyle &style)
|
||||||
|
{
|
||||||
|
m_style = style;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TreeItemDelegate::editorEvent(QEvent *event,
|
||||||
|
QAbstractItemModel *model,
|
||||||
|
const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::MouseMove)
|
||||||
|
m_mousePos = static_cast<QMouseEvent *>(event)->pos();
|
||||||
|
|
||||||
|
return QStyledItemDelegate::editorEvent(event, model, option, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,63 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "curveeditorstyle.h"
|
||||||
|
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class TreeItemDelegate : public QStyledItemDelegate
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TreeItemDelegate(const CurveEditorStyle &style, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||||
|
|
||||||
|
void paint(
|
||||||
|
QPainter *painter,
|
||||||
|
const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const override;
|
||||||
|
|
||||||
|
void setStyle(const CurveEditorStyle &style);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool editorEvent(
|
||||||
|
QEvent *event,
|
||||||
|
QAbstractItemModel *model,
|
||||||
|
const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
CurveEditorStyle m_style;
|
||||||
|
|
||||||
|
QPoint m_mousePos;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,156 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "treemodel.h"
|
||||||
|
#include "treeitem.h"
|
||||||
|
#include "detail/graphicsview.h"
|
||||||
|
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
TreeModel::TreeModel(QObject *parent)
|
||||||
|
: QAbstractItemModel(parent)
|
||||||
|
, m_view(nullptr)
|
||||||
|
, m_root(new TreeItem("Root"))
|
||||||
|
{}
|
||||||
|
|
||||||
|
TreeModel::~TreeModel()
|
||||||
|
{
|
||||||
|
if (m_root) {
|
||||||
|
delete m_root;
|
||||||
|
m_root = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_view = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TreeModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
TreeItem *item = static_cast<TreeItem *>(index.internalPointer());
|
||||||
|
|
||||||
|
if (role == Qt::DecorationRole && index.column() == 0)
|
||||||
|
return item->icon();
|
||||||
|
|
||||||
|
if (role != Qt::DisplayRole)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
return item->data(index.column());
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TreeModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (role != Qt::DisplayRole)
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if (orientation == Qt::Horizontal)
|
||||||
|
return m_root->headerData(section);
|
||||||
|
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (!hasIndex(row, column, parent))
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
TreeItem *parentItem = m_root;
|
||||||
|
|
||||||
|
if (parent.isValid())
|
||||||
|
parentItem = static_cast<TreeItem *>(parent.internalPointer());
|
||||||
|
|
||||||
|
if (TreeItem *childItem = parentItem->child(row))
|
||||||
|
return createIndex(row, column, childItem);
|
||||||
|
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex TreeModel::parent(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
if (!index.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
TreeItem *childItem = static_cast<TreeItem *>(index.internalPointer());
|
||||||
|
|
||||||
|
if (TreeItem *parentItem = childItem->parent()) {
|
||||||
|
if (parentItem == m_root)
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
return createIndex(parentItem->row(), 0, parentItem);
|
||||||
|
}
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
int TreeModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (parent.column() > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
TreeItem *parentItem = m_root;
|
||||||
|
|
||||||
|
if (parent.isValid())
|
||||||
|
parentItem = static_cast<TreeItem *>(parent.internalPointer());
|
||||||
|
|
||||||
|
return parentItem->rowCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
int TreeModel::columnCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
return m_root->columnCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeModel::setGraphicsView(GraphicsView *view)
|
||||||
|
{
|
||||||
|
m_view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsView *TreeModel::graphicsView() const
|
||||||
|
{
|
||||||
|
return m_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeModel::initialize()
|
||||||
|
{
|
||||||
|
if (m_root)
|
||||||
|
delete m_root;
|
||||||
|
|
||||||
|
m_root = new TreeItem("Root");
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeItem *TreeModel::root()
|
||||||
|
{
|
||||||
|
return m_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeItem *TreeModel::find(unsigned int id)
|
||||||
|
{
|
||||||
|
return m_root->find(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,75 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class GraphicsView;
|
||||||
|
class TreeItem;
|
||||||
|
|
||||||
|
class TreeModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TreeModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
~TreeModel() override;
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
QModelIndex parent(const QModelIndex &index) const override;
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
void setGraphicsView(GraphicsView *view);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
GraphicsView *graphicsView() const;
|
||||||
|
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
TreeItem *root();
|
||||||
|
|
||||||
|
TreeItem *find(unsigned int id);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GraphicsView *m_view;
|
||||||
|
|
||||||
|
TreeItem *m_root;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,127 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
#include "treeview.h"
|
||||||
|
#include "curveeditormodel.h"
|
||||||
|
#include "curveitem.h"
|
||||||
|
#include "treeitem.h"
|
||||||
|
#include "treeitemdelegate.h"
|
||||||
|
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
TreeView::TreeView(CurveEditorModel *model, QWidget *parent)
|
||||||
|
: QTreeView(parent)
|
||||||
|
{
|
||||||
|
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
|
||||||
|
setUniformRowHeights(true);
|
||||||
|
setRootIsDecorated(false);
|
||||||
|
setMouseTracking(true);
|
||||||
|
setHeaderHidden(true);
|
||||||
|
|
||||||
|
model->setParent(this);
|
||||||
|
setModel(model);
|
||||||
|
|
||||||
|
auto expandItems = [this]() { expandAll(); };
|
||||||
|
connect(model, &QAbstractItemModel::modelReset, expandItems);
|
||||||
|
|
||||||
|
auto *delegate = new TreeItemDelegate(model->style(), this);
|
||||||
|
setItemDelegate(delegate);
|
||||||
|
|
||||||
|
setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
|
||||||
|
connect(selectionModel(), &QItemSelectionModel::selectionChanged, this, &TreeView::changeSelection);
|
||||||
|
setStyle(model->style());
|
||||||
|
|
||||||
|
header()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||||
|
header()->setSectionResizeMode(1, QHeaderView::Fixed);
|
||||||
|
header()->setSectionResizeMode(2, QHeaderView::Fixed);
|
||||||
|
|
||||||
|
header()->setStretchLastSection(false);
|
||||||
|
header()->resizeSection(1, 20);
|
||||||
|
header()->resizeSection(2, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeView::setStyle(const CurveEditorStyle &style)
|
||||||
|
{
|
||||||
|
QPalette pal = palette();
|
||||||
|
pal.setBrush(QPalette::Base, style.backgroundBrush);
|
||||||
|
pal.setBrush(QPalette::Button, style.backgroundAlternateBrush);
|
||||||
|
pal.setBrush(QPalette::Text, style.fontColor);
|
||||||
|
|
||||||
|
// Tmp to see what happens on windows/macOS.
|
||||||
|
pal.setBrush(backgroundRole(), Qt::white);
|
||||||
|
pal.setBrush(foregroundRole(), Qt::white);
|
||||||
|
|
||||||
|
setPalette(pal);
|
||||||
|
|
||||||
|
if (auto *delegate = qobject_cast<TreeItemDelegate *>(itemDelegate()))
|
||||||
|
delegate->setStyle(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeView::changeCurve(unsigned int id, const AnimationCurve &curve)
|
||||||
|
{
|
||||||
|
if (auto *curveModel = qobject_cast<CurveEditorModel *>(model()))
|
||||||
|
curveModel->setCurve(id, curve);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeView::changeSelection(const QItemSelection &selected, const QItemSelection &deselected)
|
||||||
|
{
|
||||||
|
Q_UNUSED(selected);
|
||||||
|
Q_UNUSED(deselected);
|
||||||
|
|
||||||
|
std::vector<CurveItem *> curves;
|
||||||
|
for (auto index : selectedIndexes()) {
|
||||||
|
if (index.isValid() && index.column() == 0) {
|
||||||
|
auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
|
||||||
|
if (auto *propertyItem = treeItem->asPropertyItem())
|
||||||
|
curves.push_back(new CurveItem(treeItem->id(), propertyItem->curve()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit curvesSelected(curves);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize TreeView::sizeHint() const
|
||||||
|
{
|
||||||
|
return QSize(170, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeView::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
QModelIndex index = indexAt(event->pos());
|
||||||
|
if (index.isValid()) {
|
||||||
|
auto *treeItem = static_cast<TreeItem *>(index.internalPointer());
|
||||||
|
if (index.column() == 1)
|
||||||
|
treeItem->setLocked(!treeItem->locked());
|
||||||
|
else if (index.column() == 2)
|
||||||
|
treeItem->setPinned(!treeItem->pinned());
|
||||||
|
}
|
||||||
|
QTreeView::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -0,0 +1,61 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QTreeView>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class AnimationCurve;
|
||||||
|
class CurveEditorModel;
|
||||||
|
class CurveItem;
|
||||||
|
|
||||||
|
struct CurveEditorStyle;
|
||||||
|
|
||||||
|
class TreeView : public QTreeView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void curvesSelected(const std::vector<CurveItem *> &curves);
|
||||||
|
|
||||||
|
public:
|
||||||
|
TreeView(CurveEditorModel *model, QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
void changeCurve(unsigned int id, const AnimationCurve &curve);
|
||||||
|
|
||||||
|
void setStyle(const CurveEditorStyle &style);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
|
||||||
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void changeSelection(const QItemSelection &selected, const QItemSelection &deselected);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
107
src/plugins/qmldesigner/components/curveeditor/detail/utils.cpp
Normal file
107
src/plugins/qmldesigner/components/curveeditor/detail/utils.cpp
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <QPalette>
|
||||||
|
#include <QPointF>
|
||||||
|
#include <QRectF>
|
||||||
|
#include <QTransform>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
double clamp(double val, double lo, double hi)
|
||||||
|
{
|
||||||
|
return val < lo ? lo : (val > hi ? hi : val);
|
||||||
|
}
|
||||||
|
|
||||||
|
double lerp(double blend, double a, double b)
|
||||||
|
{
|
||||||
|
return (1.0 - blend) * a + blend * b;
|
||||||
|
}
|
||||||
|
|
||||||
|
double scaleX(const QTransform &transform)
|
||||||
|
{
|
||||||
|
return transform.m11();
|
||||||
|
}
|
||||||
|
|
||||||
|
double scaleY(const QTransform &transform)
|
||||||
|
{
|
||||||
|
return transform.m22();
|
||||||
|
}
|
||||||
|
|
||||||
|
void grow(QRectF &rect, const QPointF &point)
|
||||||
|
{
|
||||||
|
if (rect.left() > point.x())
|
||||||
|
rect.setLeft(point.x());
|
||||||
|
|
||||||
|
if (rect.right() < point.x())
|
||||||
|
rect.setRight(point.x());
|
||||||
|
|
||||||
|
if (rect.top() > point.y())
|
||||||
|
rect.setTop(point.y());
|
||||||
|
|
||||||
|
if (rect.bottom() < point.y())
|
||||||
|
rect.setBottom(point.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF bbox(const QRectF &rect, const QTransform &transform)
|
||||||
|
{
|
||||||
|
QRectF out = rect;
|
||||||
|
grow(out, transform.map(rect.topLeft()));
|
||||||
|
grow(out, transform.map(rect.topRight()));
|
||||||
|
grow(out, transform.map(rect.bottomLeft()));
|
||||||
|
grow(out, transform.map(rect.bottomRight()));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPalette singleColorPalette(const QColor &color)
|
||||||
|
{
|
||||||
|
QPalette palette;
|
||||||
|
palette.setColor(QPalette::Window, color);
|
||||||
|
palette.setColor(QPalette::Background, color);
|
||||||
|
palette.setColor(QPalette::WindowText, color);
|
||||||
|
palette.setColor(QPalette::Foreground, color);
|
||||||
|
palette.setColor(QPalette::Base, color);
|
||||||
|
palette.setColor(QPalette::AlternateBase, color);
|
||||||
|
palette.setColor(QPalette::ToolTipBase, color);
|
||||||
|
palette.setColor(QPalette::ToolTipText, color);
|
||||||
|
palette.setColor(QPalette::Text, color);
|
||||||
|
|
||||||
|
palette.setColor(QPalette::Button, color);
|
||||||
|
palette.setColor(QPalette::ButtonText, color);
|
||||||
|
palette.setColor(QPalette::BrightText, color);
|
||||||
|
palette.setColor(QPalette::Light, color);
|
||||||
|
palette.setColor(QPalette::Midlight, color);
|
||||||
|
palette.setColor(QPalette::Dark, color);
|
||||||
|
palette.setColor(QPalette::Mid, color);
|
||||||
|
palette.setColor(QPalette::Shadow, color);
|
||||||
|
palette.setColor(QPalette::Highlight, color);
|
||||||
|
palette.setColor(QPalette::HighlightedText, color);
|
||||||
|
palette.setColor(QPalette::Link, color);
|
||||||
|
palette.setColor(QPalette::LinkVisited, color);
|
||||||
|
return palette;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -1,9 +1,9 @@
|
|||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
**
|
**
|
||||||
** Copyright (C) 2016 The Qt Company Ltd.
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
** Contact: https://www.qt.io/licensing/
|
** Contact: https://www.qt.io/licensing/
|
||||||
**
|
**
|
||||||
** This file is part of Qt Creator.
|
** This file is part of the Qt Design Tooling
|
||||||
**
|
**
|
||||||
** Commercial License Usage
|
** Commercial License Usage
|
||||||
** Licensees holding valid commercial Qt licenses may use this file in
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
@@ -25,10 +25,28 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QtGlobal>
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QColor;
|
||||||
|
class QPalette;
|
||||||
|
class QPointF;
|
||||||
|
class QRectF;
|
||||||
|
class QTransform;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#if defined(QMLDESIGNEREXTENSION_LIBRARY)
|
namespace DesignTools {
|
||||||
# define QMLDESIGNEREXTENSIONSHARED_EXPORT Q_DECL_EXPORT
|
|
||||||
#else
|
double clamp(double val, double lo, double hi);
|
||||||
# define QMLDESIGNEREXTENSIONSHARED_EXPORT Q_DECL_IMPORT
|
|
||||||
#endif
|
double lerp(double blend, double a, double b);
|
||||||
|
|
||||||
|
double scaleX(const QTransform &transform);
|
||||||
|
|
||||||
|
double scaleY(const QTransform &transform);
|
||||||
|
|
||||||
|
void grow(QRectF &rect, const QPointF &point);
|
||||||
|
|
||||||
|
QRectF bbox(const QRectF &rect, const QTransform &transform);
|
||||||
|
|
||||||
|
QPalette singleColorPalette(const QColor &color);
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
88
src/plugins/qmldesigner/components/curveeditor/keyframe.cpp
Normal file
88
src/plugins/qmldesigner/components/curveeditor/keyframe.cpp
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "keyframe.h"
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
Keyframe::Keyframe()
|
||||||
|
: m_position()
|
||||||
|
, m_leftHandle()
|
||||||
|
, m_rightHandle()
|
||||||
|
{}
|
||||||
|
|
||||||
|
Keyframe::Keyframe(const QPointF &position)
|
||||||
|
: m_position(position)
|
||||||
|
, m_leftHandle()
|
||||||
|
, m_rightHandle()
|
||||||
|
{}
|
||||||
|
|
||||||
|
Keyframe::Keyframe(const QPointF &position, const QPointF &leftHandle, const QPointF &rightHandle)
|
||||||
|
: m_position(position)
|
||||||
|
, m_leftHandle(leftHandle)
|
||||||
|
, m_rightHandle(rightHandle)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool Keyframe::hasLeftHandle() const
|
||||||
|
{
|
||||||
|
return !m_leftHandle.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Keyframe::hasRightHandle() const
|
||||||
|
{
|
||||||
|
return !m_rightHandle.isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF Keyframe::position() const
|
||||||
|
{
|
||||||
|
return m_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF Keyframe::leftHandle() const
|
||||||
|
{
|
||||||
|
return m_leftHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF Keyframe::rightHandle() const
|
||||||
|
{
|
||||||
|
return m_rightHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyframe::setPosition(const QPointF &pos)
|
||||||
|
{
|
||||||
|
m_position = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyframe::setLeftHandle(const QPointF &pos)
|
||||||
|
{
|
||||||
|
m_leftHandle = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Keyframe::setRightHandle(const QPointF &pos)
|
||||||
|
{
|
||||||
|
m_rightHandle = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
65
src/plugins/qmldesigner/components/curveeditor/keyframe.h
Normal file
65
src/plugins/qmldesigner/components/curveeditor/keyframe.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QPointF>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class Keyframe
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Keyframe();
|
||||||
|
|
||||||
|
Keyframe(const QPointF &position);
|
||||||
|
|
||||||
|
Keyframe(const QPointF &position, const QPointF &leftHandle, const QPointF &rightHandle);
|
||||||
|
|
||||||
|
bool hasLeftHandle() const;
|
||||||
|
|
||||||
|
bool hasRightHandle() const;
|
||||||
|
|
||||||
|
QPointF position() const;
|
||||||
|
|
||||||
|
QPointF leftHandle() const;
|
||||||
|
|
||||||
|
QPointF rightHandle() const;
|
||||||
|
|
||||||
|
void setPosition(const QPointF &pos);
|
||||||
|
|
||||||
|
void setLeftHandle(const QPointF &pos);
|
||||||
|
|
||||||
|
void setRightHandle(const QPointF &pos);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPointF m_position;
|
||||||
|
|
||||||
|
QPointF m_leftHandle;
|
||||||
|
|
||||||
|
QPointF m_rightHandle;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
227
src/plugins/qmldesigner/components/curveeditor/treeitem.cpp
Normal file
227
src/plugins/qmldesigner/components/curveeditor/treeitem.cpp
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "treeitem.h"
|
||||||
|
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
TreeItem::TreeItem(const QString &name)
|
||||||
|
: m_name(name)
|
||||||
|
, m_id(0)
|
||||||
|
, m_locked(false)
|
||||||
|
, m_pinned(false)
|
||||||
|
, m_parent(nullptr)
|
||||||
|
, m_children()
|
||||||
|
{}
|
||||||
|
|
||||||
|
TreeItem::~TreeItem()
|
||||||
|
{
|
||||||
|
m_parent = nullptr;
|
||||||
|
|
||||||
|
qDeleteAll(m_children);
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon TreeItem::icon() const
|
||||||
|
{
|
||||||
|
return QIcon();
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeTreeItem *TreeItem::asNodeItem()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
PropertyTreeItem *TreeItem::asPropertyItem()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int TreeItem::id() const
|
||||||
|
{
|
||||||
|
return m_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TreeItem::locked() const
|
||||||
|
{
|
||||||
|
return m_locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TreeItem::pinned() const
|
||||||
|
{
|
||||||
|
return m_pinned;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TreeItem::row() const
|
||||||
|
{
|
||||||
|
if (m_parent) {
|
||||||
|
for (size_t i = 0; i < m_parent->m_children.size(); ++i) {
|
||||||
|
if (m_parent->m_children[i] == this)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TreeItem::column() const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TreeItem::rowCount() const
|
||||||
|
{
|
||||||
|
return m_children.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
int TreeItem::columnCount() const
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeItem *TreeItem::parent() const
|
||||||
|
{
|
||||||
|
return m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeItem *TreeItem::child(int row) const
|
||||||
|
{
|
||||||
|
if (row < 0 || row >= static_cast<int>(m_children.size()))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return m_children.at(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeItem *TreeItem::find(unsigned int id) const
|
||||||
|
{
|
||||||
|
for (auto *child : m_children) {
|
||||||
|
if (child->id() == id)
|
||||||
|
return child;
|
||||||
|
|
||||||
|
if (auto *childsChild = child->find(id))
|
||||||
|
return childsChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TreeItem::data(int column) const
|
||||||
|
{
|
||||||
|
switch (column) {
|
||||||
|
case 0:
|
||||||
|
return QVariant(m_name);
|
||||||
|
case 1:
|
||||||
|
return QVariant(m_locked);
|
||||||
|
case 2:
|
||||||
|
return QVariant(m_pinned);
|
||||||
|
case 3:
|
||||||
|
return QVariant(m_id);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TreeItem::headerData(int column) const
|
||||||
|
{
|
||||||
|
switch (column) {
|
||||||
|
case 0:
|
||||||
|
return QString("Name");
|
||||||
|
case 1:
|
||||||
|
return QString("L");
|
||||||
|
case 2:
|
||||||
|
return QString("P");
|
||||||
|
case 3:
|
||||||
|
return QString("Id");
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeItem::setId(unsigned int &id)
|
||||||
|
{
|
||||||
|
m_id = id;
|
||||||
|
|
||||||
|
for (auto *child : m_children)
|
||||||
|
child->setId(++id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeItem::addChild(TreeItem *child)
|
||||||
|
{
|
||||||
|
child->m_parent = this;
|
||||||
|
m_children.push_back(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeItem::setLocked(bool locked)
|
||||||
|
{
|
||||||
|
m_locked = locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TreeItem::setPinned(bool pinned)
|
||||||
|
{
|
||||||
|
m_pinned = pinned;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NodeTreeItem::NodeTreeItem(const QString &name, const QIcon &icon)
|
||||||
|
: TreeItem(name)
|
||||||
|
, m_icon(icon)
|
||||||
|
{
|
||||||
|
Q_UNUSED(icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeTreeItem *NodeTreeItem::asNodeItem()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
QIcon NodeTreeItem::icon() const
|
||||||
|
{
|
||||||
|
return m_icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PropertyTreeItem::PropertyTreeItem(const QString &name, const AnimationCurve &curve)
|
||||||
|
: TreeItem(name)
|
||||||
|
, m_curve(curve)
|
||||||
|
{}
|
||||||
|
|
||||||
|
PropertyTreeItem *PropertyTreeItem::asPropertyItem()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimationCurve PropertyTreeItem::curve() const
|
||||||
|
{
|
||||||
|
return m_curve;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PropertyTreeItem::setCurve(const AnimationCurve &curve)
|
||||||
|
{
|
||||||
|
m_curve = curve;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
137
src/plugins/qmldesigner/components/curveeditor/treeitem.h
Normal file
137
src/plugins/qmldesigner/components/curveeditor/treeitem.h
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2019 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of the Qt Design Tooling
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "animationcurve.h"
|
||||||
|
|
||||||
|
#include <QIcon>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QIcon;
|
||||||
|
class QVariant;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace DesignTools {
|
||||||
|
|
||||||
|
class NodeTreeItem;
|
||||||
|
class PropertyTreeItem;
|
||||||
|
|
||||||
|
class TreeItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TreeItem(const QString &name);
|
||||||
|
|
||||||
|
virtual ~TreeItem();
|
||||||
|
|
||||||
|
virtual QIcon icon() const;
|
||||||
|
|
||||||
|
virtual NodeTreeItem *asNodeItem();
|
||||||
|
|
||||||
|
virtual PropertyTreeItem *asPropertyItem();
|
||||||
|
|
||||||
|
unsigned int id() const;
|
||||||
|
|
||||||
|
bool locked() const;
|
||||||
|
|
||||||
|
bool pinned() const;
|
||||||
|
|
||||||
|
int row() const;
|
||||||
|
|
||||||
|
int column() const;
|
||||||
|
|
||||||
|
int rowCount() const;
|
||||||
|
|
||||||
|
int columnCount() const;
|
||||||
|
|
||||||
|
TreeItem *parent() const;
|
||||||
|
|
||||||
|
TreeItem *child(int row) const;
|
||||||
|
|
||||||
|
TreeItem *find(unsigned int row) const;
|
||||||
|
|
||||||
|
QVariant data(int column) const;
|
||||||
|
|
||||||
|
QVariant headerData(int column) const;
|
||||||
|
|
||||||
|
void setId(unsigned int &id);
|
||||||
|
|
||||||
|
void addChild(TreeItem *child);
|
||||||
|
|
||||||
|
void setLocked(bool locked);
|
||||||
|
|
||||||
|
void setPinned(bool pinned);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QString m_name;
|
||||||
|
|
||||||
|
unsigned int m_id;
|
||||||
|
|
||||||
|
bool m_locked;
|
||||||
|
|
||||||
|
bool m_pinned;
|
||||||
|
|
||||||
|
TreeItem *m_parent;
|
||||||
|
|
||||||
|
std::vector<TreeItem *> m_children;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class NodeTreeItem : public TreeItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NodeTreeItem(const QString &name, const QIcon &icon);
|
||||||
|
|
||||||
|
NodeTreeItem *asNodeItem() override;
|
||||||
|
|
||||||
|
QIcon icon() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QIcon m_icon;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PropertyTreeItem : public TreeItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PropertyTreeItem(const QString &name, const AnimationCurve &curve);
|
||||||
|
|
||||||
|
PropertyTreeItem *asPropertyItem() override;
|
||||||
|
|
||||||
|
AnimationCurve curve() const;
|
||||||
|
|
||||||
|
void setCurve(const AnimationCurve &curve);
|
||||||
|
|
||||||
|
private:
|
||||||
|
using TreeItem::addChild;
|
||||||
|
|
||||||
|
AnimationCurve m_curve;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace DesignTools.
|
@@ -246,14 +246,29 @@ Qt::ItemFlags NavigatorTreeModel::flags(const QModelIndex &index) const
|
|||||||
| Qt::ItemNeverHasChildren;
|
| Qt::ItemNeverHasChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void static appendForcedNodes(const NodeListProperty &property, QList<ModelNode> &list)
|
||||||
|
{
|
||||||
|
const QStringList visibleProperties = NodeHints::fromModelNode(property.parentModelNode()).visibleNonDefaultProperties();
|
||||||
|
for (const ModelNode &node : property.parentModelNode().directSubModelNodes()) {
|
||||||
|
if (!list.contains(node) && visibleProperties.contains(QString::fromUtf8(node.parentProperty().name())))
|
||||||
|
list.append(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QList<ModelNode> filteredList(const NodeListProperty &property, bool filter)
|
QList<ModelNode> filteredList(const NodeListProperty &property, bool filter)
|
||||||
{
|
{
|
||||||
if (!filter)
|
if (!filter)
|
||||||
return property.toModelNodeList();
|
return property.toModelNodeList();
|
||||||
|
|
||||||
return Utils::filtered(property.toModelNodeList(), [] (const ModelNode &arg) {
|
QList<ModelNode> list;
|
||||||
|
|
||||||
|
list.append(Utils::filtered(property.toModelNodeList(), [] (const ModelNode &arg) {
|
||||||
return QmlItemNode::isValidQmlItemNode(arg) || NodeHints::fromModelNode(arg).visibleInNavigator();
|
return QmlItemNode::isValidQmlItemNode(arg) || NodeHints::fromModelNode(arg).visibleInNavigator();
|
||||||
});
|
}));
|
||||||
|
|
||||||
|
appendForcedNodes(property, list);
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex NavigatorTreeModel::index(int row, int column,
|
QModelIndex NavigatorTreeModel::index(int row, int column,
|
||||||
@@ -431,7 +446,8 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
|
|||||||
static bool findTargetProperty(const QModelIndex &rowModelIndex,
|
static bool findTargetProperty(const QModelIndex &rowModelIndex,
|
||||||
NavigatorTreeModel *navigatorTreeModel,
|
NavigatorTreeModel *navigatorTreeModel,
|
||||||
NodeAbstractProperty *targetProperty,
|
NodeAbstractProperty *targetProperty,
|
||||||
int *targetRowNumber)
|
int *targetRowNumber,
|
||||||
|
const PropertyName &propertyName = {})
|
||||||
{
|
{
|
||||||
QModelIndex targetItemIndex;
|
QModelIndex targetItemIndex;
|
||||||
PropertyName targetPropertyName;
|
PropertyName targetPropertyName;
|
||||||
@@ -445,7 +461,10 @@ static bool findTargetProperty(const QModelIndex &rowModelIndex,
|
|||||||
if (!targetNode.metaInfo().hasDefaultProperty())
|
if (!targetNode.metaInfo().hasDefaultProperty())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
targetPropertyName = targetNode.metaInfo().defaultPropertyName();
|
if (propertyName.isEmpty() || !targetNode.metaInfo().hasProperty(propertyName))
|
||||||
|
targetPropertyName = targetNode.metaInfo().defaultPropertyName();
|
||||||
|
else
|
||||||
|
targetPropertyName = propertyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disallow dropping items between properties, which are listed first.
|
// Disallow dropping items between properties, which are listed first.
|
||||||
@@ -494,26 +513,30 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
|
|||||||
int targetRowNumber = rowNumber;
|
int targetRowNumber = rowNumber;
|
||||||
NodeAbstractProperty targetProperty;
|
NodeAbstractProperty targetProperty;
|
||||||
|
|
||||||
bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber);
|
const ItemLibraryEntry itemLibraryEntry =
|
||||||
|
createItemLibraryEntryFromMimeData(mimeData->data("application/vnd.bauhaus.itemlibraryinfo"));
|
||||||
|
|
||||||
|
const NodeHints hints = NodeHints::fromItemLibraryEntry(itemLibraryEntry);
|
||||||
|
|
||||||
|
const QString targetPropertyName = hints.forceNonDefaultProperty();
|
||||||
|
|
||||||
|
bool foundTarget = findTargetProperty(rowModelIndex, this, &targetProperty, &targetRowNumber, targetPropertyName.toUtf8());
|
||||||
|
|
||||||
if (foundTarget) {
|
if (foundTarget) {
|
||||||
const ItemLibraryEntry itemLibraryEntry =
|
|
||||||
createItemLibraryEntryFromMimeData(mimeData->data("application/vnd.bauhaus.itemlibraryinfo"));
|
|
||||||
|
|
||||||
if (!NodeHints::fromItemLibraryEntry(itemLibraryEntry).canBeDroppedInNavigator())
|
if (!NodeHints::fromItemLibraryEntry(itemLibraryEntry).canBeDroppedInNavigator())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QmlItemNode newQmlItemNode = QmlItemNode::createQmlItemNode(m_view, itemLibraryEntry, QPointF(), targetProperty);
|
const QmlObjectNode newQmlObjectNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, QPointF(), targetProperty);
|
||||||
|
|
||||||
if (newQmlItemNode.isValid() && targetProperty.isNodeListProperty()) {
|
if (newQmlObjectNode.isValid() && targetProperty.isNodeListProperty()) {
|
||||||
QList<ModelNode> newModelNodeList;
|
QList<ModelNode> newModelNodeList;
|
||||||
newModelNodeList.append(newQmlItemNode);
|
newModelNodeList.append(newQmlObjectNode);
|
||||||
|
|
||||||
moveNodesInteractive(targetProperty, newModelNodeList, targetRowNumber);
|
moveNodesInteractive(targetProperty, newModelNodeList, targetRowNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newQmlItemNode.isValid())
|
if (newQmlObjectNode.isValid())
|
||||||
m_view->selectModelNode(newQmlItemNode.modelNode());
|
m_view->selectModelNode(newQmlObjectNode.modelNode());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -394,7 +394,8 @@ void NavigatorView::upButtonClicked()
|
|||||||
index--;
|
index--;
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
index = node.parentProperty().count() - 1; //wrap around
|
index = node.parentProperty().count() - 1; //wrap around
|
||||||
node.parentProperty().toNodeListProperty().slide(oldIndex, index);
|
if (oldIndex != index)
|
||||||
|
node.parentProperty().toNodeListProperty().slide(oldIndex, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateItemSelection();
|
updateItemSelection();
|
||||||
@@ -411,7 +412,8 @@ void NavigatorView::downButtonClicked()
|
|||||||
index++;
|
index++;
|
||||||
if (index >= node.parentProperty().count())
|
if (index >= node.parentProperty().count())
|
||||||
index = 0; //wrap around
|
index = 0; //wrap around
|
||||||
node.parentProperty().toNodeListProperty().slide(oldIndex, index);
|
if (oldIndex != index)
|
||||||
|
node.parentProperty().toNodeListProperty().slide(oldIndex, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateItemSelection();
|
updateItemSelection();
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user