source: trunk/tools/designer/src/lib/shared/qdesigner_dnditem.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

File size: 9.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt Designer of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdesigner_dnditem_p.h"
43#include "formwindowbase_p.h"
44#include "ui4_p.h"
45
46#include <QtGui/QPainter>
47#include <QtGui/QBitmap>
48#include <QtGui/QPixmap>
49#include <QtGui/QImage>
50#include <QtGui/QLabel>
51#include <QtGui/QDrag>
52#include <QtGui/QCursor>
53#include <QtGui/QDropEvent>
54#include <QtGui/QRgb>
55
56#include <QtCore/QMultiMap>
57
58QT_BEGIN_NAMESPACE
59
60namespace qdesigner_internal {
61
62QDesignerDnDItem::QDesignerDnDItem(DropType type, QWidget *source) :
63 m_source(source),
64 m_type(type),
65 m_dom_ui(0),
66 m_widget(0),
67 m_decoration(0)
68{
69}
70
71void QDesignerDnDItem::init(DomUI *ui, QWidget *widget, QWidget *decoration,
72 const QPoint &global_mouse_pos)
73{
74 Q_ASSERT(widget != 0 || ui != 0);
75 Q_ASSERT(decoration != 0);
76
77 m_dom_ui = ui;
78 m_widget = widget;
79 m_decoration = decoration;
80
81 const QRect geometry = m_decoration->geometry();
82 m_hot_spot = global_mouse_pos - m_decoration->geometry().topLeft();
83}
84
85QDesignerDnDItem::~QDesignerDnDItem()
86{
87 if (m_decoration != 0)
88 m_decoration->deleteLater();
89 delete m_dom_ui;
90}
91
92DomUI *QDesignerDnDItem::domUi() const
93{
94 return m_dom_ui;
95}
96
97QWidget *QDesignerDnDItem::decoration() const
98{
99 return m_decoration;
100}
101
102QPoint QDesignerDnDItem::hotSpot() const
103{
104 return m_hot_spot;
105}
106
107QWidget *QDesignerDnDItem::widget() const
108{
109 return m_widget;
110}
111
112QDesignerDnDItem::DropType QDesignerDnDItem::type() const
113{
114 return m_type;
115}
116
117QWidget *QDesignerDnDItem::source() const
118{
119 return m_source;
120}
121
122void QDesignerDnDItem::setDomUi(DomUI *dom_ui)
123{
124 delete m_dom_ui;
125 m_dom_ui = dom_ui;
126}
127
128// ---------- QDesignerMimeData
129
130// Make pixmap transparent on Windows only. Mac is transparent by default, Unix usually does not work.
131#ifdef Q_WS_WIN
132# define TRANSPARENT_DRAG_PIXMAP
133#endif
134
135QDesignerMimeData::QDesignerMimeData(const QDesignerDnDItems &items, QDrag *drag) :
136 m_items(items)
137{
138 enum { Alpha = 200 };
139 QPoint decorationTopLeft;
140 switch (m_items.size()) {
141 case 0:
142 break;
143 case 1: {
144 QWidget *deco = m_items.first()->decoration();
145 decorationTopLeft = deco->pos();
146 const QPixmap widgetPixmap = QPixmap::grabWidget(deco);
147#ifdef TRANSPARENT_DRAG_PIXMAP
148 QImage image(widgetPixmap.size(), QImage::Format_ARGB32);
149 image.fill(QColor(Qt::transparent).rgba());
150 QPainter painter(&image);
151 painter.drawPixmap(QPoint(0, 0), widgetPixmap);
152 painter.end();
153 setImageTransparency(image, Alpha);
154 drag->setPixmap(QPixmap::fromImage(image));
155#else
156#ifndef QT_NO_DRAGANDDROP
157 drag->setPixmap(widgetPixmap);
158#endif
159#endif
160 }
161 break;
162 default: {
163 // determine size of drag decoration by uniting all geometries
164 const QDesignerDnDItems::const_iterator cend = m_items.constEnd();
165 QDesignerDnDItems::const_iterator it =m_items.constBegin();
166 QRect unitedGeometry = (*it)->decoration()->geometry();
167 for (++it; it != cend; ++it )
168 unitedGeometry = unitedGeometry .united((*it)->decoration()->geometry());
169
170 // paint with offset. At the same time, create a mask bitmap, containing widget rectangles.
171 QImage image(unitedGeometry.size(), QImage::Format_ARGB32);
172 image.fill(QColor(Qt::transparent).rgba());
173 QBitmap mask(unitedGeometry.size());
174 mask.clear();
175 // paint with offset, determine action
176 QPainter painter(&image);
177 QPainter maskPainter(&mask);
178 decorationTopLeft = unitedGeometry.topLeft();
179 for (it = m_items.constBegin() ; it != cend; ++it ) {
180 QWidget *w = (*it)->decoration();
181 const QPixmap wp = QPixmap::grabWidget(w);
182 const QPoint pos = w->pos() - decorationTopLeft;
183 painter.drawPixmap(pos, wp);
184 maskPainter.fillRect(QRect(pos, wp.size()), Qt::color1);
185 }
186 painter.end();
187 maskPainter.end();
188#ifdef TRANSPARENT_DRAG_PIXMAP
189 setImageTransparency(image, Alpha);
190#endif
191 QPixmap pixmap = QPixmap::fromImage(image);
192 pixmap.setMask(mask);
193#ifndef QT_NO_DRAGANDDROP
194 drag->setPixmap(pixmap);
195#endif
196 }
197 break;
198 }
199 // determine hot spot and reconstruct the exact starting position as form window
200 // introduces some offset when detecting DnD
201 m_globalStartPos = m_items.first()->decoration()->pos() + m_items.first()->hotSpot();
202 m_hotSpot = m_globalStartPos - decorationTopLeft;
203#ifndef QT_NO_DRAGANDDROP
204 drag->setHotSpot(m_hotSpot);
205
206 drag->setMimeData(this);
207#endif
208}
209
210QDesignerMimeData::~QDesignerMimeData()
211{
212 const QDesignerDnDItems::const_iterator cend = m_items.constEnd();
213 for (QDesignerDnDItems::const_iterator it = m_items.constBegin(); it != cend; ++it )
214 delete *it;
215}
216
217Qt::DropAction QDesignerMimeData::proposedDropAction() const
218{
219 return m_items.first()->type() == QDesignerDnDItemInterface::CopyDrop ? Qt::CopyAction : Qt::MoveAction;
220}
221
222Qt::DropAction QDesignerMimeData::execDrag(const QDesignerDnDItems &items, QWidget * dragSource)
223{
224 if (items.empty())
225 return Qt::IgnoreAction;
226
227#ifndef QT_NO_DRAGANDDROP
228 QDrag *drag = new QDrag(dragSource);
229 QDesignerMimeData *mimeData = new QDesignerMimeData(items, drag);
230
231 // Store pointers to widgets that are to be re-shown if a move operation is canceled
232 QWidgetList reshowWidgets;
233 const QDesignerDnDItems::const_iterator cend = items.constEnd();
234 for (QDesignerDnDItems::const_iterator it = items.constBegin(); it != cend; ++it )
235 if (QWidget *w = (*it)->widget())
236 if ((*it)->type() == QDesignerDnDItemInterface::MoveDrop)
237 reshowWidgets.push_back(w);
238
239 const Qt::DropAction executedAction = drag->exec(Qt::CopyAction|Qt::MoveAction, mimeData->proposedDropAction());
240
241 if (executedAction == Qt::IgnoreAction && !reshowWidgets.empty())
242 foreach (QWidget *w, reshowWidgets)
243 w->show();
244
245 return executedAction;
246#else
247 return Qt::IgnoreAction;
248#endif
249}
250
251
252void QDesignerMimeData::moveDecoration(const QPoint &globalPos) const
253{
254 const QPoint relativeDistance = globalPos - m_globalStartPos;
255 const QDesignerDnDItems::const_iterator cend = m_items.constEnd();
256 for (QDesignerDnDItems::const_iterator it =m_items.constBegin(); it != cend; ++it ) {
257 QWidget *w = (*it)->decoration();
258 w->move(w->pos() + relativeDistance);
259 }
260}
261
262void QDesignerMimeData::removeMovedWidgetsFromSourceForm(const QDesignerDnDItems &items)
263{
264 typedef QMultiMap<FormWindowBase *, QWidget *> FormWidgetMap;
265 FormWidgetMap formWidgetMap;
266 // Find moved widgets per form
267 const QDesignerDnDItems::const_iterator cend = items.constEnd();
268 for (QDesignerDnDItems::const_iterator it = items.constBegin(); it != cend; ++it )
269 if ((*it)->type() == QDesignerDnDItemInterface::MoveDrop)
270 if (QWidget *w = (*it)->widget())
271 if (FormWindowBase *fb = qobject_cast<FormWindowBase *>((*it)->source()))
272 formWidgetMap.insert(fb, w);
273 if (formWidgetMap.empty())
274 return;
275
276 foreach (FormWindowBase * fb, formWidgetMap.keys())
277 fb->deleteWidgetList(formWidgetMap.values(fb));
278}
279
280void QDesignerMimeData::acceptEventWithAction(Qt::DropAction desiredAction, QDropEvent *e)
281{
282#ifndef QT_NO_DRAGANDDROP
283 if (e->proposedAction() == desiredAction) {
284 e->acceptProposedAction();
285 } else {
286 e->setDropAction(desiredAction);
287 e->accept();
288 }
289#endif
290}
291
292void QDesignerMimeData::acceptEvent(QDropEvent *e) const
293{
294 acceptEventWithAction(proposedDropAction(), e);
295}
296
297void QDesignerMimeData::setImageTransparency(QImage &image, int alpha)
298{
299 const int height = image.height();
300 for (int l = 0; l < height; l++) {
301 QRgb *line = reinterpret_cast<QRgb *>(image.scanLine(l));
302 QRgb *lineEnd = line + image.width();
303 for ( ; line < lineEnd; line++) {
304 const QRgb rgba = *line;
305 *line = qRgba(qRed(rgba), qGreen(rgba), qBlue(rgba), alpha);
306 }
307 }
308}
309
310} // namespace qdesigner_internal
311
312QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.