1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Designer of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include "formwindow_widgetstack.h" |
30 | #include <QtDesigner/abstractformwindowtool.h> |
31 | |
32 | #include <QtWidgets/qwidget.h> |
33 | #include <QtGui/qevent.h> |
34 | #include <QtWidgets/qaction.h> |
35 | #include <QtWidgets/qstackedlayout.h> |
36 | #include <QtWidgets/qboxlayout.h> |
37 | |
38 | #include <QtCore/qdebug.h> |
39 | |
40 | QT_BEGIN_NAMESPACE |
41 | |
42 | using namespace qdesigner_internal; |
43 | |
44 | FormWindowWidgetStack::FormWindowWidgetStack(QObject *parent) : |
45 | QObject(parent), |
46 | m_formContainer(new QWidget), |
47 | m_formContainerLayout(new QStackedLayout), |
48 | m_layout(new QStackedLayout) |
49 | { |
50 | m_layout->setContentsMargins(QMargins()); |
51 | m_layout->setSpacing(0); |
52 | m_layout->setStackingMode(QStackedLayout::StackAll); |
53 | |
54 | // We choose a QStackedLayout as immediate layout for |
55 | // the form windows as it ignores the sizePolicy of |
56 | // its child (for example, Fixed would cause undesired side effects). |
57 | m_formContainerLayout->setContentsMargins(QMargins()); |
58 | m_formContainer->setObjectName(QStringLiteral("formContainer" )); |
59 | m_formContainer->setLayout(m_formContainerLayout); |
60 | m_formContainerLayout->setStackingMode(QStackedLayout::StackAll); |
61 | // System settings might have different background colors, autofill them |
62 | // (affects for example mainwindow status bars) |
63 | m_formContainer->setAutoFillBackground(true); |
64 | } |
65 | |
66 | FormWindowWidgetStack::~FormWindowWidgetStack() = default; |
67 | |
68 | int FormWindowWidgetStack::count() const |
69 | { |
70 | return m_tools.count(); |
71 | } |
72 | |
73 | QDesignerFormWindowToolInterface *FormWindowWidgetStack::currentTool() const |
74 | { |
75 | return tool(index: currentIndex()); |
76 | } |
77 | |
78 | void FormWindowWidgetStack::setCurrentTool(int index) |
79 | { |
80 | const int cnt = count(); |
81 | if (index < 0 || index >= cnt) { |
82 | qDebug(msg: "FormWindowWidgetStack::setCurrentTool(): invalid index: %d" , index); |
83 | return; |
84 | } |
85 | |
86 | const int cur = currentIndex(); |
87 | if (index == cur) |
88 | return; |
89 | |
90 | if (cur != -1) |
91 | m_tools.at(i: cur)->deactivated(); |
92 | |
93 | |
94 | m_layout->setCurrentIndex(index); |
95 | // Show the widget editor and the current tool |
96 | for (int i = 0; i < cnt; i++) |
97 | m_tools.at(i)->editor()->setVisible(i == 0 || i == index); |
98 | |
99 | QDesignerFormWindowToolInterface *tool = m_tools.at(i: index); |
100 | tool->activated(); |
101 | |
102 | emit currentToolChanged(index); |
103 | } |
104 | |
105 | void FormWindowWidgetStack::setSenderAsCurrentTool() |
106 | { |
107 | QDesignerFormWindowToolInterface *tool = nullptr; |
108 | QAction *action = qobject_cast<QAction*>(object: sender()); |
109 | if (action == nullptr) { |
110 | qDebug(msg: "FormWindowWidgetStack::setSenderAsCurrentTool(): sender is not a QAction" ); |
111 | return; |
112 | } |
113 | |
114 | for (QDesignerFormWindowToolInterface *t : qAsConst(t&: m_tools)) { |
115 | if (action == t->action()) { |
116 | tool = t; |
117 | break; |
118 | } |
119 | } |
120 | |
121 | if (tool == nullptr) { |
122 | qDebug(msg: "FormWindowWidgetStack::setSenderAsCurrentTool(): unknown tool" ); |
123 | return; |
124 | } |
125 | |
126 | setCurrentTool(tool); |
127 | } |
128 | |
129 | int FormWindowWidgetStack::indexOf(QDesignerFormWindowToolInterface *tool) const |
130 | { |
131 | return m_tools.indexOf(t: tool); |
132 | } |
133 | |
134 | void FormWindowWidgetStack::setCurrentTool(QDesignerFormWindowToolInterface *tool) |
135 | { |
136 | int index = indexOf(tool); |
137 | if (index == -1) { |
138 | qDebug(msg: "FormWindowWidgetStack::setCurrentTool(): unknown tool" ); |
139 | return; |
140 | } |
141 | |
142 | setCurrentTool(index); |
143 | } |
144 | |
145 | void FormWindowWidgetStack::setMainContainer(QWidget *w) |
146 | { |
147 | // This code is triggered once by the formwindow and |
148 | // by integrations doing "revert to saved". Anything changing? |
149 | const int previousCount = m_formContainerLayout->count(); |
150 | QWidget *previousMainContainer = previousCount |
151 | ? m_formContainerLayout->itemAt(0)->widget() : nullptr; |
152 | if (previousMainContainer == w) |
153 | return; |
154 | // Swap |
155 | if (previousCount) |
156 | delete m_formContainerLayout->takeAt(0); |
157 | if (w) |
158 | m_formContainerLayout->addWidget(w); |
159 | } |
160 | |
161 | void FormWindowWidgetStack::addTool(QDesignerFormWindowToolInterface *tool) |
162 | { |
163 | if (QWidget *w = tool->editor()) { |
164 | w->setVisible(m_layout->count() == 0); // Initially only form editor is visible |
165 | m_layout->addWidget(w); |
166 | } else { |
167 | // The form editor might not have a tool initially, use dummy. Assert on anything else |
168 | Q_ASSERT(m_tools.isEmpty()); |
169 | m_layout->addWidget(w: m_formContainer); |
170 | } |
171 | |
172 | m_tools.append(t: tool); |
173 | |
174 | connect(sender: tool->action(), signal: &QAction::triggered, |
175 | receiver: this, slot: &FormWindowWidgetStack::setSenderAsCurrentTool); |
176 | } |
177 | |
178 | QDesignerFormWindowToolInterface *FormWindowWidgetStack::tool(int index) const |
179 | { |
180 | if (index < 0 || index >= count()) |
181 | return nullptr; |
182 | |
183 | return m_tools.at(i: index); |
184 | } |
185 | |
186 | int FormWindowWidgetStack::currentIndex() const |
187 | { |
188 | return m_layout->currentIndex(); |
189 | } |
190 | |
191 | QWidget *FormWindowWidgetStack::defaultEditor() const |
192 | { |
193 | if (m_tools.isEmpty()) |
194 | return nullptr; |
195 | |
196 | return m_tools.at(i: 0)->editor(); |
197 | } |
198 | |
199 | QLayout *FormWindowWidgetStack::layout() const |
200 | { |
201 | return m_layout; |
202 | } |
203 | |
204 | QT_END_NAMESPACE |
205 | |