/* This file is part of the KDE project Copyright (C) 2002-2004 Alexander Dymo 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 "view.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "canvas.h" #include "box.h" #include "commdefs.h" #include "reportitem.h" #include "label.h" #include "field.h" #include "specialfield.h" #include "calcfield.h" #include "line.h" #include "kugartemplate.h" #include "detailbase.h" #include "band.h" #include "command.h" #include "plugin.h" namespace Kudesigner { void SelectionRect::draw( TQPainter & painter ) { // painter.setPen(TQt::NoPen); /* TQPrinter pr; if ( pr.setup() ) { TQPainter p(&pr); m_canvas->drawArea( m_canvas->rect(), &p ); } */ /* kdDebug(31000) << "creating pixmap" << endl; TQPixmap mp(rect().size()); kdDebug(31000) << "creating painter" << endl; TQPainter p(&mp); kdDebug(31000) << "filling pixmap" << endl; m_canvas->drawArea(m_canvas->rect(), &p); kdDebug(31000) << "converting to image" << endl; TQImage im = mp.convertToImage(); if (!im.isNull()) { kdDebug(31000) << "do dither" << endl; mp.convertFromImage(im, TQt::OrderedAlphaDither); kdDebug(31000) << "creating brush" << endl; TQBrush br(TDEGlobalSettings::highlightColor(),TQt::CustomPattern); br.setPixmap(mp); painter.setBrush(br); } kdDebug(31000) << "drawing" << endl;*/ // painter.drawRect(rect()); TQPen pen( TQColor( 0, 0, 0 ), 0, TQt::DotLine ); painter.setPen( pen ); painter.setBrush( TQBrush( NoBrush ) ); painter.drawRect( rect() ); // TQCanvasRectangle::draw(painter); } View::View( Canvas *canvas, TQWidget *parent, const char *name, WFlags f ) : TQCanvasView( canvas, parent, name, f ), selectionBuf( 0 ), m_plugin( 0 ), m_canvas( canvas ) { itemToInsert = 0; moving = 0; resizing = 0; selectionStarted = 0; request = RequestNone; selectionRect = new SelectionRect( 0, 0, 0, 0, canvas ); connect( m_canvas, TQ_SIGNAL( itemSelected() ), this, TQ_SLOT( selectItem() ) ); } void View::deleteItem( TQCanvasItemList &l ) { for ( TQCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it ) { m_canvas->unselectItem( static_cast( *it ) ); if ( m_canvas->kugarTemplate() ->removeReportItem( *it ) ) break; } } void View::editItem( TQCanvasItemList & /* l */ ) { //display editor for report items or sections /* for (TQCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) { if ((*it)->rtti() >= 1800) //for my own report items { CanvasKudesigner::Box *l = (CanvasKudesigner::Box*)(*it); dlgItemOptions *dlgOpts = new dlgItemOptions(&(l->props), this); dlgOpts->exec(); delete dlgOpts; if ((*it)->rtti() == KugarTemplate) ((CanvasKugarTemplate*)(*it))->updatePaperProps(); (*it)->hide(); (*it)->show(); if ((*it)->rtti() < 2000) ((MyCanvas *)(m_canvas))->templ->arrangeSections(); m_canvas->update(); emit modificationPerformed(); break; } }*/ } void View::selectItemFromList( TQCanvasItemList &l ) { //display editor for report items or sections for ( TQCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it ) { if ( ( *it ) ->rtti() >= 1800 ) //include bands and the template itself { Kudesigner::Box * b = static_cast( *it ); if ( !m_canvas->selected.contains( b ) ) { m_canvas->unselectAll(); m_canvas->selectItem( b, false ); m_canvas->update(); // tqWarning("selected item set"); // selected->drawHolders(); return ; } if ( m_canvas->selected.contains( b ) ) { if ( m_canvas->selected.count() > 1 ) { m_canvas->unselectAll(); m_canvas->selectItem( b, false ); m_canvas->update(); } return ; } } } m_canvas->unselectAll(); // tqWarning("unselect"); } void View::placeItem( TQCanvasItemList &l, TQMouseEvent *e ) { for ( TQCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it ) { if ( ( ( *it ) ->rtti() > 1800 ) && ( ( ( *it ) ->rtti() < 2000 ) ) ) { int band = ( *it ) ->rtti(); int bandLevel = -1; if ( ( band == Rtti_DetailHeader ) || ( band == Rtti_Detail ) || ( band == Rtti_DetailFooter ) ) bandLevel = static_cast( *it ) ->level(); emit itemPlaced( e->x(), e->y(), band, bandLevel ); // emit modificationPerformed(); } } itemToInsert = 0; emit selectedActionProcessed(); } bool View::startResizing( TQMouseEvent * /*e*/, TQPoint &p ) { if ( m_canvas->selected.count() == 0 ) return false; for ( BoxList::iterator it = m_canvas->selected.begin(); it != m_canvas->selected.end(); ++it ) { Kudesigner::Box *cbx = *it; resizing_type = cbx->isInHolder( p ); /* tqWarning("POINT: %d %d", p.x(), p.y()); tqWarning("RESIZE: %d", resizing_type);*/ if ( resizing_type ) { m_canvas->selectItem( cbx, false ); //kdDebug()<<"A Widget should be resized"<rtti() > 2001 ) { ReportItem * item = static_cast( cbx ); resizing_constraint.setX( ( int ) item->section() ->x() ); resizing_constraint.setY( ( int ) item->section() ->y() ); resizing_constraint.setWidth( item->section() ->width() ); resizing_constraint.setHeight( item->section() ->height() ); if ( cbx->rtti() != Rtti_Line ) { resizing_minSize.setWidth( 10 ); resizing_minSize.setHeight( 10 ); } else { resizing_minSize.setWidth( 0 ); resizing_minSize.setHeight( 0 ); } } else if ( cbx->rtti() >= Rtti_ReportHeader ) { resizing_constraint = TQRect( 0, 0, 1000, 1000 ); resizing_minSize.setWidth( 0 ); resizing_minSize.setHeight( static_cast( cbx ) ->minHeight() ); } else { resizing_constraint = TQRect( 0, 0, 1000, 1000 ); resizing_minSize.setWidth( 0 ); resizing_minSize.setHeight( 10 ); } return true; } } return false; } void View::startMoveOrResizeOrSelectItem( TQCanvasItemList &l, TQMouseEvent * /*e*/, TQPoint &p ) { //allow user to move any item except for page rectangle for ( TQCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it ) { Kudesigner::Box *cb = static_cast( *it ); if ( cb->rtti() >= 1700 ) //> 2001) { moving_start = p; moving_offsetX = 0; moving_offsetY = 0; resizing_type = cb->isInHolder( p ); if ( ( *it ) ->rtti() > 2001 ) { ReportItem * item = static_cast( *it ); moving = item; resizing = 0; return ; } } } moving = 0; resizing = 0; // tqWarning("1"); selectionStarted = 1; selectionRect->setX( p.x() ); selectionRect->setY( p.y() ); selectionRect->setZ( 50 ); // tqWarning("2"); selectionRect->show(); // tqWarning("3"); } void View::contentsMousePressEvent( TQMouseEvent* e ) { TQPoint p = inverseWorldMatrix().TQWMatrix::map( e->pos() ); TQCanvasItemList l = m_canvas->collisions( p ); //if there is a request for properties or for delete operation //perform that and do not take care about mouse buttons // tqWarning("mouse press"); switch ( request ) { case RequestProps: clearRequest(); editItem( l ); return ; case RequestDelete: deleteItem( l ); clearRequest(); return ; case RequestNone: break; } moving = 0; resizing = 0; selectionStarted = 0; /* Kudesigner::Box *b; tqWarning("Selected items:"); for (b = selected.first(); b; b = selected.next()) tqWarning("%s", b->props["Text"].first.latin1()); */ switch ( e->button() ) { case TQt::LeftButton: if ( itemToInsert ) { // tqWarning("placing item"); m_canvas->unselectAll(); placeItem( l, e ); } else { // tqWarning("starting move or resize"); if ( !startResizing( e, p ) ) { selectItemFromList( l ); startMoveOrResizeOrSelectItem( l, e, p ); } } break; default: break; } } void View::contentsMouseReleaseEvent( TQMouseEvent* e ) { selectionRect->setSize( 0, 0 ); selectionRect->setX( 0 ); selectionRect->setY( 0 ); selectionRect->hide(); TQPoint p = inverseWorldMatrix().TQWMatrix::map( e->pos() ); TQCanvasItemList l = m_canvas->collisions( p ); switch ( e->button() ) { case TQt::LeftButton: if ( selectionStarted ) finishSelection(); break; /* case MidButton: deleteItem(l); break; case RightButton: editItem(l); break;*/ default: break; } } void View::fixMinValues( double &pos, double minv, double &offset ) { if ( pos < minv ) { offset = offset + pos - minv; pos = minv; } else { if ( offset < 0 ) { offset = offset + pos - minv; if ( offset < 0 ) pos = minv; else { pos = offset + minv; offset = 0; } } } } void View::fixMaxValues( double &pos, double size, double maxv, double &offset ) { double tmpMax = pos + size; if ( tmpMax > maxv ) { offset = offset + tmpMax - maxv; pos = maxv - size; } else { if ( offset > 0 ) { offset = offset + tmpMax - maxv; if ( offset > 0 ) pos = maxv - size; else { pos = offset + maxv - size; offset = 0; } } } } #ifdef TQ_WS_WIN double rint( double x ) { if ( fabs( x - floor( x ) ) < fabs( x - ceil( x ) ) ) return floor( x ); else return ceil( x ); } #endif void View::stickToGrid( double &x, double &y ) { int cx = int( rint( x / Config::gridSize() ) ); int cy = int( rint( y / Config::gridSize() ) ); x = cx * Config::gridSize(); y = cy * Config::gridSize(); } void View::stickDimToGrid( double x, double y, double &w, double &h ) { int rightX = int( x + w ); int bottomY = int( y + h ); int nx = int( rint( rightX /Config::gridSize() ) * Config::gridSize() ); int ny = int( rint( bottomY / Config::gridSize() ) * Config::gridSize() ); w = nx - x; h = ny - y; } void View::contentsMouseMoveEvent( TQMouseEvent* e ) { TQPoint p = inverseWorldMatrix().map( e->pos() ); /* TQCanvasItemList l=m_canvas->collisions(p); setCursor(TQCursor(TQt::ArrowCursor)); unsetCursor(); for (TQCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) { if ((*it)->rtti() > 2000) { CanvasReportItem *item = (CanvasReportItem*)(*it); if (item->bottomRightResizableRect().contains(e->pos())) setCursor(TQCursor(TQt::SizeFDiagCursor)); } }*/ if ( moving ) { double newXPos = moving->x() + p.x() - moving_start.x(); double newYPos = moving->y() + p.y() - moving_start.y(); fixMinValues( newYPos, moving->parentSection->y(), moving_offsetY ); fixMinValues( newXPos, moving->parentSection->x(), moving_offsetX ); fixMaxValues( newYPos, moving->height(), moving->parentSection->y() + moving->parentSection->height(), moving_offsetY ); fixMaxValues( newXPos, moving->width(), moving->parentSection->x() + moving->parentSection->width(), moving_offsetX ); double sx = newXPos; double sy = newYPos; if ( Config::gridSize() > 1 ) stickToGrid( newXPos, newYPos ); moving->move( newXPos, newYPos ); /* attempt to prevent item collisions TQCanvasItemList l=m_canvas->collisions(moving->rect()); if (l.count() > 2) { moving->moveBy(-(p.x() - moving_start.x()), -(p.y() - moving_start.y())); m_canvas->update(); return; }*/ // moving_start = p; moving_start = TQPoint( p.x() + ( int ) ( newXPos - sx ), p.y() + ( int ) ( newYPos - sy ) ); moving->updateGeomProps(); m_canvas->update(); emit modificationPerformed(); } if ( resizing ) { TQCanvasRectangle * r = ( TQCanvasRectangle * ) resizing; double newXPos = r->x(); double newYPos = r->y(); double h = r->height(); double w = r->width(); // kdDebug()<<"resizing"<y(), resizing_constraint.bottom(), moving_offsetY ); if ( resizing->rtti() != Rtti_Line ) fixMinValues( h, resizing_minSize.height(), moving_offsetY ); } else if ( resizing_type & Kudesigner::Box::ResizeTop ) { // kdDebug()<<"Resize top"<y() + p.y() - moving_start.y(); fixMinValues( newYPos, resizing_constraint.top(), moving_offsetY ); if ( resizing->rtti() != Rtti_Line ) fixMaxValues( newYPos, resizing_minSize.height(), r->y() + r->height(), moving_offsetY ); h = h + ( r->y() - newYPos ); } //horizontal resizing if ( resizing_type & Kudesigner::Box::ResizeRight ) { //kdDebug()<<"Resize right"<x(), resizing_constraint.right(), moving_offsetX ); if ( resizing->rtti() != Rtti_Line ) fixMinValues( w, resizing_minSize.width(), moving_offsetX ); } else if ( resizing_type & Kudesigner::Box::ResizeLeft ) { // kdDebug()<<"Resize left"<x() + p.x() - moving_start.x(); fixMinValues( newXPos, resizing_constraint.left(), moving_offsetX ); if ( resizing->rtti() != Rtti_Line ) fixMaxValues( newXPos, resizing_minSize.width(), r->x() + r->width(), moving_offsetX ); w = w + ( r->x() - newXPos ); } //sticky stuff double sx = newXPos; double sy = newYPos; if ( Config::gridSize() > 1 ) stickToGrid( newXPos, newYPos ); r->move( newXPos, newYPos ); int dx = ( int ) ( newXPos - sx ); int dy = ( int ) ( newYPos - sy ); // moving_start = TQPoint(p.x() + dx, p.y() + dy); w -= dx; h -= dy; // moving_start = p; double sw = w; double sh = h; stickDimToGrid( newXPos, newYPos, w, h ); int dw = ( int ) ( w - sw ); int dh = ( int ) ( h - sh ); moving_start = TQPoint( p.x() + dx + dw, p.y() + dy + dh ); r->setSize( ( int ) w, ( int ) h ); resizing->updateGeomProps(); m_canvas->update(); emit modificationPerformed(); } if ( selectionStarted ) { selectionRect->setSize( ( int ) ( e->pos().x() - selectionRect->x() ), ( int ) ( e->pos().y() - selectionRect->y() ) ); m_canvas->unselectAll(); TQCanvasItemList l = m_canvas->collisions( selectionRect->rect() ); for ( TQCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it ) { TQRect r; int left = selectionRect->rect().left(); int right = selectionRect->rect().right(); int top = selectionRect->rect().top(); int bottom = selectionRect->rect().bottom(); r.setLeft( left < right ? left : right ); r.setRight( left < right ? right : left ); r.setTop( top < bottom ? top : bottom ); r.setBottom( top < bottom ? bottom : top ); if ( ( ( *it ) ->rtti() > 2001 ) && ( r.contains( static_cast( *it ) ->rect() ) ) ) { m_canvas->selectItem( static_cast( *it ) ); m_canvas->update(); } } /* selectionRect->setSize(e->pos().x() - selectionRect->x(), e->pos().y() - selectionRect->y()); unselectAll(); TQCanvasItemList l = m_canvas->collisions(selectionRect->rect()); for (TQCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) { if ( ((*it)->rtti() > 2001) && (selectionRect->rect().contains(((CanvasKudesigner::Box*)(*it))->rect())) ) { selectItem((CanvasKudesigner::Box*)(*it)); m_canvas->update(); } }*/ } } void View::contentsMouseDoubleClickEvent( TQMouseEvent *e ) { ReportItem * item = 0L; if ( e->button() == TQt::LeftButton && m_canvas->selected.count() == 1 ) item = dynamic_cast( m_canvas->selected.first() ); if ( item ) { item->fastProperty(); emit changed(); item->hide(); item->show(); } } void View::setRequest( RequestType r ) { switch ( r ) { case RequestProps: TQApplication::restoreOverrideCursor(); TQApplication::setOverrideCursor( TQt::PointingHandCursor ); break; case RequestDelete: TQApplication::restoreOverrideCursor(); TQApplication::setOverrideCursor( TQt::ForbiddenCursor ); break; case RequestNone: TQApplication::restoreOverrideCursor(); break; } request = r; } void View::clearRequest() { TQApplication::restoreOverrideCursor(); request = RequestNone; emit selectedEditActionProcessed(); } bool View::requested() { if ( request == RequestNone ) return false; else return true; } void View::updateProperty() { for ( Kudesigner::BoxList::iterator it = m_canvas->selected.begin(); it != m_canvas->selected.end(); ++it ) { Kudesigner::Box *b = *it; // b->props[name]->setValue(value); b->hide(); b->show(); if ( ( b->rtti() >= 1800 ) && ( b->rtti() < 2000 ) ) m_canvas->kugarTemplate() ->arrangeSections(); } } void View::finishSelection() { selectionStarted = false; if ( !m_canvas->selected.isEmpty() ) { Kudesigner::BoxList::const_iterator it = m_canvas->selected.begin(); Kudesigner::Box *b = *it; Buffer *buf = new Buffer( &( b->props ) ); ++it; // tqWarning("== %d", m_canvas->selected.count()); // Kudesigner::BoxList::const_iterator it2 = m_canvas->selected.end(); // tqWarning("41: %d", it != it2); for ( ; it != m_canvas->selected.end(); ++it ) { b = *it; buf->intersect( &( b->props ) ); } emit selectionClear(); // delete selectionBuf; selectionBuf = buf; emit selectionMade( selectionBuf ); } } void View::setPlugin( KuDesignerPlugin *plugin ) { m_plugin = plugin; } void View::contentsDragMoveEvent( TQDragMoveEvent * event ) { //perhaps this could be optimized a little bit if ( !m_plugin ) return ; TQCanvasItemList l = m_canvas->collisions( event->pos() ); /* kdDebug()<ignore(); return ; } Kudesigner::Box *b = static_cast( *( l.begin() ) ); event->accept(); if ( m_plugin->dragMove( event, b ) ) event->accept(); else event->ignore(); } void View::contentsDragEnterEvent ( TQDragEnterEvent * /*event*/ ) { // event->accept(); } void View::keyPressEvent( TQKeyEvent *e ) { kdDebug(31000) << k_funcinfo << endl; if ( m_canvas->selected.count() == 1 ) { ReportItem * item = static_cast( m_canvas->selected.first() ); switch ( e->key() ) { case TQt::Key_Delete: kdDebug(31000) << "Deleting selection" << endl; /* unselectItem(item); ( (MyCanvas*) m_canvas )->templ->removeReportItem( item ); clearRequest();*/ // deleteSelected(); //FIXME: this disregards undo/redo if ( m_canvas->selected.count() > 0 ) { emit selectionClear(); DeleteReportItemsCommand *cmd = new DeleteReportItemsCommand( m_canvas, m_canvas->selected ); cmd->execute(); delete cmd; } return ; /* Adjust height with - and + */ case TQt::Key_Minus: case TQt::Key_Plus: { int size = item->props[ "FontSize" ].value().toInt(); if ( e->key() == TQt::Key_Minus ) size--; else size++; if ( size < 5 ) size = 5; if ( size > 50 ) size = 50; item->props[ "FontSize" ].setValue( size ); item->hide(); item->show(); return ; } default: e->ignore(); } } } void View::selectItem( ) { if ( !selectionStarted ) finishSelection(); } /*void View::deleteSelected( ) { CanvasKudesigner::Box *b; TQPtrList list = m_canvas->selected; unselectAll(); for (b = list.first(); b; b = list.next()) { ( (MyCanvas*) m_canvas )->templ->removeReportItem( b ); } } */ void View::setCanvas( Canvas *canvas ) { if ( selectionRect ) delete selectionRect; TQCanvasView::setCanvas( ( TQCanvas* ) canvas ); m_canvas = canvas; selectionRect = new SelectionRect( 0, 0, 0, 0, m_canvas ); connect( m_canvas, TQ_SIGNAL( itemSelected() ), this, TQ_SLOT( selectItem() ) ); clearRequest(); } void View::setGridSize( int size ) { Config::setGridSize( size ); m_canvas->setChanged( m_canvas->rect() ); m_canvas->update(); } } #include "view.moc"