Merge remote-tracking branch 'origin/4.10'

Conflicts:
	src/libs/utils/consoleprocess.h

Change-Id: I771630cb4dc60a9e87e9d30d6295040c27348d8c
This commit is contained in:
Eike Ziller
2019-06-20 11:03:05 +02:00
268 changed files with 5888 additions and 178 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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;

View File

@@ -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

View File

@@ -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}.
*/ */

View File

@@ -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.

View File

@@ -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

View File

@@ -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 *>

View File

@@ -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
}
Image {
visible: !modelNodeBackend.multiSelection
Layout.preferredWidth: 16
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.")
} }
// workaround: without this item the lineedit does not shrink to the
// right size after resizing to a wider width
Item {
width: 0
height: 1
} }
} }
} }

View File

@@ -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()

View File

@@ -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('\\')) {

View File

@@ -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;
}; };

View File

@@ -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,10 +1329,9 @@ 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;
} }
}; };

View File

@@ -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:

View File

@@ -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());

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
} }

View File

@@ -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();

View File

@@ -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

View File

@@ -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;

View File

@@ -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)

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View 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 "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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View 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.

View File

@@ -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.

View 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.

View 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.

View 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.

View 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.

View File

@@ -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;
if (propertyName.isEmpty() || !targetNode.metaInfo().hasProperty(propertyName))
targetPropertyName = targetNode.metaInfo().defaultPropertyName(); 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);
if (foundTarget) {
const ItemLibraryEntry itemLibraryEntry = const ItemLibraryEntry itemLibraryEntry =
createItemLibraryEntryFromMimeData(mimeData->data("application/vnd.bauhaus.itemlibraryinfo")); 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 (!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());
} }
} }

View File

@@ -394,6 +394,7 @@ 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
if (oldIndex != index)
node.parentProperty().toNodeListProperty().slide(oldIndex, index); node.parentProperty().toNodeListProperty().slide(oldIndex, index);
} }
} }
@@ -411,6 +412,7 @@ void NavigatorView::downButtonClicked()
index++; index++;
if (index >= node.parentProperty().count()) if (index >= node.parentProperty().count())
index = 0; //wrap around index = 0; //wrap around
if (oldIndex != index)
node.parentProperty().toNodeListProperty().slide(oldIndex, index); node.parentProperty().toNodeListProperty().slide(oldIndex, index);
} }
} }

Some files were not shown because too many files have changed in this diff Show More