/* 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 <tdelocale.h>
# include <tdepopupmenu.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 " ) )
{
TQMouseEvent * mev = static_cast < TQMouseEvent * > ( ev ) ;
if ( mev - > button ( ) = = TQt : : 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 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 ( 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 = static_cast < 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 ( ) = = TQt : : ControlButton ) | | ( mev - > state ( ) = = TQt : : 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 ( ) = = TQt : : 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 ( ) = = TQt : : 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 ( ) = = TQt : : 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 ( ) = = ( TQt : : LeftButton | TQt : : ControlButton | TQt : : 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 " ) ) // 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 = static_cast < 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 = static_cast < TQMouseEvent * > ( e ) ;
if ( m_insertBegin ! = TQPoint ( - 1 , - 1 ) & & FormManager : : self ( ) - > isInserting ( ) & & ( ( mev - > state ( ) = = TQt : : LeftButton ) | | ( mev - > state ( ) = = ( TQt : : LeftButton | TQt : : ControlButton ) ) | |
( mev - > state ( ) = = ( TQt : : LeftButton | TQt : : ControlButton | TQt : : AltButton ) ) | | ( mev - > state ( ) = = ( TQt : : LeftButton | TQt : : 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 ( ) , TQT_TQWIDGET ( s ) ) ;
}
else if ( m_insertBegin ! = TQPoint ( - 1 , - 1 ) & & s = = m_container & & ! m_toplevel & & ( mev - > state ( ) ! = TQt : : ControlButton ) & & ! FormManager : : self ( ) - > isCreatingConnection ( ) ) // draw the selection rect
{
if ( ( mev - > state ( ) ! = TQt : : 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 ( ) = = ( TQt : : LeftButton | TQt : : 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 ( ) = = TQt : : LeftButton ) | | ( mev - > state ( ) = = ( TQt : : LeftButton | TQt : : ControlButton | TQt : : 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")))
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 layout will be reloaded when releasing mouse
{
if ( m_form - > interactiveMode ( ) )
m_state = MovingWidget ;
break ;
}
//case TQEvent::AccelOverride:
case TQEvent : : KeyPress :
{
TQKeyEvent * kev = static_cast < 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 ( ) ) , TQt : : NoButton ,
TQt : : LeftButton | TQt : : ControlButton ) ;
eventFilter ( m_moving , 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 ( ) - > 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 TQEvent : : KeyRelease :
{
TQKeyEvent * kev = static_cast < 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 ( ) ! = TQt : : RightButton ) & & m_insertRect . isValid ( ) ) // we are drawing a rect to select widgets
{
drawSelectionRect ( mev ) ;
return true ;
}
if ( mev - > button ( ) = = TQt : : RightButton ) // Right-click -> context menu
{
FormManager : : self ( ) - > createContextMenu ( TQT_TQWIDGET ( s ) , this ) ;
}
else if ( mev - > state ( ) = = ( TQt : : 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 layout
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 ( TQt : : Horizontal ) ;
m_layout = ( TQLayout * ) flow ;
createFlowLayout ( ) ;
break ;
}
case VFlow :
{
KexiFlowLayout * flow = new KexiFlowLayout ( m_container , m_margin , m_spacing ) ;
flow - > setOrientation ( TQt : : Vertical ) ;
m_layout = ( TQLayout * ) 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 )
{
TQBoxLayout * layout = static_cast < TQBoxLayout * > ( m_layout ) ;
for ( ObjectTreeItem * tree = m_tree - > children ( ) - > first ( ) ; tree ; tree = m_tree - > children ( ) - > next ( ) )
list - > append ( tree - > widget ( ) ) ;
list - > sort ( ) ;
for ( TQWidget * 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 ( ) = = TQt : : 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 ( ) = = TQt : : 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 - > 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 )
{
TQWidget * w = it . current ( ) ;
WidgetListIterator it2 = it ;
for ( ; it2 . current ( ) ! = 0 ; + + it2 ) {
TQWidget * 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 )
{
TQWidget * 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 ;
TQWidget * 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 )
{
TQWidget * w = it . current ( ) ;
WidgetListIterator it2 = it ;
if ( ! same ) {
end = w - > geometry ( ) . 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 - > geometry ( ) . right ( ) ) ) ;
if ( ! same )
end = w - > geometry ( ) . right ( ) ;
}
}
kdDebug ( ) < < " the new grid will have n columns: n == " < < cols . size ( ) < < endl ;
// We create the layout ..
TQGridLayout * layout = 0 ;
if ( ! testOnly ) {
layout = new TQGridLayout ( m_container , rows . size ( ) , cols . size ( ) , m_margin , m_spacing , " grid " ) ;
m_layout = ( TQLayout * ) layout ;
}
// .. and we fill it with widgets
for ( WidgetListIterator it ( * vlist ) ; it . current ( ) ! = 0 ; + + it )
{
TQWidget * w = it . current ( ) ;
TQRect 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 ) ;
}
}
}
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 ( ) ! = TQt : : 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 - > 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 ( 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 - > children ( ) - > first ( ) ; item ; item = m_tree - > children ( ) - > next ( ) )
{
TQWidget * 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 = TQRect ( ) ;
m_state = DoingNothing ;
m_container - > repaint ( ) ;
}
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 ( ) = = ( TQt : : LeftButton | TQt : : ControlButton | TQt : : 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 - > repaint ( ) ;
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 - > geometry ( ) ;
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 " ) | | w - > parent ( ) - > inherits ( " TQWidgetStack " ) )
continue ;
if ( w - > parentWidget ( ) & & w - > parentWidget ( ) - > isA ( " TQWidgetStack " ) )
{
w = w - > parentWidget ( ) ; // widget is WidgetStack page
if ( w - > parentWidget ( ) & & w - > parentWidget ( ) - > inherits ( " TQTabWidget " ) ) // 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 " ) | | w - > parent ( ) - > inherits ( " TQWidgetStack " ) )
continue ;
if ( w - > parentWidget ( ) & & w - > parentWidget ( ) - > isA ( " TQWidgetStack " ) )
{
w = w - > parentWidget ( ) ; // widget is WidgetStack page
if ( w - > parentWidget ( ) & & w - > parentWidget ( ) - > inherits ( " TQTabWidget " ) ) // widget is tabwidget page
w = w - > parentWidget ( ) ;
}
int tmpx , tmpy ;
if ( ! FormManager : : self ( ) - > snapWidgetsToGrid ( ) | | ( mev & & mev - > state ( ) = = ( TQt : : LeftButton | TQt : : ControlButton | TQt : : 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"