diff options
| author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
|---|---|---|
| committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
| commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
| tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /kexi/formeditor/container.cpp | |
| download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip | |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kexi/formeditor/container.cpp')
| -rw-r--r-- | kexi/formeditor/container.cpp | 1182 |
1 files changed, 1182 insertions, 0 deletions
diff --git a/kexi/formeditor/container.cpp b/kexi/formeditor/container.cpp new file mode 100644 index 000000000..75a6dea6c --- /dev/null +++ b/kexi/formeditor/container.cpp @@ -0,0 +1,1182 @@ +/* This file is part of the KDE project + Copyright (C) 2003 Lucijan Busch <lucijan@gmx.at> + Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. +*/ + +#include <qpainter.h> +#include <qpixmap.h> +#include <qrect.h> +#include <qevent.h> +#include <qvaluevector.h> +#include <qlayout.h> +#include <qcursor.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kpopupmenu.h> + +#include <cstdlib> // for abs() + +#include "utils.h" +#include "container.h" +#include "widgetlibrary.h" +#include "objecttree.h" +#include "form.h" +#include "formmanager.h" +#include "commands.h" +#include "events.h" +#include "kexiflowlayout.h" + +using namespace KFormDesigner; + +EventEater::EventEater(QWidget *widget, QObject *container) + : QObject(container) +{ + m_widget = widget; + m_container = container; + + installRecursiveEventFilter(m_widget, this); +} + +bool +EventEater::eventFilter(QObject *, QEvent *ev) +{ + if(!m_container) + return false; + + // When the user click the empty part of tab bar, only MouseReleaseEvent is sent, + // we need to simulate the Press event + if(ev->type() == QEvent::MouseButtonRelease && m_widget->inherits("QTabWidget")) + { + QMouseEvent *mev = static_cast<QMouseEvent*>(ev); + if(mev->button() == LeftButton) + { + QMouseEvent *myev = new QMouseEvent(QEvent::MouseButtonPress, mev->pos(), mev->button(), mev->state()); + m_container->eventFilter(m_widget, myev); + delete myev; + //return true; + } + } +// else if(ev->type() == QEvent::ChildInserted) { + // widget's children have changed, we need to reinstall filter +// installRecursiveEventFilter(m_widget, this); +// } + + return m_container->eventFilter(m_widget, ev); +} + +EventEater::~EventEater() +{ + if(m_widget) + removeRecursiveEventFilter(m_widget, this); +} + +// Container itself + +Container::Container(Container *toplevel, QWidget *container, QObject *parent, const char *name) +: QObject(parent, name) +, m_insertBegin(-1,-1) +, m_mousePressEventReceived(false) +, m_mouseReleaseEvent(QEvent::None, QPoint(), 0, 0) +{ + m_container = container; + m_toplevel = toplevel; + + m_moving = 0; + m_tree = 0; + m_form = toplevel ? toplevel->form() : 0; + m_layout = 0; + m_layType = NoLayout; + m_state = DoingNothing; + + QCString classname = container->className(); + if((classname == "HBox") || (classname == "Grid") || (classname == "VBox") || + (classname == "HFlow") || (classname == "VFlow")) + m_margin = 4; // those containers don't have frames, so little margin + else + m_margin = m_form ? m_form->defaultMargin() : 0; + m_spacing = m_form ? m_form->defaultSpacing() : 0; + + if(toplevel) + { + ObjectTreeItem *it = new ObjectTreeItem(m_form->library()->displayName(classname), + widget()->name(), widget(), this, this); + setObjectTree(it); + + if(parent->isWidgetType()) + { + QString n = parent->name(); + ObjectTreeItem *parent = m_form->objectTree()->lookup(n); + m_form->objectTree()->addItem(parent, it); + } + else + m_form->objectTree()->addItem(toplevel->objectTree(), it); + + connect(toplevel, SIGNAL(destroyed()), this, SLOT(widgetDeleted())); + } + + connect(container, SIGNAL(destroyed()), this, SLOT(widgetDeleted())); +} + +Container::~Container() +{ + kdDebug() << " Container being deleted this == " << name() << endl; +} + +void +Container::setForm(Form *form) +{ + m_form = form; + m_margin = m_form ? m_form->defaultMargin() : 0; + m_spacing = m_form ? m_form->defaultSpacing() : 0; +} + +bool +Container::eventFilter(QObject *s, QEvent *e) +{ +// kdDebug() << e->type() << endl; + switch(e->type()) + { + case QEvent::MouseButtonPress: + { + m_insertBegin = QPoint(-1, -1); + m_mousePressEventReceived = true; + + kdDebug() << "QEvent::MouseButtonPress sender object = " << s->name() + << "of type " << s->className() << endl; + kdDebug() << "QEvent::MouseButtonPress this = " << name() << endl; + + m_moving = static_cast<QWidget*>(s); + QMouseEvent *mev = static_cast<QMouseEvent*>(e); + m_grab = QPoint(mev->x(), mev->y()); + + // we are drawing a connection + if(FormManager::self()->isCreatingConnection()) { + drawConnection(mev); + return true; + } + + if(((mev->state() == ControlButton) || (mev->state() == ShiftButton)) + && (!FormManager::self()->isInserting())) // multiple selection mode + { + if(m_form->selectedWidgets()->findRef(m_moving) != -1) // widget is already selected + { + if(m_form->selectedWidgets()->count() > 1) // we remove it from selection + unSelectWidget(m_moving); + else // the widget is the only selected, so it means we want to copy it + { + //m_copyRect = m_moving->geometry(); + m_state = CopyingWidget; + if(m_form->formWidget()) + m_form->formWidget()->initBuffer(); + } + } + else // the widget is not yet selected, we add it + setSelectedWidget(m_moving, true, (mev->button() == RightButton)); + } + else if((m_form->selectedWidgets()->count() > 1))//&& (!m_form->manager()->isInserting())) // more than one widget selected + { + if(m_form->selectedWidgets()->findRef(m_moving) == -1) // widget is not selected, it becomes the only selected widget + setSelectedWidget(m_moving, false, (mev->button() == RightButton)); + // If the widget is already selected, we do nothing (to ease widget moving, etc.) + } + else// if(!m_form->manager()->isInserting()) + setSelectedWidget(m_moving, false, (mev->button() == RightButton)); + + // we are inserting a widget or drawing a selection rect in the form + if((/*s == m_container &&*/ FormManager::self()->isInserting()) || ((s == m_container) && !m_toplevel)) + { + int tmpx,tmpy; + if(!FormManager::self()->snapWidgetsToGrid() || (mev->state() == (LeftButton|ControlButton|AltButton))) + { + tmpx = mev->x(); + tmpy = mev->y(); + } + else + { + int gridX = m_form->gridSize(); + int gridY = m_form->gridSize(); + tmpx = int( (float)mev->x() / ((float)gridX) + 0.5 ); // snap to grid + tmpx *= gridX; + tmpy = int( (float)mev->y() / ((float)gridY) + 0.5 ); + tmpy *= gridX; + } + + m_insertBegin = (static_cast<QWidget*>(s))->mapTo(m_container, QPoint(tmpx, tmpy)); + if(m_form->formWidget()) + m_form->formWidget()->initBuffer(); + + if(!FormManager::self()->isInserting()) + m_state = DrawingSelectionRect; + } + else { + if(s->inherits("QTabWidget")) // to allow changing page by clicking tab + return false; + } + + if (m_objectForMouseReleaseEvent) { + const bool res = handleMouseReleaseEvent(m_objectForMouseReleaseEvent, &m_mouseReleaseEvent); + m_objectForMouseReleaseEvent = 0; + return res; + } + return true; + } + + case QEvent::MouseButtonRelease: + { + QMouseEvent *mev = static_cast<QMouseEvent*>(e); + if (!m_mousePressEventReceived) { + m_mouseReleaseEvent = *mev; + m_objectForMouseReleaseEvent = s; + return true; + } + m_mousePressEventReceived = false; + m_objectForMouseReleaseEvent = 0; + return handleMouseReleaseEvent(s, mev); + } + + case QEvent::MouseMove: + { + QMouseEvent *mev = static_cast<QMouseEvent*>(e); + if(m_insertBegin!=QPoint(-1,-1) && FormManager::self()->isInserting() && ((mev->state() == LeftButton) || (mev->state() == (LeftButton|ControlButton)) || + (mev->state() == (LeftButton|ControlButton|AltButton)) || (mev->state() == (LeftButton|ShiftButton)) ) ) + // draw the insert rect + { + drawInsertRect(mev, s); + return true; + } + // Creating a connection, we highlight sender and receiver, and we draw a link between them + else if(FormManager::self()->isCreatingConnection() && !FormManager::self()->createdConnection()->sender().isNull()) + { + ObjectTreeItem *tree = m_form->objectTree()->lookup(FormManager::self()->createdConnection()->sender()); + if(!tree || !tree->widget()) + return true; + + if(m_form->formWidget() && (tree->widget() != s)) + m_form->formWidget()->highlightWidgets(tree->widget(), static_cast<QWidget*>(s)); + } + else if(m_insertBegin!=QPoint(-1,-1) && s == m_container && !m_toplevel && (mev->state() != ControlButton) && !FormManager::self()->isCreatingConnection()) // draw the selection rect + { + if((mev->state() != LeftButton) || /*m_inlineEditing*/ m_state == InlineEditing) + return true; + int topx = (m_insertBegin.x() < mev->x()) ? m_insertBegin.x() : mev->x(); + int topy = (m_insertBegin.y() < mev->y()) ? m_insertBegin.y() : mev->y(); + int botx = (m_insertBegin.x() > mev->x()) ? m_insertBegin.x() : mev->x(); + int boty = (m_insertBegin.y() > mev->y()) ? m_insertBegin.y() : mev->y(); + QRect r = QRect(QPoint(topx, topy), QPoint(botx, boty)); + m_insertRect = r; + + if(m_form->formWidget()) + m_form->formWidget()->drawRect(r, 1); + + m_state = DoingNothing; + return true; + } + else if(mev->state() == (LeftButton|ControlButton)) // draw the insert rect for the copied widget + { + if(s == m_container)// || (m_form->selectedWidgets()->count() > 1)) + return true; + drawCopiedWidgetRect(mev); + return true; + } + else if( ( (mev->state() == Qt::LeftButton) || (mev->state() == (LeftButton|ControlButton|AltButton)) ) + && !FormManager::self()->isInserting() && (m_state != CopyingWidget)) // we are dragging the widget(s) to move it + { + if(!m_toplevel && m_moving == m_container) // no effect for form + return false; + if((!m_moving) || (!m_moving->parentWidget()))// || (m_moving->parentWidget()->inherits("QWidgetStack"))) + return true; + + moveSelectedWidgetsBy(mev->x() - m_grab.x(), mev->y() - m_grab.y()); + m_state = MovingWidget; + } + + return true; // eat + } + + case QEvent::Paint: // Draw the dotted background + { + if(s != m_container) + return false; + int gridX = m_form->gridSize(); + int gridY = m_form->gridSize(); + + QPainter p(m_container); + p.setPen(QPen(white, 2)); + p.setRasterOp(XorROP); + int cols = m_container->width() / gridX; + int rows = m_container->height() / gridY; + + for(int rowcursor = 1; rowcursor <= rows; ++rowcursor) + { + for(int colcursor = 1; colcursor <= cols; ++colcursor) + { + p.drawPoint(-1 + colcursor *gridX, -1 + rowcursor *gridY); + } + } + + return false; + } + + case QEvent::Resize: // we are resizing a widget, so we set m_move to true -> the layout will be reloaded when releasing mouse + { + if(m_form->interactiveMode()) + m_state = MovingWidget; + break; + } + + //case QEvent::AccelOverride: + case QEvent::KeyPress: + { + QKeyEvent *kev = static_cast<QKeyEvent*>(e); + + if(kev->key() == Key_F2) // pressing F2 == double-clicking + { + m_state = InlineEditing; + QWidget *w; + + // try to find the widget which was clicked last and should be edited + if(m_form->selectedWidgets()->count() == 1) + w = m_form->selectedWidgets()->first(); + else if(m_form->selectedWidgets()->findRef(m_moving) != -1) + w = m_moving; + else + w = m_form->selectedWidgets()->last(); + m_form->library()->startEditing(w->className(), w, this); + } + else if(kev->key() == Key_Escape) + { + if(FormManager::self()->isCreatingConnection()) + FormManager::self()->stopCreatingConnection(); + else if(FormManager::self()->isInserting()) + FormManager::self()->stopInsert(); + return true; + } + else if((kev->key() == Key_Control) && (m_state == MovingWidget)) + { + if(!m_moving) + return true; + // we simulate a mouse move event to update screen + QMouseEvent *mev = new QMouseEvent(QEvent::MouseMove, m_moving->mapFromGlobal(QCursor::pos()), NoButton, + LeftButton|ControlButton ); + eventFilter(m_moving, mev); + delete mev; + } + else if(kev->key() == FormManager::self()->contextMenuKey()) + { + FormManager::self()->createContextMenu(static_cast<QWidget*>(s), this, false); + return true; + } + else if (kev->key() == Key_Delete) + { + FormManager::self()->deleteWidget(); + return true; + } + // directional buttons move the widget + else if(kev->key() == Key_Left){ // move the widget of gridX to the left + moveSelectedWidgetsBy(-form()->gridSize(), 0); + return true; + } + else if(kev->key() == Key_Right){ // move the widget of gridX to the right + moveSelectedWidgetsBy(form()->gridSize(), 0); + return true; + } + else if(kev->key() == Key_Up){ // move the widget of gridY to the top + moveSelectedWidgetsBy(0, - form()->gridSize()); + return true; + } + else if(kev->key() == Key_Down){ // move the widget of gridX to the bottom + moveSelectedWidgetsBy(0, form()->gridSize()); + return true; + } + else if((kev->key() == Key_Tab) || (kev->key() == Key_BackTab)){ + ObjectTreeItem *item = form()->objectTree()->lookup(form()->selectedWidgets()->first()->name()); + if(!item || !item->parent()) + return true; + ObjectTreeList *list = item->parent()->children(); + if(list->count() == 1) + return true; + int index = list->findRef(item); + + if(kev->key() == Key_BackTab){ + if(index == 0) // go back to the last item + index = list->count() - 1; + else + index = index - 1; + } + else { + if(index == int(list->count() - 1)) // go back to the first item + index = 0; + else + index = index + 1; + } + + ObjectTreeItem *nextItem = list->at(index); + if(nextItem && nextItem->widget()) + form()->setSelectedWidget(nextItem->widget(), false); + } + return true; + } + + case QEvent::KeyRelease: + { + QKeyEvent *kev = static_cast<QKeyEvent*>(e); + if((kev->key() == Key_Control) && (m_state == CopyingWidget)) { + // cancel copying + //m_copyRect = QRect(); + if(m_form->formWidget()) + m_form->formWidget()->clearForm(); + } + return true; + } + + case QEvent::MouseButtonDblClick: // editing + { + kdDebug() << "Container: Mouse dbl click for widget " << s->name() << endl; + QWidget *w = static_cast<QWidget*>(s); + if(!w) + return false; + + //m_inlineEditing = true; + m_state = InlineEditing; + m_form->library()->startEditing(w->className(), w, this); + return true; + } + + case QEvent::ContextMenu: + case QEvent::Enter: + case QEvent::Leave: + case QEvent::FocusIn: + case QEvent::FocusOut: +// case QEvent::DragEnter: +// case QEvent::DragMove: +// case QEvent::DragLeave: + return true; // eat them + + default: + return false; // let the widget do the rest ... + } + return false; +} + +bool +Container::handleMouseReleaseEvent(QObject *s, QMouseEvent *mev) +{ + if(FormManager::self()->isInserting()) // we insert the widget at cursor pos + { + if(m_form->formWidget()) + m_form->formWidget()->clearForm(); + KCommand *com = new InsertWidgetCommand(this/*, mev->pos()*/); + m_form->addCommand(com, true); + m_insertBegin = QPoint(-1,-1); + m_insertRect = QRect(); + return true; + } + else if(s == m_container && !m_toplevel && (mev->button() != RightButton) && m_insertRect.isValid()) // we are drawing a rect to select widgets + { + drawSelectionRect(mev); + return true; + } + if(mev->button() == RightButton) // Right-click -> context menu + { + FormManager::self()->createContextMenu(static_cast<QWidget*>(s), this); + } + else if(mev->state() == (Qt::LeftButton|Qt::ControlButton))// && (m_copyRect.isValid())) + { + // copying a widget by Ctrl+dragging + + if(m_form->formWidget()) + m_form->formWidget()->clearForm(); + if(s == m_container) // should have no effect on form + return true; + + // prevent accidental copying of widget (when moving mouse a little while selecting) + if( ( (mev->pos().x() - m_grab.x()) < form()->gridSize() && (m_grab.x() - mev->pos().x()) < form()->gridSize() ) && + ( (mev->pos().y() - m_grab.y()) < form()->gridSize() && (m_grab.y() - mev->pos().y()) < form()->gridSize() ) ) + { + kdDebug() << "The widget has not been moved. No copying" << endl; + return true; + } + + m_form->setInteractiveMode(false); + // We simulate copy and paste + FormManager::self()->copyWidget(); + if(m_form->selectedWidgets()->count() > 1) + FormManager::self()->setInsertPoint( mev->pos() ); + else + FormManager::self()->setInsertPoint( static_cast<QWidget*>(s)->mapTo(m_container, mev->pos() - m_grab) ); + FormManager::self()->pasteWidget(); + m_form->setInteractiveMode(true); + + //m_initialPos = QPoint(); + } + else if(m_state == MovingWidget) // one widget has been moved, so we need to update the layout + reloadLayout(); + + // cancel copying as user released Ctrl before releasing mouse button + m_insertBegin = QPoint(-1,-1); + m_insertRect = QRect(); + m_state = DoingNothing; + return true; // eat +} + +void +Container::setSelectedWidget(QWidget *w, bool add, bool dontRaise, bool moreWillBeSelected) +{ + if (w) + kdDebug() << "slotSelectionChanged " << w->name()<< endl; + + if(!w) + { + m_form->setSelectedWidget(m_container); + return; + } + + m_form->setSelectedWidget(w, add, dontRaise, moreWillBeSelected); +} + +void +Container::unSelectWidget(QWidget *w) +{ + if(!w) + return; + + m_form->unSelectWidget(w); +} + +Container* +Container::toplevel() +{ + if(m_toplevel) + return m_toplevel; + else + return this; +} + +void +Container::deleteWidget(QWidget *w) +{ + if(!w) + return; +// kdDebug() << "Deleting a widget: " << w->name() << endl; + m_form->objectTree()->removeItem(w->name()); + FormManager::self()->deleteWidgetLater( w ); + m_form->setSelectedWidget(m_container); +} + +void +Container::widgetDeleted() +{ + m_container = 0; + deleteLater(); +} + +/// Layout functions + +void +Container::setLayout(LayoutType type) +{ + if(m_layType == type) + return; + + delete m_layout; + m_layout = 0; + m_layType = type; + + switch(type) + { + case HBox: + { + m_layout = (QLayout*) new QHBoxLayout(m_container, m_margin, m_spacing); + createBoxLayout(new HorWidgetList(m_form->toplevelContainer()->widget())); + break; + } + case VBox: + { + m_layout = (QLayout*) new QVBoxLayout(m_container, m_margin, m_spacing); + createBoxLayout(new VerWidgetList(m_form->toplevelContainer()->widget())); + break; + } + case Grid: + { + createGridLayout(); + break; + } + case HFlow: + { + KexiFlowLayout *flow = new KexiFlowLayout(m_container,m_margin, m_spacing); + flow->setOrientation(Horizontal); + m_layout = (QLayout*)flow; + createFlowLayout(); + break; + } + case VFlow: + { + KexiFlowLayout *flow = new KexiFlowLayout(m_container,m_margin, m_spacing); + flow->setOrientation(Vertical); + m_layout = (QLayout*)flow; + createFlowLayout(); + break; + } + default: + { + m_layType = NoLayout; + return; + } + } + m_container->setGeometry(m_container->geometry()); // just update layout + m_layout->activate(); +} + +void +Container::reloadLayout() +{ + LayoutType type = m_layType; + setLayout(NoLayout); + setLayout(type); +} + +void +Container::createBoxLayout(WidgetList *list) +{ + QBoxLayout *layout = static_cast<QBoxLayout*>(m_layout); + + for(ObjectTreeItem *tree = m_tree->children()->first(); tree; tree = m_tree->children()->next()) + list->append( tree->widget()); + list->sort(); + + for(QWidget *obj = list->first(); obj; obj = list->next()) + layout->addWidget(obj); + delete list; +} + +void +Container::createFlowLayout() +{ + KexiFlowLayout *flow = dynamic_cast<KexiFlowLayout*>(m_layout); + if(!flow || m_tree->children()->isEmpty()) + return; + + const int offset = 15; + WidgetList *list=0, *list2=0; + if(flow->orientation() == Horizontal) { + list = new VerWidgetList(m_form->toplevelContainer()->widget()); + list2 = new HorWidgetList(m_form->toplevelContainer()->widget()); + } + else { + list = new HorWidgetList(m_form->toplevelContainer()->widget()); + list2 = new VerWidgetList(m_form->toplevelContainer()->widget()); + } + + // fill the list + for(ObjectTreeItem *tree = m_tree->children()->first(); tree; tree = m_tree->children()->next()) + list->append( tree->widget()); + list->sort(); + + if(flow->orientation() == Horizontal) { + int y = list->first()->y(); + for(QWidget *w = list->first(); w; w = list->next()) { + if( (w->y() > y +offset)) { + // start a new line + list2->sort(); + for(QWidget *obj = list2->first(); obj; obj = list2->next()) + flow->add(obj); + list2->clear(); + y = w->y(); + } + list2->append(w); + } + + list2->sort(); // don't forget the last line + for(QWidget *obj = list2->first(); obj; obj = list2->next()) + flow->add(obj); + } + else { + int x = list->first()->x(); + for(QWidget *w = list->first(); w; w = list->next()) { + if( (w->x() > x +offset)) { + // start a new column + list2->sort(); + for(QWidget *obj = list2->first(); obj; obj = list2->next()) + flow->add(obj); + list2->clear(); + x = w->x(); + } + list2->append(w); + } + + list2->sort(); // don't forget the last column + for(QWidget *obj = list2->first(); obj; obj = list2->next()) + flow->add(obj); + } + + delete list; + delete list2; +} + +void +Container::createGridLayout(bool testOnly) +{ + //Those lists sort widgets by y and x + VerWidgetList *vlist = new VerWidgetList(m_form->toplevelContainer()->widget()); + HorWidgetList *hlist = new HorWidgetList(m_form->toplevelContainer()->widget()); + // The vector are used to store the x (or y) beginning of each column (or row) + QValueVector<int> cols; + QValueVector<int> rows; + int end=-1000; + bool same = false; + + for(ObjectTreeItem *tree = m_tree->children()->first(); tree; tree = m_tree->children()->next()) + vlist->append( tree->widget()); + vlist->sort(); + + for(ObjectTreeItem *tree = m_tree->children()->first(); tree; tree = m_tree->children()->next()) + hlist->append( tree->widget()); + hlist->sort(); + + // First we need to make sure that two widgets won't be in the same row, + // ie that no widget overlap another one + if(!testOnly) { + for(WidgetListIterator it(*vlist); it.current() != 0; ++it) + { + QWidget *w = it.current(); + WidgetListIterator it2 = it; + + for(; it2.current() != 0; ++it2) { + QWidget *nextw = it2.current(); + if((w->y() >= nextw->y()) || (nextw->y() >= w->geometry().bottom())) + break; + + if(!w->geometry().intersects(nextw->geometry())) + break; + // If the geometries of the two widgets intersect each other, + // we move one of the widget to the rght or bottom of the other + if((nextw->y() - w->y()) > abs(nextw->x() - w->x())) + nextw->move(nextw->x(), w->geometry().bottom()+1); + else if(nextw->x() >= w->x()) + nextw->move(w->geometry().right()+1, nextw->y()); + else + w->move(nextw->geometry().right()+1, nextw->y()); + } + } + } + + // Then we count the number of rows in the layout, and set their beginnings + for(WidgetListIterator it(*vlist); it.current() != 0; ++it) + { + QWidget *w = it.current(); + WidgetListIterator it2 = it; + if(!same) { // this widget will make a new row + end = w->geometry().bottom(); + rows.append(w->y()); + } + + // If same == true, it means we are in the same row as prev widget + // (so no need to create a new column) + ++it2; + if(!it2.current()) + break; + + QWidget *nextw = it2.current(); + if(nextw->y() >= end) + same = false; + else { + same = !(same && (nextw->y() >= w->geometry().bottom())); + if(!same) + end = w->geometry().bottom(); + } + } + kdDebug() << "the new grid will have n rows: n == " << rows.size() << endl; + + end = -10000; + same = false; + // We do the same thing for the columns + for(WidgetListIterator it(*hlist); it.current() != 0; ++it) + { + QWidget *w = it.current(); + WidgetListIterator it2 = it; + if(!same) { + end = w->geometry().right(); + cols.append(w->x()); + } + + ++it2; + if(!it2.current()) + break; + + QWidget *nextw = it2.current(); + if(nextw->x() >= end) + same = false; + else { + same = !(same && (nextw->x() >= w->geometry().right())); + if(!same) + end = w->geometry().right(); + } + } + kdDebug() << "the new grid will have n columns: n == " << cols.size() << endl; + + // We create the layout .. + QGridLayout *layout=0; + if(!testOnly) { + layout = new QGridLayout(m_container, rows.size(), cols.size(), m_margin, m_spacing, "grid"); + m_layout = (QLayout*)layout; + } + + // .. and we fill it with widgets + for(WidgetListIterator it(*vlist); it.current() != 0; ++it) + { + QWidget *w = it.current(); + QRect r = w->geometry(); + uint wcol=0, wrow=0, endrow=0, endcol=0; + uint i = 0; + + // We look for widget row(s) .. + while(r.y() >= rows[i]) + { + if(rows.size() <= i+1) // we are the last row + { + wrow = i; + break; + } + if(r.y() < rows[i+1]) + { + wrow = i; // the widget will be in this row + uint j = i + 1; + // Then we check if the widget needs to span multiple rows + while(rows.size() >= j+1 && r.bottom() > rows[j]) + { + endrow = j; + j++; + } + + break; + } + i++; + } + //kdDebug() << "the widget " << w->name() << " wil be in the row " << wrow << + //" and will go to the row " << endrow << endl; + + // .. and column(s) + i = 0; + while(r.x() >= cols[i]) + { + if(cols.size() <= i+1) // last column + { + wcol = i; + break; + } + if(r.x() < cols[i+1]) + { + wcol = i; + uint j = i + 1; + // Then we check if the widget needs to span multiple columns + while(cols.size() >= j+1 && r.right() > cols[j]) + { + endcol = j; + j++; + } + + break; + } + i++; + } + //kdDebug() << "the widget " << w->name() << " wil be in the col " << wcol << + // " and will go to the col " << endcol << endl; + + ObjectTreeItem *item = m_form->objectTree()->lookup(w->name()); + if(!endrow && !endcol) { + if(!testOnly) + layout->addWidget(w, wrow, wcol); + item->setGridPos(wrow, wcol, 0, 0); + } + else { + if(!endcol) endcol = wcol; + if(!endrow) endrow = wrow; + if(!testOnly) + layout->addMultiCellWidget(w, wrow, endrow, wcol, endcol); + item->setGridPos(wrow, wcol, endrow-wrow+1, endcol-wcol+1); + } + } +} + +QString +Container::layoutTypeToString(int type) +{ + switch(type) + { + case HBox: return "HBox"; + case VBox: return "VBox"; + case Grid: return "Grid"; + case HFlow: return "HFlow"; + case VFlow: return "VFlow"; + default: return "NoLayout"; + } +} + +Container::LayoutType +Container::stringToLayoutType(const QString &name) +{ + if(name == "HBox") return HBox; + if(name == "VBox") return VBox; + if(name == "Grid") return Grid; + if(name == "HFlow") return HFlow; + if(name == "VFlow") return VFlow; + return NoLayout; +} + +/// Drawing functions used by eventFilter +void +Container::drawConnection(QMouseEvent *mev) +{ + if(mev->button() != LeftButton) + { + FormManager::self()->resetCreatedConnection(); + return; + } + // First click, we select the sender and display menu to choose signal + if(FormManager::self()->createdConnection()->sender().isNull()) + { + FormManager::self()->createdConnection()->setSender(m_moving->name()); + if(m_form->formWidget()) + { + m_form->formWidget()->initBuffer(); + m_form->formWidget()->highlightWidgets(m_moving, 0/*, QPoint()*/); + } + FormManager::self()->createSignalMenu(m_moving); + return; + } + // the user clicked outside the menu, we cancel the connection + if(FormManager::self()->createdConnection()->signal().isNull()) + { + FormManager::self()->stopCreatingConnection(); + return; + } + // second click to choose the receiver + if(FormManager::self()->createdConnection()->receiver().isNull()) + { + FormManager::self()->createdConnection()->setReceiver(m_moving->name()); + FormManager::self()->createSlotMenu(m_moving); + m_container->repaint(); + return; + } + // the user clicked outside the menu, we cancel the connection + if(FormManager::self()->createdConnection()->slot().isNull()) + { + FormManager::self()->stopCreatingConnection(); + return; + } +} + +void +Container::drawSelectionRect(QMouseEvent *mev) +{ + //finish drawing unclipped selection rectangle: clear the surface + if(m_form->formWidget()) + m_form->formWidget()->clearForm(); + int topx = (m_insertBegin.x() < mev->x()) ? m_insertBegin.x() : mev->x(); + int topy = (m_insertBegin.y() < mev->y()) ? m_insertBegin.y() : mev->y(); + int botx = (m_insertBegin.x() > mev->x()) ? m_insertBegin.x() : mev->x(); + int boty = (m_insertBegin.y() > mev->y()) ? m_insertBegin.y() : mev->y(); + QRect r = QRect(QPoint(topx, topy), QPoint(botx, boty)); + + setSelectedWidget(m_container, false); + QWidget *widgetToSelect = 0; + // We check which widgets are in the rect and select them + for(ObjectTreeItem *item = m_tree->children()->first(); item; item = m_tree->children()->next()) + { + QWidget *w = item->widget(); + if(!w) + continue; + if(w->geometry().intersects(r) && w != m_container) { + if (widgetToSelect) + setSelectedWidget(widgetToSelect, true/*add*/, false/*raise*/, true/*moreWillBeSelected*/); + widgetToSelect = w; //select later + } + } + if (widgetToSelect) //the last one left + setSelectedWidget(widgetToSelect, true/*add*/, false/*raise*/, false/*!moreWillBeSelected*/); + + m_insertRect = QRect(); + m_state = DoingNothing; + m_container->repaint(); +} + +void +Container::drawInsertRect(QMouseEvent *mev, QObject *s) +{ + int tmpx, tmpy; + QPoint pos = static_cast<QWidget*>(s)->mapTo(m_container, mev->pos()); + int gridX = m_form->gridSize(); + int gridY = m_form->gridSize(); + if(!FormManager::self()->snapWidgetsToGrid() || (mev->state() == (LeftButton|ControlButton|AltButton)) ) + { + tmpx = pos.x(); + tmpy = pos.y(); + } + else + { + tmpx = int( (float) pos.x() / ((float)gridX) + 0.5); + tmpx *= gridX; + tmpy = int( (float)pos.y() / ((float)gridY) + 0.5); + tmpy *= gridX; + } + + int topx = (m_insertBegin.x() < tmpx) ? m_insertBegin.x() : tmpx; + int topy = (m_insertBegin.y() < tmpy) ? m_insertBegin.y() : tmpy; + int botx = (m_insertBegin.x() > tmpx) ? m_insertBegin.x() : tmpx; + int boty = (m_insertBegin.y() > tmpy) ? m_insertBegin.y() : tmpy; + m_insertRect = QRect(QPoint(topx, topy), QPoint(botx, boty)); + + if(m_insertRect.x() < 0) + m_insertRect.setLeft(0); + if(m_insertRect.y() < 0) + m_insertRect.setTop(0); + if(m_insertRect.right() > m_container->width()) + m_insertRect.setRight(m_container->width()); + if(m_insertRect.bottom() > m_container->height()) + m_insertRect.setBottom(m_container->height()); + + if(FormManager::self()->isInserting() && m_insertRect.isValid()) + { + if(m_form->formWidget()) + { + QRect drawRect = QRect(m_container->mapTo(m_form->widget(), m_insertRect.topLeft()) + , m_insertRect.size()); + m_form->formWidget()->drawRect(drawRect, 2); + } + } +} + +void +Container::drawCopiedWidgetRect(QMouseEvent *mev) +{ + // We've been dragging a widget, but Ctrl was hold, so we start copy + if(m_state == MovingWidget) { + //FormManager::self()->undo(); // undo last moving + //m_moving->move(m_initialPos); + if(m_form->formWidget()) { + m_container->repaint(); + m_form->formWidget()->initBuffer(); + } + m_state = CopyingWidget; + } + + //m_copyRect.moveTopLeft(m_container->mapFromGlobal( mev->globalPos()) - m_grab); + + if(m_form->formWidget()) { + QValueList<QRect> rectList; + for(QWidget *w = m_form->selectedWidgets()->first(); w; w = m_form->selectedWidgets()->next()) { + QRect drawRect = w->geometry(); + QPoint p = mev->pos() - m_grab; + drawRect.moveBy(p.x(), p.y()); + p = m_container->mapTo(m_form->widget(), QPoint(0, 0)); + //drawRect = QRect( ((QWidget*)s)->mapTo(m_form->widget(), drawRect.topLeft()), drawRect.size()); + drawRect.moveBy(p.x(), p.y()); + rectList.append(drawRect); + } + + m_form->formWidget()->drawRects(rectList, 2); + } +} + +/// Other functions used by eventFilter +void +Container::moveSelectedWidgetsBy(int realdx, int realdy, QMouseEvent *mev) +{ + if (m_form->selectedWidget() == m_form->widget()) + return; //do not move top-level widget + + const int gridX = m_form->gridSize(); + const int gridY = m_form->gridSize(); + int dx=realdx, dy=realdy; + + for(QWidget *w = m_form->selectedWidgets()->first(); w; w = m_form->selectedWidgets()->next()) + { + if(!w || !w->parent() || w->parent()->inherits("QTabWidget") || w->parent()->inherits("QWidgetStack")) + continue; + + if(w->parentWidget() && w->parentWidget()->isA("QWidgetStack")) + { + w = w->parentWidget(); // widget is WidgetStack page + if(w->parentWidget() && w->parentWidget()->inherits("QTabWidget")) // widget is tabwidget page + w = w->parentWidget(); + } + + int tmpx = w->x() + realdx; + int tmpy = w->y() + realdy; + if(tmpx < 0) + dx = QMAX(0 - w->x(), dx); // because dx is <0 + else if(tmpx > w->parentWidget()->width() - gridX) + dx = QMIN(w->parentWidget()->width() - gridX - w->x(), dx); + + if(tmpy < 0) + dy = QMAX(0 - w->y(), dy); // because dy is <0 + else if(tmpy > w->parentWidget()->height() - gridY) + dy = QMIN(w->parentWidget()->height() - gridY - w->y(), dy); + } + + for(QWidget *w = m_form->selectedWidgets()->first(); w; w = m_form->selectedWidgets()->next()) + { + // Don't move tab widget pages (or widget stack pages) + if(!w || !w->parent() || w->parent()->inherits("QTabWidget") || w->parent()->inherits("QWidgetStack")) + continue; + + if(w->parentWidget() && w->parentWidget()->isA("QWidgetStack")) + { + w = w->parentWidget(); // widget is WidgetStack page + if(w->parentWidget() && w->parentWidget()->inherits("QTabWidget")) // widget is tabwidget page + w = w->parentWidget(); + } + + int tmpx, tmpy; + if(!FormManager::self()->snapWidgetsToGrid() || (mev && mev->state() == (LeftButton|ControlButton|AltButton)) ) + { + tmpx = w->x() + dx; + tmpy = w->y() + dy; + } + else + { + tmpx = int( float( w->x() + dx) / float(gridX) + 0.5) * gridX; + tmpy = int( float( w->y() + dy) / float(gridY) + 0.5) * gridY; + } + + if((tmpx != w->x()) || (tmpy != w->y())) + w->move(tmpx,tmpy); + } +} + +//////////// + +DesignTimeDynamicChildWidgetHandler::DesignTimeDynamicChildWidgetHandler() + : m_item(0) +{ +} + +DesignTimeDynamicChildWidgetHandler::~DesignTimeDynamicChildWidgetHandler() +{ +} + +void +DesignTimeDynamicChildWidgetHandler::childWidgetAdded(QWidget* w) +{ + if (m_item) { + installRecursiveEventFilter(w, m_item->eventEater()); + } +} + +#include "container.moc" |
