QmlDesigner: Annotation List

- Annotation Dialog structure was reworked
 - Added ListView to Global Annotation Dialog
 - Added Apply button to all Annotation dialogs

Task-number: QDS-2243
Change-Id: I2f271d4ae91d33b26a050287b20a86050e081830
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Aleksei German
2021-07-09 17:34:17 +02:00
parent 9eee8e4b84
commit 3e1fa0f170
22 changed files with 1468 additions and 299 deletions

View File

@@ -638,9 +638,13 @@ extend_qtc_plugin(QmlDesigner
extend_qtc_plugin(QmlDesigner extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX components/annotationeditor SOURCES_PREFIX components/annotationeditor
SOURCES annotationcommenttab.cpp annotationcommenttab.h annotationcommenttab.ui SOURCES annotationcommenttab.cpp annotationcommenttab.h annotationcommenttab.ui
annotationeditordialog.cpp annotationeditordialog.h annotationeditordialog.ui annotationeditordialog.cpp annotationeditordialog.h
annotationeditorwidget.cpp annotationeditorwidget.h annotationeditorwidget.ui
annotationeditor.cpp annotationeditor.h annotationeditor.cpp annotationeditor.h
annotationlist.cpp annotationlist.h
annotationlistwidget.cpp annotationlistwidget.h
globalannotationeditor.cpp globalannotationeditor.h globalannotationeditor.cpp globalannotationeditor.h
globalannotationdialog.cpp globalannotationdialog.h
defaultannotations.cpp defaultannotations.h defaultannotations.cpp defaultannotations.h
annotationtableview.cpp annotationtableview.h annotationtableview.cpp annotationtableview.h
annotationtabwidget.cpp annotationtabwidget.h annotationtabwidget.cpp annotationtabwidget.h

View File

@@ -46,8 +46,6 @@ AnnotationEditor::AnnotationEditor(QObject *parent)
: ModelNodeEditorProxy(parent) : ModelNodeEditorProxy(parent)
{} {}
AnnotationEditor::~AnnotationEditor() {}
QWidget *AnnotationEditor::createWidget() QWidget *AnnotationEditor::createWidget()
{ {
const auto &node = m_modelNode; const auto &node = m_modelNode;
@@ -64,6 +62,8 @@ QWidget *AnnotationEditor::createWidget()
&AnnotationEditorDialog::rejected, &AnnotationEditorDialog::rejected,
this, this,
&AnnotationEditor::cancelClicked); &AnnotationEditor::cancelClicked);
QObject::connect(dialog, &AnnotationEditorDialog::appliedDialog,
this, &AnnotationEditor::appliedClicked);
return dialog; return dialog;
} }
@@ -91,19 +91,7 @@ void AnnotationEditor::removeFullAnnotation()
void AnnotationEditor::acceptedClicked() void AnnotationEditor::acceptedClicked()
{ {
if (const auto *dialog = qobject_cast<AnnotationEditorDialog *>(widget())) { applyChanges();
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_ANNOTATION_ADDED);
const QString customId = dialog->customId();
const Annotation annotation = dialog->annotation();
auto &node = this->m_modelNode;
node.setCustomId(customId);
if (annotation.comments().isEmpty())
node.removeAnnotation();
else
node.setAnnotation(annotation);
}
hideWidget(); hideWidget();
@@ -122,4 +110,30 @@ void AnnotationEditor::cancelClicked()
emit annotationChanged(); emit annotationChanged();
} }
void AnnotationEditor::appliedClicked()
{
applyChanges();
emit applied();
emit customIdChanged();
emit annotationChanged();
}
void AnnotationEditor::applyChanges()
{
if (const auto *dialog = qobject_cast<AnnotationEditorDialog *>(widget())) {
QmlDesignerPlugin::emitUsageStatistics(Constants::EVENT_ANNOTATION_ADDED);
const QString customId = dialog->customId();
const Annotation annotation = dialog->annotation();
auto &node = this->m_modelNode;
node.setCustomId(customId);
if (annotation.comments().isEmpty())
node.removeAnnotation();
else
node.setAnnotation(annotation);
}
}
} //namespace QmlDesigner } //namespace QmlDesigner

View File

@@ -36,7 +36,7 @@ class AnnotationEditor : public ModelNodeEditorProxy
Q_OBJECT Q_OBJECT
public: public:
explicit AnnotationEditor(QObject *parent = nullptr); explicit AnnotationEditor(QObject *parent = nullptr);
~AnnotationEditor(); ~AnnotationEditor() = default;
QWidget *createWidget() override; QWidget *createWidget() override;
Q_INVOKABLE void removeFullAnnotation(); Q_INVOKABLE void removeFullAnnotation();
@@ -46,10 +46,15 @@ public:
signals: signals:
void accepted(); void accepted();
void canceled(); void canceled();
void applied();
private slots: private slots:
void acceptedClicked(); void acceptedClicked();
void cancelClicked(); void cancelClicked();
void appliedClicked();
private:
void applyChanges();
}; };
} //namespace QmlDesigner } //namespace QmlDesigner

View File

