From 3e1fa0f170d523971d2c3c12da15a6e291f56511 Mon Sep 17 00:00:00 2001 From: Aleksei German Date: Fri, 9 Jul 2021 17:34:17 +0200 Subject: [PATCH] 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 Reviewed-by: Thomas Hartmann --- src/plugins/qmldesigner/CMakeLists.txt | 6 +- .../annotationeditor/annotationeditor.cpp | 44 ++- .../annotationeditor/annotationeditor.h | 7 +- .../annotationeditor/annotationeditor.pri | 10 +- .../annotationeditordialog.cpp | 184 +++------- .../annotationeditor/annotationeditordialog.h | 55 ++- .../annotationeditorwidget.cpp | 243 +++++++++++++ .../annotationeditor/annotationeditorwidget.h | 104 ++++++ ...tordialog.ui => annotationeditorwidget.ui} | 62 +--- .../annotationeditor/annotationlist.cpp | 322 ++++++++++++++++++ .../annotationeditor/annotationlist.h | 139 ++++++++ .../annotationeditor/annotationlistwidget.cpp | 119 +++++++ .../annotationeditor/annotationlistwidget.h | 70 ++++ .../annotationeditor/annotationtableview.h | 2 +- .../annotationeditor/annotationtabwidget.cpp | 6 +- .../annotationeditor/annotationtabwidget.h | 6 +- .../globalannotationdialog.cpp | 176 ++++++++++ .../annotationeditor/globalannotationdialog.h | 96 ++++++ .../globalannotationeditor.cpp | 83 +++-- .../annotationeditor/globalannotationeditor.h | 21 +- src/plugins/qmldesigner/editorproxy.cpp | 2 +- src/plugins/qmldesigner/qmldesignerplugin.qbs | 10 +- 22 files changed, 1468 insertions(+), 299 deletions(-) create mode 100644 src/plugins/qmldesigner/components/annotationeditor/annotationeditorwidget.cpp create mode 100644 src/plugins/qmldesigner/components/annotationeditor/annotationeditorwidget.h rename src/plugins/qmldesigner/components/annotationeditor/{annotationeditordialog.ui => annotationeditorwidget.ui} (76%) create mode 100644 src/plugins/qmldesigner/components/annotationeditor/annotationlist.cpp create mode 100644 src/plugins/qmldesigner/components/annotationeditor/annotationlist.h create mode 100644 src/plugins/qmldesigner/components/annotationeditor/annotationlistwidget.cpp create mode 100644 src/plugins/qmldesigner/components/annotationeditor/annotationlistwidget.h create mode 100644 src/plugins/qmldesigner/components/annotationeditor/globalannotationdialog.cpp create mode 100644 src/plugins/qmldesigner/components/annotationeditor/globalannotationdialog.h diff --git a/src/plugins/qmldesigner/CMakeLists.txt b/src/plugins/qmldesigner/CMakeLists.txt index 1c29b9c58df..f3ab6fe3738 100644 --- a/src/plugins/qmldesigner/CMakeLists.txt +++ b/src/plugins/qmldesigner/CMakeLists.txt @@ -638,9 +638,13 @@ extend_qtc_plugin(QmlDesigner extend_qtc_plugin(QmlDesigner SOURCES_PREFIX components/annotationeditor 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 + annotationlist.cpp annotationlist.h + annotationlistwidget.cpp annotationlistwidget.h globalannotationeditor.cpp globalannotationeditor.h + globalannotationdialog.cpp globalannotationdialog.h defaultannotations.cpp defaultannotations.h annotationtableview.cpp annotationtableview.h annotationtabwidget.cpp annotationtabwidget.h diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp b/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp index 448aa3c46e5..54add870e48 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.cpp @@ -46,8 +46,6 @@ AnnotationEditor::AnnotationEditor(QObject *parent) : ModelNodeEditorProxy(parent) {} -AnnotationEditor::~AnnotationEditor() {} - QWidget *AnnotationEditor::createWidget() { const auto &node = m_modelNode; @@ -64,6 +62,8 @@ QWidget *AnnotationEditor::createWidget() &AnnotationEditorDialog::rejected, this, &AnnotationEditor::cancelClicked); + QObject::connect(dialog, &AnnotationEditorDialog::appliedDialog, + this, &AnnotationEditor::appliedClicked); return dialog; } @@ -91,19 +91,7 @@ void AnnotationEditor::removeFullAnnotation() void AnnotationEditor::acceptedClicked() { - if (const auto *dialog = qobject_cast(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); - } + applyChanges(); hideWidget(); @@ -122,4 +110,30 @@ void AnnotationEditor::cancelClicked() emit annotationChanged(); } +void AnnotationEditor::appliedClicked() +{ + applyChanges(); + + emit applied(); + emit customIdChanged(); + emit annotationChanged(); +} + +void AnnotationEditor::applyChanges() +{ + if (const auto *dialog = qobject_cast(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 diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.h b/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.h index 3ebfd2d28b5..cadeeac7e37 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.h +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.h @@ -36,7 +36,7 @@ class AnnotationEditor : public ModelNodeEditorProxy Q_OBJECT public: explicit AnnotationEditor(QObject *parent = nullptr); - ~AnnotationEditor(); + ~AnnotationEditor() = default; QWidget *createWidget() override; Q_INVOKABLE void removeFullAnnotation(); @@ -46,10 +46,15 @@ public: signals: void accepted(); void canceled(); + void applied(); private slots: void acceptedClicked(); void cancelClicked(); + void appliedClicked(); + +private: + void applyChanges(); }; } //namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.pri b/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.pri index ff79353960d..649a2df47d6 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.pri +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationeditor.pri @@ -5,6 +5,10 @@ HEADERS += $$PWD/globalannotationeditor.h HEADERS += $$PWD/defaultannotations.h HEADERS += $$PWD/annotationtableview.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/annotationeditordialog.cpp @@ -13,9 +17,13 @@ SOURCES += $$PWD/globalannotationeditor.cpp SOURCES += $$PWD/defaultannotations.cpp SOURCES += $$PWD/annotationtableview.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/annotationeditordialog.ui +FORMS += $$PWD/annotationeditorwidget.ui INCLUDEPATH += $$PWD diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationeditordialog.cpp b/src/plugins/qmldesigner/components/annotationeditor/annotationeditordialog.cpp index bf4e3ce74da..7e0030b2db8 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationeditordialog.cpp +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationeditordialog.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -27,184 +27,89 @@ #include "annotation.h" #include "annotationcommenttab.h" #include "defaultannotations.h" - -#include "ui_annotationeditordialog.h" +#include "annotationeditorwidget.h" #include #include #include #include +#include +#include #include #include +#include namespace QmlDesigner { AnnotationEditorDialog::AnnotationEditorDialog(QWidget *parent, const QString &targetId, const QString &customId) : QDialog(parent) - , ui(std::make_unique()) , m_customId(customId) , m_defaults(std::make_unique()) + , m_editorWidget(new AnnotationEditorWidget(this, targetId, customId)) { - ui->setupUi(this); - setGlobal(m_isGlobal); + setWindowTitle(tr("Annotation Editor")); setWindowFlag(Qt::Tool, true); setModal(true); - loadDefaultAnnotations(DefaultAnnotationsModel::defaultJsonFilePath()); - ui->tabWidget->setDefaultAnnotations(defaultAnnotations()); - ui->tableView->setDefaultAnnotations(defaultAnnotations()); - connect(ui->tableView, - &AnnotationTableView::richTextEditorRequested, - this, - [&](int index, QString const &) { - switchToTabView(); - ui->tabWidget->setCurrentIndex(index); - }); + const QDialogButtonBox::StandardButtons buttonsToCreate = + QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::Apply; - connect(ui->statusAddButton, &QPushButton::clicked, this, [&](bool) { - setStatusVisibility(true); - }); + m_buttonBox = new QDialogButtonBox(buttonsToCreate, this); - connect(ui->rbTableView, - &QRadioButton::clicked, - this, - &AnnotationEditorDialog::switchToTableView); - connect(ui->rbTabView, - &QRadioButton::clicked, - this, &AnnotationEditorDialog::switchToTabView); + if (!QWidget::layout()) + new QVBoxLayout(this); - setStatus(m_globalStatus); - switchToTabView(); + QWidget::layout()->addWidget(m_editorWidget); + 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 { - return m_isGlobal; -} - -void AnnotationEditorDialog::setGlobal(bool global) { - ui->annotationContainer->setVisible(!global); - 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(); +void AnnotationEditorDialog::buttonClicked(QAbstractButton *button) +{ + if (button) { + const QDialogButtonBox::StandardButton buttonType = m_buttonBox->standardButton(button); + if (buttonType == QDialogButtonBox::Apply) { + appliedClicked(); + } } } -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() { updateAnnotation(); emit AnnotationEditorDialog::acceptedDialog(); } -void AnnotationEditorDialog::fillFields() +void AnnotationEditorDialog::appliedClicked() { - ui->customIdEdit->setText(m_customId); - ui->tabWidget->setupComments(m_annotation.comments()); - ui->tableView->setupComments(m_annotation.comments()); + updateAnnotation(); + emit AnnotationEditorDialog::appliedDialog(); } void AnnotationEditorDialog::updateAnnotation() { - m_customId = ui->customIdEdit->text(); - Annotation annotation; - switch (viewMode()) { - 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()); + m_editorWidget->updateAnnotation(); + m_customId = m_editorWidget->customId(); + m_annotation = m_editorWidget->annotation(); } -void AnnotationEditorDialog::addComment(const Comment &comment) -{ - 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 +const Annotation &AnnotationEditorDialog::annotation() const { return m_annotation; } @@ -212,29 +117,28 @@ Annotation const &AnnotationEditorDialog::annotation() const void AnnotationEditorDialog::setAnnotation(const 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 { - return m_defaults.get(); + return m_editorWidget->defaultAnnotations(); } void AnnotationEditorDialog::setCustomId(const QString &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; } - } //namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationeditordialog.h b/src/plugins/qmldesigner/components/annotationeditor/annotationeditordialog.h index eefccba6efd..42de0325208 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationeditordialog.h +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationeditordialog.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -25,72 +25,63 @@ #pragma once +#include "annotation.h" + #include -#include "annotation.h" + +QT_BEGIN_NAMESPACE +class QAbstractButton; +class QDialogButtonBox; +QT_END_NAMESPACE namespace QmlDesigner { -namespace Ui { -class AnnotationEditorDialog; -} class DefaultAnnotationsModel; +class AnnotationEditorWidget; class AnnotationEditorDialog : public QDialog { Q_OBJECT public: - enum ViewMode { TableView, TabsView }; + enum class ViewMode { TableView, + TabsView }; explicit AnnotationEditorDialog(QWidget *parent, const QString &targetId = {}, const QString &customId = {}); ~AnnotationEditorDialog(); - ViewMode viewMode() const; - - Annotation const &annotation() const; + const Annotation &annotation() const; void setAnnotation(const Annotation &annotation); - QString customId() const; + const QString &customId() const; void setCustomId(const QString &customId); - bool isGlobal() const; - void setGlobal(bool = true); - - void loadDefaultAnnotations(QString const &filename); - DefaultAnnotationsModel *defaultAnnotations() const; - void setStatus(GlobalAnnotationStatus status); - GlobalAnnotationStatus globalStatus() const; - -public slots: - void showStatusContainer(bool show); - void switchToTabView(); - void switchToTableView(); + void loadDefaultAnnotations(const QString &filename); private slots: + void buttonClicked(QAbstractButton *button); + void acceptedClicked(); + void appliedClicked(); signals: void acceptedDialog(); //use instead of QDialog::accepted - void globalChanged(); + void appliedDialog(); + private: - void fillFields(); void updateAnnotation(); - void addComment(const Comment &comment); - void removeComment(int index); - - void setStatusVisibility(bool hasStatus); - - std::unique_ptr ui; +private: GlobalAnnotationStatus m_globalStatus = GlobalAnnotationStatus::NoStatus; - bool m_statusIsActive = false; - bool m_isGlobal = false; Annotation m_annotation; QString m_customId; std::unique_ptr m_defaults; + AnnotationEditorWidget *m_editorWidget; + + QDialogButtonBox *m_buttonBox; }; diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationeditorwidget.cpp b/src/plugins/qmldesigner/components/annotationeditor/annotationeditorwidget.cpp new file mode 100644 index 00000000000..0d87d615d0d --- /dev/null +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationeditorwidget.cpp @@ -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 +#include + +#include +#include +#include +#include +#include + +namespace QmlDesigner { +AnnotationEditorWidget::AnnotationEditorWidget(QWidget *parent, + const QString &targetId, + const QString &customId) + : QWidget(parent) + , m_defaults(std::make_unique()) + , ui(std::make_unique()) + , 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(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 diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationeditorwidget.h b/src/plugins/qmldesigner/components/annotationeditor/annotationeditorwidget.h new file mode 100644 index 00000000000..c6114977d88 --- /dev/null +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationeditorwidget.h @@ -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 + + +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 m_defaults; + std::unique_ptr ui; + GlobalAnnotationStatus m_globalStatus = GlobalAnnotationStatus::NoStatus; + bool m_statusIsActive = false; + bool m_isGlobal = false; + Annotation m_annotation; + QString m_customId; +}; + + +} //namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationeditordialog.ui b/src/plugins/qmldesigner/components/annotationeditor/annotationeditorwidget.ui similarity index 76% rename from src/plugins/qmldesigner/components/annotationeditor/annotationeditordialog.ui rename to src/plugins/qmldesigner/components/annotationeditor/annotationeditorwidget.ui index 379069aa6be..95b37d04aa2 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationeditordialog.ui +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationeditorwidget.ui @@ -1,7 +1,7 @@ - QmlDesigner::AnnotationEditorDialog - + QmlDesigner::AnnotationEditorWidget + 0 @@ -10,10 +10,7 @@ 819 - - Dialog - - + @@ -170,19 +167,6 @@ - - - - Qt::StrongFocus - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - @@ -198,44 +182,6 @@
annotationtableview.h
- - targetIdEdit - customIdEdit - tabWidget - - - - buttonBox - accepted() - QmlDesigner::AnnotationEditorDialog - accept() - - - 261 - 473 - - - 157 - 274 - - - - - buttonBox - rejected() - QmlDesigner::AnnotationEditorDialog - reject() - - - 329 - 473 - - - 286 - 274 - - - - +
diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationlist.cpp b/src/plugins/qmldesigner/components/annotationeditor/annotationlist.cpp new file mode 100644 index 00000000000..898ddae331b --- /dev/null +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationlist.cpp @@ -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 +#include + +#include + +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 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(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(); +} + +} diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationlist.h b/src/plugins/qmldesigner/components/annotationeditor/annotationlist.h new file mode 100644 index 00000000000..098c6a6b1a3 --- /dev/null +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationlist.h @@ -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 + +#include +#include +#include +#include + +#include +#include + + +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 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; +}; + +} + diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationlistwidget.cpp b/src/plugins/qmldesigner/components/annotationeditor/annotationlistwidget.cpp new file mode 100644 index 00000000000..5266f27dbd5 --- /dev/null +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationlistwidget.cpp @@ -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 +#include +#include + +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(); +} + +} diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationlistwidget.h b/src/plugins/qmldesigner/components/annotationeditor/annotationlistwidget.h new file mode 100644 index 00000000000..5c095804c17 --- /dev/null +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationlistwidget.h @@ -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 + +#include +#include +#include + + +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; +}; + +} + diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationtableview.h b/src/plugins/qmldesigner/components/annotationeditor/annotationtableview.h index b30fe271de3..050f6b356f1 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationtableview.h +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationtableview.h @@ -84,7 +84,7 @@ public: QAbstractItemModel *model, const QModelIndex &index) const override; signals: - void commentChanged(int row, Comment const &); + void commentChanged(int row, const QmlDesigner::Comment &comment); }; class CommentValueDelegate : public CommentDelegate diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationtabwidget.cpp b/src/plugins/qmldesigner/components/annotationeditor/annotationtabwidget.cpp index 960920284a5..3f9a6d1e175 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationtabwidget.cpp +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationtabwidget.cpp @@ -66,8 +66,6 @@ AnnotationTabWidget::AnnotationTabWidget(QWidget *parent) setCornerWidget(commentCornerWidget, Qt::TopRightCorner); } -AnnotationTabWidget::~AnnotationTabWidget() {} - QVector AnnotationTabWidget::fetchComments() const { QVector comments; @@ -85,7 +83,7 @@ QVector AnnotationTabWidget::fetchComments() const return comments; } -void AnnotationTabWidget::setupComments(QVector const &comments) +void AnnotationTabWidget::setupComments(const QVector &comments) { setUpdatesEnabled(false); @@ -124,7 +122,7 @@ void AnnotationTabWidget::onCommentTitleChanged(const QString &text, QWidget *ta setTabText(tabIndex, defaultTabName + " " + QString::number(tabIndex + 1)); } -void AnnotationTabWidget::addCommentTab(const Comment &comment) +void AnnotationTabWidget::addCommentTab(const QmlDesigner::Comment &comment) { auto *commentTab = new AnnotationCommentTab(); commentTab->setDefaultAnnotations(m_defaults); diff --git a/src/plugins/qmldesigner/components/annotationeditor/annotationtabwidget.h b/src/plugins/qmldesigner/components/annotationeditor/annotationtabwidget.h index 944400f5e63..b13416601ba 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/annotationtabwidget.h +++ b/src/plugins/qmldesigner/components/annotationeditor/annotationtabwidget.h @@ -37,16 +37,16 @@ class AnnotationTabWidget : public QTabWidget Q_OBJECT public: AnnotationTabWidget(QWidget *parent = nullptr); - ~AnnotationTabWidget(); + ~AnnotationTabWidget() = default; QVector fetchComments() const; - void setupComments(QVector const &comments); + void setupComments(const QVector &comments); DefaultAnnotationsModel *defaultAnnotations() const; void setDefaultAnnotations(DefaultAnnotationsModel *); public slots: - void addCommentTab(const Comment &comment = {}); + void addCommentTab(const QmlDesigner::Comment &comment = {}); void deleteAllTabs(); private slots: diff --git a/src/plugins/qmldesigner/components/annotationeditor/globalannotationdialog.cpp b/src/plugins/qmldesigner/components/annotationeditor/globalannotationdialog.cpp new file mode 100644 index 00000000000..1d785e22f9a --- /dev/null +++ b/src/plugins/qmldesigner/components/annotationeditor/globalannotationdialog.cpp @@ -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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace QmlDesigner { + +GlobalAnnotationDialog::GlobalAnnotationDialog(ModelNode rootNode, QWidget *parent) + : QDialog(parent) + , m_statusIsActive(false) + , m_defaults(std::make_unique()) + , 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 diff --git a/src/plugins/qmldesigner/components/annotationeditor/globalannotationdialog.h b/src/plugins/qmldesigner/components/annotationeditor/globalannotationdialog.h new file mode 100644 index 00000000000..eb3f8b17933 --- /dev/null +++ b/src/plugins/qmldesigner/components/annotationeditor/globalannotationdialog.h @@ -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 + +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 m_defaults; + AnnotationEditorWidget *m_editorWidget = nullptr; + AnnotationListWidget *m_annotationListWidget = nullptr; + + QTabWidget *m_tabWidget = nullptr; + QDialogButtonBox *m_buttonBox = nullptr; +}; + + +} //namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/annotationeditor/globalannotationeditor.cpp b/src/plugins/qmldesigner/components/annotationeditor/globalannotationeditor.cpp index 6dfdf0f285e..08bd0cbf87d 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/globalannotationeditor.cpp +++ b/src/plugins/qmldesigner/components/annotationeditor/globalannotationeditor.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -26,10 +26,10 @@ #include "globalannotationeditor.h" #include "annotation.h" -#include "annotationeditordialog.h" - +#include "globalannotationdialog.h" #include + #include namespace QmlDesigner { @@ -38,24 +38,19 @@ GlobalAnnotationEditor::GlobalAnnotationEditor(QObject *parent) : ModelNodeEditorProxy(parent) {} -GlobalAnnotationEditor::~GlobalAnnotationEditor() {} - 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->setAnnotation(this->m_modelNode.globalAnnotation()); - QObject::connect(dialog, - &AnnotationEditorDialog::acceptedDialog, - this, - &GlobalAnnotationEditor::acceptedClicked); - QObject::connect(dialog, - &AnnotationEditorDialog::rejected, - this, - &GlobalAnnotationEditor::cancelClicked); + QObject::connect(dialog, &GlobalAnnotationDialog::acceptedDialog, + this, &GlobalAnnotationEditor::acceptedClicked); + QObject::connect(dialog, &GlobalAnnotationDialog::rejected, + this, &GlobalAnnotationEditor::cancelClicked); + QObject::connect(dialog, &GlobalAnnotationDialog::appliedDialog, + this, &GlobalAnnotationEditor::appliedClicked); return dialog; }; @@ -65,9 +60,9 @@ void GlobalAnnotationEditor::removeFullAnnotation() if (!node.isValid()) return; - QString dialogTitle = tr("Global Annotation"); + const QString dialogTitle = tr("Global Annotation"); if (QMessageBox::question(Core::ICore::dialogParent(), - tr("Global Annotation"), + dialogTitle, tr("Delete this annotation?")) == QMessageBox::Yes) { node.removeGlobalAnnotation(); @@ -77,9 +72,42 @@ void GlobalAnnotationEditor::removeFullAnnotation() void GlobalAnnotationEditor::acceptedClicked() { - if (const auto *dialog = qobject_cast(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(widget())) { + //first save global annotation: auto &node = this->m_modelNode; - const Annotation annotation = dialog->annotation(); + const Annotation &annotation = dialog->annotation(); if (annotation.comments().isEmpty()) node.removeGlobalAnnotation(); @@ -92,20 +120,11 @@ void GlobalAnnotationEditor::acceptedClicked() node.removeGlobalStatus(); else node.setGlobalStatus(status); + + + //then save annotations list: + dialog->saveAnnotationListChanges(); } - - hideWidget(); - - emit accepted(); - emit annotationChanged(); -} - -void GlobalAnnotationEditor::cancelClicked() -{ - hideWidget(); - - emit canceled(); - emit annotationChanged(); } } //namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/annotationeditor/globalannotationeditor.h b/src/plugins/qmldesigner/components/annotationeditor/globalannotationeditor.h index 6b14fb892fd..c331b2a1409 100644 --- a/src/plugins/qmldesigner/components/annotationeditor/globalannotationeditor.h +++ b/src/plugins/qmldesigner/components/annotationeditor/globalannotationeditor.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -25,23 +25,23 @@ #pragma once +#include "annotation.h" +#include "editorproxy.h" +#include "modelnode.h" + #include #include #include -#include "abstractaction.h" -#include "annotation.h" - -#include "editorproxy.h" -#include "modelnode.h" namespace QmlDesigner { + class GlobalAnnotationEditor : public ModelNodeEditorProxy { Q_OBJECT public: explicit GlobalAnnotationEditor(QObject *parent = nullptr); - ~GlobalAnnotationEditor(); + ~GlobalAnnotationEditor() = default; QWidget *createWidget() override; @@ -50,12 +50,15 @@ public: signals: void accepted(); void canceled(); - void modelNodeBackendChanged(); - void annotationChanged(); + void applied(); private slots: void acceptedClicked(); + void appliedClicked(); void cancelClicked(); + +private: + void applyChanges(); }; } //namespace QmlDesigner diff --git a/src/plugins/qmldesigner/editorproxy.cpp b/src/plugins/qmldesigner/editorproxy.cpp index 16bc65cdff3..d7b8b1dd04b 100644 --- a/src/plugins/qmldesigner/editorproxy.cpp +++ b/src/plugins/qmldesigner/editorproxy.cpp @@ -36,7 +36,7 @@ EditorProxy::EditorProxy(QObject *parent) EditorProxy::~EditorProxy() { - hideWidget(); + EditorProxy::hideWidget(); } void EditorProxy::showWidget() diff --git a/src/plugins/qmldesigner/qmldesignerplugin.qbs b/src/plugins/qmldesigner/qmldesignerplugin.qbs index 9d5c3cfc530..a1cf95c0e8b 100644 --- a/src/plugins/qmldesigner/qmldesignerplugin.qbs +++ b/src/plugins/qmldesigner/qmldesignerplugin.qbs @@ -737,11 +737,19 @@ Project { "annotationeditor/annotationeditor.cpp", "annotationeditor/annotationeditor.h", "annotationeditor/annotationeditor.qrc", + "annotationeditor/annotationlist.cpp", + "annotationeditor/annotationlist.h", + "annotationeditor/annotationlistwidget.cpp", + "annotationeditor/annotationlistwidget.h", "annotationeditor/globalannotationeditor.cpp", "annotationeditor/globalannotationeditor.h", + "annotationeditor/globalannotationdialog.cpp", + "annotationeditor/globalannotationdialog.h", "annotationeditor/annotationeditordialog.cpp", "annotationeditor/annotationeditordialog.h", - "annotationeditor/annotationeditordialog.ui", + "annotationeditor/annotationeditorwidget.cpp", + "annotationeditor/annotationeditorwidget.h", + "annotationeditor/annotationeditorwidget.ui", "annotationeditor/defaultannotations.cpp", "annotationeditor/defaultannotations.h", "annotationeditor/annotationtableview.cpp",