1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "annotationtabwidget.h"
27 
28 #include "annotationcommenttab.h"
29 
30 #include <timelineeditor/timelineicons.h>
31 
32 #include <QAction>
33 #include <QMessageBox>
34 #include <QToolBar>
35 
36 namespace QmlDesigner {
AnnotationTabWidget(QWidget * parent)37 AnnotationTabWidget::AnnotationTabWidget(QWidget *parent)
38     : QTabWidget(parent)
39 {
40     auto *commentCornerWidget = new QToolBar;
41 
42     //Making it look similar to timeline editor button:
43     commentCornerWidget->setStyleSheet("QToolBar { background-color: transparent; border-width: 1px; }");
44 
45     auto *commentAddAction = new QAction(TimelineIcons::ADD_TIMELINE.icon(),
46                                          tr("Add Comment")); //timeline icons?
47     auto *commentRemoveAction = new QAction(TimelineIcons::REMOVE_TIMELINE.icon(),
48                                             tr("Remove Comment")); //timeline icons?
49     connect(commentAddAction, &QAction::triggered, this, [this]() { addCommentTab(); });
50 
51     connect(commentRemoveAction, &QAction::triggered, this, [this]() {
52         int currentIndex = this->currentIndex();
53         QString currentTitle = tabText(currentIndex);
54         if (QMessageBox::question(this,
55                                   currentTitle,
56                                   tr("Delete this comment?"))
57             == QMessageBox::Yes) {
58             removeTab(currentIndex);
59             if (count() == 0) //lets be sure that tabWidget is never empty
60                 addCommentTab();
61         }
62     });
63 
64     commentCornerWidget->addAction(commentAddAction);
65     commentCornerWidget->addAction(commentRemoveAction);
66     setCornerWidget(commentCornerWidget, Qt::TopRightCorner);
67 }
68 
~AnnotationTabWidget()69 AnnotationTabWidget::~AnnotationTabWidget() {}
70 
fetchComments() const71 QVector<Comment> AnnotationTabWidget::fetchComments() const
72 {
73     QVector<Comment> comments;
74     for (int i = 0; i < count(); i++) {
75         auto *tab = qobject_cast<AnnotationCommentTab *>(widget(i));
76         if (!tab)
77             continue;
78 
79         Comment comment = tab->currentComment();
80 
81         if (!comment.isEmpty())
82             comments.push_back(comment);
83     }
84 
85     return comments;
86 }
87 
setupComments(QVector<Comment> const & comments)88 void AnnotationTabWidget::setupComments(QVector<Comment> const &comments)
89 {
90     setUpdatesEnabled(false);
91 
92     deleteAllTabs();
93     if (comments.isEmpty())
94         addCommentTab();
95 
96     for (const Comment &comment : comments)
97         addCommentTab(comment);
98 
99     setUpdatesEnabled(true);
100 }
101 
defaultAnnotations() const102 DefaultAnnotationsModel *AnnotationTabWidget::defaultAnnotations() const
103 {
104     return m_defaults;
105 }
106 
setDefaultAnnotations(DefaultAnnotationsModel * defaults)107 void AnnotationTabWidget::setDefaultAnnotations(DefaultAnnotationsModel *defaults)
108 {
109     m_defaults = defaults;
110     for (int i = 0; i < count(); i++) {
111         // The tab widget might be contain regular QTabs initially, hence we need this qobject_cast test
112         if (auto *tab = qobject_cast<AnnotationCommentTab *>(widget(i)))
113             tab->setDefaultAnnotations(defaults);
114     }
115 }
116 
onCommentTitleChanged(const QString & text,QWidget * tab)117 void AnnotationTabWidget::onCommentTitleChanged(const QString &text, QWidget *tab)
118 {
119     int tabIndex = indexOf(tab);
120     if (tabIndex >= 0)
121         setTabText(tabIndex, text);
122 
123     if (text.isEmpty())
124         setTabText(tabIndex, defaultTabName + " " + QString::number(tabIndex + 1));
125 }
126 
addCommentTab(const Comment & comment)127 void AnnotationTabWidget::addCommentTab(const Comment &comment)
128 {
129     auto *commentTab = new AnnotationCommentTab();
130     commentTab->setDefaultAnnotations(m_defaults);
131     commentTab->setComment(comment);
132 
133     QString tabTitle(comment.title());
134     int tabIndex = addTab(commentTab, tabTitle);
135     setCurrentIndex(tabIndex);
136 
137     if (tabTitle.isEmpty()) {
138         const QString appendix = ((tabIndex > 0) ? QString::number(tabIndex + 1) : "");
139         tabTitle = QString("%1 %2").arg(defaultTabName).arg(appendix);
140         setTabText(tabIndex, tabTitle);
141     }
142     connect(commentTab,
143             &AnnotationCommentTab::titleChanged,
144             this,
145             &AnnotationTabWidget::onCommentTitleChanged);
146 }
147 
deleteAllTabs()148 void AnnotationTabWidget::deleteAllTabs()
149 {
150     while (count() > 0) {
151         QWidget *w = widget(0);
152         removeTab(0);
153         delete w;
154     }
155 }
156 
157 } // namespace QmlDesigner
158