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 "default_actionprovider.h"
30#include "invisible_widget_p.h"
31#include "qdesigner_toolbar_p.h"
32
33#include <QtWidgets/qaction.h>
34#include <QtWidgets/qapplication.h>
35#include <QtCore/qrect.h>
36#include <QtCore/qdebug.h>
37
38QT_BEGIN_NAMESPACE
39
40namespace qdesigner_internal {
41
42// ------------ ActionProviderBase:
43// Draws the drag indicator when dragging an action over a widget
44// that receives action Dnd, such as ToolBar, Menu or MenuBar.
45ActionProviderBase::ActionProviderBase(QWidget *widget) :
46 m_indicator(new InvisibleWidget(widget))
47{
48 Q_ASSERT(widget != nullptr);
49
50 m_indicator->setAutoFillBackground(true);
51 m_indicator->setBackgroundRole(QPalette::Window);
52
53 QPalette p;
54 p.setColor(acr: m_indicator->backgroundRole(), acolor: Qt::red);
55 m_indicator->setPalette(p);
56 m_indicator->hide();
57}
58
59enum { indicatorSize = 2 };
60
61// Position an indicator horizontally over the rectangle, indicating
62// 'Insert before' (left or right according to layout direction)
63static inline QRect horizontalIndicatorRect(const QRect &rect, Qt::LayoutDirection layoutDirection)
64{
65 // Position right?
66 QRect rc = QRect(rect.x(), 0, indicatorSize, rect.height() - 1);
67 if (layoutDirection == Qt::RightToLeft)
68 rc.moveLeft(pos: rc.x() + rect.width() - indicatorSize);
69 return rc;
70}
71
72// Position an indicator vertically over the rectangle, indicating 'Insert before' (top)
73static inline QRect verticalIndicatorRect(const QRect &rect)
74{
75 return QRect(0, rect.top(), rect.width() - 1, indicatorSize);
76}
77
78// Determine the geometry of the indicator by retrieving
79// the action under mouse and positioning the bar within its geometry.
80QRect ActionProviderBase::indicatorGeometry(const QPoint &pos, Qt::LayoutDirection layoutDirection) const
81{
82 QAction *action = actionAt(pos);
83 if (!action)
84 return QRect();
85 QRect rc = actionGeometry(action);
86 return orientation() == Qt::Horizontal ? horizontalIndicatorRect(rect: rc, layoutDirection) : verticalIndicatorRect(rect: rc);
87}
88
89// Adjust the indicator while dragging. (-1,1) is called to finish a DND operation
90void ActionProviderBase::adjustIndicator(const QPoint &pos)
91{
92 if (pos == QPoint(-1, -1)) {
93 m_indicator->hide();
94 return;
95 }
96 const QRect ig = indicatorGeometry(pos, layoutDirection: m_indicator->layoutDirection());
97 if (ig.isValid()) {
98 m_indicator->setGeometry(ig);
99 QPalette p = m_indicator->palette();
100 if (p.color(cr: m_indicator->backgroundRole()) != Qt::red) {
101 p.setColor(acr: m_indicator->backgroundRole(), acolor: Qt::red);
102 m_indicator->setPalette(p);
103 }
104 m_indicator->show();
105 m_indicator->raise();
106 } else {
107 m_indicator->hide();
108 }
109}
110
111// ------------- QToolBarActionProvider
112QToolBarActionProvider::QToolBarActionProvider(QToolBar *widget, QObject *parent) :
113 QObject(parent),
114 ActionProviderBase(widget),
115 m_widget(widget)
116{
117}
118
119QRect QToolBarActionProvider::actionGeometry(QAction *action) const
120{
121 return m_widget->actionGeometry(action);
122}
123
124QAction *QToolBarActionProvider::actionAt(const QPoint &pos) const
125{
126 return ToolBarEventFilter::actionAt(tb: m_widget, pos);
127}
128
129Qt::Orientation QToolBarActionProvider::orientation() const
130{
131 return m_widget->orientation();
132}
133
134QRect QToolBarActionProvider::indicatorGeometry(const QPoint &pos, Qt::LayoutDirection layoutDirection) const
135{
136 const QRect actionRect = ActionProviderBase::indicatorGeometry(pos, layoutDirection);
137 if (actionRect.isValid())
138 return actionRect;
139 // Toolbar differs in that is has no dummy placeholder to 'insert before'
140 // when intending to append. Check the free area.
141 const QRect freeArea = ToolBarEventFilter::freeArea(tb: m_widget);
142 if (!freeArea.contains(p: pos))
143 return QRect();
144 return orientation() == Qt::Horizontal ? horizontalIndicatorRect(rect: freeArea, layoutDirection) : verticalIndicatorRect(rect: freeArea);
145}
146
147// ------------- QMenuBarActionProvider
148QMenuBarActionProvider::QMenuBarActionProvider(QMenuBar *widget, QObject *parent) :
149 QObject(parent),
150 ActionProviderBase(widget),
151 m_widget(widget)
152{
153}
154
155QRect QMenuBarActionProvider::actionGeometry(QAction *action) const
156{
157 return m_widget->actionGeometry(action);
158}
159
160QAction *QMenuBarActionProvider::actionAt(const QPoint &pos) const
161{
162 return m_widget->actionAt(pos);
163}
164
165Qt::Orientation QMenuBarActionProvider::orientation() const
166{
167 return Qt::Horizontal;
168}
169
170// ------------- QMenuActionProvider
171QMenuActionProvider::QMenuActionProvider(QMenu *widget, QObject *parent) :
172 QObject(parent),
173 ActionProviderBase(widget),
174 m_widget(widget)
175{
176}
177
178QRect QMenuActionProvider::actionGeometry(QAction *action) const
179{
180 return m_widget->actionGeometry(action);
181}
182
183QAction *QMenuActionProvider::actionAt(const QPoint &pos) const
184{
185 return m_widget->actionAt(pos);
186}
187
188Qt::Orientation QMenuActionProvider::orientation() const
189{
190 return Qt::Vertical;
191}
192}
193
194QT_END_NAMESPACE
195

source code of qttools/src/designer/src/components/formeditor/default_actionprovider.cpp