1
/****************************************************************************
3
** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
5
** This file is part of the designer application of the Qt Toolkit.
7
** This file may be distributed under the terms of the Q Public License
8
** as defined by Trolltech AS of Norway and appearing in the file
9
** LICENSE.QPL included in the packaging of this file.
11
** This file may be distributed and/or modified under the terms of the
12
** GNU General Public License version 2 as published by the Free Software
13
** Foundation and appearing in the file LICENSE.GPL included in the
14
** packaging of this file.
16
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
17
** information about Qt Commercial License Agreements.
18
** See http://www.trolltech.com/qpl/ for QPL licensing information.
19
** See http://www.trolltech.com/gpl/ for GPL licensing information.
21
** Contact info@trolltech.com if any conditions of this licensing are
24
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27
****************************************************************************/
29
#include "widgetselection.h"
30
#include "formwindow.h"
31
#include "formwindowmanager.h"
34
#include <QtDesigner/QtDesigner>
35
#include <QtDesigner/QExtensionManager>
38
#include <qdesigner_command_p.h>
40
#include <layoutinfo_p.h>
42
#include <QtGui/QMenu>
43
#include <QtGui/QWidget>
44
#include <QtGui/QApplication>
45
#include <QtGui/QLabel>
46
#include <QtGui/QPainter>
47
#include <QtGui/QMouseEvent>
48
#include <QtGui/QStylePainter>
49
#include <QtGui/QGridLayout>
51
#include <QtCore/QVariant>
52
#include <QtCore/qdebug.h>
57
using namespace qdesigner_internal;
60
class TopWidget: public InvisibleWidget
64
TopWidget(QWidget *parent)
65
: InvisibleWidget(parent)
67
setAttribute(Qt::WA_TransparentForMouseEvents);
71
WidgetHandle::WidgetHandle(FormWindow *parent, WidgetHandle::Type t, WidgetSelection *s)
72
: InvisibleWidget(parent)
77
setMouseTracking(false);
81
if (type == TaskMenu) {
82
setBackgroundRole(QPalette::Button);
85
setBackgroundRole(active ? QPalette::Text : QPalette::Dark);
92
void WidgetHandle::updateCursor()
95
setCursor(Qt::ArrowCursor);
101
setCursor(Qt::SizeFDiagCursor);
104
setCursor(Qt::SizeVerCursor);
107
setCursor(Qt::SizeBDiagCursor);
110
setCursor(Qt::SizeHorCursor);
113
setCursor(Qt::SizeFDiagCursor);
116
setCursor(Qt::SizeVerCursor);
119
setCursor(Qt::SizeBDiagCursor);
122
setCursor(Qt::SizeHorCursor);
125
setCursor(Qt::ArrowCursor);
132
QDesignerFormEditorInterface *WidgetHandle::core() const
134
if (QDesignerFormWindowInterface *fw = formWindow)
140
void WidgetHandle::setActive(bool a)
143
if (type != TaskMenu) {
144
setBackgroundRole(active ? QPalette::Text : QPalette::Dark);
149
void WidgetHandle::setWidget(QWidget *w)
154
void WidgetHandle::paintEvent(QPaintEvent *)
156
FormWindow *fw = formWindow;
157
QDesignerFormWindowManagerInterface *m = fw->core()->formWindowManager();
159
QStylePainter p(this);
160
if (type == TaskMenu) {
161
QStyleOptionToolButton option;
163
option.state |= QStyle::State_Raised;
164
option.arrowType = Qt::RightArrow;
165
option.toolButtonStyle = Qt::ToolButtonIconOnly;
166
option.features = QStyleOptionToolButton::Arrow;
167
option.subControls = QStyle::SC_ToolButton;
168
p.drawComplexControl(QStyle::CC_ToolButton, option);
169
} else if (fw->currentWidget() == widget) {
170
p.setPen(m->activeFormWindow() == fw ? Qt::blue : Qt::red);
171
p.drawRect(0, 0, width() - 1, height() - 1);
175
void WidgetHandle::mousePressEvent(QMouseEvent *e)
179
if (!formWindow->hasFeature(FormWindow::EditFeature))
182
if (!(widget && e->button() == Qt::LeftButton))
185
if (!(active || type == TaskMenu))
188
QWidget *container = widget->parentWidget();
190
oldPressPos = container->mapFromGlobal(e->globalPos());
191
geom = origGeom = widget->geometry();
193
if (type == TaskMenu && e->button() == Qt::LeftButton) {
194
Q_ASSERT(sel->taskMenuExtension());
197
foreach (QAction *a, sel->taskMenuExtension()->taskActions()) {
200
m.exec(e->globalPos());
205
int WidgetHandle::adjustPoint(int x, int dx)
206
{ return (x / dx) * dx + 1; }
208
void WidgetHandle::mouseMoveEvent(QMouseEvent *e)
210
if (!(widget && active && e->buttons() & Qt::LeftButton))
213
if (type == TaskMenu)
218
QWidget *container = widget->parentWidget();
220
QPoint rp = container->mapFromGlobal(e->globalPos());
221
QPoint d = rp - oldPressPos;
224
QRect pr = container->rect();
225
QPoint grid = formWindow->grid();
233
if (rp.x() > pr.width() - 2 * width() || rp.y() > pr.height() - 2 * height())
236
int w = geom.width() - d.x();
238
w = adjustPoint(w, grid.x());
240
int h = geom.height() - d.y();
242
h = adjustPoint(h, grid.y());
244
int dx = widget->width() - w;
245
int dy = widget->height() - h;
247
trySetGeometry(widget, widget->x() + dx, widget->y() + dy, w, h);
251
if (rp.y() > pr.height() - 2 * height())
254
int h = geom.height() - d.y();
256
h = adjustPoint(h, grid.y());
258
int dy = widget->height() - h;
259
trySetGeometry(widget, widget->x(), widget->y() + dy, widget->width(), h);
263
if (rp.x() < 2 * width() || rp.y() > pr.height() - 2 * height())
266
int h = geom.height() - d.y();
268
h = adjustPoint(h, grid.y());
270
int dy = widget->height() - h;
272
int w = geom.width() + d.x();
274
w = adjustPoint(w, grid.x());
276
trySetGeometry(widget, widget->x(), widget->y() + dy, w, h);
280
if (rp.x() < 2 * width())
283
int w = geom.width() + d.x();
285
w = adjustPoint(w, grid.x());
287
tryResize(widget, w, widget->height());
291
if (rp.x() < 2 * width() || rp.y() < 2 * height())
294
int w = geom.width() + d.x();
296
w = adjustPoint(w, grid.x());
298
int h = geom.height() + d.y();
300
h = adjustPoint(h, grid.y());
302
tryResize(widget, w, h);
306
if (rp.y() < 2 * height())
309
int h = geom.height() + d.y();
311
h = adjustPoint(h, grid.y());
313
tryResize(widget, widget->width(), h);
317
if (rp.x() > pr.width() - 2 * width() || rp.y() < 2 * height())
320
int w = geom.width() - d.x();
322
w = adjustPoint(w, grid.x());
324
int h = geom.height() + d.y();
326
h = adjustPoint(h, grid.y());
328
int dx = widget->width() - w;
330
trySetGeometry(widget, widget->x() + dx, widget->y(), w, h);
334
if (rp.x() > pr.width() - 2 * width())
337
int w = geom.width() - d.x();
339
w = adjustPoint(w, grid.x());
341
int dx = widget->width() - w;
343
trySetGeometry(widget, widget->x() + dx, widget->y(), w, widget->height());
350
sel->updateGeometry();
352
if (LayoutInfo::layoutType(formWindow->core(), widget) != LayoutInfo::NoLayout)
353
formWindow->updateChildSelections(widget);
356
void WidgetHandle::mouseReleaseEvent(QMouseEvent *e)
358
if (e->button() != Qt::LeftButton || !active)
361
if (type == TaskMenu)
366
if (!formWindow->hasFeature(FormWindow::EditFeature))
369
LayoutInfo::Type layoutType = widget->parentWidget()
370
? LayoutInfo::layoutType(formWindow->core(), widget->parentWidget())
371
: LayoutInfo::NoLayout;
373
if (layoutType == LayoutInfo::Grid) {
374
QSize size = widget->parentWidget()->size();
375
QGridLayout *grid = static_cast<QGridLayout*>(widget->parentWidget()->layout());
377
QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(core()->extensionManager(), widget->parentWidget());
379
int index = deco->indexOf(widget);
380
QRect info = deco->itemInfo(index);
381
int top = deco->findItemAt(info.top() - 1, info.left());
382
int left = deco->findItemAt(info.top(), info.left() - 1);
383
int bottom = deco->findItemAt(info.bottom() + 1, info.left());
384
int right = deco->findItemAt(info.top(), info.right() + 1);
386
QPoint pt = origGeom.center() - widget->geometry().center();
388
ChangeLayoutItemGeometry *cmd = 0;
393
case WidgetHandle::Top: {
394
if (pt.y() < 0 && info.height() > 1) {
395
cmd = new ChangeLayoutItemGeometry(formWindow);
396
cmd->init(widget, info.y() + 1, info.x(), info.height() - 1, info.width());
397
} else if (pt.y() > 0 && top != -1 && grid->itemAt(top)->spacerItem()) {
398
cmd = new ChangeLayoutItemGeometry(formWindow);
399
cmd->init(widget, info.y() - 1, info.x(), info.height() + 1, info.width());
403
case WidgetHandle::Left: {
404
if (pt.x() < 0 && info.width() > 1) {
405
cmd = new ChangeLayoutItemGeometry(formWindow);
406
cmd->init(widget, info.y(), info.x() + 1, info.height(), info.width() - 1);
407
} else if (pt.x() > 0 && left != -1 && grid->itemAt(left)->spacerItem()) {
408
cmd = new ChangeLayoutItemGeometry(formWindow);
409
cmd->init(widget, info.y(), info.x() - 1, info.height(), info.width() + 1);
413
case WidgetHandle::Right: {
414
if (pt.x() > 0 && info.width() > 1) {
415
cmd = new ChangeLayoutItemGeometry(formWindow);
416
cmd->init(widget, info.y(), info.x(), info.height(), info.width() - 1);
417
} else if (pt.x() < 0 && right != -1 && grid->itemAt(right)->spacerItem()) {
418
cmd = new ChangeLayoutItemGeometry(formWindow);
419
cmd->init(widget, info.y(), info.x(), info.height(), info.width() + 1);
423
case WidgetHandle::Bottom: {
424
if (pt.y() > 0 && info.width() > 1) {
425
cmd = new ChangeLayoutItemGeometry(formWindow);
426
cmd->init(widget, info.y(), info.x(), info.height() - 1, info.width());
427
} else if (pt.y() < 0 && bottom != -1 && grid->itemAt(bottom)->spacerItem()) {
428
cmd = new ChangeLayoutItemGeometry(formWindow);
429
cmd->init(widget, info.y(), info.x(), info.height() + 1, info.width());
435
formWindow->commandHistory()->push(cmd);
439
formWindow->clearSelection(false);
440
formWindow->selectWidget(widget);
442
} else if (geom != widget->geometry()) {
443
SetPropertyCommand *cmd = new SetPropertyCommand(formWindow);
444
cmd->init(widget, QLatin1String("geometry"), widget->geometry());
445
cmd->setOldValue(origGeom);
446
formWindow->commandHistory()->push(cmd);
447
formWindow->emitSelectionChanged();
451
void WidgetHandle::trySetGeometry(QWidget *w, int x, int y, int width, int height)
453
if (!formWindow->hasFeature(FormWindow::EditFeature))
456
int minw = qMax(w->minimumSizeHint().width(), w->minimumSize().width());
457
minw = qMax(minw, 2 * formWindow->grid().x());
459
int minh = qMax(w->minimumSizeHint().height(), w->minimumSize().height());
460
minh = qMax(minh, 2 * formWindow->grid().y());
462
if (qMax(minw, width) > w->maximumWidth() ||
463
qMax(minh, height) > w->maximumHeight())
466
if (width < minw && x != w->x())
469
if (height < minh && y != w->y())
472
w->setGeometry(x, y, qMax(minw, width), qMax(minh, height));
475
void WidgetHandle::tryResize(QWidget *w, int width, int height)
477
int minw = qMax(w->minimumSizeHint().width(), w->minimumSize().width());
478
minw = qMax(minw, 16);
480
int minh = qMax(w->minimumSizeHint().height(), w->minimumSize().height());
481
minh = qMax(minh, 16);
483
w->resize(qMax(minw, width), qMax(minh, height));
486
// ------------------------------------------------------------------------
488
WidgetSelection::WidgetSelection(FormWindow *parent, QHash<QWidget *, WidgetSelection *> *selDict)
489
: selectionDict(selDict)
494
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) {
495
handles.insert(i, new WidgetHandle(formWindow, (WidgetHandle::Type)i, this));
503
void WidgetSelection::setWidget(QWidget *w, bool updateDict)
505
taskMenu = 0; // ### qt_extension<QDesignerTaskMenuExtension*>(core()->extensionManager(), w);
509
Q_ASSERT(m_topWidget->parentWidget() != 0);
510
m_topWidget->parentWidget()->setAttribute(Qt::WA_ContentsPropagated, false);
518
wid->removeEventFilter(this);
523
selectionDict->remove(wid);
530
wid->installEventFilter(this);
532
bool active = LayoutInfo::isWidgetLaidout(formWindow->core(), wid) == false;
534
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) {
535
if (WidgetHandle *h = handles[i]) {
537
h->setActive(active);
541
QLayout *layout = LayoutInfo::managedLayout(formWindow->core(), formWindow->designerWidget(wid->parentWidget()));
542
if (QGridLayout *grid = qobject_cast<QGridLayout*>(layout)) {
543
int index = grid->indexOf(wid);
545
#if defined(QD_DEBUG)
546
qWarning() << "unexpected call to WidgetSelection::setWidget()" << "widget:" << wid << "grid:"<< grid;
551
Q_ASSERT(index != -1);
553
QDesignerLayoutDecorationExtension *deco = qt_extension<QDesignerLayoutDecorationExtension*>(core()->extensionManager(), wid->parentWidget());
555
// try with the actual layout
556
deco = qt_extension<QDesignerLayoutDecorationExtension*>(core()->extensionManager(), layout);
561
handles[WidgetHandle::Bottom]->setActive(true);
563
handles[WidgetHandle::Top]->setActive(true);
565
handles[WidgetHandle::Left]->setActive(true);
567
handles[WidgetHandle::Right]->setActive(true);
569
qWarning() << "no QDesignerLayoutDecorationExtension for widget:" << wid;
574
wid->setAttribute(Qt::WA_ContentsPropagated, true);
575
m_topWidget = new TopWidget(wid);
576
QPalette p = m_topWidget->palette();
577
p.setColor(m_topWidget->backgroundRole(), QColor(255, 0, 0, 32));
578
m_topWidget->setPalette(p);
585
selectionDict->insert(w, this);
588
bool WidgetSelection::isUsed() const
593
void WidgetSelection::updateGeometry()
595
if (!wid || !wid->parentWidget())
598
QPoint p = wid->parentWidget()->mapToGlobal(wid->pos());
599
p = formWindow->mapFromGlobal(p);
600
QRect r(p, wid->size());
605
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) {
606
WidgetHandle *hndl = handles[ i ];
610
case WidgetHandle::LeftTop:
611
hndl->move(r.x() - w / 2, r.y() - h / 2);
613
case WidgetHandle::Top:
614
hndl->move(r.x() + r.width() / 2 - w / 2, r.y() - h / 2);
616
case WidgetHandle::RightTop:
617
hndl->move(r.x() + r.width() - w / 2, r.y() - h / 2);
619
case WidgetHandle::Right:
620
hndl->move(r.x() + r.width() - w / 2, r.y() + r.height() / 2 - h / 2);
622
case WidgetHandle::RightBottom:
623
hndl->move(r.x() + r.width() - w / 2, r.y() + r.height() - h / 2);
625
case WidgetHandle::Bottom:
626
hndl->move(r.x() + r.width() / 2 - w / 2, r.y() + r.height() - h / 2);
628
case WidgetHandle::LeftBottom:
629
hndl->move(r.x() - w / 2, r.y() + r.height() - h / 2);
631
case WidgetHandle::Left:
632
hndl->move(r.x() - w / 2, r.y() + r.height() / 2 - h / 2);
634
case WidgetHandle::TaskMenu:
635
hndl->move(r.x() + r.width() - w / 2, r.y() + h - h / 2);
644
m_topWidget->setGeometry(wid->rect());
649
void WidgetSelection::hide()
651
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) {
652
WidgetHandle *h = handles[ i ];
663
void WidgetSelection::show()
665
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) {
666
WidgetHandle *h = handles[ i ];
668
if (i == WidgetHandle::TaskMenu) {
669
h->setVisible(taskMenuExtension() != 0);
681
m_topWidget->raise();
686
void WidgetSelection::update()
688
for (int i = WidgetHandle::LeftTop; i < WidgetHandle::TypeCount; ++i) {
689
WidgetHandle *h = handles[ i ];
696
m_topWidget->update();
700
QWidget *WidgetSelection::widget() const
705
QDesignerFormEditorInterface *WidgetSelection::core() const
708
return formWindow->core();
713
bool WidgetSelection::eventFilter(QObject *object, QEvent *event)
715
if (object != widget())
718
switch (event->type()) {
730
#include "widgetselection.moc"