@@ -5,6 +5,10 @@ HEADERS += $$PWD/globalannotationeditor.h
HEADERS += $$PWD/defaultannotations.h HEADERS += $$PWD/defaultannotations.h
HEADERS += $$PWD/annotationtableview.h HEADERS += $$PWD/annotationtableview.h
HEADERS += $$PWD/annotationtabwidget.h HEADERS += $$PWD/annotationtabwidget.h
HEADERS += $$PWD/annotationeditorwidget.h
HEADERS += $$PWD/globalannotationdialog.h
HEADERS += $$PWD/annotationlist.h
HEADERS += $$PWD/annotationlistwidget.h
SOURCES += $$PWD/annotationcommenttab.cpp SOURCES += $$PWD/annotationcommenttab.cpp
SOURCES += $$PWD/annotationeditordialog.cpp SOURCES += $$PWD/annotationeditordialog.cpp
@@ -13,9 +17,13 @@ SOURCES += $$PWD/globalannotationeditor.cpp
SOURCES += $$PWD/defaultannotations.cpp SOURCES += $$PWD/defaultannotations.cpp
SOURCES += $$PWD/annotationtableview.cpp SOURCES += $$PWD/annotationtableview.cpp
SOURCES += $$PWD/annotationtabwidget.cpp SOURCES += $$PWD/annotationtabwidget.cpp
SOURCES += $$PWD/annotationeditorwidget.cpp
SOURCES += $$PWD/globalannotationdialog.cpp
SOURCES += $$PWD/annotationlist.cpp
SOURCES += $$PWD/annotationlistwidget.cpp
FORMS += $$PWD/annotationcommenttab.ui FORMS += $$PWD/annotationcommenttab.ui
FORMS += $$PWD/annotationeditordialog.ui FORMS += $$PWD/annotationeditorwidget.ui
INCLUDEPATH += $$PWD INCLUDEPATH += $$PWD

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -27,184 +27,89 @@
#include "annotation.h" #include "annotation.h"
#include "annotationcommenttab.h" #include "annotationcommenttab.h"
#include "defaultannotations.h" #include "defaultannotations.h"
#include "annotationeditorwidget.h"
#include "ui_annotationeditordialog.h"
#include <timelineicons.h> #include <timelineicons.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QAction> #include <QAction>
#include <QMessageBox> #include <QMessageBox>
#include <QDialogButtonBox>
#include <QAbstractButton>
#include <QObject> #include <QObject>
#include <QToolBar> #include <QToolBar>
#include <QVBoxLayout>
namespace QmlDesigner { namespace QmlDesigner {
AnnotationEditorDialog::AnnotationEditorDialog(QWidget *parent, AnnotationEditorDialog::AnnotationEditorDialog(QWidget *parent,
const QString &targetId, const QString &targetId,
const QString &customId) const QString &customId)
: QDialog(parent) : QDialog(parent)
, ui(std::make_unique<Ui::AnnotationEditorDialog>())
, m_customId(customId) , m_customId(customId)
, m_defaults(std::make_unique<DefaultAnnotationsModel>()) , m_defaults(std::make_unique<DefaultAnnotationsModel>())
, m_editorWidget(new AnnotationEditorWidget(this, targetId, customId))
{ {
ui->setupUi(this); setWindowTitle(tr("Annotation Editor"));
setGlobal(m_isGlobal);
setWindowFlag(Qt::Tool, true); setWindowFlag(Qt::Tool, true);
setModal(true); setModal(true);
loadDefaultAnnotations(DefaultAnnotationsModel::defaultJsonFilePath());
ui->tabWidget->setDefaultAnnotations(defaultAnnotations());
ui->tableView->setDefaultAnnotations(defaultAnnotations());
connect(ui->tableView, const QDialogButtonBox::StandardButtons buttonsToCreate =
&AnnotationTableView::richTextEditorRequested, QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply;
this,
[&](int index, QString const &) {
switchToTabView();
ui->tabWidget->setCurrentIndex(index);
});
connect(ui->statusAddButton, &QPushButton::clicked, this, [&](bool) { m_buttonBox = new QDialogButtonBox(buttonsToCreate, this);
setStatusVisibility(true);
});
connect(ui->rbTableView, if (!QWidget::layout())
&QRadioButton::clicked, new QVBoxLayout(this);
this,
&AnnotationEditorDialog::switchToTableView);
connect(ui->rbTabView,
&QRadioButton::clicked,
this, &AnnotationEditorDialog::switchToTabView);
setStatus(m_globalStatus); QWidget::layout()->addWidget(m_editorWidget);
switchToTabView(); QWidget::layout()->addWidget(m_buttonBox);
connect(this, &QDialog::accepted, this, &AnnotationEditorDialog::acceptedClicked);
ui->targetIdEdit->setText(targetId); connect(this, &QDialog::accepted,
this, &AnnotationEditorDialog::acceptedClicked);
connect(m_buttonBox, &QDialogButtonBox::accepted,
this, &AnnotationEditorDialog::acceptedClicked);
connect(m_buttonBox, &QDialogButtonBox::clicked,
this, &AnnotationEditorDialog::buttonClicked);
connect(m_buttonBox, &QDialogButtonBox::rejected,
this, &QDialog::close);
} }
AnnotationEditorDialog::~AnnotationEditorDialog() { AnnotationEditorDialog::~AnnotationEditorDialog() = default;
}
bool AnnotationEditorDialog::isGlobal() const { void AnnotationEditorDialog::buttonClicked(QAbstractButton *button)
return m_isGlobal; {
} if (button) {
const QDialogButtonBox::StandardButton buttonType = m_buttonBox->standardButton(button);
void AnnotationEditorDialog::setGlobal(bool global) { if (buttonType == QDialogButtonBox::Apply) {
ui->annotationContainer->setVisible(!global); appliedClicked();
ui->statusAddButton->setVisible(global); }
ui->statusComboBox->setVisible(global);
setWindowTitle(global ? tr("Global Annotation Editor") : tr("Annotation Editor"));
if (m_isGlobal != global) {
m_isGlobal = global;
emit globalChanged();
} }
} }
AnnotationEditorDialog::ViewMode AnnotationEditorDialog::viewMode() const
{
return ui->rbTableView->isChecked() ? TableView : TabsView;
}
void AnnotationEditorDialog::setStatus(GlobalAnnotationStatus status)
{
m_globalStatus = status;
bool hasStatus = status.status() != GlobalAnnotationStatus::NoStatus;
if (hasStatus)
ui->statusComboBox->setCurrentIndex(int(status.status()));
setStatusVisibility(hasStatus);
}
GlobalAnnotationStatus AnnotationEditorDialog::globalStatus() const
{
return m_globalStatus;
}
void AnnotationEditorDialog::showStatusContainer(bool show)
{
ui->statusContainer->setVisible(show);
}
void AnnotationEditorDialog::switchToTabView()
{
m_annotation.setComments(ui->tableView->fetchComments());
ui->rbTabView->setChecked(true);
ui->tableView->hide();
ui->tabWidget->show();
fillFields();
}
void AnnotationEditorDialog::switchToTableView()
{
m_annotation.setComments(ui->tabWidget->fetchComments());
ui->rbTableView->setChecked(true);
ui->tabWidget->hide();
ui->tableView->show();
fillFields();
}
void AnnotationEditorDialog::acceptedClicked() void AnnotationEditorDialog::acceptedClicked()
{ {
updateAnnotation(); updateAnnotation();
emit AnnotationEditorDialog::acceptedDialog(); emit AnnotationEditorDialog::acceptedDialog();
} }
void AnnotationEditorDialog::fillFields() void AnnotationEditorDialog::appliedClicked()
{ {
ui->customIdEdit->setText(m_customId); updateAnnotation();
ui->tabWidget->setupComments(m_annotation.comments()); emit AnnotationEditorDialog::appliedDialog();
ui->tableView->setupComments(m_annotation.comments());
} }
void AnnotationEditorDialog::updateAnnotation() void AnnotationEditorDialog::updateAnnotation()
{ {
m_customId = ui->customIdEdit->text(); m_editorWidget->updateAnnotation();
Annotation annotation; m_customId = m_editorWidget->customId();
switch (viewMode()) { m_annotation = m_editorWidget->annotation();
case TabsView:
annotation.setComments(ui->tabWidget->fetchComments());
break;
case TableView:
annotation.setComments(ui->tableView->fetchComments());
break;
}
m_annotation = annotation;
if (m_statusIsActive && m_isGlobal)
m_globalStatus.setStatus(ui->statusComboBox->currentIndex());
} }
void AnnotationEditorDialog::addComment(const Comment &comment) const Annotation &AnnotationEditorDialog::annotation() const
{
m_annotation.addComment(comment);
ui->tabWidget->addCommentTab(comment);
}
void AnnotationEditorDialog::removeComment(int index)
{
if ((m_annotation.commentsSize() > index) && (index >= 0)) {
m_annotation.removeComment(index);
ui->tabWidget->removeTab(index);
}
}
void AnnotationEditorDialog::setStatusVisibility(bool hasStatus)
{
ui->statusAddButton->setVisible(!hasStatus && m_isGlobal);
ui->statusComboBox->setVisible(hasStatus && m_isGlobal);
m_statusIsActive = hasStatus;
}
Annotation const &AnnotationEditorDialog::annotation() const
{ {
return m_annotation; return m_annotation;
} }
@@ -212,29 +117,28 @@ Annotation const &AnnotationEditorDialog::annotation() const
void AnnotationEditorDialog::setAnnotation(const Annotation &annotation) void AnnotationEditorDialog::setAnnotation(const Annotation &annotation)
{ {
m_annotation = annotation; m_annotation = annotation;
fillFields(); m_editorWidget->setAnnotation(m_annotation);
} }
void AnnotationEditorDialog::loadDefaultAnnotations(QString const &filename) void AnnotationEditorDialog::loadDefaultAnnotations(const QString &filename)
{ {
m_defaults->loadFromFile(filename); m_editorWidget->loadDefaultAnnotations(filename);
} }
DefaultAnnotationsModel *AnnotationEditorDialog::defaultAnnotations() const DefaultAnnotationsModel *AnnotationEditorDialog::defaultAnnotations() const
{ {
return m_defaults.get(); return m_editorWidget->defaultAnnotations();
} }
void AnnotationEditorDialog::setCustomId(const QString &customId) void AnnotationEditorDialog::setCustomId(const QString &customId)
{ {
m_customId = customId; m_customId = customId;
ui->customIdEdit->setText(m_customId); m_editorWidget->setCustomId(customId);
} }
QString AnnotationEditorDialog::customId() const const QString &AnnotationEditorDialog::customId() const
{ {
return m_customId; return m_customId;
} }
} //namespace QmlDesigner } //namespace QmlDesigner

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -25,72 +25,63 @@
#pragma once #pragma once
#include "annotation.h"
#include <QDialog> #include <QDialog>
#include "annotation.h"
QT_BEGIN_NAMESPACE
class QAbstractButton;
class QDialogButtonBox;
QT_END_NAMESPACE
namespace QmlDesigner { namespace QmlDesigner {
namespace Ui {
class AnnotationEditorDialog;
}
class DefaultAnnotationsModel; class DefaultAnnotationsModel;
class AnnotationEditorWidget;
class AnnotationEditorDialog : public QDialog class AnnotationEditorDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
enum ViewMode { TableView, TabsView }; enum class ViewMode { TableView,
TabsView };
explicit AnnotationEditorDialog(QWidget *parent, explicit AnnotationEditorDialog(QWidget *parent,
const QString &targetId = {}, const QString &targetId = {},
const QString &customId = {}); const QString &customId = {});
~AnnotationEditorDialog(); ~AnnotationEditorDialog();
ViewMode viewMode() const; const Annotation &annotation() const;
Annotation const &annotation() const;
void setAnnotation(const Annotation &annotation); void setAnnotation(const Annotation &annotation);
QString customId() const; const QString &customId() const;
void setCustomId(const QString &customId); void setCustomId(const QString &customId);
bool isGlobal() const;
void setGlobal(bool = true);
void loadDefaultAnnotations(QString const &filename);
DefaultAnnotationsModel *defaultAnnotations() const; DefaultAnnotationsModel *defaultAnnotations() const;
void setStatus(GlobalAnnotationStatus status); void loadDefaultAnnotations(const QString &filename);
GlobalAnnotationStatus globalStatus() const;
public slots:
void showStatusContainer(bool show);
void switchToTabView();
void switchToTableView();
private slots: private slots:
void buttonClicked(QAbstractButton *button);
void acceptedClicked(); void acceptedClicked();
void appliedClicked();
signals: signals:
void acceptedDialog(); //use instead of QDialog::accepted void acceptedDialog(); //use instead of QDialog::accepted
void globalChanged(); void appliedDialog();
private: private:
void fillFields();
void updateAnnotation(); void updateAnnotation();
void addComment(const Comment &comment); private:
void removeComment(int index);
void setStatusVisibility(bool hasStatus);
std::unique_ptr<Ui::AnnotationEditorDialog> ui;
GlobalAnnotationStatus m_globalStatus = GlobalAnnotationStatus::NoStatus; GlobalAnnotationStatus m_globalStatus = GlobalAnnotationStatus::NoStatus;
bool m_statusIsActive = false;
bool m_isGlobal = false;
Annotation m_annotation; Annotation m_annotation;
QString m_customId; QString m_customId;
std::unique_ptr<DefaultAnnotationsModel> m_defaults; std::unique_ptr<DefaultAnnotationsModel> m_defaults;
AnnotationEditorWidget *m_editorWidget;
QDialogButtonBox *m_buttonBox;
}; };

View File

@@ -0,0 +1,243 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "annotationeditorwidget.h"
#include "annotation.h"
#include "annotationcommenttab.h"
#include "defaultannotations.h"
#include "ui_annotationeditorwidget.h"
#include <timelineicons.h>
#include <utils/qtcassert.h>
#include <QAction>
#include <QMessageBox>
#include <QObject>
#include <QToolBar>
#include <QAbstractButton>
namespace QmlDesigner {
AnnotationEditorWidget::AnnotationEditorWidget(QWidget *parent,
const QString &targetId,
const QString &customId)
: QWidget(parent)
, m_defaults(std::make_unique<DefaultAnnotationsModel>())
, ui(std::make_unique<Ui::AnnotationEditorWidget>())
, m_statusIsActive(false)
, m_customId(customId)
{
ui->setupUi(this);
setGlobal(m_isGlobal);
loadDefaultAnnotations(DefaultAnnotationsModel::defaultJsonFilePath());
ui->tabWidget->setDefaultAnnotations(defaultAnnotations());
ui->tableView->setDefaultAnnotations(defaultAnnotations());
connect(ui->tableView,
&AnnotationTableView::richTextEditorRequested,
this,
[&](int index, const QString &) {
switchToTabView();
ui->tabWidget->setCurrentIndex(index);
});
connect(ui->statusAddButton, &QPushButton::clicked, this, [&](bool) {
setStatusVisibility(true);
});
connect(ui->rbTableView,
&QRadioButton::clicked,
this,
&AnnotationEditorWidget::switchToTableView);
connect(ui->rbTabView,
&QRadioButton::clicked,
this, &AnnotationEditorWidget::switchToTabView);
setStatus(m_globalStatus);
switchToTabView();
ui->targetIdEdit->setText(targetId);
}
//have to default it in here instead of the header because of unique_ptr with forward declared type
AnnotationEditorWidget::~AnnotationEditorWidget() = default;
bool AnnotationEditorWidget::isGlobal() const
{
return m_isGlobal;
}
void AnnotationEditorWidget::setGlobal(bool global)
{
ui->annotationContainer->setVisible(!global);
ui->statusAddButton->setVisible(global);
ui->statusComboBox->setVisible(global);
if (m_isGlobal != global) {
m_isGlobal = global;
emit globalChanged();
}
}
AnnotationEditorWidget::ViewMode AnnotationEditorWidget::viewMode() const
{
return ui->rbTableView->isChecked() ? ViewMode::TableView : ViewMode::TabsView;
}
void AnnotationEditorWidget::setStatus(GlobalAnnotationStatus status)
{
m_globalStatus = status;
bool hasStatus = status.status() != GlobalAnnotationStatus::NoStatus;
if (hasStatus)
ui->statusComboBox->setCurrentIndex(static_cast<int>(status.status()));
setStatusVisibility(hasStatus);
}
GlobalAnnotationStatus AnnotationEditorWidget::globalStatus() const
{
return m_globalStatus;
}
void AnnotationEditorWidget::showStatusContainer(bool show)
{
ui->statusContainer->setVisible(show);
}
void AnnotationEditorWidget::switchToTabView()
{
m_annotation.setComments(ui->tableView->fetchComments());
ui->rbTabView->setChecked(true);
ui->tableView->hide();
ui->tabWidget->show();
fillFields();
if (ui->tabWidget->count() > 0)
ui->tabWidget->setCurrentIndex(0);
}
void AnnotationEditorWidget::switchToTableView()
{
m_annotation.setComments(ui->tabWidget->fetchComments());
ui->rbTableView->setChecked(true);
ui->tabWidget->hide();
ui->tableView->show();
fillFields();
}
void AnnotationEditorWidget::fillFields()
{
ui->customIdEdit->setText(m_customId);
ui->tabWidget->setupComments(m_annotation.comments());
ui->tableView->setupComments(m_annotation.comments());
}
void AnnotationEditorWidget::updateAnnotation()
{
m_customId = ui->customIdEdit->text();
Annotation annotation;
switch (viewMode()) {
case ViewMode::TabsView:
annotation.setComments(ui->tabWidget->fetchComments());
break;
case ViewMode::TableView:
annotation.setComments(ui->tableView->fetchComments());
break;
}
m_annotation = annotation;
if (m_statusIsActive && m_isGlobal)
m_globalStatus.setStatus(ui->statusComboBox->currentIndex());
}
void AnnotationEditorWidget::addComment(const Comment &comment)
{
m_annotation.addComment(comment);
ui->tabWidget->addCommentTab(comment);
}
void AnnotationEditorWidget::removeComment(int index)
{
if ((m_annotation.commentsSize() > index) && (index >= 0)) {
m_annotation.removeComment(index);
ui->tabWidget->removeTab(index);
}
}
void AnnotationEditorWidget::setStatusVisibility(bool hasStatus)
{
ui->statusAddButton->setVisible(!hasStatus && m_isGlobal);
ui->statusComboBox->setVisible(hasStatus && m_isGlobal);
m_statusIsActive = hasStatus;
}
const Annotation &AnnotationEditorWidget::annotation() const
{
return m_annotation;
}
void AnnotationEditorWidget::setAnnotation(const Annotation &annotation)
{
m_annotation = annotation;
fillFields();
}
void AnnotationEditorWidget::loadDefaultAnnotations(const QString &filename)
{
m_defaults->loadFromFile(filename);
}
DefaultAnnotationsModel *AnnotationEditorWidget::defaultAnnotations() const
{
return m_defaults.get();
}
void AnnotationEditorWidget::setTargetId(const QString &targetId)
{
ui->targetIdEdit->setText(targetId);
}
QString AnnotationEditorWidget::targetId() const
{
return ui->targetIdEdit->text();
}
void AnnotationEditorWidget::setCustomId(const QString &customId)
{
m_customId = customId;
ui->customIdEdit->setText(m_customId);
}
const QString &AnnotationEditorWidget::customId() const
{
return m_customId;
}
} //namespace QmlDesigner

View File

@@ -0,0 +1,104 @@
/****************************************************************************
**
** Copyright (C) 2021 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 <QWidget>
QT_BEGIN_NAMESPACE
class QAbstractButton;
QT_END_NAMESPACE
namespace QmlDesigner {
namespace Ui {
class AnnotationEditorWidget;
}
class DefaultAnnotationsModel;
class AnnotationEditorWidget : public QWidget
{
Q_OBJECT
public:
enum class ViewMode { TableView, TabsView };
explicit AnnotationEditorWidget(QWidget *parent,
const QString &targetId = {},
const QString &customId = {});
~AnnotationEditorWidget();
ViewMode viewMode() const;
const Annotation &annotation() const;
void setAnnotation(const Annotation &annotation);
QString targetId() const;
void setTargetId(const QString &targetId);
const QString &customId() const;
void setCustomId(const QString &customId);
bool isGlobal() const;
void setGlobal(bool = true);
DefaultAnnotationsModel *defaultAnnotations() const;
void loadDefaultAnnotations(const QString &filename);
GlobalAnnotationStatus globalStatus() const;
void setStatus(GlobalAnnotationStatus status);
void updateAnnotation();
public slots:
void showStatusContainer(bool show);
void switchToTabView();
void switchToTableView();
signals:
void globalChanged();
private:
void fillFields();
void addComment(const Comment &comment);
void removeComment(int index);
void setStatusVisibility(bool hasStatus);
private:
std::unique_ptr<DefaultAnnotationsModel> m_defaults;
std::unique_ptr<Ui::AnnotationEditorWidget> ui;
GlobalAnnotationStatus m_globalStatus = GlobalAnnotationStatus::NoStatus;
bool m_statusIsActive = false;
bool m_isGlobal = false;
Annotation m_annotation;
QString m_customId;
};
} //namespace QmlDesigner

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>QmlDesigner::AnnotationEditorDialog</class> <class>QmlDesigner::AnnotationEditorWidget</class>
<widget class="QDialog" name="QmlDesigner::AnnotationEditorDialog"> <widget class="QWidget" name="QmlDesigner::AnnotationEditorWidget">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@@ -10,10 +10,7 @@
<height>819</height> <height>819</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <layout class="QVBoxLayout" name="verticalLayout">
<string notr="true">Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item> <item>
<widget class="QWidget" name="statusContainer" native="true"> <widget class="QWidget" name="statusContainer" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QHBoxLayout" name="horizontalLayout_3">
@@ -170,19 +167,6 @@
<item> <item>
<widget class="AnnotationTableView" name="tableView"/> <widget class="AnnotationTableView" name="tableView"/>
</item> </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> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
@@ -198,44 +182,6 @@
<header>annotationtableview.h</header> <header>annotationtableview.h</header>
</customwidget> </customwidget>
</customwidgets> </customwidgets>
<tabstops>
<tabstop>targetIdEdit</tabstop>
<tabstop>customIdEdit</tabstop>
<tabstop>tabWidget</tabstop>
</tabstops>
<resources/> <resources/>
<connections> <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> </ui>

View File

@@ -0,0 +1,322 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "annotationlist.h"
#include <QPainter>
#include <QItemSelectionModel>
#include <variant>
namespace QmlDesigner {
// Entry
AnnotationListEntry::AnnotationListEntry(const ModelNode &modelnode)
: id(modelnode.id())
, annotationName(modelnode.customId())
, annotation(modelnode.annotation())
, node(modelnode)
{
}
AnnotationListEntry::AnnotationListEntry(const QString &argId, const QString &argAnnotationName,
const Annotation &argAnnotation, const ModelNode &argNode)
: id(argId)
, annotationName(argAnnotationName)
, annotation(argAnnotation)
, node(argNode)
{
}
// Model
AnnotationListModel::AnnotationListModel(ModelNode rootNode, AnnotationListView *parent)
: QAbstractItemModel(parent)
, m_annotationView(parent)
, m_rootNode(rootNode)
{
fillModel();
}
void AnnotationListModel::setRootNode(ModelNode rootNode)
{
m_rootNode = rootNode;
resetModel();
}
void AnnotationListModel::resetModel()
{
beginResetModel();
m_annoList.clear();
fillModel();
endResetModel();
}
ModelNode AnnotationListModel::getModelNode(int id) const
{
if (id >= 0 && id < m_annoList.size())
return m_annoList.at(id).node;
return {};
}
AnnotationListEntry AnnotationListModel::getStoredAnnotation(int id) const
{
if (id >= 0 && id < m_annoList.size())
return m_annoList.at(id);
return {};
}
void AnnotationListModel::fillModel()
{
if (m_rootNode.isValid()) {
const QList<QmlDesigner::ModelNode> allNodes = m_rootNode.allSubModelNodesAndThisNode();
for (const QmlDesigner::ModelNode &node : allNodes) {
if (node.hasCustomId() || node.hasAnnotation()) {
m_annoList.emplace_back(node);
}
}
}
}
QModelIndex AnnotationListModel::index(int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(parent)
return createIndex(row, column);
}
QModelIndex AnnotationListModel::parent(const QModelIndex &) const
{
return {};
}
int AnnotationListModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return static_cast<int>(m_annoList.size());
}
int AnnotationListModel::columnCount(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return m_numberOfColumns;
}
QVariant AnnotationListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= m_annoList.size())
return {};
const auto &item = m_annoList.at(index.row());
switch (role) {
case AnnotationListModel::IdRow:
return item.id;
case AnnotationListModel::NameRow:
return item.annotationName;
case AnnotationListModel::AnnotationsCountRow:
return item.annotation.commentsSize();
default:
return {};
}
}
Qt::ItemFlags AnnotationListModel::flags(const QModelIndex &index) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= m_annoList.size())
return Qt::NoItemFlags;
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
void AnnotationListModel::storeChanges(int row, const QString &customId, const Annotation &annotation)
{
if (row < 0 || row >= rowCount())
return;
auto &item = m_annoList[row];
item.annotationName = customId;
item.annotation = annotation;
emit dataChanged(index(row, 1), index(row, 2));
}
void AnnotationListModel::saveChanges()
{
for (auto &item : m_annoList) {
ModelNode &node = item.node;
if (node.isValid()) {
const QString &annoName = item.annotationName;
const Annotation &anno = item.annotation;
node.setCustomId(annoName);
node.setAnnotation(anno);
}
}
}
// View
AnnotationListView::AnnotationListView(ModelNode rootNode, QWidget *parent)
: Utils::ListView(parent)
, m_model(new AnnotationListModel(rootNode, this))
{
setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
setModel(m_model);
setItemDelegate(new AnnotationListDelegate(this));
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setSelectionMode(QAbstractItemView::SingleSelection);
setSelectionBehavior(QAbstractItemView::SelectRows);
setActivationMode(Utils::SingleClickActivation);
setSelectionRectVisible(true);
setDragEnabled(false);
}
void AnnotationListView::setRootNode(ModelNode rootNode)
{
m_model->setRootNode(rootNode);
}
ModelNode AnnotationListView::getModelNodeByAnnotationId(int id) const
{
return m_model->getModelNode(id);
}
AnnotationListEntry AnnotationListView::getStoredAnnotationById(int id) const
{
return m_model->getStoredAnnotation(id);
}
void AnnotationListView::selectRow(int row)
{
if (m_model->rowCount() > row) {
QModelIndex index = m_model->index(row, 0);
setCurrentIndex(index);
emit activated(index);
}
}
int AnnotationListView::rowCount() const
{
return m_model->rowCount();
}
void AnnotationListView::storeChangesInModel(int row, const QString &customId, const Annotation &annotation)
{
m_model->storeChanges(row, customId, annotation);
}
void AnnotationListView::saveChangesFromModel()
{
m_model->saveChanges();
}
// Delegate
AnnotationListDelegate::AnnotationListDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
QSize AnnotationListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
QFontMetrics fm(option.font);
QSize s;
s.setWidth(option.rect.width());
s.setHeight(fm.height() * 2 + 10);
return s;
}
void AnnotationListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItem opt = option;
initStyleOption(&opt, index);
painter->save();
QFontMetrics fm(opt.font);
QColor backgroundColor;
QColor textColor;
bool selected = opt.state & QStyle::State_Selected;
if (selected) {
painter->setBrush(opt.palette.highlight().color());
backgroundColor = opt.palette.highlight().color();
} else {
backgroundColor = opt.palette.window().color();
painter->setBrush(backgroundColor);
}
painter->setPen(Qt::NoPen);
painter->drawRect(opt.rect);
// Set Text Color
if (opt.state & QStyle::State_Selected)
textColor = opt.palette.highlightedText().color();
else
textColor = opt.palette.text().color();
painter->setPen(textColor);
const QString itemId = index.data(AnnotationListModel::IdRow).toString();
painter->drawText(6, 2 + opt.rect.top() + fm.ascent(), itemId);
const QString annotationCounter = index.data(AnnotationListModel::AnnotationsCountRow).toString();
painter->drawText(opt.rect.right() - fm.horizontalAdvance(annotationCounter) - 6,
2 + opt.rect.top() + fm.ascent(), annotationCounter);
// Annotation name block:
QColor mix;
mix.setRgbF(0.7 * textColor.redF() + 0.3 * backgroundColor.redF(),
0.7 * textColor.greenF() + 0.3 * backgroundColor.greenF(),
0.7 * textColor.blueF() + 0.3 * backgroundColor.blueF());
painter->setPen(mix);
const QString annotationName = index.data(AnnotationListModel::NameRow).toString().trimmed();
painter->drawText(6, opt.rect.top() + fm.ascent() + fm.height() + 6, annotationName);
// Separator lines
const QRectF innerRect = QRectF(opt.rect).adjusted(0.5, 0.5, -0.5, -0.5);
painter->setPen(QColor::fromRgb(150, 150, 150));
painter->drawLine(innerRect.bottomLeft(), innerRect.bottomRight());
painter->restore();
}
}

View File

@@ -0,0 +1,139 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "modelnode.h"
#include <utils/itemviews.h>
#include <QWidget>
#include <QStandardItemModel>
#include <QListView>
#include <QStyledItemDelegate>
#include <tuple>
#include <vector>
namespace QmlDesigner {
class AnnotationListView;
//structure is used as a storage for the model data
//id, annotationname and annotation are storages, that will be submited into node on save
struct AnnotationListEntry {
QString id;
QString annotationName;
Annotation annotation;
ModelNode node;
AnnotationListEntry() = default;
AnnotationListEntry(const ModelNode &modelnode);
AnnotationListEntry(const QString &argId, const QString &argAnnotationName,
const Annotation &argAnnotation, const ModelNode &argNode);
};
class AnnotationListModel final : public QAbstractItemModel
{
Q_OBJECT
public:
enum ColumnRoles {
IdRow = Qt::UserRole,
NameRow,
AnnotationsCountRow
};
AnnotationListModel(ModelNode rootNode, AnnotationListView *view = nullptr);
~AnnotationListModel() = default;
void setRootNode(ModelNode rootNode);
void resetModel();
ModelNode getModelNode(int id) const;
AnnotationListEntry getStoredAnnotation(int id) const;
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
void storeChanges(int row, const QString &customId, const Annotation &annotation);
void saveChanges();
private:
void fillModel();
private:
QListView *m_annotationView = nullptr;
ModelNode m_rootNode;
std::vector<AnnotationListEntry> m_annoList;
const int m_numberOfColumns = 3;
};
class AnnotationListView final : public Utils::ListView
{
Q_OBJECT
public:
explicit AnnotationListView(ModelNode rootNode, QWidget *parent = nullptr);
~AnnotationListView() = default;
void setRootNode(ModelNode rootNode);
ModelNode getModelNodeByAnnotationId(int id) const;
AnnotationListEntry getStoredAnnotationById(int id) const;
void selectRow(int row);
int rowCount() const;
void storeChangesInModel(int row, const QString &customId, const Annotation &annotation);
void saveChangesFromModel();
private:
AnnotationListModel *m_model = nullptr;
};
class AnnotationListDelegate final : public QStyledItemDelegate
{
Q_OBJECT
public:
AnnotationListDelegate(QObject *parent = nullptr);
private:
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
};
}

View File

@@ -0,0 +1,119 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "annotationlistwidget.h"
#include "annotationeditorwidget.h"
#include "annotationlist.h"
#include <QLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
namespace QmlDesigner {
AnnotationListWidget::AnnotationListWidget(ModelNode rootNode, QWidget *parent)
: QWidget(parent)
, m_listView(new AnnotationListView(rootNode, this))
, m_editor(new AnnotationEditorWidget(this))
{
createUI();
connect(m_listView, &Utils::ListView::activated,
this, &AnnotationListWidget::changeAnnotation);
if (validateListSize())
m_listView->selectRow(0);
}
void AnnotationListWidget::setRootNode(ModelNode rootNode)
{
m_listView->setRootNode(rootNode);
m_currentItem = -1;
if (validateListSize())
m_listView->selectRow(0);
}
void AnnotationListWidget::saveAllChanges()
{
//first commit currently opened item
if (m_currentItem != -1) {
m_editor->updateAnnotation();
const QString oldCustomId = m_editor->customId();
const Annotation oldAnno = m_editor->annotation();
m_listView->storeChangesInModel(m_currentItem, oldCustomId, oldAnno);
}
//save all
m_listView->saveChangesFromModel();
}
void AnnotationListWidget::createUI()
{
QHBoxLayout *layout = new QHBoxLayout(this);
const QSizePolicy policy = m_listView->sizePolicy();
m_listView->setSizePolicy(QSizePolicy::Minimum, policy.verticalPolicy());
layout->addWidget(m_listView);
layout->addWidget(m_editor);
}
bool AnnotationListWidget::validateListSize()
{
const bool isFilled = m_listView->rowCount() > 0;
m_editor->setEnabled(isFilled);
return isFilled;
}
void AnnotationListWidget::changeAnnotation(const QModelIndex &index)
{
//store previous data
if (m_currentItem != -1) {
m_editor->updateAnnotation();
const QString &oldCustomId = m_editor->customId();
const Annotation &oldAnno = m_editor->annotation();
m_listView->storeChangesInModel(m_currentItem, oldCustomId, oldAnno);
}
//show new data
if (!index.isValid() || index.row() < 0 || index.row() >= m_listView->rowCount())
return;
const auto annotationData = m_listView->getStoredAnnotationById(index.row());
m_editor->setTargetId(annotationData.id);
m_editor->setCustomId(annotationData.annotationName);
m_editor->setAnnotation(annotationData.annotation);
m_currentItem = index.row();
}
}

View File

@@ -0,0 +1,70 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "modelnode.h"
#include <coreplugin/icore.h>
#include <QWidget>
#include <QDialog>
#include <QListView>
namespace QmlDesigner {
class AnnotationListView;
class AnnotationEditorWidget;
class AnnotationListWidget : public QWidget
{
Q_OBJECT
public:
explicit AnnotationListWidget(ModelNode rootNode, QWidget *parent = nullptr);
~AnnotationListWidget() = default;
void setRootNode(ModelNode rootNode);
void saveAllChanges();
private:
void createUI();
bool validateListSize();
private slots:
void changeAnnotation(const QModelIndex &index);
private:
AnnotationListView *m_listView;
AnnotationEditorWidget *m_editor;
int m_currentItem = -1;
};
}

View File

@@ -84,7 +84,7 @@ public:
QAbstractItemModel *model, QAbstractItemModel *model,
const QModelIndex &index) const override; const QModelIndex &index) const override;
signals: signals:
void commentChanged(int row, Comment const &); void commentChanged(int row, const QmlDesigner::Comment &comment);
}; };
class CommentValueDelegate : public CommentDelegate class CommentValueDelegate : public CommentDelegate

View File

@@ -66,8 +66,6 @@ AnnotationTabWidget::AnnotationTabWidget(QWidget *parent)
setCornerWidget(commentCornerWidget, Qt::TopRightCorner); setCornerWidget(commentCornerWidget, Qt::TopRightCorner);
} }
AnnotationTabWidget::~AnnotationTabWidget() {}
QVector<Comment> AnnotationTabWidget::fetchComments() const QVector<Comment> AnnotationTabWidget::fetchComments() const
{ {
QVector<Comment> comments; QVector<Comment> comments;
@@ -85,7 +83,7 @@ QVector<Comment> AnnotationTabWidget::fetchComments() const
return comments; return comments;
} }
void AnnotationTabWidget::setupComments(QVector<Comment> const &comments) void AnnotationTabWidget::setupComments(const QVector<Comment> &comments)
{ {
setUpdatesEnabled(false); setUpdatesEnabled(false);
@@ -124,7 +122,7 @@ void AnnotationTabWidget::onCommentTitleChanged(const QString &text, QWidget *ta
setTabText(tabIndex, defaultTabName + " " + QString::number(tabIndex + 1)); setTabText(tabIndex, defaultTabName + " " + QString::number(tabIndex + 1));
} }
void AnnotationTabWidget::addCommentTab(const Comment &comment) void AnnotationTabWidget::addCommentTab(const QmlDesigner::Comment &comment)
{ {
auto *commentTab = new AnnotationCommentTab(); auto *commentTab = new AnnotationCommentTab();
commentTab->setDefaultAnnotations(m_defaults); commentTab->setDefaultAnnotations(m_defaults);

View File

@@ -37,16 +37,16 @@ class AnnotationTabWidget : public QTabWidget
Q_OBJECT Q_OBJECT
public: public:
AnnotationTabWidget(QWidget *parent = nullptr); AnnotationTabWidget(QWidget *parent = nullptr);
~AnnotationTabWidget(); ~AnnotationTabWidget() = default;
QVector<Comment> fetchComments() const; QVector<Comment> fetchComments() const;
void setupComments(QVector<Comment> const &comments); void setupComments(const QVector<Comment> &comments);
DefaultAnnotationsModel *defaultAnnotations() const; DefaultAnnotationsModel *defaultAnnotations() const;
void setDefaultAnnotations(DefaultAnnotationsModel *); void setDefaultAnnotations(DefaultAnnotationsModel *);
public slots: public slots:
void addCommentTab(const Comment &comment = {}); void addCommentTab(const QmlDesigner::Comment &comment = {});
void deleteAllTabs(); void deleteAllTabs();
private slots: private slots:

View File

@@ -0,0 +1,176 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "globalannotationdialog.h"
#include "annotation.h"
#include "annotationcommenttab.h"
#include "defaultannotations.h"
#include "annotationeditorwidget.h"
#include "annotationlistwidget.h"
#include <timelineicons.h>
#include <utils/qtcassert.h>
#include <QAction>
#include <QMessageBox>
#include <QObject>
#include <QToolBar>
#include <QTabWidget>
#include <QVBoxLayout>
#include <QDialogButtonBox>
#include <QAbstractButton>
namespace QmlDesigner {
GlobalAnnotationDialog::GlobalAnnotationDialog(ModelNode rootNode, QWidget *parent)
: QDialog(parent)
, m_statusIsActive(false)
, m_defaults(std::make_unique<DefaultAnnotationsModel>())
, m_editorWidget(new AnnotationEditorWidget(this))
, m_annotationListWidget(new AnnotationListWidget(rootNode, this))
{
setupUI();
setStatus(m_globalStatus);
m_editorWidget->setGlobal(true);
connect(this, &QDialog::accepted,
this, &GlobalAnnotationDialog::acceptedClicked);
connect(m_buttonBox, &QDialogButtonBox::accepted,
this, &GlobalAnnotationDialog::acceptedClicked);
connect(m_buttonBox, &QDialogButtonBox::clicked,
this, &GlobalAnnotationDialog::buttonClicked);
connect(m_buttonBox, &QDialogButtonBox::rejected,
this, &QDialog::close);
}
GlobalAnnotationDialog::~GlobalAnnotationDialog() = default;
void GlobalAnnotationDialog::setStatus(GlobalAnnotationStatus status)
{
m_editorWidget->setStatus(status);
}
GlobalAnnotationStatus GlobalAnnotationDialog::globalStatus() const
{
return m_editorWidget->globalStatus();
}
GlobalAnnotationDialog::ViewMode GlobalAnnotationDialog::viewMode() const
{
if (!m_tabWidget)
return ViewMode::GlobalAnnotation;
return (m_tabWidget->currentIndex() == 0)
? ViewMode::GlobalAnnotation
: ViewMode::List;
}
void GlobalAnnotationDialog::saveAnnotationListChanges()
{
m_annotationListWidget->saveAllChanges();
}
void GlobalAnnotationDialog::buttonClicked(QAbstractButton *button)
{
if (button) {
const QDialogButtonBox::StandardButton buttonType = m_buttonBox->standardButton(button);
if (buttonType == QDialogButtonBox::Apply) {
appliedClicked();
}
}
}
void GlobalAnnotationDialog::acceptedClicked()
{
updateAnnotation();
emit GlobalAnnotationDialog::acceptedDialog();
}
void GlobalAnnotationDialog::appliedClicked()
{
updateAnnotation();
emit GlobalAnnotationDialog::appliedDialog();
}
void GlobalAnnotationDialog::updateAnnotation()
{
m_editorWidget->updateAnnotation();
m_annotation = m_editorWidget->annotation();
m_statusIsActive = (m_editorWidget->globalStatus().status() != GlobalAnnotationStatus::NoStatus);
m_globalStatus = m_editorWidget->globalStatus();
}
void GlobalAnnotationDialog::setupUI()
{
setWindowFlag(Qt::Tool, true);
setWindowTitle(tr("Global Annotation Editor"));
setModal(true);
if (!QWidget::layout())
new QVBoxLayout(this);
m_tabWidget = new QTabWidget(this);
m_tabWidget->setTabsClosable(false);
m_tabWidget->setMovable(false);
QWidget::layout()->addWidget(m_tabWidget);
m_tabWidget->addTab(m_editorWidget, tr("Global Annotation"));
m_tabWidget->addTab(m_annotationListWidget, tr("All Annotations"));
const QDialogButtonBox::StandardButtons buttonsToCreate =
QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply;
m_buttonBox = new QDialogButtonBox(buttonsToCreate, this);
QWidget::layout()->addWidget(m_buttonBox);
}
const Annotation &GlobalAnnotationDialog::annotation() const
{
return m_annotation;
}
void GlobalAnnotationDialog::setAnnotation(const Annotation &annotation)
{
m_annotation = annotation;
m_editorWidget->setAnnotation(m_annotation);
}
void GlobalAnnotationDialog::loadDefaultAnnotations(const QString &filename)
{
m_editorWidget->loadDefaultAnnotations(filename);
}
DefaultAnnotationsModel *GlobalAnnotationDialog::defaultAnnotations() const
{
return m_editorWidget->defaultAnnotations();
}
} //namespace QmlDesigner

View File

@@ -0,0 +1,96 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "modelnode.h"
#include <QDialog>
QT_BEGIN_NAMESPACE
class QTabWidget;
class QDialogButtonBox;
class QAbstractButton;
QT_END_NAMESPACE
namespace QmlDesigner {
class DefaultAnnotationsModel;
class AnnotationEditorWidget;
class AnnotationListWidget;
class GlobalAnnotationDialog : public QDialog
{
Q_OBJECT
public:
enum class ViewMode { GlobalAnnotation,
List };
explicit GlobalAnnotationDialog(ModelNode rootNode, QWidget *parent);
~GlobalAnnotationDialog();
const Annotation &annotation() const;
void setAnnotation(const Annotation &annotation);
DefaultAnnotationsModel *defaultAnnotations() const;
void loadDefaultAnnotations(const QString &filename);
GlobalAnnotationStatus globalStatus() const;
void setStatus(GlobalAnnotationStatus status);
ViewMode viewMode() const;
void saveAnnotationListChanges();
private slots:
void buttonClicked(QAbstractButton *button);
void acceptedClicked();
void appliedClicked();
signals:
void acceptedDialog(); //use instead of QDialog::accepted
void appliedDialog();
void globalChanged();
private:
void updateAnnotation();
void setupUI();
private:
GlobalAnnotationStatus m_globalStatus = GlobalAnnotationStatus::NoStatus;
bool m_statusIsActive = false;
Annotation m_annotation;
std::unique_ptr<DefaultAnnotationsModel> m_defaults;
AnnotationEditorWidget *m_editorWidget = nullptr;
AnnotationListWidget *m_annotationListWidget = nullptr;
QTabWidget *m_tabWidget = nullptr;
QDialogButtonBox *m_buttonBox = nullptr;
};
} //namespace QmlDesigner

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -26,10 +26,10 @@
#include "globalannotationeditor.h" #include "globalannotationeditor.h"
#include "annotation.h" #include "annotation.h"
#include "annotationeditordialog.h" #include "globalannotationdialog.h"
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <QMessageBox> #include <QMessageBox>
namespace QmlDesigner { namespace QmlDesigner {
@@ -38,24 +38,19 @@ GlobalAnnotationEditor::GlobalAnnotationEditor(QObject *parent)
: ModelNodeEditorProxy(parent) : ModelNodeEditorProxy(parent)
{} {}
GlobalAnnotationEditor::~GlobalAnnotationEditor() {}
QWidget *GlobalAnnotationEditor::createWidget() QWidget *GlobalAnnotationEditor::createWidget()
{ {
auto *dialog = new AnnotationEditorDialog(Core::ICore::dialogParent()); GlobalAnnotationDialog *dialog = new GlobalAnnotationDialog(m_modelNode, Core::ICore::dialogParent());
dialog->setGlobal(true);
dialog->setStatus(m_modelNode.globalStatus()); dialog->setStatus(m_modelNode.globalStatus());
dialog->setAnnotation(this->m_modelNode.globalAnnotation()); dialog->setAnnotation(this->m_modelNode.globalAnnotation());
QObject::connect(dialog, QObject::connect(dialog, &GlobalAnnotationDialog::acceptedDialog,
&AnnotationEditorDialog::acceptedDialog, this, &GlobalAnnotationEditor::acceptedClicked);
this, QObject::connect(dialog, &GlobalAnnotationDialog::rejected,
&GlobalAnnotationEditor::acceptedClicked); this, &GlobalAnnotationEditor::cancelClicked);
QObject::connect(dialog, QObject::connect(dialog, &GlobalAnnotationDialog::appliedDialog,
&AnnotationEditorDialog::rejected, this, &GlobalAnnotationEditor::appliedClicked);
this,
&GlobalAnnotationEditor::cancelClicked);
return dialog; return dialog;
}; };
@@ -65,9 +60,9 @@ void GlobalAnnotationEditor::removeFullAnnotation()
if (!node.isValid()) if (!node.isValid())
return; return;
QString dialogTitle = tr("Global Annotation"); const QString dialogTitle = tr("Global Annotation");
if (QMessageBox::question(Core::ICore::dialogParent(), if (QMessageBox::question(Core::ICore::dialogParent(),
tr("Global Annotation"), dialogTitle,
tr("Delete this annotation?")) tr("Delete this annotation?"))
== QMessageBox::Yes) { == QMessageBox::Yes) {
node.removeGlobalAnnotation(); node.removeGlobalAnnotation();
@@ -77,9 +72,42 @@ void GlobalAnnotationEditor::removeFullAnnotation()
void GlobalAnnotationEditor::acceptedClicked() void GlobalAnnotationEditor::acceptedClicked()
{ {
if (const auto *dialog = qobject_cast<AnnotationEditorDialog *>(widget())) { applyChanges();
hideWidget();
emit accepted();
emit annotationChanged();
emit customIdChanged();
}
void GlobalAnnotationEditor::appliedClicked()
{
applyChanges();
emit applied();
emit annotationChanged();
emit customIdChanged();
}
void GlobalAnnotationEditor::cancelClicked()
{
hideWidget();
emit canceled();
emit annotationChanged();
emit customIdChanged();
}
void GlobalAnnotationEditor::applyChanges()
{
if (GlobalAnnotationDialog * const dialog = qobject_cast<GlobalAnnotationDialog *>(widget())) {
//first save global annotation:
auto &node = this->m_modelNode; auto &node = this->m_modelNode;
const Annotation annotation = dialog->annotation(); const Annotation &annotation = dialog->annotation();
if (annotation.comments().isEmpty()) if (annotation.comments().isEmpty())
node.removeGlobalAnnotation(); node.removeGlobalAnnotation();
@@ -92,20 +120,11 @@ void GlobalAnnotationEditor::acceptedClicked()
node.removeGlobalStatus(); node.removeGlobalStatus();
else else
node.setGlobalStatus(status); node.setGlobalStatus(status);
//then save annotations list:
dialog->saveAnnotationListChanges();
} }
hideWidget();
emit accepted();
emit annotationChanged();
}
void GlobalAnnotationEditor::cancelClicked()
{
hideWidget();
emit canceled();
emit annotationChanged();
} }
} //namespace QmlDesigner } //namespace QmlDesigner

View File

@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
** **
** Copyright (C) 2020 The Qt Company Ltd. ** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/ ** Contact: https://www.qt.io/licensing/
** **
** This file is part of Qt Creator. ** This file is part of Qt Creator.
@@ -25,23 +25,23 @@
#pragma once #pragma once
#include "annotation.h"
#include "editorproxy.h"
#include "modelnode.h"
#include <QObject> #include <QObject>
#include <QPointer> #include <QPointer>
#include <QtQml> #include <QtQml>
#include "abstractaction.h"
#include "annotation.h"
#include "editorproxy.h"
#include "modelnode.h"
namespace QmlDesigner { namespace QmlDesigner {
class GlobalAnnotationEditor : public ModelNodeEditorProxy class GlobalAnnotationEditor : public ModelNodeEditorProxy
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit GlobalAnnotationEditor(QObject *parent = nullptr); explicit GlobalAnnotationEditor(QObject *parent = nullptr);
~GlobalAnnotationEditor(); ~GlobalAnnotationEditor() = default;
QWidget *createWidget() override; QWidget *createWidget() override;
@@ -50,12 +50,15 @@ public:
signals: signals:
void accepted(); void accepted();
void canceled(); void canceled();
void modelNodeBackendChanged(); void applied();
void annotationChanged();
private slots: private slots:
void acceptedClicked(); void acceptedClicked();
void appliedClicked();
void cancelClicked(); void cancelClicked();
private:
void applyChanges();
}; };
} //namespace QmlDesigner } //namespace QmlDesigner

View File

@@ -36,7 +36,7 @@ EditorProxy::EditorProxy(QObject *parent)
EditorProxy::~EditorProxy() EditorProxy::~EditorProxy()
{ {
hideWidget(); EditorProxy::hideWidget();
} }
void EditorProxy::showWidget() void EditorProxy::showWidget()

View File

@@ -737,11 +737,19 @@ Project {
"annotationeditor/annotationeditor.cpp", "annotationeditor/annotationeditor.cpp",
"annotationeditor/annotationeditor.h", "annotationeditor/annotationeditor.h",
"annotationeditor/annotationeditor.qrc", "annotationeditor/annotationeditor.qrc",
"annotationeditor/annotationlist.cpp",
"annotationeditor/annotationlist.h",
"annotationeditor/annotationlistwidget.cpp",
"annotationeditor/annotationlistwidget.h",
"annotationeditor/globalannotationeditor.cpp", "annotationeditor/globalannotationeditor.cpp",
"annotationeditor/globalannotationeditor.h", "annotationeditor/globalannotationeditor.h",
"annotationeditor/globalannotationdialog.cpp",
"annotationeditor/globalannotationdialog.h",
"annotationeditor/annotationeditordialog.cpp", "annotationeditor/annotationeditordialog.cpp",
"annotationeditor/annotationeditordialog.h", "annotationeditor/annotationeditordialog.h",
"annotationeditor/annotationeditordialog.ui", "annotationeditor/annotationeditorwidget.cpp",
"annotationeditor/annotationeditorwidget.h",
"annotationeditor/annotationeditorwidget.ui",
"annotationeditor/defaultannotations.cpp", "annotationeditor/defaultannotations.cpp",
"annotationeditor/defaultannotations.h", "annotationeditor/defaultannotations.h",
"annotationeditor/annotationtableview.cpp", "annotationeditor/annotationtableview.cpp",