/* 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 <tqpainter.h> #include <tqpixmap.h> #include <tqrect.h> #include <tqevent.h> #include <tqvaluevector.h> #include <tqlayout.h> #include <tqcursor.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(TQWidget *widget, TQObject *container) : TQObject(container) { m_widget = widget; m_container = container; installRecursiveEventFilter(TQT_TQOBJECT(m_widget), this); } bool EventEater::eventFilter(TQObject *, TQEvent *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() == TQEvent::MouseButtonRelease && m_widget->inherits(TQTABWIDGET_OBJECT_NAME_STRING)) { TQMouseEvent *mev = TQT_TQMOUSEEVENT(ev); if(mev->button() == Qt::LeftButton) { TQMouseEvent *myev = new TQMouseEvent(TQEvent::MouseButtonPress, mev->pos(), mev->button(), mev->state()); m_container->eventFilter(m_widget, myev); delete myev; //return true; } } // else if(ev->type() == TQEvent::ChildInserted) { // widget's tqchildren have changed, we need to reinstall filter // installRecursiveEventFilter(m_widget, this); // } return m_container->eventFilter(m_widget, ev); } EventEater::~EventEater() { if(m_widget) removeRecursiveEventFilter(TQT_TQOBJECT(m_widget), TQT_TQOBJECT(this)); } // Container itself Container::Container(Container *toplevel, TQWidget *container, TQObject *parent, const char *name) : TQObject(parent, name) , m_insertBegin(-1,-1) , m_mousePressEventReceived(false) , m_mouseReleaseEvent(TQEvent::None, TQPoint(), 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; TQCString 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()) { TQString 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, TQT_SIGNAL(destroyed()), this, TQT_SLOT(widgetDeleted())); } connect(container, TQT_SIGNAL(destroyed()), this, TQT_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(TQObject *s, TQEvent *e) { // kdDebug() << e->type() << endl; switch(e->type()) { case TQEvent::MouseButtonPress: { m_insertBegin = TQPoint(-1, -1); m_mousePressEventReceived = true; kdDebug() << "TQEvent::MouseButtonPress sender object = " << s->name() << "of type " << s->className() << endl; kdDebug() << "TQEvent::MouseButtonPress this = " << name() << endl; m_moving = TQT_TQWIDGET(s); TQMouseEvent *mev = TQT_TQMOUSEEVENT(e); m_grab = TQPoint(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->tqgeometry(); 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() == Qt::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() == Qt::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() == Qt::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() == (Qt::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 = (TQT_TQWIDGET(s))->mapTo(m_container, TQPoint(tmpx, tmpy)); if(m_form->formWidget()) m_form->formWidget()->initBuffer(); if(!FormManager::self()->isInserting()) m_state = DrawingSelectionRect; } else { if(s->inherits(TQTABWIDGET_OBJECT_NAME_STRING)) // 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 TQEvent::MouseButtonRelease: { TQMouseEvent *mev = TQT_TQMOUSEEVENT(e); if (!m_mousePressEventReceived) { m_mouseReleaseEvent = *mev; m_objectForMouseReleaseEvent = s; return true; } m_mousePressEventReceived = false; m_objectForMouseReleaseEvent = 0; return handleMouseReleaseEvent(s, mev); } case TQEvent::MouseMove: { TQMouseEvent *mev = TQT_TQMOUSEEVENT(e); if(m_insertBegin!=TQPoint(-1,-1) && FormManager::self()->isInserting() && ((mev->state() == Qt::LeftButton) || (mev->state() == (Qt::LeftButton|ControlButton)) || (mev->state() == (Qt::LeftButton|ControlButton|AltButton)) || (mev->state() == (Qt::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() && (TQT_BASE_OBJECT(tree->widget()) != TQT_BASE_OBJECT(s))) m_form->formWidget()->highlightWidgets(tree->widget(), TQT_TQWIDGET(s)); } else if(m_insertBegin!=TQPoint(-1,-1) && s == m_container && !m_toplevel && (mev->state() != ControlButton) && !FormManager::self()->isCreatingConnection()) // draw the selection rect { if((mev->state() != Qt::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(); TQRect r = TQRect(TQPoint(topx, topy), TQPoint(botx, boty)); m_insertRect = r; if(m_form->formWidget()) m_form->formWidget()->drawRect(r, 1); m_state = DoingNothing; return true; } else if(mev->state() == (Qt::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() == (Qt::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(TQWIDGETSTACK_OBJECT_NAME_STRING))) return true; moveSelectedWidgetsBy(mev->x() - m_grab.x(), mev->y() - m_grab.y()); m_state = MovingWidget; } return true; // eat } case TQEvent::Paint: // Draw the dotted background { if(s != m_container) return false; int gridX = m_form->gridSize(); int gridY = m_form->gridSize(); TQPainter p(m_container); p.setPen(TQPen(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 TQEvent::Resize: // we are resizing a widget, so we set m_move to true -> the tqlayout will be reloaded when releasing mouse { if(m_form->interactiveMode()) m_state = MovingWidget; break; } //case TQEvent::AccelOverride: case TQEvent::KeyPress: { TQKeyEvent *kev = TQT_TQKEYEVENT(e); if(kev->key() == Key_F2) // pressing F2 == double-clicking { m_state = InlineEditing; TQWidget *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 TQMouseEvent *mev = new TQMouseEvent(TQEvent::MouseMove, m_moving->mapFromGlobal(TQCursor::pos()), Qt::NoButton, Qt::LeftButton|ControlButton ); eventFilter(TQT_TQOBJECT(m_moving), TQT_TQEVENT(mev)); delete mev; } else if(kev->key() == FormManager::self()->contextMenuKey()) { FormManager::self()->createContextMenu(TQT_TQWIDGET(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()->tqchildren(); 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 TQEvent::KeyRelease: { TQKeyEvent *kev = TQT_TQKEYEVENT(e); if((kev->key() == Key_Control) && (m_state == CopyingWidget)) { // cancel copying //m_copyRect = TQRect(); if(m_form->formWidget()) m_form->formWidget()->clearForm(); } return true; } case TQEvent::MouseButtonDblClick: // editing { kdDebug() << "Container: Mouse dbl click for widget " << s->name() << endl; TQWidget *w = TQT_TQWIDGET(s); if(!w) return false; //m_inlineEditing = true; m_state = InlineEditing; m_form->library()->startEditing(w->className(), w, this); return true; } case TQEvent::ContextMenu: case TQEvent::Enter: case TQEvent::Leave: case TQEvent::FocusIn: case TQEvent::FocusOut: // case TQEvent::DragEnter: // case TQEvent::DragMove: // case TQEvent::DragLeave: return true; // eat them default: return false; // let the widget do the rest ... } return false; } bool Container::handleMouseReleaseEvent(TQObject *s, TQMouseEvent *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 = TQPoint(-1,-1); m_insertRect = TQRect(); return true; } else if(s == m_container && !m_toplevel && (mev->button() != Qt::RightButton) && m_insertRect.isValid()) // we are drawing a rect to select widgets { drawSelectionRect(mev); return true; } if(mev->button() == Qt::RightButton) // Right-click -> context menu { FormManager::self()->createContextMenu(TQT_TQWIDGET(s), this); } else if(mev->state() == (Qt::LeftButton|TQt::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( TQT_TQWIDGET(s)->mapTo(m_container, mev->pos() - m_grab) ); FormManager::self()->pasteWidget(); m_form->setInteractiveMode(true); //m_initialPos = TQPoint(); } else if(m_state == MovingWidget) // one widget has been moved, so we need to update the tqlayout reloadLayout(); // cancel copying as user released Ctrl before releasing mouse button m_insertBegin = TQPoint(-1,-1); m_insertRect = TQRect(); m_state = DoingNothing; return true; // eat } void Container::setSelectedWidget(TQWidget *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(TQWidget *w) { if(!w) return; m_form->unSelectWidget(w); } Container* Container::toplevel() { if(m_toplevel) return m_toplevel; else return this; } void Container::deleteWidget(TQWidget *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 = (TQLayout*) new TQHBoxLayout(m_container, m_margin, m_spacing); createBoxLayout(new HorWidgetList(m_form->toplevelContainer()->widget())); break; } case VBox: { m_layout = (TQLayout*) new TQVBoxLayout(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(Qt::Horizontal); m_layout = (TQLayout*)flow; createFlowLayout(); break; } case VFlow: { KexiFlowLayout *flow = new KexiFlowLayout(m_container,m_margin, m_spacing); flow->setOrientation(Qt::Vertical); m_layout = (TQLayout*)flow; createFlowLayout(); break; } default: { m_layType = NoLayout; return; } } m_container->setGeometry(m_container->tqgeometry()); // just update tqlayout m_layout->activate(); } void Container::reloadLayout() { LayoutType type = m_layType; setLayout(NoLayout); setLayout(type); } void Container::createBoxLayout(WidgetList *list) { TQBoxLayout *tqlayout = static_cast<TQBoxLayout*>(m_layout); for(ObjectTreeItem *tree = m_tree->tqchildren()->first(); tree; tree = m_tree->tqchildren()->next()) list->append( tree->widget()); list->sort(); for(TQWidget *obj = list->first(); obj; obj = list->next()) tqlayout->addWidget(obj); delete list; } void Container::createFlowLayout() { KexiFlowLayout *flow = dynamic_cast<KexiFlowLayout*>(m_layout); if(!flow || m_tree->tqchildren()->isEmpty()) return; const int offset = 15; WidgetList *list=0, *list2=0; if(flow->orientation() ==Qt::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->tqchildren()->first(); tree; tree = m_tree->tqchildren()->next()) list->append( tree->widget()); list->sort(); if(flow->orientation() ==Qt::Horizontal) { int y = list->first()->y(); for(TQWidget *w = list->first(); w; w = list->next()) { if( (w->y() > y +offset)) { // start a new line list2->sort(); for(TQWidget *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(TQWidget *obj = list2->first(); obj; obj = list2->next()) flow->add(obj); } else { int x = list->first()->x(); for(TQWidget *w = list->first(); w; w = list->next()) { if( (w->x() > x +offset)) { // start a new column list2->sort(); for(TQWidget *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(TQWidget *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) TQValueVector<int> cols; TQValueVector<int> rows; int end=-1000; bool same = false; for(ObjectTreeItem *tree = m_tree->tqchildren()->first(); tree; tree = m_tree->tqchildren()->next()) vlist->append( tree->widget()); vlist->sort(); for(ObjectTreeItem *tree = m_tree->tqchildren()->first(); tree; tree = m_tree->tqchildren()->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) { TQWidget *w = it.current(); WidgetListIterator it2 = it; for(; it2.current() != 0; ++it2) { TQWidget *nextw = it2.current(); if((w->y() >= nextw->y()) || (nextw->y() >= w->tqgeometry().bottom())) break; if(!w->tqgeometry().intersects(nextw->tqgeometry())) 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->tqgeometry().bottom()+1); else if(nextw->x() >= w->x()) nextw->move(w->tqgeometry().right()+1, nextw->y()); else w->move(nextw->tqgeometry().right()+1, nextw->y()); } } } // Then we count the number of rows in the tqlayout, and set their beginnings for(WidgetListIterator it(*vlist); it.current() != 0; ++it) { TQWidget *w = it.current(); WidgetListIterator it2 = it; if(!same) { // this widget will make a new row end = w->tqgeometry().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; TQWidget *nextw = it2.current(); if(nextw->y() >= end) same = false; else { same = !(same && (nextw->y() >= w->tqgeometry().bottom())); if(!same) end = w->tqgeometry().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) { TQWidget *w = it.current(); WidgetListIterator it2 = it; if(!same) { end = w->tqgeometry().right(); cols.append(w->x()); } ++it2; if(!it2.current()) break; TQWidget *nextw = it2.current(); if(nextw->x() >= end) same = false; else { same = !(same && (nextw->x() >= w->tqgeometry().right())); if(!same) end = w->tqgeometry().right(); } } kdDebug() << "the new grid will have n columns: n == " << cols.size() << endl; // We create the tqlayout .. TQGridLayout *tqlayout=0; if(!testOnly) { tqlayout = new TQGridLayout(m_container, rows.size(), cols.size(), m_margin, m_spacing, "grid"); m_layout = (TQLayout*)tqlayout; } // .. and we fill it with widgets for(WidgetListIterator it(*vlist); it.current() != 0; ++it) { TQWidget *w = it.current(); TQRect r = w->tqgeometry(); 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) tqlayout->addWidget(w, wrow, wcol); item->setGridPos(wrow, wcol, 0, 0); } else { if(!endcol) endcol = wcol; if(!endrow) endrow = wrow; if(!testOnly) tqlayout->addMultiCellWidget(w, wrow, endrow, wcol, endcol); item->setGridPos(wrow, wcol, endrow-wrow+1, endcol-wcol+1); } } } TQString 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 TQString &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(TQMouseEvent *mev) { if(mev->button() != Qt::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/*, TQPoint()*/); } 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->tqrepaint(); return; } // the user clicked outside the menu, we cancel the connection if(FormManager::self()->createdConnection()->slot().isNull()) { FormManager::self()->stopCreatingConnection(); return; } } void Container::drawSelectionRect(TQMouseEvent *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(); TQRect r = TQRect(TQPoint(topx, topy), TQPoint(botx, boty)); setSelectedWidget(m_container, false); TQWidget *widgetToSelect = 0; // We check which widgets are in the rect and select them for(ObjectTreeItem *item = m_tree->tqchildren()->first(); item; item = m_tree->tqchildren()->next()) { TQWidget *w = item->widget(); if(!w) continue; if(w->tqgeometry().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 = TQRect(); m_state = DoingNothing; m_container->tqrepaint(); } void Container::drawInsertRect(TQMouseEvent *mev, TQObject *s) { int tmpx, tmpy; TQPoint pos = TQT_TQWIDGET(s)->mapTo(m_container, mev->pos()); int gridX = m_form->gridSize(); int gridY = m_form->gridSize(); if(!FormManager::self()->snapWidgetsToGrid() || (mev->state() == (Qt::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 = TQRect(TQPoint(topx, topy), TQPoint(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()) { TQRect drawRect = TQRect(m_container->mapTo(m_form->widget(), m_insertRect.topLeft()) , m_insertRect.size()); m_form->formWidget()->drawRect(drawRect, 2); } } } void Container::drawCopiedWidgetRect(TQMouseEvent *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->tqrepaint(); m_form->formWidget()->initBuffer(); } m_state = CopyingWidget; } //m_copyRect.moveTopLeft(m_container->mapFromGlobal( mev->globalPos()) - m_grab); if(m_form->formWidget()) { TQValueList<TQRect> rectList; for(TQWidget *w = m_form->selectedWidgets()->first(); w; w = m_form->selectedWidgets()->next()) { TQRect drawRect = w->tqgeometry(); TQPoint p = mev->pos() - m_grab; drawRect.moveBy(p.x(), p.y()); p = m_container->mapTo(m_form->widget(), TQPoint(0, 0)); //drawRect = TQRect( ((TQWidget*)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, TQMouseEvent *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(TQWidget *w = m_form->selectedWidgets()->first(); w; w = m_form->selectedWidgets()->next()) { if(!w || !w->parent() || w->parent()->inherits(TQTABWIDGET_OBJECT_NAME_STRING) || w->parent()->inherits(TQWIDGETSTACK_OBJECT_NAME_STRING)) continue; if(w->parentWidget() && w->parentWidget()->isA(TQWIDGETSTACK_OBJECT_NAME_STRING)) { w = w->parentWidget(); // widget is WidgetStack page if(w->parentWidget() && w->parentWidget()->inherits(TQTABWIDGET_OBJECT_NAME_STRING)) // widget is tabwidget page w = w->parentWidget(); } int tmpx = w->x() + realdx; int tmpy = w->y() + realdy; if(tmpx < 0) dx = TQMAX(0 - w->x(), dx); // because dx is <0 else if(tmpx > w->parentWidget()->width() - gridX) dx = TQMIN(w->parentWidget()->width() - gridX - w->x(), dx); if(tmpy < 0) dy = TQMAX(0 - w->y(), dy); // because dy is <0 else if(tmpy > w->parentWidget()->height() - gridY) dy = TQMIN(w->parentWidget()->height() - gridY - w->y(), dy); } for(TQWidget *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(TQTABWIDGET_OBJECT_NAME_STRING) || w->parent()->inherits(TQWIDGETSTACK_OBJECT_NAME_STRING)) continue; if(w->parentWidget() && w->parentWidget()->isA(TQWIDGETSTACK_OBJECT_NAME_STRING)) { w = w->parentWidget(); // widget is WidgetStack page if(w->parentWidget() && w->parentWidget()->inherits(TQTABWIDGET_OBJECT_NAME_STRING)) // widget is tabwidget page w = w->parentWidget(); } int tmpx, tmpy; if(!FormManager::self()->snapWidgetsToGrid() || (mev && mev->state() == (Qt::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(TQWidget* w) { if (m_item) { installRecursiveEventFilter(TQT_TQOBJECT(w), m_item->eventEater()); } } #include "container.moc"