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 "edit3dwidget.h"
27 #include "edit3dview.h"
28 #include "edit3dcanvas.h"
29 #include "edit3dactions.h"
30 
31 #include "qmldesignerplugin.h"
32 #include "designersettings.h"
33 #include "qmldesignerconstants.h"
34 #include "viewmanager.h"
35 
36 #include <coreplugin/actionmanager/actionmanager.h>
37 #include <coreplugin/actionmanager/command.h>
38 #include <coreplugin/icore.h>
39 #include <toolbox.h>
40 #include <utils/utilsicons.h>
41 
42 #include <QActionGroup>
43 #include <QVBoxLayout>
44 
45 namespace QmlDesigner {
46 
Edit3DWidget(Edit3DView * view)47 Edit3DWidget::Edit3DWidget(Edit3DView *view) :
48     m_view(view)
49 {
50     Core::Context context(Constants::C_QMLEDITOR3D);
51     m_context = new Core::IContext(this);
52     m_context->setContext(context);
53     m_context->setWidget(this);
54 
55     setMouseTracking(true);
56     setFocusPolicy(Qt::WheelFocus);
57 
58     auto fillLayout = new QVBoxLayout(this);
59     fillLayout->setContentsMargins(0, 0, 0, 0);
60     fillLayout->setSpacing(0);
61     setLayout(fillLayout);
62 
63     // Initialize toolbar
64     m_toolBox = new ToolBox(this);
65     fillLayout->addWidget(m_toolBox.data());
66 
67     // Iterate through view actions. A null action indicates a separator and a second null action
68     // after separator indicates an exclusive group.
69     auto addActionsToToolBox = [this, &context](const QVector<Edit3DAction *> &actions, bool left) {
70         bool previousWasSeparator = true;
71         QActionGroup *group = nullptr;
72         for (auto action : actions) {
73             if (action) {
74                 if (group)
75                     group->addAction(action->action());
76                 addAction(action->action());
77                 if (left)
78                     m_toolBox->addLeftSideAction(action->action());
79                 else
80                     m_toolBox->addRightSideAction(action->action());
81                 previousWasSeparator = false;
82 
83                 // Register action as creator command to make it configurable
84                 Core::Command *command = Core::ActionManager::registerAction(
85                             action->action(), action->menuId().constData(), context);
86                 command->setDefaultKeySequence(action->action()->shortcut());
87                 command->augmentActionWithShortcutToolTip(action->action());
88                 // Clear action shortcut so it doesn't conflict with command's override action
89                 action->action()->setShortcut({});
90             } else {
91                 if (previousWasSeparator) {
92                     group = new QActionGroup(this);
93                     previousWasSeparator = false;
94                 } else {
95                     group = nullptr;
96                     auto separator = new QAction(this);
97                     separator->setSeparator(true);
98                     addAction(separator);
99                     m_toolBox->addLeftSideAction(separator);
100                     previousWasSeparator = true;
101                 }
102             }
103         }
104     };
105     addActionsToToolBox(view->leftActions(), true);
106     addActionsToToolBox(view->rightActions(), false);
107 
108     // Onboarding label contains instructions for new users how to get 3D content into the project
109     m_onboardingLabel = new QLabel(this);
110     QString labelText =
111             tr("Your file does not import Qt Quick 3D.<br><br>"
112                "To create a 3D view, add the QtQuick3D module in the Library view. Or click"
113                " <a href=\"#add_import\"><span style=\"text-decoration:none;color:%1\">here</span></a> "
114                "here to add it immediately.<br><br>"
115                "To import 3D assets from another tool, click the \"Add New Assets...\" button in the Assets tab of the Library view.");
116     m_onboardingLabel->setText(labelText.arg(Utils::creatorTheme()->color(Utils::Theme::TextColorLink).name()));
117     m_onboardingLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
118     connect(m_onboardingLabel, &QLabel::linkActivated, this, &Edit3DWidget::linkActivated);
119     fillLayout->addWidget(m_onboardingLabel.data());
120 
121     // Canvas is used to render the actual edit 3d view
122     m_canvas = new Edit3DCanvas(this);
123     fillLayout->addWidget(m_canvas.data());
124     showCanvas(false);
125 }
126 
contextHelp(const Core::IContext::HelpCallback & callback) const127 void Edit3DWidget::contextHelp(const Core::IContext::HelpCallback &callback) const
128 {
129     if (m_view)
130         m_view->contextHelp(callback);
131 
132     callback({});
133 }
134 
showCanvas(bool show)135 void Edit3DWidget::showCanvas(bool show)
136 {
137     if (!show) {
138         QImage emptyImage;
139         m_canvas->updateRenderImage(emptyImage);
140     }
141     m_canvas->setVisible(show);
142     m_onboardingLabel->setVisible(!show);
143 }
144 
linkActivated(const QString & link)145 void Edit3DWidget::linkActivated(const QString &link)
146 {
147     Q_UNUSED(link)
148     if (m_view)
149         m_view->addQuick3DImport();
150 }
151 
canvas() const152 Edit3DCanvas *Edit3DWidget::canvas() const
153 {
154     return m_canvas.data();
155 }
156 
view() const157 Edit3DView *Edit3DWidget::view() const
158 {
159     return m_view.data();
160 }
161 
162 }
163