forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/master' into 4.12
Change-Id: If4508ed26484913d803cdf9d4c06831ec4e98ae7
This commit is contained in:
@@ -9,7 +9,6 @@ defines = Q_QDOC \
|
||||
Q_OS_.* \
|
||||
Q_BYTE_ORDER \
|
||||
QT_DEPRECATED \
|
||||
Q_NO_USING_KEYWORD \
|
||||
__cplusplus
|
||||
Q_NO_USING_KEYWORD
|
||||
|
||||
versionsym = QT_VERSION_STR
|
||||
|
@@ -41,7 +41,7 @@ for (doc_file, DOC_FILES) {
|
||||
DOC_TARGETDIR = $$DOC_TARGET
|
||||
DOC_OUTPUTDIR = $${DOCS_BASE_OUTDIR}/$${DOC_TARGETDIR}$${DOC_OUTDIR_POSTFIX}
|
||||
|
||||
html_docs_$${DOC_TARGET}.commands = $$QDOC -outputdir $$shell_quote($$DOC_OUTPUTDIR) $$doc_file $$DOC_INDEXES
|
||||
html_docs_$${DOC_TARGET}.commands = $$QDOC -outputdir $$shell_quote($$DOC_OUTPUTDIR) $$doc_file $$DOC_INDEXES $$DOC_INCLUDES
|
||||
QMAKE_EXTRA_TARGETS += html_docs_$${DOC_TARGET}
|
||||
|
||||
!isEmpty(html_docs.commands): html_docs.commands += &&
|
||||
|
13
docs.pri
13
docs.pri
@@ -41,4 +41,17 @@ DOC_HTML_INSTALLDIR = $$INSTALL_DOC_PATH
|
||||
DOC_QCH_OUTDIR = $$IDE_DOC_PATH
|
||||
DOC_QCH_INSTALLDIR = $$INSTALL_DOC_PATH
|
||||
|
||||
minQtVersion(5, 11, 0) {
|
||||
for (include_path, INCLUDEPATH): \
|
||||
DOC_INCLUDES += -I $$shell_quote($$include_path)
|
||||
for (module, QT) {
|
||||
MOD_INCLUDES = $$eval(QT.$${module}.includes)
|
||||
for (include_path, MOD_INCLUDES): \
|
||||
DOC_INCLUDES += -I $$shell_quote($$include_path)
|
||||
}
|
||||
for (include_path, QMAKE_DEFAULT_INCDIRS): \
|
||||
DOC_INCLUDES += -I $$shell_quote($$include_path)
|
||||
macos: DOC_INCLUDES += -F $$shell_quote($$[QT_INSTALL_LIBS])
|
||||
}
|
||||
|
||||
include(doc/doc_targets.pri)
|
||||
|
@@ -107,8 +107,8 @@ Rectangle {
|
||||
|
||||
}
|
||||
Item {
|
||||
Layout.preferredWidth: 16
|
||||
Layout.preferredHeight: 16
|
||||
Layout.preferredWidth: 20
|
||||
Layout.preferredHeight: 20
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,8 +134,10 @@ Rectangle {
|
||||
|
||||
Image {
|
||||
visible: !modelNodeBackend.multiSelection
|
||||
Layout.preferredWidth: 16
|
||||
Layout.preferredHeight: 16
|
||||
Layout.preferredWidth: 20
|
||||
Layout.preferredHeight: 20
|
||||
horizontalAlignment: Image.AlignHCenter
|
||||
verticalAlignment: Image.AlignVCenter
|
||||
source: hasAliasExport ? "image://icons/alias-export-checked" : "image://icons/alias-export-unchecked"
|
||||
ToolTipArea {
|
||||
enabled: !modelNodeBackend.multiSelection
|
||||
@@ -145,6 +147,110 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Label {
|
||||
text: qsTr("Custom id")
|
||||
}
|
||||
|
||||
SecondColumnLayout {
|
||||
enabled: !modelNodeBackend.multiSelection
|
||||
visible: enabled
|
||||
spacing: 2
|
||||
|
||||
LineEdit {
|
||||
id: annotationEdit
|
||||
enabled: annotationEditor.hasAuxData
|
||||
visible: enabled
|
||||
|
||||
backendValue: backendValues.customId__AUX
|
||||
placeholderText: qsTr("customId")
|
||||
text: backendValue.value
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 240
|
||||
width: 240
|
||||
showTranslateCheckBox: false
|
||||
showExtendedFunctionButton: false
|
||||
|
||||
onHoveredChanged: annotationEditor.checkAux()
|
||||
}
|
||||
|
||||
StudioControls.AbstractButton {
|
||||
id: editAnnotationButton
|
||||
enabled: annotationEditor.hasAuxData
|
||||
visible: enabled
|
||||
Layout.preferredWidth: 22
|
||||
Layout.preferredHeight: 22
|
||||
width: 22
|
||||
|
||||
buttonIcon: StudioTheme.Constants.edit
|
||||
|
||||
onClicked: annotationEditor.showWidget()
|
||||
|
||||
onHoveredChanged: annotationEditor.checkAux()
|
||||
}
|
||||
|
||||
StudioControls.AbstractButton {
|
||||
id: removeAnnotationButton
|
||||
enabled: annotationEditor.hasAuxData
|
||||
visible: enabled
|
||||
Layout.preferredWidth: 22
|
||||
Layout.preferredHeight: 22
|
||||
width: 22
|
||||
|
||||
buttonIcon: StudioTheme.Constants.closeCross
|
||||
|
||||
onClicked: annotationEditor.removeFullAnnotation()
|
||||
|
||||
onHoveredChanged: annotationEditor.checkAux()
|
||||
}
|
||||
|
||||
StudioControls.AbstractButton {
|
||||
id: addAnnotationButton
|
||||
enabled: !annotationEditor.hasAuxData
|
||||
visible: enabled
|
||||
|
||||
buttonIcon: qsTr("Add Annotation")
|
||||
iconFont: StudioTheme.Constants.font
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredWidth: 240
|
||||
|
||||
onClicked: annotationEditor.showWidget()
|
||||
|
||||
onHoveredChanged: annotationEditor.checkAux()
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.preferredWidth: 22
|
||||
Layout.preferredHeight: 22
|
||||
enabled: !annotationEditor.hasAuxData
|
||||
visible: enabled
|
||||
}
|
||||
|
||||
AnnotationEditor {
|
||||
id: annotationEditor
|
||||
|
||||
modelNodeBackendProperty: modelNodeBackend
|
||||
|
||||
property bool hasAuxData: (annotationEditor.hasAnnotation || annotationEditor.hasCustomId)
|
||||
|
||||
onModelNodeBackendChanged: checkAux()
|
||||
onCustomIdChanged: checkAux()
|
||||
onAnnotationChanged: checkAux()
|
||||
|
||||
function checkAux() {
|
||||
hasAuxData = (annotationEditor.hasAnnotation || annotationEditor.hasCustomId)
|
||||
annotationEdit.update()
|
||||
}
|
||||
|
||||
onAccepted: {
|
||||
hideWidget()
|
||||
}
|
||||
|
||||
onCanceled: {
|
||||
hideWidget()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -44,27 +44,46 @@ namespace Internal {
|
||||
|
||||
// FullCommandLineAspect
|
||||
|
||||
FullCommandLineAspect::FullCommandLineAspect(RunConfiguration *rc)
|
||||
class FullCommandLineAspect : public BaseStringAspect
|
||||
{
|
||||
setLabelText(QdbRunConfiguration::tr("Full command line:"));
|
||||
Q_DECLARE_TR_FUNCTIONS(Qdb::Internal::QdbRunConfiguration);
|
||||
|
||||
auto exeAspect = rc->aspect<ExecutableAspect>();
|
||||
auto argumentsAspect = rc->aspect<ArgumentsAspect>();
|
||||
public:
|
||||
explicit FullCommandLineAspect(RunConfiguration *rc)
|
||||
{
|
||||
setLabelText(tr("Full command line:"));
|
||||
|
||||
auto updateCommandLine = [this, rc, exeAspect, argumentsAspect] {
|
||||
const QString usedExecutable = exeAspect->executable().toString();
|
||||
const QString args = argumentsAspect->arguments(rc->macroExpander());
|
||||
setValue(QString(Constants::AppcontrollerFilepath)
|
||||
+ ' ' + usedExecutable + ' ' + args);
|
||||
};
|
||||
auto exeAspect = rc->aspect<ExecutableAspect>();
|
||||
auto argumentsAspect = rc->aspect<ArgumentsAspect>();
|
||||
|
||||
auto updateCommandLine = [this, rc, exeAspect, argumentsAspect] {
|
||||
const QString usedExecutable = exeAspect->executable().toString();
|
||||
const QString args = argumentsAspect->arguments(rc->macroExpander());
|
||||
setValue(QString(Constants::AppcontrollerFilepath)
|
||||
+ ' ' + usedExecutable + ' ' + args);
|
||||
};
|
||||
|
||||
connect(argumentsAspect, &ArgumentsAspect::argumentsChanged, this, updateCommandLine);
|
||||
connect(exeAspect, &ExecutableAspect::changed, this, updateCommandLine);
|
||||
updateCommandLine();
|
||||
}
|
||||
};
|
||||
|
||||
connect(argumentsAspect, &ArgumentsAspect::argumentsChanged, this, updateCommandLine);
|
||||
connect(exeAspect, &ExecutableAspect::changed, this, updateCommandLine);
|
||||
updateCommandLine();
|
||||
}
|
||||
|
||||
// QdbRunConfiguration
|
||||
|
||||
class QdbRunConfiguration : public RunConfiguration
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Qdb::Internal::QdbRunConfiguration);
|
||||
|
||||
public:
|
||||
QdbRunConfiguration(Target *target, Core::Id id);
|
||||
|
||||
private:
|
||||
Tasks checkForIssues() const override;
|
||||
QString defaultDisplayName() const;
|
||||
};
|
||||
|
||||
QdbRunConfiguration::QdbRunConfiguration(Target *target, Core::Id id)
|
||||
: RunConfiguration(target, id)
|
||||
{
|
||||
|
@@ -30,26 +30,6 @@
|
||||
namespace Qdb {
|
||||
namespace Internal {
|
||||
|
||||
class FullCommandLineAspect : public ProjectExplorer::BaseStringAspect
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FullCommandLineAspect(ProjectExplorer::RunConfiguration *rc);
|
||||
};
|
||||
|
||||
class QdbRunConfiguration : public ProjectExplorer::RunConfiguration
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QdbRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
|
||||
|
||||
private:
|
||||
ProjectExplorer::Tasks checkForIssues() const override;
|
||||
QString defaultDisplayName() const;
|
||||
};
|
||||
|
||||
class QdbRunConfigurationFactory : public ProjectExplorer::RunConfigurationFactory
|
||||
{
|
||||
public:
|
||||
|
@@ -37,29 +37,38 @@
|
||||
|
||||
#include <QStandardPaths>
|
||||
|
||||
using namespace Nim;
|
||||
using namespace ProjectExplorer;
|
||||
|
||||
NimbleRunConfiguration::NimbleRunConfiguration(ProjectExplorer::Target *target, Core::Id id)
|
||||
: RunConfiguration(target, id)
|
||||
namespace Nim {
|
||||
|
||||
// NimbleRunConfiguration
|
||||
|
||||
class NimbleRunConfiguration : public RunConfiguration
|
||||
{
|
||||
addAspect<LocalEnvironmentAspect>(target);
|
||||
addAspect<ExecutableAspect>();
|
||||
addAspect<ArgumentsAspect>();
|
||||
addAspect<WorkingDirectoryAspect>();
|
||||
addAspect<TerminalAspect>();
|
||||
Q_DECLARE_TR_FUNCTIONS(Nim::NimbleRunConfiguration)
|
||||
|
||||
setUpdater([this] {
|
||||
BuildTargetInfo bti = buildTargetInfo();
|
||||
setDisplayName(bti.displayName);
|
||||
setDefaultDisplayName(bti.displayName);
|
||||
aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
|
||||
aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory);
|
||||
});
|
||||
public:
|
||||
NimbleRunConfiguration(Target *target, Core::Id id)
|
||||
: RunConfiguration(target, id)
|
||||
{
|
||||
addAspect<LocalEnvironmentAspect>(target);
|
||||
addAspect<ExecutableAspect>();
|
||||
addAspect<ArgumentsAspect>();
|
||||
addAspect<WorkingDirectoryAspect>();
|
||||
addAspect<TerminalAspect>();
|
||||
|
||||
connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update);
|
||||
update();
|
||||
}
|
||||
setUpdater([this] {
|
||||
BuildTargetInfo bti = buildTargetInfo();
|
||||
setDisplayName(bti.displayName);
|
||||
setDefaultDisplayName(bti.displayName);
|
||||
aspect<ExecutableAspect>()->setExecutable(bti.targetFilePath);
|
||||
aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(bti.workingDirectory);
|
||||
});
|
||||
|
||||
connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update);
|
||||
update();
|
||||
}
|
||||
};
|
||||
|
||||
NimbleRunConfigurationFactory::NimbleRunConfigurationFactory()
|
||||
: RunConfigurationFactory()
|
||||
@@ -69,22 +78,26 @@ NimbleRunConfigurationFactory::NimbleRunConfigurationFactory()
|
||||
addSupportedTargetDeviceType(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE);
|
||||
}
|
||||
|
||||
QList<RunConfigurationCreationInfo> NimbleRunConfigurationFactory::availableCreators(Target *parent) const
|
||||
{
|
||||
return RunConfigurationFactory::availableCreators(parent);
|
||||
}
|
||||
|
||||
NimbleTestConfiguration::NimbleTestConfiguration(Target *target, Core::Id id)
|
||||
: RunConfiguration(target, id)
|
||||
{
|
||||
addAspect<ExecutableAspect>()->setExecutable(Utils::FilePath::fromString(QStandardPaths::findExecutable("nimble")));
|
||||
addAspect<ArgumentsAspect>()->setArguments("test");
|
||||
addAspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(project()->projectDirectory());
|
||||
addAspect<TerminalAspect>();
|
||||
// NimbleTestConfiguration
|
||||
|
||||
setDisplayName(tr("Nimble Test"));
|
||||
setDefaultDisplayName(tr("Nimble Test"));
|
||||
}
|
||||
class NimbleTestConfiguration : public RunConfiguration
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(Nim::NimbleTestConfiguration)
|
||||
|
||||
public:
|
||||
NimbleTestConfiguration(ProjectExplorer::Target *target, Core::Id id)
|
||||
: RunConfiguration(target, id)
|
||||
{
|
||||
addAspect<ExecutableAspect>()->setExecutable(Utils::FilePath::fromString(QStandardPaths::findExecutable("nimble")));
|
||||
addAspect<ArgumentsAspect>()->setArguments("test");
|
||||
addAspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(project()->projectDirectory());
|
||||
addAspect<TerminalAspect>();
|
||||
|
||||
setDisplayName(tr("Nimble Test"));
|
||||
setDefaultDisplayName(tr("Nimble Test"));
|
||||
}
|
||||
};
|
||||
|
||||
NimbleTestConfigurationFactory::NimbleTestConfigurationFactory()
|
||||
: FixedRunConfigurationFactory(QString())
|
||||
@@ -92,3 +105,5 @@ NimbleTestConfigurationFactory::NimbleTestConfigurationFactory()
|
||||
registerRunConfiguration<NimbleTestConfiguration>("Nim.NimbleTestConfiguration");
|
||||
addSupportedProjectType(Constants::C_NIMBLEPROJECT_ID);
|
||||
}
|
||||
|
||||
} // Nim
|
||||
|
@@ -29,35 +29,16 @@
|
||||
|
||||
namespace Nim {
|
||||
|
||||
class NimbleRunConfiguration : public ProjectExplorer::RunConfiguration
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NimbleRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
|
||||
};
|
||||
|
||||
class NimbleRunConfigurationFactory : public ProjectExplorer::RunConfigurationFactory
|
||||
class NimbleRunConfigurationFactory final : public ProjectExplorer::RunConfigurationFactory
|
||||
{
|
||||
public:
|
||||
NimbleRunConfigurationFactory();
|
||||
|
||||
protected:
|
||||
QList<ProjectExplorer::RunConfigurationCreationInfo> availableCreators(ProjectExplorer::Target *parent) const override;
|
||||
};
|
||||
|
||||
class NimbleTestConfiguration : public ProjectExplorer::RunConfiguration
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NimbleTestConfiguration(ProjectExplorer::Target *target, Core::Id id);
|
||||
};
|
||||
|
||||
class NimbleTestConfigurationFactory : public ProjectExplorer::FixedRunConfigurationFactory
|
||||
class NimbleTestConfigurationFactory final : public ProjectExplorer::FixedRunConfigurationFactory
|
||||
{
|
||||
public:
|
||||
NimbleTestConfigurationFactory();
|
||||
};
|
||||
|
||||
}
|
||||
} // Nim
|
||||
|
@@ -41,31 +41,37 @@ using namespace Utils;
|
||||
|
||||
namespace Nim {
|
||||
|
||||
NimRunConfiguration::NimRunConfiguration(Target *target, Core::Id id)
|
||||
: RunConfiguration(target, id)
|
||||
class NimRunConfiguration final : public RunConfiguration
|
||||
{
|
||||
addAspect<LocalEnvironmentAspect>(target);
|
||||
addAspect<ExecutableAspect>();
|
||||
addAspect<ArgumentsAspect>();
|
||||
addAspect<WorkingDirectoryAspect>();
|
||||
addAspect<TerminalAspect>();
|
||||
Q_DECLARE_TR_FUNCTIONS(Nim::NimRunConfiguration)
|
||||
|
||||
setDisplayName(tr("Current Build Target"));
|
||||
setDefaultDisplayName(tr("Current Build Target"));
|
||||
public:
|
||||
NimRunConfiguration(Target *target, Core::Id id)
|
||||
: RunConfiguration(target, id)
|
||||
{
|
||||
addAspect<LocalEnvironmentAspect>(target);
|
||||
addAspect<ExecutableAspect>();
|
||||
addAspect<ArgumentsAspect>();
|
||||
addAspect<WorkingDirectoryAspect>();
|
||||
addAspect<TerminalAspect>();
|
||||
|
||||
setUpdater([this] {
|
||||
auto buildConfiguration = qobject_cast<NimBuildConfiguration *>(activeBuildConfiguration());
|
||||
QTC_ASSERT(buildConfiguration, return);
|
||||
const QFileInfo outFileInfo = buildConfiguration->outFilePath().toFileInfo();
|
||||
aspect<ExecutableAspect>()->setExecutable(FilePath::fromString(outFileInfo.absoluteFilePath()));
|
||||
const QString workingDirectory = outFileInfo.absoluteDir().absolutePath();
|
||||
aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(FilePath::fromString(workingDirectory));
|
||||
});
|
||||
setDisplayName(tr("Current Build Target"));
|
||||
setDefaultDisplayName(tr("Current Build Target"));
|
||||
|
||||
// Connect target signals
|
||||
connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update);
|
||||
update();
|
||||
}
|
||||
setUpdater([this] {
|
||||
auto buildConfiguration = qobject_cast<NimBuildConfiguration *>(activeBuildConfiguration());
|
||||
QTC_ASSERT(buildConfiguration, return);
|
||||
const QFileInfo outFileInfo = buildConfiguration->outFilePath().toFileInfo();
|
||||
aspect<ExecutableAspect>()->setExecutable(FilePath::fromString(outFileInfo.absoluteFilePath()));
|
||||
const QString workingDirectory = outFileInfo.absoluteDir().absolutePath();
|
||||
aspect<WorkingDirectoryAspect>()->setDefaultWorkingDirectory(FilePath::fromString(workingDirectory));
|
||||
});
|
||||
|
||||
// Connect target signals
|
||||
connect(target, &Target::buildSystemUpdated, this, &RunConfiguration::update);
|
||||
update();
|
||||
}
|
||||
};
|
||||
|
||||
// NimRunConfigurationFactory
|
||||
|
||||
|
@@ -29,15 +29,7 @@
|
||||
|
||||
namespace Nim {
|
||||
|
||||
class NimRunConfiguration : public ProjectExplorer::RunConfiguration
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NimRunConfiguration(ProjectExplorer::Target *target, Core::Id id);
|
||||
};
|
||||
|
||||
class NimRunConfigurationFactory : public ProjectExplorer::FixedRunConfigurationFactory
|
||||
class NimRunConfigurationFactory final : public ProjectExplorer::FixedRunConfigurationFactory
|
||||
{
|
||||
public:
|
||||
NimRunConfigurationFactory();
|
||||
|
@@ -208,6 +208,7 @@ extend_qtc_plugin(QmlDesigner
|
||||
controlelement.cpp controlelement.h
|
||||
dragtool.cpp dragtool.h
|
||||
formeditor.qrc
|
||||
formeditorannotationicon.cpp formeditorannotationicon.h
|
||||
formeditorgraphicsview.cpp formeditorgraphicsview.h
|
||||
formeditoritem.cpp formeditoritem.h
|
||||
formeditorscene.cpp formeditorscene.h
|
||||
@@ -538,6 +539,15 @@ extend_qtc_plugin(QmlDesigner
|
||||
SOURCES colortool.cpp colortool.h
|
||||
)
|
||||
|
||||
extend_qtc_plugin(QmlDesigner
|
||||
SOURCES_PREFIX components/annotationeditor
|
||||
SOURCES annotation.cpp annotation.h
|
||||
annotationcommenttab.cpp annotationcommenttab.h annotationcommenttab.ui
|
||||
annotationeditordialog.cpp annotationeditordialog.h annotationeditordialog.ui
|
||||
annotationeditor.cpp annotationeditor.h
|
||||
annotationtool.cpp annotationtool.h
|
||||
)
|
||||
|
||||
extend_qtc_plugin(QmlDesigner
|
||||
SOURCES_PREFIX components/connectioneditor
|
||||
SOURCES
|
||||
|
@@ -0,0 +1,307 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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 "annotation.h"
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
static const QString s_sep = " //;;// "; //separator
|
||||
|
||||
Comment::Comment()
|
||||
: m_title(QString())
|
||||
, m_author(QString())
|
||||
, m_text(QString())
|
||||
, m_timestamp(0)
|
||||
{}
|
||||
|
||||
Comment::Comment(const QString &title, const QString &author, const QString &text, qint64 timestamp)
|
||||
: m_title(title)
|
||||
, m_author(author)
|
||||
, m_text(text)
|
||||
, m_timestamp(timestamp)
|
||||
{}
|
||||
|
||||
QString Comment::title() const
|
||||
{
|
||||
return m_title;
|
||||
}
|
||||
|
||||
void Comment::setTitle(const QString &title)
|
||||
{
|
||||
m_title = title;
|
||||
}
|
||||
|
||||
QString Comment::author() const
|
||||
{
|
||||
return m_author;
|
||||
}
|
||||
|
||||
void Comment::setAuthor(const QString &author)
|
||||
{
|
||||
m_author = author;
|
||||
}
|
||||
|
||||
QString Comment::text() const
|
||||
{
|
||||
return m_text;
|
||||
}
|
||||
|
||||
void Comment::setText(const QString &text)
|
||||
{
|
||||
m_text = text;
|
||||
}
|
||||
|
||||
QString Comment::timestampStr() const
|
||||
{
|
||||
return QDateTime::fromSecsSinceEpoch(m_timestamp).toString();
|
||||
}
|
||||
|
||||
QString Comment::timestampStr(const QString &format) const
|
||||
{
|
||||
return QDateTime::fromSecsSinceEpoch(m_timestamp).toString(format);
|
||||
}
|
||||
|
||||
qint64 Comment::timestamp() const
|
||||
{
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
void Comment::setTimestamp(qint64 timestamp)
|
||||
{
|
||||
m_timestamp = timestamp;
|
||||
}
|
||||
|
||||
void Comment::updateTimestamp()
|
||||
{
|
||||
m_timestamp = QDateTime::currentSecsSinceEpoch();
|
||||
}
|
||||
|
||||
bool Comment::sameContent(const Comment &comment) const
|
||||
{
|
||||
return sameContent(*this, comment);
|
||||
}
|
||||
|
||||
bool Comment::sameContent(const Comment &a, const Comment &b)
|
||||
{
|
||||
return ((a.title() == b.title())
|
||||
&& (a.author() == b.author())
|
||||
&& (a.text() == b.text()));
|
||||
}
|
||||
|
||||
bool Comment::operator==(const Comment &comment) const
|
||||
{
|
||||
return (sameContent(comment) && (m_timestamp == comment.timestamp()));
|
||||
}
|
||||
|
||||
bool Comment::isEmpty()
|
||||
{
|
||||
return sameContent(Comment());
|
||||
}
|
||||
|
||||
QString Comment::toQString() const
|
||||
{
|
||||
QStringList result;
|
||||
|
||||
result.push_back(m_title);
|
||||
result.push_back(m_author);
|
||||
result.push_back(m_text);
|
||||
result.push_back(QString::number(m_timestamp));
|
||||
|
||||
return result.join(s_sep);
|
||||
}
|
||||
|
||||
QDebug &operator<<(QDebug &stream, const Comment &comment)
|
||||
{
|
||||
stream << "\"title: " << comment.m_title << "\" ";
|
||||
stream << "\"author: " << comment.m_author << "\" ";
|
||||
stream << "\"text: " << comment.m_text << "\" ";
|
||||
stream << "\"timestamp: " << comment.m_timestamp << "\" ";
|
||||
stream << "\"date/time: " << QDateTime::fromSecsSinceEpoch(comment.m_timestamp).toString() << "\" ";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &stream, const Comment &comment)
|
||||
{
|
||||
stream << comment.m_title;
|
||||
stream << comment.m_author;
|
||||
stream << comment.m_text;
|
||||
stream << comment.m_timestamp;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &stream, Comment &comment)
|
||||
{
|
||||
stream >> comment.m_title;
|
||||
stream >> comment.m_author;
|
||||
stream >> comment.m_text;
|
||||
stream >> comment.m_timestamp;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
|
||||
//Annotation
|
||||
|
||||
Annotation::Annotation()
|
||||
: m_comments()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QVector<Comment> Annotation::comments() const
|
||||
{
|
||||
return m_comments;
|
||||
}
|
||||
|
||||
|
||||
bool Annotation::hasComments() const
|
||||
{
|
||||
return !m_comments.isEmpty();
|
||||
}
|
||||
|
||||
void Annotation::setComments(const QVector<Comment> &comments)
|
||||
{
|
||||
m_comments = comments;
|
||||
}
|
||||
|
||||
void Annotation::removeComments()
|
||||
{
|
||||
m_comments.clear();
|
||||
}
|
||||
|
||||
int Annotation::commentsSize() const
|
||||
{
|
||||
return m_comments.size();
|
||||
}
|
||||
|
||||
Comment Annotation::comment(int n) const
|
||||
{
|
||||
if (m_comments.size() > n)
|
||||
return m_comments.at(n);
|
||||
else
|
||||
return Comment();
|
||||
}
|
||||
|
||||
void Annotation::addComment(const Comment &comment)
|
||||
{
|
||||
m_comments.push_back(comment);
|
||||
}
|
||||
|
||||
bool Annotation::updateComment(const Comment &comment, int n)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if ((m_comments.size() > n) && (n > 0)) {
|
||||
m_comments[n] = comment;
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool Annotation::removeComment(int n)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (m_comments.size() > n) {
|
||||
m_comments.remove(n);
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QString Annotation::toQString() const
|
||||
{
|
||||
QStringList result;
|
||||
|
||||
result.push_back(QString::number(m_comments.size()));
|
||||
|
||||
for (const Comment &com : m_comments)
|
||||
result.push_back(com.toQString());
|
||||
|
||||
return result.join(s_sep);
|
||||
}
|
||||
|
||||
void Annotation::fromQString(const QString &str)
|
||||
{
|
||||
QStringList strl (str.split(s_sep, QString::SplitBehavior::KeepEmptyParts));
|
||||
removeComments();
|
||||
|
||||
const int intro = 1;
|
||||
const int comSize = 4;
|
||||
|
||||
if (!strl.isEmpty()) {
|
||||
|
||||
if (strl.size() >= intro) {
|
||||
|
||||
int size = strl.at(0).toInt();
|
||||
|
||||
if (size > 0) {
|
||||
if (strl.size() == (size*comSize) + intro)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const int offset = intro + (i * comSize);
|
||||
Comment com;
|
||||
com.setTitle(strl.at(offset + 0));
|
||||
com.setAuthor(strl.at(offset + 1));
|
||||
com.setText(strl.at(offset + 2));
|
||||
com.setTimestamp(strl.at(offset + 3).toLongLong());
|
||||
|
||||
m_comments.push_back(com);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QDebug &operator<<(QDebug &stream, const Annotation &annotation)
|
||||
{
|
||||
stream << "\"Annotation: " << annotation.m_comments << "\" ";
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &operator<<(QDataStream &stream, const Annotation &annotation)
|
||||
{
|
||||
stream << annotation.m_comments;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
QDataStream &operator>>(QDataStream &stream, Annotation &annotation)
|
||||
{
|
||||
stream >> annotation.m_comments;
|
||||
|
||||
return stream;
|
||||
}
|
||||
|
||||
} // QmlDesigner namespace
|
122
src/plugins/qmldesigner/components/annotationeditor/annotation.h
Normal file
122
src/plugins/qmldesigner/components/annotationeditor/annotation.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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 <QObject>
|
||||
#include <QDebug>
|
||||
#include <QDataStream>
|
||||
|
||||
#include "nodeinstanceglobal.h"
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
static const PropertyName customIdProperty = {("customId")};
|
||||
static const PropertyName annotationProperty = {("annotation")};
|
||||
|
||||
class Comment
|
||||
{
|
||||
public:
|
||||
Comment();
|
||||
Comment(const QString &title, const QString &author = QString(), const QString &text = QString(), qint64 timestamp = 0);
|
||||
|
||||
~Comment() = default;
|
||||
|
||||
QString title() const;
|
||||
void setTitle(const QString &title);
|
||||
|
||||
QString text() const;
|
||||
void setText(const QString &text);
|
||||
|
||||
QString author() const;
|
||||
void setAuthor(const QString &author);
|
||||
|
||||
QString timestampStr() const;
|
||||
QString timestampStr(const QString &format) const;
|
||||
qint64 timestamp() const;
|
||||
void setTimestamp(qint64 timestamp);
|
||||
void updateTimestamp();
|
||||
|
||||
bool sameContent(const Comment &comment) const; //everything is similar besides timestamp
|
||||
static bool sameContent(const Comment &a, const Comment &b);
|
||||
bool operator==(const Comment &comment) const; //everything is similar.
|
||||
|
||||
bool isEmpty();
|
||||
|
||||
QString toQString() const;
|
||||
|
||||
friend QDebug &operator<<(QDebug &stream, const Comment &comment);
|
||||
|
||||
friend QDataStream &operator<<(QDataStream &stream, const Comment &comment);
|
||||
friend QDataStream &operator>>(QDataStream &stream, Comment &comment);
|
||||
|
||||
private:
|
||||
QString m_title;
|
||||
QString m_author;
|
||||
QString m_text;
|
||||
qint64 m_timestamp;
|
||||
};
|
||||
|
||||
class Annotation
|
||||
{
|
||||
public:
|
||||
Annotation();
|
||||
~Annotation() = default;
|
||||
|
||||
QVector<Comment> comments() const;
|
||||
bool hasComments() const;
|
||||
void setComments(const QVector<Comment> &comments);
|
||||
void removeComments();
|
||||
int commentsSize() const;
|
||||
|
||||
Comment comment(int n) const;
|
||||
void addComment(const Comment &comment);
|
||||
bool updateComment(const Comment &comment, int n);
|
||||
bool removeComment(int n);
|
||||
|
||||
QString toQString() const;
|
||||
void fromQString(const QString &str);
|
||||
|
||||
friend QDebug &operator<<(QDebug &stream, const Annotation &annotation);
|
||||
|
||||
friend QDataStream &operator<<(QDataStream &stream, const Annotation &annotation);
|
||||
friend QDataStream &operator>>(QDataStream &stream, Annotation &annotation);
|
||||
|
||||
private:
|
||||
QVector<Comment> m_comments;
|
||||
};
|
||||
|
||||
QDebug &operator<<(QDebug &stream, const Comment &comment);
|
||||
QDebug &operator<<(QDebug &stream, const Annotation &annotation);
|
||||
|
||||
QDataStream &operator<<(QDataStream &stream, const Comment &comment);
|
||||
QDataStream &operator>>(QDataStream &stream, Comment &comment);
|
||||
QDataStream &operator<<(QDataStream &stream, const Annotation &annotation);
|
||||
QDataStream &operator>>(QDataStream &stream, Annotation &annotation);
|
||||
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(QmlDesigner::Comment);
|
||||
Q_DECLARE_METATYPE(QmlDesigner::Annotation);
|
@@ -0,0 +1,95 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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 "annotationcommenttab.h"
|
||||
#include "ui_annotationcommenttab.h"
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
AnnotationCommentTab::AnnotationCommentTab(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::AnnotationCommentTab)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->titleEdit, &QLineEdit::textEdited,
|
||||
this, &AnnotationCommentTab::commentTitleChanged);
|
||||
}
|
||||
|
||||
AnnotationCommentTab::~AnnotationCommentTab()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
Comment AnnotationCommentTab::currentComment() const
|
||||
{
|
||||
Comment result;
|
||||
|
||||
result.setTitle(ui->titleEdit->text().trimmed());
|
||||
result.setAuthor(ui->authorEdit->text().trimmed());
|
||||
result.setText(ui->textEdit->toPlainText().trimmed());
|
||||
|
||||
if (m_comment.sameContent(result))
|
||||
result.setTimestamp(m_comment.timestamp());
|
||||
else
|
||||
result.updateTimestamp();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Comment AnnotationCommentTab::originalComment() const
|
||||
{
|
||||
return m_comment;
|
||||
}
|
||||
|
||||
void AnnotationCommentTab::setComment(const Comment &comment)
|
||||
{
|
||||
m_comment = comment;
|
||||
resetUI();
|
||||
}
|
||||
|
||||
void AnnotationCommentTab::resetUI()
|
||||
{
|
||||
ui->titleEdit->setText(m_comment.title());
|
||||
ui->authorEdit->setText(m_comment.author());
|
||||
ui->textEdit->setText(m_comment.text());
|
||||
|
||||
if (m_comment.timestamp() > 0)
|
||||
ui->timeLabel->setText(m_comment.timestampStr());
|
||||
else
|
||||
ui->timeLabel->setText("");
|
||||
}
|
||||
|
||||
void AnnotationCommentTab::resetComment()
|
||||
{
|
||||
m_comment = currentComment();
|
||||
}
|
||||
|
||||
void AnnotationCommentTab::commentTitleChanged(const QString &text)
|
||||
{
|
||||
emit titleChanged(text, this);
|
||||
}
|
||||
|
||||
} //namespace QmlDesigner
|
@@ -0,0 +1,66 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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>
|
||||
|
||||
#include "annotation.h"
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
namespace Ui {
|
||||
class AnnotationCommentTab;
|
||||
}
|
||||
|
||||
class AnnotationCommentTab : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AnnotationCommentTab(QWidget *parent = nullptr);
|
||||
~AnnotationCommentTab();
|
||||
|
||||
Comment currentComment() const;
|
||||
|
||||
Comment originalComment() const;
|
||||
void setComment(const Comment &comment);
|
||||
|
||||
void resetUI();
|
||||
void resetComment();
|
||||
|
||||
signals:
|
||||
void titleChanged(const QString &text, QWidget *widget);
|
||||
|
||||
private slots:
|
||||
void commentTitleChanged(const QString &text);
|
||||
|
||||
private:
|
||||
Ui::AnnotationCommentTab *ui;
|
||||
|
||||
Comment m_comment;
|
||||
};
|
||||
|
||||
} //namespace QmlDesigner
|
@@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QmlDesigner::AnnotationCommentTab</class>
|
||||
<widget class="QWidget" name="QmlDesigner::AnnotationCommentTab">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>537</width>
|
||||
<height>382</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="titileLabel">
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="titleEdit"/>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="textLabel">
|
||||
<property name="text">
|
||||
<string>Text</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QTextEdit" name="textEdit">
|
||||
<property name="tabChangesFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="authorLabel">
|
||||
<property name="text">
|
||||
<string>Author</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="authorEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="timeLabel">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>titleEdit</tabstop>
|
||||
<tabstop>authorEdit</tabstop>
|
||||
<tabstop>textEdit</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@@ -0,0 +1,190 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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 "annotationeditor.h"
|
||||
|
||||
#include "annotationeditordialog.h"
|
||||
#include "annotation.h"
|
||||
|
||||
#include "qmlmodelnodeproxy.h"
|
||||
#include <coreplugin/icore.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QToolBar>
|
||||
#include <QAction>
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
AnnotationEditor::AnnotationEditor(QObject *)
|
||||
{
|
||||
}
|
||||
|
||||
AnnotationEditor::~AnnotationEditor()
|
||||
{
|
||||
hideWidget();
|
||||
}
|
||||
|
||||
void AnnotationEditor::registerDeclarativeType()
|
||||
{
|
||||
qmlRegisterType<AnnotationEditor>("HelperWidgets", 2, 0, "AnnotationEditor");
|
||||
}
|
||||
|
||||
void AnnotationEditor::showWidget()
|
||||
{
|
||||
m_dialog = new AnnotationEditorDialog(Core::ICore::dialogParent(),
|
||||
modelNode().validId(),
|
||||
modelNode().customId(),
|
||||
modelNode().annotation());
|
||||
|
||||
QObject::connect(m_dialog, &AnnotationEditorDialog::accepted,
|
||||
this, &AnnotationEditor::acceptedClicked);
|
||||
QObject::connect(m_dialog, &AnnotationEditorDialog::rejected,
|
||||
this, &AnnotationEditor::cancelClicked);
|
||||
|
||||
m_dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
m_dialog->open();
|
||||
}
|
||||
|
||||
void AnnotationEditor::showWidget(int x, int y)
|
||||
{
|
||||
showWidget();
|
||||
m_dialog->move(x, y);
|
||||
}
|
||||
|
||||
void AnnotationEditor::hideWidget()
|
||||
{
|
||||
if (m_dialog)
|
||||
m_dialog->close();
|
||||
m_dialog = nullptr;
|
||||
}
|
||||
|
||||
void AnnotationEditor::setModelNode(const ModelNode &modelNode)
|
||||
{
|
||||
m_modelNodeBackend = {};
|
||||
m_modelNode = modelNode;
|
||||
}
|
||||
|
||||
ModelNode AnnotationEditor::modelNode() const
|
||||
{
|
||||
return m_modelNode;
|
||||
}
|
||||
|
||||
void AnnotationEditor::setModelNodeBackend(const QVariant &modelNodeBackend)
|
||||
{
|
||||
if (!modelNodeBackend.isNull() && modelNodeBackend.isValid()) {
|
||||
m_modelNodeBackend = modelNodeBackend;
|
||||
|
||||
const auto modelNodeBackendObject = modelNodeBackend.value<QObject*>();
|
||||
const auto backendObjectCasted =
|
||||
qobject_cast<const QmlDesigner::QmlModelNodeProxy *>(modelNodeBackendObject);
|
||||
|
||||
if (backendObjectCasted)
|
||||
m_modelNode = backendObjectCasted->qmlObjectNode().modelNode();
|
||||
|
||||
emit modelNodeBackendChanged();
|
||||
}
|
||||
}
|
||||
|
||||
QVariant AnnotationEditor::modelNodeBackend() const
|
||||
{
|
||||
return m_modelNodeBackend;
|
||||
}
|
||||
|
||||
bool AnnotationEditor::hasCustomId() const
|
||||
{
|
||||
if (m_modelNode.isValid())
|
||||
return m_modelNode.hasCustomId();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AnnotationEditor::hasAnnotation() const
|
||||
{
|
||||
if (m_modelNode.isValid())
|
||||
return m_modelNode.hasAnnotation();
|
||||
return false;
|
||||
}
|
||||
|
||||
void AnnotationEditor::removeFullAnnotation()
|
||||
{
|
||||
if (!m_modelNode.isValid())
|
||||
return;
|
||||
|
||||
QString dialogTitle = tr("Annotation");
|
||||
if (!m_modelNode.customId().isNull()) {
|
||||
dialogTitle = m_modelNode.customId();
|
||||
}
|
||||
QMessageBox *deleteDialog = new QMessageBox(Core::ICore::dialogParent());
|
||||
deleteDialog->setWindowTitle(dialogTitle);
|
||||
deleteDialog->setText(tr("Delete this annotation?"));
|
||||
deleteDialog->setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
deleteDialog->setDefaultButton(QMessageBox::Yes);
|
||||
|
||||
int result = deleteDialog->exec();
|
||||
if (deleteDialog) deleteDialog->deleteLater();
|
||||
|
||||
if (result == QMessageBox::Yes) {
|
||||
m_modelNode.removeCustomId();
|
||||
m_modelNode.removeAnnotation();
|
||||
}
|
||||
|
||||
emit customIdChanged();
|
||||
emit annotationChanged();
|
||||
}
|
||||
|
||||
void AnnotationEditor::acceptedClicked()
|
||||
{
|
||||
if (m_dialog) {
|
||||
QString customId = m_dialog->customId();
|
||||
Annotation annotation = m_dialog->annotation();
|
||||
|
||||
m_modelNode.setCustomId(customId);
|
||||
|
||||
if (annotation.comments().isEmpty())
|
||||
m_modelNode.removeAnnotation();
|
||||
else
|
||||
m_modelNode.setAnnotation(annotation);
|
||||
}
|
||||
|
||||
hideWidget();
|
||||
|
||||
emit accepted();
|
||||
|
||||
emit customIdChanged();
|
||||
emit annotationChanged();
|
||||
}
|
||||
|
||||
void AnnotationEditor::cancelClicked()
|
||||
{
|
||||
hideWidget();
|
||||
|
||||
emit canceled();
|
||||
|
||||
emit customIdChanged();
|
||||
emit annotationChanged();
|
||||
}
|
||||
|
||||
} //namespace QmlDesigner
|
@@ -0,0 +1,89 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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 <QObject>
|
||||
#include <QtQml>
|
||||
#include <QPointer>
|
||||
|
||||
#include "annotationeditordialog.h"
|
||||
#include "annotation.h"
|
||||
|
||||
#include "modelnode.h"
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class AnnotationEditor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QVariant modelNodeBackendProperty READ modelNodeBackend WRITE setModelNodeBackend NOTIFY modelNodeBackendChanged)
|
||||
Q_PROPERTY(bool hasCustomId READ hasCustomId NOTIFY customIdChanged)
|
||||
Q_PROPERTY(bool hasAnnotation READ hasAnnotation NOTIFY annotationChanged)
|
||||
|
||||
public:
|
||||
explicit AnnotationEditor(QObject *parent = nullptr);
|
||||
~AnnotationEditor();
|
||||
|
||||
static void registerDeclarativeType();
|
||||
|
||||
Q_INVOKABLE void showWidget();
|
||||
Q_INVOKABLE void showWidget(int x, int y);
|
||||
Q_INVOKABLE void hideWidget();
|
||||
|
||||
void setModelNode(const ModelNode &modelNode);
|
||||
ModelNode modelNode() const;
|
||||
|
||||
void setModelNodeBackend(const QVariant &modelNodeBackend);
|
||||
QVariant modelNodeBackend() const;
|
||||
|
||||
Q_INVOKABLE bool hasCustomId() const;
|
||||
Q_INVOKABLE bool hasAnnotation() const;
|
||||
|
||||
Q_INVOKABLE void removeFullAnnotation();
|
||||
|
||||
signals:
|
||||
void accepted();
|
||||
void canceled();
|
||||
void modelNodeBackendChanged();
|
||||
|
||||
void customIdChanged();
|
||||
void annotationChanged();
|
||||
|
||||
private slots:
|
||||
void acceptedClicked();
|
||||
void cancelClicked();
|
||||
|
||||
private:
|
||||
QPointer<AnnotationEditorDialog> m_dialog;
|
||||
|
||||
ModelNode m_modelNode;
|
||||
QVariant m_modelNodeBackend;
|
||||
};
|
||||
|
||||
} //namespace QmlDesigner
|
||||
|
||||
QML_DECLARE_TYPE(QmlDesigner::AnnotationEditor)
|
@@ -0,0 +1,14 @@
|
||||
HEADERS += $$PWD/annotation.h
|
||||
HEADERS += $$PWD/annotationtool.h
|
||||
HEADERS += $$PWD/annotationcommenttab.h
|
||||
HEADERS += $$PWD/annotationeditordialog.h
|
||||
HEADERS += $$PWD/annotationeditor.h
|
||||
|
||||
SOURCES += $$PWD/annotation.cpp
|
||||
SOURCES += $$PWD/annotationtool.cpp
|
||||
SOURCES += $$PWD/annotationcommenttab.cpp
|
||||
SOURCES += $$PWD/annotationeditordialog.cpp
|
||||
SOURCES += $$PWD/annotationeditor.cpp
|
||||
|
||||
FORMS += $$PWD/annotationcommenttab.ui
|
||||
FORMS += $$PWD/annotationeditordialog.ui
|
@@ -0,0 +1,248 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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 "annotationeditordialog.h"
|
||||
#include "ui_annotationeditordialog.h"
|
||||
#include "annotation.h"
|
||||
#include "annotationcommenttab.h"
|
||||
|
||||
#include "ui_annotationcommenttab.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QToolBar>
|
||||
#include <QAction>
|
||||
#include <QMessageBox>
|
||||
|
||||
|
||||
#include "timelineicons.h" //replace timeline icons with our own?
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
AnnotationEditorDialog::AnnotationEditorDialog(QWidget *parent, const QString &targetId, const QString &customId, const Annotation &annotation)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::AnnotationEditorDialog)
|
||||
, m_customId(customId)
|
||||
, m_annotation(annotation)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
setWindowFlag(Qt::Tool, true);
|
||||
setWindowTitle(titleString);
|
||||
|
||||
connect(this, &QDialog::accepted, this, &AnnotationEditorDialog::acceptedClicked);
|
||||
|
||||
connect(ui->tabWidget, &QTabWidget::currentChanged, this, &AnnotationEditorDialog::tabChanged);
|
||||
|
||||
auto *commentCornerWidget = new QToolBar;
|
||||
|
||||
auto *commentAddAction = new QAction(TimelineIcons::ADD_TIMELINE.icon(), tr("Add Comment")); //timeline icons?
|
||||
auto *commentRemoveAction = new QAction(TimelineIcons::REMOVE_TIMELINE.icon(),
|
||||
tr("Remove Comment")); //timeline icons?
|
||||
|
||||
connect(commentAddAction, &QAction::triggered, this, [this]() {
|
||||
addComment(Comment());
|
||||
});
|
||||
|
||||
connect(commentRemoveAction, &QAction::triggered, this, [this]() {
|
||||
|
||||
if (ui->tabWidget->count() == 0) //it is not even supposed to happen but lets be sure
|
||||
return;
|
||||
|
||||
int currentIndex = ui->tabWidget->currentIndex();
|
||||
QString currentTitle = ui->tabWidget->tabText(currentIndex);
|
||||
|
||||
QMessageBox *deleteDialog = new QMessageBox(this);
|
||||
deleteDialog->setWindowTitle(currentTitle);
|
||||
deleteDialog->setText(tr("Delete this comment?"));
|
||||
deleteDialog->setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
deleteDialog->setDefaultButton(QMessageBox::Yes);
|
||||
|
||||
int result = deleteDialog->exec();
|
||||
|
||||
if (result == QMessageBox::Yes) {
|
||||
removeComment(currentIndex);
|
||||
}
|
||||
|
||||
if (ui->tabWidget->count() == 0) //lets be sure that tabWidget is never empty
|
||||
addComment(Comment());
|
||||
});
|
||||
|
||||
commentCornerWidget->addAction(commentAddAction);
|
||||
commentCornerWidget->addAction(commentRemoveAction);
|
||||
|
||||
ui->tabWidget->setCornerWidget(commentCornerWidget, Qt::TopRightCorner);
|
||||
ui->targetIdEdit->setText(targetId);
|
||||
|
||||
fillFields();
|
||||
}
|
||||
|
||||
AnnotationEditorDialog::~AnnotationEditorDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AnnotationEditorDialog::setAnnotation(const Annotation &annotation)
|
||||
{
|
||||
m_annotation = annotation;
|
||||
fillFields();
|
||||
}
|
||||
|
||||
Annotation AnnotationEditorDialog::annotation() const
|
||||
{
|
||||
return m_annotation;
|
||||
}
|
||||
|
||||
void AnnotationEditorDialog::setCustomId(const QString &customId)
|
||||
{
|
||||
m_customId = customId;
|
||||
ui->customIdEdit->setText(m_customId);
|
||||
}
|
||||
|
||||
QString AnnotationEditorDialog::customId() const
|
||||
{
|
||||
return m_customId;
|
||||
}
|
||||
|
||||
void AnnotationEditorDialog::acceptedClicked()
|
||||
{
|
||||
m_customId = ui->customIdEdit->text();
|
||||
|
||||
Annotation annotation;
|
||||
|
||||
annotation.removeComments();
|
||||
|
||||
for (int i = 0; i < ui->tabWidget->count(); i++) {
|
||||
AnnotationCommentTab* tab = reinterpret_cast<AnnotationCommentTab*>(ui->tabWidget->widget(i));
|
||||
if (!tab)
|
||||
continue;
|
||||
|
||||
Comment comment = tab->currentComment();
|
||||
|
||||
if (!comment.isEmpty())
|
||||
annotation.addComment(comment);
|
||||
}
|
||||
|
||||
m_annotation = annotation;
|
||||
|
||||
emit AnnotationEditorDialog::accepted();
|
||||
}
|
||||
|
||||
void AnnotationEditorDialog::commentTitleChanged(const QString &text, QWidget *tab)
|
||||
{
|
||||
int tabIndex = ui->tabWidget->indexOf(tab);
|
||||
if (tabIndex >= 0)
|
||||
ui->tabWidget->setTabText(tabIndex, text);
|
||||
|
||||
if (text.isEmpty())
|
||||
ui->tabWidget->setTabText(tabIndex,
|
||||
(defaultTabName + " " + QString::number(tabIndex+1)));
|
||||
}
|
||||
|
||||
void AnnotationEditorDialog::fillFields()
|
||||
{
|
||||
ui->customIdEdit->setText(m_customId);
|
||||
setupComments();
|
||||
}
|
||||
|
||||
void AnnotationEditorDialog::setupComments()
|
||||
{
|
||||
ui->tabWidget->setUpdatesEnabled(false);
|
||||
|
||||
deleteAllTabs();
|
||||
|
||||
const QVector<Comment> comments = m_annotation.comments();
|
||||
|
||||
if (comments.isEmpty())
|
||||
addComment(Comment());
|
||||
|
||||
for (const Comment &comment : comments) {
|
||||
addCommentTab(comment);
|
||||
}
|
||||
|
||||
ui->tabWidget->setUpdatesEnabled(true);
|
||||
}
|
||||
|
||||
void AnnotationEditorDialog::addComment(const Comment &comment)
|
||||
{
|
||||
m_annotation.addComment(comment);
|
||||
addCommentTab(comment);
|
||||
}
|
||||
|
||||
void AnnotationEditorDialog::removeComment(int index)
|
||||
{
|
||||
if ((m_annotation.commentsSize() > index) && (index >= 0)) {
|
||||
m_annotation.removeComment(index);
|
||||
removeCommentTab(index);
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationEditorDialog::addCommentTab(const Comment &comment)
|
||||
{
|
||||
auto commentTab = new AnnotationCommentTab();
|
||||
commentTab->setComment(comment);
|
||||
int tabIndex = ui->tabWidget->addTab(commentTab, comment.title());
|
||||
|
||||
if (comment.title().isEmpty())
|
||||
ui->tabWidget->setTabText(tabIndex,
|
||||
(defaultTabName + " " + QString::number(tabIndex+1)));
|
||||
|
||||
connect(commentTab, &AnnotationCommentTab::titleChanged,
|
||||
this, &AnnotationEditorDialog::commentTitleChanged);
|
||||
}
|
||||
|
||||
void AnnotationEditorDialog::removeCommentTab(int index)
|
||||
{
|
||||
if ((ui->tabWidget->count() > index) && (index >= 0)) {
|
||||
ui->tabWidget->removeTab(index);
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationEditorDialog::deleteAllTabs()
|
||||
{
|
||||
while (ui->tabWidget->count() > 0) {
|
||||
QWidget *w = ui->tabWidget->widget(0);
|
||||
ui->tabWidget->removeTab(0);
|
||||
delete w;
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationEditorDialog::tabChanged(int index)
|
||||
{
|
||||
QWidget *w = ui->tabWidget->widget(index);
|
||||
AnnotationCommentTab *tab = nullptr;
|
||||
if (w)
|
||||
tab = reinterpret_cast<AnnotationCommentTab*>(w);
|
||||
|
||||
if (tab) {
|
||||
//this tab order resetting doesn't work
|
||||
QWidget::setTabOrder(ui->targetIdEdit, ui->customIdEdit);
|
||||
QWidget::setTabOrder(ui->customIdEdit, ui->tabWidget);
|
||||
QWidget::setTabOrder(ui->tabWidget, tab);
|
||||
QWidget::setTabOrder(tab, ui->buttonBox);
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace QmlDesigner
|
@@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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>
|
||||
|
||||
#include "annotation.h"
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
namespace Ui {
|
||||
class AnnotationEditorDialog;
|
||||
}
|
||||
|
||||
class AnnotationEditorDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AnnotationEditorDialog(QWidget *parent, const QString &targetId, const QString &customId, const Annotation &annotation);
|
||||
~AnnotationEditorDialog();
|
||||
|
||||
void setAnnotation(const Annotation &annotation);
|
||||
Annotation annotation() const;
|
||||
|
||||
void setCustomId(const QString &customId);
|
||||
QString customId() const;
|
||||
|
||||
signals:
|
||||
void accepted();
|
||||
|
||||
private slots:
|
||||
void acceptedClicked();
|
||||
void tabChanged(int index);
|
||||
void commentTitleChanged(const QString &text, QWidget *tab);
|
||||
|
||||
private:
|
||||
void fillFields();
|
||||
void setupComments();
|
||||
void addComment(const Comment &comment);
|
||||
void removeComment(int index);
|
||||
|
||||
void addCommentTab(const Comment &comment);
|
||||
void removeCommentTab(int index);
|
||||
void deleteAllTabs();
|
||||
|
||||
private:
|
||||
const QString titleString = {tr("Annotation Editor")};
|
||||
const QString defaultTabName = {tr("Annotation")};
|
||||
Ui::AnnotationEditorDialog *ui;
|
||||
|
||||
QString m_customId;
|
||||
Annotation m_annotation;
|
||||
};
|
||||
|
||||
} //namespace QmlDesigner
|
@@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QmlDesigner::AnnotationEditorDialog</class>
|
||||
<widget class="QDialog" name="QmlDesigner::AnnotationEditorDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>700</width>
|
||||
<height>487</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="targetIdLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="targetIdLabel">
|
||||
<property name="text">
|
||||
<string>Selected Item</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="targetIdEdit">
|
||||
<property name="frame">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="customIdLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="customIdLabel">
|
||||
<property name="text">
|
||||
<string>Custom ID</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="customIdEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="movable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Tab 1</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Tab 2</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>targetIdEdit</tabstop>
|
||||
<tabstop>customIdEdit</tabstop>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>QmlDesigner::AnnotationEditorDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>261</x>
|
||||
<y>473</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>QmlDesigner::AnnotationEditorDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>329</x>
|
||||
<y>473</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@@ -0,0 +1,258 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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 "annotationtool.h"
|
||||
|
||||
#include "formeditorscene.h"
|
||||
#include "formeditorview.h"
|
||||
#include "formeditorwidget.h"
|
||||
#include "itemutilfunctions.h"
|
||||
#include "formeditoritem.h"
|
||||
|
||||
#include "nodemetainfo.h"
|
||||
#include "qmlitemnode.h"
|
||||
#include <qmldesignerplugin.h>
|
||||
#include <abstractaction.h>
|
||||
#include <designeractionmanager.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QPair>
|
||||
#include <QUrl>
|
||||
#include <QMetaType>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class AnnotationToolAction : public AbstractAction
|
||||
{
|
||||
public:
|
||||
AnnotationToolAction() : AbstractAction(QCoreApplication::translate("AnnotationToolAction","Edit Annotation"))
|
||||
{
|
||||
}
|
||||
|
||||
QByteArray category() const override
|
||||
{
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
QByteArray menuId() const override
|
||||
{
|
||||
return "AnnotationTool";
|
||||
}
|
||||
|
||||
int priority() const override
|
||||
{
|
||||
return CustomActionsPriority + 5;
|
||||
}
|
||||
|
||||
Type type() const override
|
||||
{
|
||||
return FormEditorAction;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool isVisible(const SelectionContext &selectionContext) const override
|
||||
{
|
||||
return selectionContext.singleNodeIsSelected();
|
||||
}
|
||||
|
||||
bool isEnabled(const SelectionContext &selectionContext) const override
|
||||
{
|
||||
return isVisible(selectionContext);
|
||||
}
|
||||
};
|
||||
|
||||
AnnotationTool::AnnotationTool()
|
||||
{
|
||||
auto annotationToolAction = new AnnotationToolAction;
|
||||
QmlDesignerPlugin::instance()->designerActionManager().addDesignerAction(annotationToolAction);
|
||||
connect(annotationToolAction->action(), &QAction::triggered, [=]() {
|
||||
view()->changeCurrentToolTo(this);
|
||||
});
|
||||
}
|
||||
|
||||
AnnotationTool::~AnnotationTool() = default;
|
||||
|
||||
void AnnotationTool::clear()
|
||||
{
|
||||
if (m_annotationEditor)
|
||||
m_annotationEditor->deleteLater();
|
||||
|
||||
AbstractFormEditorTool::clear();
|
||||
}
|
||||
|
||||
void AnnotationTool::mousePressEvent(const QList<QGraphicsItem*> &itemList,
|
||||
QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
AbstractFormEditorTool::mousePressEvent(itemList, event);
|
||||
}
|
||||
|
||||
void AnnotationTool::mouseMoveEvent(const QList<QGraphicsItem*> & /*itemList*/,
|
||||
QGraphicsSceneMouseEvent * /*event*/)
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationTool::hoverMoveEvent(const QList<QGraphicsItem*> & /*itemList*/,
|
||||
QGraphicsSceneMouseEvent * /*event*/)
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationTool::keyPressEvent(QKeyEvent * /*keyEvent*/)
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationTool::dragLeaveEvent(const QList<QGraphicsItem*> &/*itemList*/, QGraphicsSceneDragDropEvent * /*event*/)
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationTool::dragMoveEvent(const QList<QGraphicsItem*> &/*itemList*/, QGraphicsSceneDragDropEvent * /*event*/)
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationTool::mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
|
||||
QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
AbstractFormEditorTool::mouseReleaseEvent(itemList, event);
|
||||
}
|
||||
|
||||
|
||||
void AnnotationTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList, QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
AbstractFormEditorTool::mouseDoubleClickEvent(itemList, event);
|
||||
}
|
||||
|
||||
void AnnotationTool::itemsAboutToRemoved(const QList<FormEditorItem*> &removedItemList)
|
||||
{
|
||||
if (m_annotationEditor.isNull())
|
||||
return;
|
||||
|
||||
if (removedItemList.contains(m_formEditorItem))
|
||||
view()->changeToSelectionTool();
|
||||
}
|
||||
|
||||
void AnnotationTool::selectedItemsChanged(const QList<FormEditorItem*> &itemList)
|
||||
{
|
||||
if (!itemList.isEmpty()) {
|
||||
m_formEditorItem = itemList.constFirst();
|
||||
|
||||
m_oldCustomId = m_formEditorItem->qmlItemNode().modelNode().customId();
|
||||
m_oldAnnotation = m_formEditorItem->qmlItemNode().modelNode().annotation();
|
||||
|
||||
if (m_annotationEditor.isNull()) {
|
||||
m_annotationEditor = new AnnotationEditorDialog(view()->formEditorWidget()->parentWidget(),
|
||||
m_formEditorItem->qmlItemNode().modelNode().displayName(),
|
||||
m_oldCustomId, m_oldAnnotation);
|
||||
|
||||
connect(m_annotationEditor, &AnnotationEditorDialog::accepted, this, &AnnotationTool::annotationDialogAccepted);
|
||||
connect(m_annotationEditor, &QDialog::rejected, this, &AnnotationTool::annotationDialogRejected);
|
||||
// connect(m_colorDialog.data(), &QColorDialog::currentColorChanged, this, &ColorTool::currentColorChanged);
|
||||
|
||||
m_annotationEditor->exec();
|
||||
}
|
||||
} else {
|
||||
view()->changeToSelectionTool();
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationTool::instancesCompleted(const QList<FormEditorItem*> & /*itemList*/)
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationTool::instancesParentChanged(const QList<FormEditorItem *> & /*itemList*/)
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationTool::instancePropertyChange(const QList<QPair<ModelNode, PropertyName> > & /*propertyList*/)
|
||||
{
|
||||
}
|
||||
|
||||
void AnnotationTool::formEditorItemsChanged(const QList<FormEditorItem*> & /*itemList*/)
|
||||
{
|
||||
}
|
||||
|
||||
int AnnotationTool::wantHandleItem(const ModelNode & /*modelNode*/) const
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
QString AnnotationTool::name() const
|
||||
{
|
||||
return tr("Annotation Tool");
|
||||
}
|
||||
|
||||
void AnnotationTool::annotationDialogAccepted()
|
||||
{
|
||||
if (m_annotationEditor) {
|
||||
saveNewCustomId(m_annotationEditor->customId());
|
||||
saveNewAnnotation(m_annotationEditor->annotation());
|
||||
|
||||
m_annotationEditor->close();
|
||||
m_annotationEditor->deleteLater();
|
||||
}
|
||||
|
||||
m_annotationEditor = nullptr;
|
||||
|
||||
view()->changeToSelectionTool();
|
||||
}
|
||||
|
||||
void AnnotationTool::saveNewCustomId(const QString &customId)
|
||||
{
|
||||
if (m_formEditorItem) {
|
||||
m_oldCustomId = customId;
|
||||
m_formEditorItem->qmlItemNode().modelNode().setCustomId(customId);
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationTool::saveNewAnnotation(const Annotation &annotation)
|
||||
{
|
||||
if (m_formEditorItem) {
|
||||
if (annotation.comments().isEmpty())
|
||||
m_formEditorItem->qmlItemNode().modelNode().removeAnnotation();
|
||||
else
|
||||
m_formEditorItem->qmlItemNode().modelNode().setAnnotation(annotation);
|
||||
|
||||
m_oldAnnotation = annotation;
|
||||
}
|
||||
}
|
||||
|
||||
void AnnotationTool::annotationDialogRejected()
|
||||
{
|
||||
if (m_annotationEditor) {
|
||||
m_annotationEditor->close();
|
||||
m_annotationEditor->deleteLater();
|
||||
}
|
||||
|
||||
m_annotationEditor = nullptr;
|
||||
|
||||
view()->changeToSelectionTool();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,93 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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 "annotation.h"
|
||||
#include "annotationeditordialog.h"
|
||||
#include "abstractcustomtool.h"
|
||||
#include "selectionindicator.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QPointer>
|
||||
#include <QDialog>
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class AnnotationTool : public QObject, public AbstractCustomTool
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AnnotationTool();
|
||||
~AnnotationTool() override;
|
||||
|
||||
void mousePressEvent(const QList<QGraphicsItem*> &itemList,
|
||||
QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
|
||||
QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
|
||||
QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList,
|
||||
QGraphicsSceneMouseEvent *event) override;
|
||||
void hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
|
||||
QGraphicsSceneMouseEvent *event) override;
|
||||
void keyPressEvent(QKeyEvent *event) override;
|
||||
void keyReleaseEvent(QKeyEvent *keyEvent) override;
|
||||
|
||||
void dragLeaveEvent(const QList<QGraphicsItem*> &itemList,
|
||||
QGraphicsSceneDragDropEvent * event) override;
|
||||
void dragMoveEvent(const QList<QGraphicsItem*> &itemList,
|
||||
QGraphicsSceneDragDropEvent * event) override;
|
||||
|
||||
void itemsAboutToRemoved(const QList<FormEditorItem*> &itemList) override;
|
||||
|
||||
void selectedItemsChanged(const QList<FormEditorItem*> &itemList) override; //impl needed
|
||||
|
||||
void instancesCompleted(const QList<FormEditorItem*> &itemList) override;
|
||||
void instancesParentChanged(const QList<FormEditorItem *> &itemList) override;
|
||||
void instancePropertyChange(const QList<QPair<ModelNode, PropertyName> > &propertyList) override;
|
||||
|
||||
void clear() override;
|
||||
|
||||
void formEditorItemsChanged(const QList<FormEditorItem*> &itemList) override;
|
||||
|
||||
int wantHandleItem(const ModelNode &modelNode) const override;
|
||||
|
||||
QString name() const override;
|
||||
|
||||
private:
|
||||
void annotationDialogAccepted();
|
||||
void annotationDialogRejected();
|
||||
void saveNewCustomId(const QString &customId);
|
||||
void saveNewAnnotation(const Annotation &annotation);
|
||||
|
||||
private:
|
||||
FormEditorItem *m_formEditorItem = nullptr;
|
||||
QString m_oldCustomId;
|
||||
Annotation m_oldAnnotation;
|
||||
QPointer<AnnotationEditorDialog> m_annotationEditor;
|
||||
};
|
||||
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 449 B |
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
@@ -36,7 +36,8 @@ SOURCES += formeditoritem.cpp \
|
||||
contentnoteditableindicator.cpp \
|
||||
backgroundaction.cpp \
|
||||
formeditortoolbutton.cpp \
|
||||
option3daction.cpp
|
||||
option3daction.cpp \
|
||||
formeditorannotationicon.cpp
|
||||
|
||||
HEADERS += formeditorscene.h \
|
||||
formeditorwidget.h \
|
||||
@@ -75,6 +76,7 @@ HEADERS += formeditorscene.h \
|
||||
contentnoteditableindicator.h \
|
||||
backgroundaction.h \
|
||||
formeditortoolbutton.h \
|
||||
option3daction.h
|
||||
option3daction.h \
|
||||
formeditorannotationicon.h
|
||||
|
||||
RESOURCES += formeditor.qrc
|
||||
|
@@ -6,5 +6,7 @@
|
||||
<file>no_snapping@2x.png</file>
|
||||
<file>snapping_and_anchoring.png</file>
|
||||
<file>snapping_and_anchoring@2x.png</file>
|
||||
<file>annotationsIcon.png</file>
|
||||
<file>annotationsIconActive.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@@ -0,0 +1,463 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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 "formeditorannotationicon.h"
|
||||
|
||||
#include <QGraphicsSceneMouseEvent>
|
||||
#include <QGraphicsLinearLayout>
|
||||
#include <QPainter>
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <utils/theme/theme.h>
|
||||
#include <utils/stylehelper.h>
|
||||
#include <annotationeditor/annotation.h>
|
||||
#include <annotationeditor/annotationeditordialog.h>
|
||||
#include <formeditorscene.h>
|
||||
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
FormEditorAnnotationIcon::FormEditorAnnotationIcon(const ModelNode &modelNode, QGraphicsItem *parent)
|
||||
: QGraphicsObject(parent)
|
||||
, m_modelNode(modelNode)
|
||||
, m_readerIsActive(false)
|
||||
, m_customId(modelNode.customId())
|
||||
, m_annotation(modelNode.annotation())
|
||||
, m_annotationEditor(nullptr)
|
||||
, m_normalIconStr(":icon/layout/annotationsIcon.png")
|
||||
, m_activeIconStr(":icon/layout/annotationsIconActive.png")
|
||||
, m_iconW(40)
|
||||
, m_iconH(32)
|
||||
{
|
||||
setAcceptHoverEvents(true);
|
||||
|
||||
bool hasAuxData = modelNode.hasAnnotation() || modelNode.hasCustomId();
|
||||
|
||||
setEnabled(hasAuxData);
|
||||
setVisible(hasAuxData);
|
||||
|
||||
FormEditorScene *scene = qobject_cast<FormEditorScene*>(parentItem()->scene());
|
||||
if (scene) {
|
||||
m_readerIsActive = scene->annotationVisibility();
|
||||
if (m_readerIsActive) {
|
||||
drawReader();
|
||||
}
|
||||
}
|
||||
|
||||
setToolTip(tr("Annotation"));
|
||||
setCursor(Qt::ArrowCursor);
|
||||
}
|
||||
|
||||
FormEditorAnnotationIcon::~FormEditorAnnotationIcon()
|
||||
{
|
||||
if (m_annotationEditor) {
|
||||
m_annotationEditor->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
|
||||
{
|
||||
painter->save();
|
||||
painter->setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
painter->setPen(Qt::NoPen);
|
||||
|
||||
if (!isEnabled())
|
||||
setOpacity(0.5);
|
||||
|
||||
bool hasAuxData = m_modelNode.hasAnnotation() || m_modelNode.hasCustomId();
|
||||
|
||||
if (hasAuxData) {
|
||||
FormEditorScene *scene = qobject_cast<FormEditorScene*>(parentItem()->scene());
|
||||
if (scene)
|
||||
m_readerIsActive = scene->annotationVisibility();
|
||||
|
||||
QPixmap icon( (m_readerIsActive ? m_activeIconStr : m_normalIconStr) );
|
||||
|
||||
painter->drawPixmap(0, 0,
|
||||
static_cast<int>(m_iconW), static_cast<int>(m_iconH),
|
||||
icon);
|
||||
|
||||
m_customId = m_modelNode.customId();
|
||||
m_annotation = m_modelNode.annotation();
|
||||
|
||||
if (m_readerIsActive)
|
||||
resetReader();
|
||||
}
|
||||
else {
|
||||
hideReader();
|
||||
}
|
||||
|
||||
setEnabled(hasAuxData);
|
||||
setVisible(hasAuxData);
|
||||
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
QRectF FormEditorAnnotationIcon::boundingRect() const
|
||||
{
|
||||
return QRectF(0, 0, m_iconW, m_iconH);
|
||||
}
|
||||
|
||||
qreal FormEditorAnnotationIcon::iconWidth()
|
||||
{
|
||||
return m_iconW;
|
||||
}
|
||||
|
||||
qreal FormEditorAnnotationIcon::iconHeight()
|
||||
{
|
||||
return m_iconH;
|
||||
}
|
||||
|
||||
bool FormEditorAnnotationIcon::isReaderActive()
|
||||
{
|
||||
return m_readerIsActive;
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::setActive(bool readerStatus)
|
||||
{
|
||||
m_readerIsActive = readerStatus;
|
||||
|
||||
if (m_readerIsActive)
|
||||
resetReader();
|
||||
else
|
||||
hideReader();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::hoverEnterEvent(QGraphicsSceneHoverEvent * event)
|
||||
{
|
||||
QGraphicsItem::hoverEnterEvent(event);
|
||||
event->accept();
|
||||
update();
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::hoverLeaveEvent(QGraphicsSceneHoverEvent * event)
|
||||
{
|
||||
QGraphicsItem::hoverLeaveEvent(event);
|
||||
event->accept();
|
||||
update();
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::hoverMoveEvent(QGraphicsSceneHoverEvent * event)
|
||||
{
|
||||
QGraphicsItem::hoverMoveEvent(event);
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::mousePressEvent(QGraphicsSceneMouseEvent * event)
|
||||
{
|
||||
event->accept();
|
||||
Qt::MouseButton button = event->button();
|
||||
|
||||
if (button == Qt::LeftButton) {
|
||||
if (m_readerIsActive) {
|
||||
hideReader();
|
||||
m_readerIsActive = false;
|
||||
} else {
|
||||
drawReader();
|
||||
m_readerIsActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
FormEditorScene *scene = qobject_cast<FormEditorScene*>(parentItem()->scene());
|
||||
if (scene)
|
||||
scene->setAnnotationVisibility(m_readerIsActive);
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
|
||||
{
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
|
||||
{
|
||||
QMenu menu;
|
||||
menu.addAction(tr("Edit Annotation"), [this]() {
|
||||
createAnnotationEditor();
|
||||
});
|
||||
|
||||
menu.addAction(tr("Remove Annotation"), [this]() {
|
||||
removeAnnotationDialog();
|
||||
});
|
||||
|
||||
menu.exec(event->screenPos());
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::resetReader()
|
||||
{
|
||||
hideReader();
|
||||
drawReader();
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::drawReader()
|
||||
{
|
||||
const qreal width = 290;
|
||||
const qreal height = 200;
|
||||
const qreal offset = 5;
|
||||
|
||||
const QRectF titleRect(0, 0, width, 30);
|
||||
const QPointF cornerPosition(m_iconW + offset, 0);
|
||||
|
||||
QGraphicsItem *titleBubble = createTitleBubble(titleRect, m_customId, this);
|
||||
titleBubble->setPos(cornerPosition);
|
||||
|
||||
if (m_annotation.hasComments()) {
|
||||
QList<QGraphicsItem*> comments;
|
||||
|
||||
QPointF commentPosition(cornerPosition.x(), 40);
|
||||
QRectF commentRect(0, 0, width, height);
|
||||
|
||||
for (const Comment &comment : m_annotation.comments()) {
|
||||
QGraphicsItem *commentBubble = createCommentBubble(commentRect, comment.title(),
|
||||
comment.author(), comment.text(),
|
||||
comment.timestampStr(), this);
|
||||
commentBubble->setPos(commentPosition);
|
||||
|
||||
commentPosition += QPointF(width + offset, 0);
|
||||
comments.push_back(commentBubble);
|
||||
}
|
||||
|
||||
|
||||
int currentColumn = 0;
|
||||
qreal columnHeight = 0;
|
||||
const qreal maxHeight = 650;
|
||||
const QPointF commentsStartPosition(cornerPosition.x(), cornerPosition.y() + titleRect.height() + (offset*2));
|
||||
QPointF newPos(commentsStartPosition);
|
||||
|
||||
for (QGraphicsItem *comment : comments) {
|
||||
qreal itemHeight = comment->boundingRect().height();
|
||||
|
||||
if ((columnHeight + offset + itemHeight) > maxHeight) {
|
||||
// have no extra space
|
||||
columnHeight = 0;
|
||||
++currentColumn;
|
||||
|
||||
newPos = commentsStartPosition + QPointF(currentColumn * (offset + width), 0);
|
||||
|
||||
} else {
|
||||
//few normal comments, lets stack them
|
||||
}
|
||||
|
||||
columnHeight += itemHeight + offset;
|
||||
|
||||
comment->setPos(newPos);
|
||||
|
||||
newPos += QPointF(0, itemHeight + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::hideReader()
|
||||
{
|
||||
if (!childItems().isEmpty()) {
|
||||
for (QGraphicsItem *item : childItems()) {
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QGraphicsItem *FormEditorAnnotationIcon::createCommentBubble(const QRectF &rect, const QString &title,
|
||||
const QString &author, const QString &text,
|
||||
const QString &date, QGraphicsItem *parent)
|
||||
{
|
||||
static QColor textColor = Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_FormEditorForegroundColor);
|
||||
static QColor backgroundColor = Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_BackgroundColorDarker);
|
||||
static QColor frameColor = Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_BackgroundColor);
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
|
||||
QGraphicsRectItem *frameItem = new QGraphicsRectItem(rect, parent);
|
||||
|
||||
QGraphicsTextItem *titleItem = new QGraphicsTextItem(frameItem);
|
||||
titleItem->setPlainText(title);
|
||||
titleItem->setFont(font);
|
||||
titleItem->setDefaultTextColor(textColor);
|
||||
titleItem->setTextWidth(rect.width());
|
||||
titleItem->update();
|
||||
|
||||
QGraphicsTextItem *authorItem = new QGraphicsTextItem(frameItem);
|
||||
authorItem->setPlainText(tr("By: ") + author);
|
||||
authorItem->setDefaultTextColor(textColor);
|
||||
authorItem->setTextWidth(rect.width());
|
||||
authorItem->setPos(titleItem->x(), titleItem->boundingRect().height() + titleItem->y());
|
||||
authorItem->update();
|
||||
|
||||
QGraphicsTextItem *textItem = new QGraphicsTextItem(frameItem);
|
||||
textItem->setPlainText(text);
|
||||
textItem->setDefaultTextColor(textColor);
|
||||
textItem->setTextWidth(rect.width());
|
||||
textItem->setPos(authorItem->x(), authorItem->boundingRect().height() + authorItem->y() + 5);
|
||||
textItem->update();
|
||||
|
||||
qreal contentRect = titleItem->boundingRect().height()
|
||||
+ authorItem->boundingRect().height()
|
||||
+ textItem->boundingRect().height();
|
||||
|
||||
if ((contentRect + 60) > rect.height()) {
|
||||
frameItem->setRect(rect.x(), rect.y(), rect.width(), contentRect+60);
|
||||
}
|
||||
|
||||
QGraphicsTextItem *dateItem = new QGraphicsTextItem(frameItem);
|
||||
dateItem->setPlainText(tr("Edited: ") + date);
|
||||
dateItem->setDefaultTextColor(textColor);
|
||||
dateItem->setTextWidth(rect.width());
|
||||
dateItem->setPos(frameItem->boundingRect().bottomLeft() + QPointF(0, -30));
|
||||
dateItem->update();
|
||||
|
||||
QPen pen;
|
||||
pen.setCosmetic(true);
|
||||
pen.setWidth(2);
|
||||
pen.setCapStyle(Qt::RoundCap);
|
||||
pen.setJoinStyle(Qt::BevelJoin);
|
||||
pen.setColor(frameColor);
|
||||
|
||||
frameItem->setPen(pen); //outline
|
||||
frameItem->setBrush(backgroundColor); //back
|
||||
frameItem->update();
|
||||
|
||||
return frameItem;
|
||||
}
|
||||
|
||||
QGraphicsItem *FormEditorAnnotationIcon::createTitleBubble(const QRectF &rect, const QString &text, QGraphicsItem *parent)
|
||||
{
|
||||
static QColor textColor = Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_FormEditorForegroundColor);
|
||||
static QColor backgroundColor = Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_BackgroundColorDarker);
|
||||
static QColor frameColor = Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_BackgroundColor);
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
|
||||
QGraphicsRectItem *frameItem = new QGraphicsRectItem(rect, parent);
|
||||
QGraphicsTextItem *titleItem = new QGraphicsTextItem(text, frameItem);
|
||||
|
||||
titleItem->setDefaultTextColor(textColor);
|
||||
titleItem->setFont(font);
|
||||
titleItem->update();
|
||||
|
||||
if (titleItem->boundingRect().width() > rect.width()) {
|
||||
frameItem->setRect(QRectF(rect.x(), rect.y(),
|
||||
titleItem->boundingRect().width(), rect.height()));
|
||||
}
|
||||
|
||||
QPen pen;
|
||||
pen.setCosmetic(true);
|
||||
pen.setWidth(2);
|
||||
pen.setCapStyle(Qt::RoundCap);
|
||||
pen.setJoinStyle(Qt::BevelJoin);
|
||||
pen.setColor(frameColor);
|
||||
|
||||
frameItem->setPen(pen); //outline
|
||||
frameItem->setBrush(backgroundColor); //back
|
||||
frameItem->update();
|
||||
|
||||
return frameItem;
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::createAnnotationEditor()
|
||||
{
|
||||
if (m_annotationEditor) {
|
||||
m_annotationEditor->close();
|
||||
m_annotationEditor->deleteLater();
|
||||
m_annotationEditor = nullptr;
|
||||
}
|
||||
|
||||
m_annotationEditor = new AnnotationEditorDialog(Core::ICore::dialogParent(),
|
||||
m_modelNode.displayName(),
|
||||
m_modelNode.customId(),
|
||||
m_modelNode.annotation());
|
||||
|
||||
connect(m_annotationEditor, &AnnotationEditorDialog::accepted,
|
||||
this, &FormEditorAnnotationIcon::annotationDialogAccepted);
|
||||
connect(m_annotationEditor, &QDialog::rejected,
|
||||
this, &FormEditorAnnotationIcon::annotationDialogRejected);
|
||||
|
||||
m_annotationEditor->open();
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::removeAnnotationDialog()
|
||||
{
|
||||
QString dialogTitle = tr("Annotation");
|
||||
if (!m_customId.isNull()) {
|
||||
dialogTitle = m_customId;
|
||||
}
|
||||
QMessageBox *deleteDialog = new QMessageBox(Core::ICore::dialogParent());
|
||||
deleteDialog->setWindowTitle(dialogTitle);
|
||||
deleteDialog->setText(tr("Delete this annotation?"));
|
||||
deleteDialog->setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
deleteDialog->setDefaultButton(QMessageBox::Yes);
|
||||
|
||||
int result = deleteDialog->exec();
|
||||
if (deleteDialog) deleteDialog->deleteLater();
|
||||
|
||||
if (result == QMessageBox::Yes) {
|
||||
m_modelNode.removeCustomId();
|
||||
m_modelNode.removeAnnotation();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::annotationDialogAccepted()
|
||||
{
|
||||
if (m_annotationEditor) {
|
||||
QString customId = m_annotationEditor->customId();
|
||||
m_customId = customId;
|
||||
m_modelNode.setCustomId(customId);
|
||||
|
||||
Annotation annotation = m_annotationEditor->annotation();
|
||||
|
||||
if (annotation.comments().isEmpty())
|
||||
m_modelNode.removeAnnotation();
|
||||
else
|
||||
m_modelNode.setAnnotation(annotation);
|
||||
|
||||
m_annotation = annotation;
|
||||
|
||||
m_annotationEditor->close();
|
||||
m_annotationEditor->deleteLater();
|
||||
}
|
||||
|
||||
m_annotationEditor = nullptr;
|
||||
|
||||
if (m_readerIsActive)
|
||||
resetReader();
|
||||
}
|
||||
|
||||
void FormEditorAnnotationIcon::annotationDialogRejected()
|
||||
{
|
||||
if (m_annotationEditor) {
|
||||
m_annotationEditor->close();
|
||||
m_annotationEditor->deleteLater();
|
||||
}
|
||||
|
||||
m_annotationEditor = nullptr;
|
||||
}
|
||||
|
||||
} //QmlDesigner
|
@@ -0,0 +1,100 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2020 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** 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 <annotationeditor/annotation.h>
|
||||
|
||||
#include <QGraphicsItem>
|
||||
#include <QGraphicsObject>
|
||||
#include <QIcon>
|
||||
#include <QObject>
|
||||
#include <modelnode.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class AnnotationEditorDialog;
|
||||
|
||||
class FormEditorAnnotationIcon : public QGraphicsObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit FormEditorAnnotationIcon(const ModelNode &modelNode, QGraphicsItem *parent = nullptr);
|
||||
~FormEditorAnnotationIcon() override;
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
|
||||
QRectF boundingRect() const override;
|
||||
|
||||
qreal iconWidth();
|
||||
qreal iconHeight();
|
||||
|
||||
bool isReaderActive();
|
||||
void setActive(bool readerStatus);
|
||||
|
||||
void resetReader();
|
||||
|
||||
protected:
|
||||
void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override;
|
||||
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override;
|
||||
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;
|
||||
void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
|
||||
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
|
||||
|
||||
private:
|
||||
void drawReader();
|
||||
void hideReader();
|
||||
QGraphicsItem *createCommentBubble(const QRectF &rect, const QString &title,
|
||||
const QString &author, const QString &text,
|
||||
const QString &date, QGraphicsItem *parent);
|
||||
QGraphicsItem *createTitleBubble(const QRectF &rect, const QString &text, QGraphicsItem *parent);
|
||||
|
||||
void createAnnotationEditor();
|
||||
void removeAnnotationDialog();
|
||||
|
||||
void annotationDialogAccepted();
|
||||
void annotationDialogRejected();
|
||||
|
||||
private:
|
||||
ModelNode m_modelNode;
|
||||
bool m_readerIsActive;
|
||||
QString m_customId;
|
||||
Annotation m_annotation;
|
||||
AnnotationEditorDialog *m_annotationEditor;
|
||||
|
||||
QString m_normalIconStr;
|
||||
QString m_activeIconStr;
|
||||
|
||||
qreal m_iconW;
|
||||
qreal m_iconH;
|
||||
};
|
||||
|
||||
} //QmlDesigner
|
@@ -49,9 +49,10 @@
|
||||
namespace QmlDesigner {
|
||||
|
||||
FormEditorScene::FormEditorScene(FormEditorWidget *view, FormEditorView *editorView)
|
||||
: QGraphicsScene(),
|
||||
m_editorView(editorView),
|
||||
m_showBoundingRects(false)
|
||||
: QGraphicsScene()
|
||||
, m_editorView(editorView)
|
||||
, m_showBoundingRects(false)
|
||||
, m_annotationVisibility(false)
|
||||
{
|
||||
setupScene();
|
||||
view->setScene(this);
|
||||
@@ -431,5 +432,15 @@ bool FormEditorScene::showBoundingRects() const
|
||||
return m_showBoundingRects;
|
||||
}
|
||||
|
||||
bool FormEditorScene::annotationVisibility() const
|
||||
{
|
||||
return m_annotationVisibility;
|
||||
}
|
||||
|
||||
void FormEditorScene::setAnnotationVisibility(bool status)
|
||||
{
|
||||
m_annotationVisibility = status;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -95,6 +95,9 @@ public:
|
||||
void setShowBoundingRects(bool show);
|
||||
bool showBoundingRects() const;
|
||||
|
||||
bool annotationVisibility() const;
|
||||
void setAnnotationVisibility(bool status);
|
||||
|
||||
protected:
|
||||
bool event(QEvent *event) override;
|
||||
void dropEvent(QGraphicsSceneDragDropEvent * event) override;
|
||||
@@ -129,6 +132,7 @@ private:
|
||||
QPointer<LayerItem> m_manipulatorLayerItem;
|
||||
ModelNode m_dragNode;
|
||||
bool m_showBoundingRects;
|
||||
bool m_annotationVisibility;
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -501,6 +501,7 @@ void FormEditorView::changeCurrentToolTo(AbstractFormEditorTool *newTool)
|
||||
m_currentTool->clear();
|
||||
m_currentTool->setItems(scene()->itemsForQmlItemNodes(toQmlItemNodeList(
|
||||
selectedModelNodes())));
|
||||
|
||||
m_currentTool->start();
|
||||
}
|
||||
|
||||
@@ -530,6 +531,10 @@ void FormEditorView::auxiliaryDataChanged(const ModelNode &node, const PropertyN
|
||||
FormEditorItem *editorItem = m_scene->itemForQmlItemNode(item);
|
||||
if (editorItem)
|
||||
editorItem->update();
|
||||
} else if (name == "annotation" || name == "customId") {
|
||||
if (FormEditorItem *editorItem = scene()->itemForQmlItemNode(item)) {
|
||||
editorItem->update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -26,6 +26,8 @@
|
||||
#include "selectionindicator.h"
|
||||
|
||||
#include <designeractionmanager.h>
|
||||
#include "annotationeditor/annotation.h"
|
||||
#include <formeditorannotationicon.h>
|
||||
|
||||
#include <QPen>
|
||||
#include <QGraphicsScene>
|
||||
@@ -42,6 +44,7 @@ namespace QmlDesigner {
|
||||
|
||||
SelectionIndicator::SelectionIndicator(LayerItem *layerItem)
|
||||
: m_layerItem(layerItem)
|
||||
, m_annotationItem(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -75,6 +78,7 @@ void SelectionIndicator::clear()
|
||||
}
|
||||
}
|
||||
m_labelItem.reset(nullptr);
|
||||
m_annotationItem = nullptr;
|
||||
m_indicatorShapeHash.clear();
|
||||
}
|
||||
|
||||
@@ -119,6 +123,7 @@ void SelectionIndicator::setItems(const QList<FormEditorItem*> &itemList)
|
||||
if (checkSingleSelection(itemList)) {
|
||||
FormEditorItem *selectedItem = itemList.constFirst();
|
||||
m_labelItem = std::make_unique<QGraphicsPolygonItem>(m_layerItem.data());
|
||||
const qreal scaleFactor = m_layerItem->viewportTransform().m11();
|
||||
|
||||
QGraphicsWidget *toolbar = DesignerActionManager::instance().createFormEditorToolBar(m_labelItem.get());
|
||||
toolbar->setPos(1, -1);
|
||||
@@ -129,6 +134,14 @@ void SelectionIndicator::setItems(const QList<FormEditorItem*> &itemList)
|
||||
if (modelNode.hasId())
|
||||
textItem->setPlainText(modelNode.id());
|
||||
|
||||
if (modelNode.hasAnnotation() || modelNode.hasCustomId()) {
|
||||
m_annotationItem = new FormEditorAnnotationIcon(modelNode, m_labelItem.get());
|
||||
m_annotationItem->update();
|
||||
}
|
||||
else {
|
||||
m_annotationItem = nullptr;
|
||||
}
|
||||
|
||||
static QColor textColor = Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_FormEditorForegroundColor);
|
||||
|
||||
textItem->setDefaultTextColor(textColor);
|
||||
@@ -139,18 +152,25 @@ void SelectionIndicator::setItems(const QList<FormEditorItem*> &itemList)
|
||||
QPointF pos = labelRect.topLeft();
|
||||
labelRect.moveTo(0, 0);
|
||||
m_labelItem->setPolygon(labelRect);
|
||||
const int scaledHeight = labelHeight / m_layerItem->viewportTransform().m11();
|
||||
const int scaledHeight = labelHeight / scaleFactor;
|
||||
m_labelItem->setPos(pos + QPointF(0, -scaledHeight));
|
||||
const int offset = (labelHeight - textItem->boundingRect().height()) / 2;
|
||||
textItem->setPos(QPointF(toolbar->size().width(), offset));
|
||||
m_labelItem->setFlag(QGraphicsItem::ItemIsSelectable, false);
|
||||
m_labelItem->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
|
||||
|
||||
QPen pen;
|
||||
pen.setCosmetic(true);
|
||||
pen.setWidth(2);
|
||||
pen.setCapStyle(Qt::RoundCap);
|
||||
pen.setJoinStyle(Qt::BevelJoin);
|
||||
pen.setColor(selectionColor);
|
||||
|
||||
if (m_annotationItem) {
|
||||
m_annotationItem->setFlags(QGraphicsItem::ItemIgnoresTransformations);
|
||||
adjustAnnotationPosition(labelPolygon.boundingRect(), m_labelItem->boundingRect(), scaleFactor);
|
||||
}
|
||||
|
||||
m_labelItem->setPen(pen);
|
||||
m_labelItem->setBrush(selectionColor);
|
||||
m_labelItem->update();
|
||||
@@ -172,8 +192,14 @@ void SelectionIndicator::updateItems(const QList<FormEditorItem*> &itemList)
|
||||
QPolygonF labelPolygon = boundingRectInLayerItemSpaceForItem(selectedItem, m_layerItem.data());
|
||||
QRectF labelRect = labelPolygon.boundingRect();
|
||||
QPointF pos = labelRect.topLeft();
|
||||
const int scaledHeight = labelHeight / m_layerItem->viewportTransform().m11();
|
||||
const qreal scaleFactor = m_layerItem->viewportTransform().m11();
|
||||
const int scaledHeight = labelHeight / scaleFactor;
|
||||
m_labelItem->setPos(pos + QPointF(0, -scaledHeight));
|
||||
|
||||
if (m_annotationItem) {
|
||||
adjustAnnotationPosition(labelPolygon.boundingRect(), m_labelItem->boundingRect(), scaleFactor);
|
||||
}
|
||||
|
||||
m_layerItem->update();
|
||||
}
|
||||
}
|
||||
@@ -186,5 +212,24 @@ void SelectionIndicator::setCursor(const QCursor &cursor)
|
||||
item->setCursor(cursor);
|
||||
}
|
||||
|
||||
void SelectionIndicator::adjustAnnotationPosition(const QRectF &itemRect, const QRectF &labelRect, qreal scaleFactor)
|
||||
{
|
||||
if (!m_annotationItem) return;
|
||||
|
||||
const qreal iconW = 40 * 0.5; //*0.5 for a shift of an icon outide the item
|
||||
qreal iconX = 0.0;
|
||||
qreal iconY = -15.0/scaleFactor; //small offset
|
||||
|
||||
if (((labelRect.width() + iconW)/scaleFactor) > itemRect.width())
|
||||
iconY -= labelRect.height()/scaleFactor;
|
||||
|
||||
if ((iconW/scaleFactor) > itemRect.width())
|
||||
iconX = 0.0;
|
||||
else
|
||||
iconX = (itemRect.width()) - (iconW/scaleFactor);
|
||||
|
||||
m_annotationItem->setPos(iconX*scaleFactor, iconY*scaleFactor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -35,6 +35,8 @@
|
||||
|
||||
namespace QmlDesigner {
|
||||
|
||||
class FormEditorAnnotationIcon;
|
||||
|
||||
class SelectionIndicator
|
||||
{
|
||||
public:
|
||||
@@ -50,12 +52,16 @@ public:
|
||||
void updateItems(const QList<FormEditorItem*> &itemList);
|
||||
|
||||
void setCursor(const QCursor &cursor);
|
||||
private:
|
||||
void adjustAnnotationPosition(const QRectF &itemRect, const QRectF &labelRect, qreal scaleFactor);
|
||||
|
||||
private:
|
||||
QHash<FormEditorItem*, QGraphicsPolygonItem *> m_indicatorShapeHash;
|
||||
FormEditorItem *m_selectedItem;
|
||||
QPointer<LayerItem> m_layerItem;
|
||||
QCursor m_cursor;
|
||||
std::unique_ptr<QGraphicsPolygonItem> m_labelItem;
|
||||
FormEditorAnnotationIcon *m_annotationItem; //handled by m_labelItem
|
||||
};
|
||||
|
||||
} // namespace QmlDesigner
|
||||
|
@@ -159,6 +159,8 @@ QVariant properDefaultAuxiliaryProperties(const QmlObjectNode &qmlObjectNode,
|
||||
return 0;
|
||||
else if (propertyName == "break")
|
||||
return 50;
|
||||
else if (propertyName == "customId")
|
||||
return QString();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -221,6 +223,8 @@ void PropertyEditorQmlBackend::setupAuxiliaryProperties(const QmlObjectNode &qml
|
||||
|
||||
PropertyNameList propertyNames;
|
||||
|
||||
propertyNames.append("customId");
|
||||
|
||||
if (itemNode.isFlowTransition()) {
|
||||
propertyNames.append({"color", "width", "inOffset", "outOffset", "dash", "break"});
|
||||
} else if (itemNode.isFlowItem()) {
|
||||
|
@@ -34,6 +34,7 @@
|
||||
#include "simplecolorpalettemodel.h"
|
||||
#include "bindingeditor/bindingeditor.h"
|
||||
#include "bindingeditor/actioneditor.h"
|
||||
#include "annotationeditor/annotationeditor.h"
|
||||
#include "qmlanchorbindingproxy.h"
|
||||
#include "theme.h"
|
||||
#include "aligndistribute.h"
|
||||
@@ -63,6 +64,7 @@ void Quick2PropertyEditorView::registerQmlTypes()
|
||||
Internal::QmlAnchorBindingProxy::registerDeclarativeType();
|
||||
BindingEditor::registerDeclarativeType();
|
||||
ActionEditor::registerDeclarativeType();
|
||||
AnnotationEditor::registerDeclarativeType();
|
||||
AlignDistribute::registerDeclarativeType();
|
||||
Tooltip::registerDeclarativeType();
|
||||
}
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "qmldesignercorelib_global.h"
|
||||
#include <QPointer>
|
||||
#include <QList>
|
||||
#include <QVector>
|
||||
#include <QVariant>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@@ -56,6 +57,8 @@ class NodeListProperty;
|
||||
class NodeProperty;
|
||||
class NodeAbstractProperty;
|
||||
class ModelNode;
|
||||
class Comment;
|
||||
class Annotation;
|
||||
|
||||
QMLDESIGNERCORE_EXPORT QList<Internal::InternalNodePointer> toInternalNodeList(const QList<ModelNode> &nodeList);
|
||||
|
||||
@@ -183,6 +186,22 @@ public:
|
||||
bool hasAuxiliaryData(const PropertyName &name) const;
|
||||
QHash<PropertyName, QVariant> auxiliaryData() const;
|
||||
|
||||
QString customId() const;
|
||||
bool hasCustomId() const;
|
||||
void setCustomId(const QString &str);
|
||||
void removeCustomId();
|
||||
|
||||
QVector<Comment> comments() const;
|
||||
bool hasComments() const;
|
||||
void setComments(const QVector<Comment> &coms);
|
||||
void addComment(const Comment &com);
|
||||
bool updateComment(const Comment &com, int position);
|
||||
|
||||
Annotation annotation() const;
|
||||
bool hasAnnotation() const;
|
||||
void setAnnotation(const Annotation &annotation);
|
||||
void removeAnnotation();
|
||||
|
||||
qint32 internalId() const;
|
||||
|
||||
void setNodeSource(const QString&);
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include "nodelistproperty.h"
|
||||
#include "nodeproperty.h"
|
||||
#include <rewriterview.h>
|
||||
#include "annotationeditor/annotation.h"
|
||||
|
||||
#include <utils/algorithm.h>
|
||||
|
||||
@@ -1052,6 +1053,100 @@ QHash<PropertyName, QVariant> ModelNode::auxiliaryData() const
|
||||
return internalNode()->auxiliaryData();
|
||||
}
|
||||
|
||||
QString ModelNode::customId() const
|
||||
{
|
||||
QString result;
|
||||
if (hasCustomId())
|
||||
result = auxiliaryData(customIdProperty).value<QString>();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ModelNode::hasCustomId() const
|
||||
{
|
||||
return hasAuxiliaryData(customIdProperty);
|
||||
}
|
||||
|
||||
void ModelNode::setCustomId(const QString &str)
|
||||
{
|
||||
setAuxiliaryData(customIdProperty, QVariant::fromValue<QString>(str));
|
||||
}
|
||||
|
||||
void ModelNode::removeCustomId()
|
||||
{
|
||||
if (hasCustomId()) {
|
||||
removeAuxiliaryData(customIdProperty);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<Comment> ModelNode::comments() const
|
||||
{
|
||||
return annotation().comments();
|
||||
}
|
||||
|
||||
bool ModelNode::hasComments() const
|
||||
{
|
||||
return annotation().hasComments();
|
||||
}
|
||||
|
||||
void ModelNode::setComments(const QVector<Comment> &coms)
|
||||
{
|
||||
Annotation anno = annotation();
|
||||
anno.setComments(coms);
|
||||
|
||||
setAnnotation(anno);
|
||||
}
|
||||
|
||||
void ModelNode::addComment(const Comment &com)
|
||||
{
|
||||
Annotation anno = annotation();
|
||||
anno.addComment(com);
|
||||
|
||||
setAnnotation(anno);
|
||||
}
|
||||
|
||||
bool ModelNode::updateComment(const Comment &com, int position)
|
||||
{
|
||||
bool result = false;
|
||||
if (hasAnnotation()) {
|
||||
Annotation anno = annotation();
|
||||
|
||||
if (anno.updateComment(com, position)) {
|
||||
setAnnotation(anno);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Annotation ModelNode::annotation() const
|
||||
{
|
||||
Annotation result;
|
||||
|
||||
if (hasAnnotation())
|
||||
result.fromQString(auxiliaryData(annotationProperty).value<QString>());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ModelNode::hasAnnotation() const
|
||||
{
|
||||
return hasAuxiliaryData(annotationProperty);
|
||||
}
|
||||
|
||||
void ModelNode::setAnnotation(const Annotation &annotation)
|
||||
{
|
||||
setAuxiliaryData(annotationProperty, QVariant::fromValue<QString>(annotation.toQString()));
|
||||
}
|
||||
|
||||
void ModelNode::removeAnnotation()
|
||||
{
|
||||
if (hasAnnotation()) {
|
||||
removeAuxiliaryData(annotationProperty);
|
||||
}
|
||||
}
|
||||
|
||||
void ModelNode::setScriptFunctions(const QStringList &scriptFunctionList)
|
||||
{
|
||||
model()->d->setScriptFunctions(internalNode(), scriptFunctionList);
|
||||
|
@@ -530,6 +530,14 @@ QString RewriterView::auxiliaryDataAsQML() const
|
||||
|
||||
if (metaType == QMetaType::QString
|
||||
|| metaType == QMetaType::QColor) {
|
||||
|
||||
strValue.replace(QStringLiteral("\\"), QStringLiteral("\\\\"));
|
||||
strValue.replace(QStringLiteral("\""), QStringLiteral("\\\""));
|
||||
strValue.replace(QStringLiteral("\t"), QStringLiteral("\\t"));
|
||||
strValue.replace(QStringLiteral("\r"), QStringLiteral("\\r"));
|
||||
strValue.replace(QStringLiteral("\n"), QStringLiteral("\\n"));
|
||||
strValue.replace(QStringLiteral("*/"), QStringLiteral("*\\/"));
|
||||
|
||||
strValue = "\"" + strValue + "\"";
|
||||
}
|
||||
|
||||
|
@@ -37,6 +37,7 @@
|
||||
#include <connectionview.h>
|
||||
#include <sourcetool/sourcetool.h>
|
||||
#include <colortool/colortool.h>
|
||||
#include <annotationeditor/annotationtool.h>
|
||||
#include <texttool/texttool.h>
|
||||
#include <timelineeditor/timelineview.h>
|
||||
#include <pathtool/pathtool.h>
|
||||
@@ -238,6 +239,7 @@ bool QmlDesignerPlugin::delayedInitialize()
|
||||
|
||||
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::SourceTool);
|
||||
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::ColorTool);
|
||||
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::AnnotationTool);
|
||||
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::TextTool);
|
||||
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::PathTool);
|
||||
|
||||
|
@@ -29,6 +29,7 @@ include(components/timelineeditor/timelineeditor.pri)
|
||||
include(components/connectioneditor/connectioneditor.pri)
|
||||
include(components/curveeditor/curveeditor.pri)
|
||||
include(components/bindingeditor/bindingeditor.pri)
|
||||
include(components/annotationeditor/annotationeditor.pri)
|
||||
|
||||
|
||||
BUILD_PUPPET_IN_CREATOR_BINPATH = $$(BUILD_PUPPET_IN_CREATOR_BINPATH)
|
||||
|
@@ -461,6 +461,8 @@ Project {
|
||||
"formeditor/dragtool.cpp",
|
||||
"formeditor/dragtool.h",
|
||||
"formeditor/formeditor.qrc",
|
||||
"formeditor/formeditorannotationicon.cpp",
|
||||
"formeditor/formeditorannotationicon.h",
|
||||
"formeditor/formeditorgraphicsview.cpp",
|
||||
"formeditor/formeditorgraphicsview.h",
|
||||
"formeditor/formeditoritem.cpp",
|
||||
@@ -636,6 +638,18 @@ Project {
|
||||
name: "extension"
|
||||
prefix: "components/"
|
||||
files: [
|
||||
"annotationeditor/annotation.cpp",
|
||||
"annotationeditor/annotation.h",
|
||||
"annotationeditor/annotationcommenttab.cpp",
|
||||
"annotationeditor/annotationcommenttab.h",
|
||||
"annotationeditor/annotationcommenttab.ui",
|
||||
"annotationeditor/annotationeditor.cpp",
|
||||
"annotationeditor/annotationeditor.h",
|
||||
"annotationeditor/annotationeditordialog.cpp",
|
||||
"annotationeditor/annotationeditordialog.h",
|
||||
"annotationeditor/annotationeditordialog.ui
|
||||
"annotationeditor/annotationtool.cpp",
|
||||
"annotationeditor/annotationtool.h",
|
||||
"bindingeditor/bindingeditor.cpp",
|
||||
"bindingeditor/bindingeditor.h",
|
||||
"bindingeditor/actioneditor.cpp",
|
||||
|
Reference in New Issue
Block a user