diff options
Diffstat (limited to 'kugar/kudesigner_lib/view.cpp')
-rw-r--r-- | kugar/kudesigner_lib/view.cpp | 841 |
1 files changed, 841 insertions, 0 deletions
diff --git a/kugar/kudesigner_lib/view.cpp b/kugar/kudesigner_lib/view.cpp new file mode 100644 index 00000000..b2684ee1 --- /dev/null +++ b/kugar/kudesigner_lib/view.cpp @@ -0,0 +1,841 @@ +/* This file is part of the KDE project + Copyright (C) 2002-2004 Alexander Dymo <adymo@mksat.net> + + 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 <math.h> + +#include <qwmatrix.h> +#include <qevent.h> +#include <qpoint.h> +#include <qcanvas.h> +#include <qaction.h> +#include <qcursor.h> +#include <qpainter.h> +#include <qbitmap.h> +#include <qimage.h> + +#include <qprinter.h> +#include <kdebug.h> + +#include <koproperty/property.h> + +#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( QPainter & painter ) +{ + // painter.setPen(Qt::NoPen); + + /* QPrinter pr; + if ( pr.setup() ) { + QPainter p(&pr); + m_canvas->drawArea( m_canvas->rect(), &p ); + } */ + + /* kdDebug(31000) << "creating pixmap" << endl; + QPixmap mp(rect().size()); + kdDebug(31000) << "creating painter" << endl; + QPainter p(&mp); + kdDebug(31000) << "filling pixmap" << endl; + m_canvas->drawArea(m_canvas->rect(), &p); + kdDebug(31000) << "converting to image" << endl; + QImage im = mp.convertToImage(); + if (!im.isNull()) + { + kdDebug(31000) << "do dither" << endl; + mp.convertFromImage(im, Qt::OrderedAlphaDither); + + kdDebug(31000) << "creating brush" << endl; + QBrush br(KGlobalSettings::highlightColor(),Qt::CustomPattern); + br.setPixmap(mp); + painter.setBrush(br); + } + kdDebug(31000) << "drawing" << endl;*/ + // painter.drawRect(rect()); + QPen pen( QColor( 0, 0, 0 ), 0, Qt::DotLine ); + painter.setPen( pen ); + painter.setBrush( QBrush( NoBrush ) ); + painter.drawRect( rect() ); + // QCanvasRectangle::draw(painter); +} + + + +View::View( Canvas *canvas, QWidget *parent, const char *name, WFlags f ) : + QCanvasView( 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, SIGNAL( itemSelected() ), this, SLOT( selectItem() ) ); +} + +void View::deleteItem( QCanvasItemList &l ) +{ + for ( QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it ) + { + m_canvas->unselectItem( static_cast<Kudesigner::Box*>( *it ) ); + if ( m_canvas->kugarTemplate() ->removeReportItem( *it ) ) + break; + } +} + +void View::editItem( QCanvasItemList & /* l */ ) +{ + //display editor for report items or sections + /* for (QCanvasItemList::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( QCanvasItemList &l ) +{ + //display editor for report items or sections + for ( QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it ) + { + if ( ( *it ) ->rtti() >= 1800 ) //include bands and the template itself + { + Kudesigner::Box * b = static_cast<Kudesigner::Box*>( *it ); + if ( !m_canvas->selected.contains( b ) ) + { + m_canvas->unselectAll(); + m_canvas->selectItem( b, false ); + m_canvas->update(); + // qWarning("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(); + // qWarning("unselect"); +} + + +void View::placeItem( QCanvasItemList &l, QMouseEvent *e ) +{ + for ( QCanvasItemList::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<DetailBase*>( *it ) ->level(); + emit itemPlaced( e->x(), e->y(), band, bandLevel ); + + // emit modificationPerformed(); + } + } + itemToInsert = 0; + emit selectedActionProcessed(); +} + + +bool View::startResizing( QMouseEvent * /*e*/, QPoint &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 ); + /* qWarning("POINT: %d %d", p.x(), p.y()); + qWarning("RESIZE: %d", resizing_type);*/ + if ( resizing_type ) + { + m_canvas->selectItem( cbx, false ); + //kdDebug()<<"A Widget should be resized"<<endl; + moving = 0; + resizing = cbx; + moving_start = p; + moving_offsetX = 0; + moving_offsetY = 0; + + if ( cbx->rtti() > 2001 ) + { + ReportItem * item = static_cast<ReportItem*>( 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 = QRect( 0, 0, 1000, 1000 ); + resizing_minSize.setWidth( 0 ); + resizing_minSize.setHeight( static_cast<Band*>( cbx ) ->minHeight() ); + } + else + { + resizing_constraint = QRect( 0, 0, 1000, 1000 ); + resizing_minSize.setWidth( 0 ); + resizing_minSize.setHeight( 10 ); + } + return true; + } + } + return false; +} + +void View::startMoveOrResizeOrSelectItem( QCanvasItemList &l, + QMouseEvent * /*e*/, QPoint &p ) +{ + //allow user to move any item except for page rectangle + for ( QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it ) + { + Kudesigner::Box *cb = static_cast<Kudesigner::Box*>( *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<ReportItem*>( *it ); + moving = item; + resizing = 0; + return ; + } + } + } + moving = 0; + resizing = 0; + // qWarning("1"); + selectionStarted = 1; + selectionRect->setX( p.x() ); + selectionRect->setY( p.y() ); + selectionRect->setZ( 50 ); + // qWarning("2"); + selectionRect->show(); + // qWarning("3"); +} + +void View::contentsMousePressEvent( QMouseEvent* e ) +{ + QPoint p = inverseWorldMatrix().QWMatrix::map( e->pos() ); + QCanvasItemList 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 + + // qWarning("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; + qWarning("Selected items:"); + for (b = selected.first(); b; b = selected.next()) + qWarning("%s", b->props["Text"].first.latin1()); + + */ + switch ( e->button() ) + { + case LeftButton: + if ( itemToInsert ) + { + // qWarning("placing item"); + m_canvas->unselectAll(); + placeItem( l, e ); + } + else + { + // qWarning("starting move or resize"); + if ( !startResizing( e, p ) ) + { + selectItemFromList( l ); + startMoveOrResizeOrSelectItem( l, e, p ); + } + } + break; + default: + break; + } +} + +void View::contentsMouseReleaseEvent( QMouseEvent* e ) +{ + selectionRect->setSize( 0, 0 ); + selectionRect->setX( 0 ); + selectionRect->setY( 0 ); + selectionRect->hide(); + + QPoint p = inverseWorldMatrix().QWMatrix::map( e->pos() ); + QCanvasItemList l = m_canvas->collisions( p ); + + switch ( e->button() ) + { + case 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 Q_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( QMouseEvent* e ) +{ + QPoint p = inverseWorldMatrix().map( e->pos() ); + + /* QCanvasItemList l=m_canvas->collisions(p); + setCursor(QCursor(Qt::ArrowCursor)); + unsetCursor(); + for (QCanvasItemList::Iterator it=l.begin(); it!=l.end(); ++it) + { + if ((*it)->rtti() > 2000) + { + CanvasReportItem *item = (CanvasReportItem*)(*it); + if (item->bottomRightResizableRect().contains(e->pos())) + setCursor(QCursor(Qt::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 + QCanvasItemList 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 = QPoint( p.x() + ( int ) ( newXPos - sx ), p.y() + ( int ) ( newYPos - sy ) ); + moving->updateGeomProps(); + m_canvas->update(); + emit modificationPerformed(); + } + if ( resizing ) + { + QCanvasRectangle * r = ( QCanvasRectangle * ) resizing; + double newXPos = r->x(); + double newYPos = r->y(); + double h = r->height(); + double w = r->width(); + // kdDebug()<<"resizing"<<endl; + + //vertical resizing + if ( resizing_type & Kudesigner::Box::ResizeBottom ) + { + // kdDebug()<<"Resize bottom"<<endl; + h = h + p.y() - moving_start.y(); + fixMaxValues( h, r->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"<<endl; + newYPos = r->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"<<endl; + w = w + p.x() - moving_start.x(); + fixMaxValues( w, r->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"<<endl; + newXPos = r->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 = QPoint(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 = QPoint( 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(); + QCanvasItemList l = m_canvas->collisions( selectionRect->rect() ); + for ( QCanvasItemList::Iterator it = l.begin(); it != l.end(); ++it ) + { + QRect 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<Kudesigner::Box*>( *it ) ->rect() ) ) ) + { + m_canvas->selectItem( static_cast<Kudesigner::Box*>( *it ) ); + m_canvas->update(); + } + } + + + /* selectionRect->setSize(e->pos().x() - selectionRect->x(), + e->pos().y() - selectionRect->y()); + unselectAll(); + QCanvasItemList l = m_canvas->collisions(selectionRect->rect()); + for (QCanvasItemList::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( QMouseEvent *e ) +{ + ReportItem * item = 0L; + if ( e->button() == Qt::LeftButton && m_canvas->selected.count() == 1 ) + item = dynamic_cast<ReportItem*>( m_canvas->selected.first() ); + if ( item ) + { + item->fastProperty(); + emit changed(); + item->hide(); + item->show(); + } +} + +void View::setRequest( RequestType r ) +{ + switch ( r ) + { + case RequestProps: + QApplication::restoreOverrideCursor(); + QApplication::setOverrideCursor( Qt::PointingHandCursor ); + break; + case RequestDelete: + QApplication::restoreOverrideCursor(); + QApplication::setOverrideCursor( Qt::ForbiddenCursor ); + break; + case RequestNone: + QApplication::restoreOverrideCursor(); + break; + } + request = r; +} + +void View::clearRequest() +{ + QApplication::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; + // qWarning("== %d", m_canvas->selected.count()); + // Kudesigner::BoxList::const_iterator it2 = m_canvas->selected.end(); + // qWarning("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( QDragMoveEvent * event ) +{ + //perhaps this could be optimized a little bit + if ( !m_plugin ) + return ; + QCanvasItemList l = m_canvas->collisions( event->pos() ); + /* kdDebug()<<l.count()<<endl;*/ + if ( l.count() < 2 ) + { + event->ignore(); + return ; + } + Kudesigner::Box *b = static_cast<Kudesigner::Box*>( *( l.begin() ) ); + event->accept(); + if ( m_plugin->dragMove( event, b ) ) + event->accept(); + else + event->ignore(); +} + +void View::contentsDragEnterEvent ( QDragEnterEvent * /*event*/ ) +{ + // event->accept(); +} + +void View::keyPressEvent( QKeyEvent *e ) +{ + kdDebug(31000) << k_funcinfo << endl; + + if ( m_canvas->selected.count() == 1 ) + { + ReportItem * item = static_cast<ReportItem *>( m_canvas->selected.first() ); + + switch ( e->key() ) + { + case Qt::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 Qt::Key_Minus: + case Qt::Key_Plus: + { + int size = item->props[ "FontSize" ].value().toInt(); + + if ( e->key() == Qt::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; + + QPtrList<CanvasKudesigner::Box> 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; + QCanvasView::setCanvas( ( QCanvas* ) canvas ); + m_canvas = canvas; + selectionRect = new SelectionRect( 0, 0, 0, 0, m_canvas ); + connect( m_canvas, SIGNAL( itemSelected() ), this, SLOT( selectItem() ) ); + clearRequest(); +} + +void View::setGridSize( int size ) +{ + Config::setGridSize( size ); + m_canvas->setChanged( m_canvas->rect() ); + m_canvas->update(); +} + +} + +#include "view.moc" |