• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

kdgantt

kdganttgraphicsitem.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002  ** Copyright (C) 2001-2006 Klarälvdalens Datakonsult AB.  All rights reserved.
00003  **
00004  ** This file is part of the KD Gantt library.
00005  **
00006  ** This file may be used under the terms of the GNU General Public
00007  ** License versions 2.0 or 3.0 as published by the Free Software
00008  ** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
00009  ** included in the packaging of this file.  Alternatively you may (at
00010  ** your option) use any later version of the GNU General Public
00011  ** License if such license has been publicly approved by
00012  ** Klarälvdalens Datakonsult AB (or its successors, if any).
00013  ** 
00014  ** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
00015  ** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
00016  ** A PARTICULAR PURPOSE. Klarälvdalens Datakonsult AB reserves all rights
00017  ** not expressly granted herein.
00018  ** 
00019  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021  **
00022  **********************************************************************/
00023 #include "kdganttgraphicsitem.h"
00024 #include "kdganttgraphicsscene.h"
00025 #include "kdganttgraphicsview.h"
00026 #include "kdganttitemdelegate.h"
00027 #include "kdganttconstraintgraphicsitem.h"
00028 #include "kdganttconstraintmodel.h"
00029 #include "kdganttconstraint.h"
00030 #include "kdganttabstractgrid.h"
00031 #include "kdganttabstractrowcontroller.h"
00032 
00033 #include <cassert>
00034 #include <cmath>
00035 #include <algorithm>
00036 #include <iterator>
00037 
00038 #include <QPainter>
00039 #include <QAbstractItemModel>
00040 #include <QAbstractProxyModel>
00041 #include <QItemSelectionModel>
00042 #include <QGraphicsSceneMouseEvent>
00043 #include <QGraphicsLineItem>
00044 
00045 #include <QDebug>
00046 
00051 using namespace KDGantt;
00052 
00053 typedef QGraphicsItem BASE;
00054 
00055 namespace {
00056     class Updater {
00057         bool *u_ptr;
00058         bool oldval;
00059     public:
00060         Updater( bool* u ) : u_ptr( u ), oldval( *u ) {
00061             *u=true;
00062         }
00063         ~Updater() {
00064             *u_ptr = oldval;
00065         }
00066     };
00067 }
00068 
00069 GraphicsItem::GraphicsItem( QGraphicsItem* parent, GraphicsScene* scene )
00070     : BASE( parent, scene ),  m_isupdating( false )
00071 {
00072   init();
00073 }
00074 
00075 GraphicsItem::GraphicsItem( const QModelIndex& idx, QGraphicsItem* parent,
00076                                             GraphicsScene* scene )
00077     : BASE( parent, scene ),  m_index( idx ), m_isupdating( false )
00078 {
00079   init();
00080 }
00081 
00082 GraphicsItem::~GraphicsItem()
00083 {
00084 }
00085 
00086 void GraphicsItem::init()
00087 {
00088     setFlags( ItemIsMovable|ItemIsSelectable|ItemIsFocusable );
00089     setAcceptsHoverEvents( true );
00090     setHandlesChildEvents( true );
00091     setZValue( 100. );
00092     m_dragline = 0;
00093 }
00094 
00095 int GraphicsItem::type() const
00096 {
00097     return Type;
00098 }
00099 
00100 StyleOptionGanttItem GraphicsItem::getStyleOption() const
00101 {
00102     StyleOptionGanttItem opt;
00103     opt.itemRect = rect();
00104     opt.boundingRect = boundingRect();
00105     opt.displayPosition = StyleOptionGanttItem::Right;
00106     opt.displayAlignment = static_cast< Qt::Alignment >( m_index.model()->data( m_index, Qt::TextAlignmentRole ).toInt() );
00107     opt.grid = scene()->grid();
00108     opt.text = m_index.model()->data( m_index, Qt::DisplayRole ).toString(); 
00109     if ( isEnabled() ) opt.state  |= QStyle::State_Enabled;
00110     if ( isSelected() ) opt.state |= QStyle::State_Selected;
00111     if ( hasFocus() ) opt.state   |= QStyle::State_HasFocus;
00112     return opt;
00113 }
00114 
00115 GraphicsScene* GraphicsItem::scene() const
00116 {
00117     return qobject_cast<GraphicsScene*>( QGraphicsItem::scene() );
00118 }
00119 
00120 void GraphicsItem::setRect( const QRectF& r )
00121 {
00122     prepareGeometryChange();
00123     m_rect = r;
00124     updateConstraintItems();
00125     update();
00126 }
00127 
00128 void GraphicsItem::setBoundingRect( const QRectF& r )
00129 {
00130     prepareGeometryChange();
00131     m_boundingrect = r;
00132     update();
00133 }
00134 
00135 bool GraphicsItem::isEditable() const
00136 {
00137     return !scene()->isReadOnly() && m_index.model()->flags( m_index ) & Qt::ItemIsEditable;
00138 }
00139 
00140 void GraphicsItem::paint( QPainter* painter, const QStyleOptionGraphicsItem* option,
00141                                   QWidget* widget )
00142 {
00143     Q_UNUSED( widget );
00144     if ( boundingRect().isValid() && scene() ) {
00145         StyleOptionGanttItem opt = getStyleOption();
00146         *static_cast<QStyleOption*>(&opt) = *static_cast<const QStyleOption*>( option );
00147         scene()->itemDelegate()->paintGanttItem( painter, opt, index() );
00148     }
00149 }
00150 
00151 void GraphicsItem::setIndex( const QPersistentModelIndex& idx )
00152 {
00153     m_index=idx;
00154     update();
00155 }
00156 
00157 QString GraphicsItem::ganttToolTip() const
00158 {
00159     // TODO: Make delegate handle this
00160     const QAbstractItemModel* model = index().model();
00161     if ( !model ) return QString();
00162     QString tip = model->data( index(), Qt::ToolTipRole ).toString();
00163     if ( !tip.isNull() ) return tip;
00164     else return GraphicsScene::tr( "%1 -> %2: %3" )
00165         .arg( model->data( index(), StartTimeRole ).toString() )
00166         .arg( model->data( index(), EndTimeRole ).toString() )
00167         .arg( model->data( index(), Qt::DisplayRole ).toString() );
00168 }
00169 
00170 QRectF GraphicsItem::boundingRect() const
00171 {
00172     return m_boundingrect;
00173 }
00174 
00175 QPointF GraphicsItem::startConnector( int relationType ) const
00176 {
00177     switch ( relationType ) {
00178         case Constraint::StartStart:
00179         case Constraint::StartFinish:
00180             return mapToScene( m_rect.left(), m_rect.top()+m_rect.height()/2. );
00181         default:
00182             break;
00183     }
00184     return mapToScene( m_rect.right(), m_rect.top()+m_rect.height()/2. );
00185 }
00186 
00187 QPointF GraphicsItem::endConnector( int relationType ) const
00188 {
00189     switch ( relationType ) {
00190         case Constraint::FinishFinish:
00191         case Constraint::StartFinish:
00192             return mapToScene( m_rect.right(), m_rect.top()+m_rect.height()/2. );
00193         default:
00194             break;
00195     }
00196     return mapToScene( m_rect.left(), m_rect.top()+m_rect.height()/2. );
00197 }
00198 
00199 
00200 void GraphicsItem::addStartConstraint( ConstraintGraphicsItem* item )
00201 {
00202     assert( item );
00203     m_startConstraints << item;
00204     item->setStart( startConnector( item->constraint().relationType() ) );
00205 }
00206 
00207 void GraphicsItem::addEndConstraint( ConstraintGraphicsItem* item )
00208 {
00209     assert( item );
00210     m_endConstraints << item;
00211     item->setEnd( endConnector( item->constraint().relationType() ) );
00212 }
00213 
00214 void GraphicsItem::removeStartConstraint( ConstraintGraphicsItem* item )
00215 {
00216     assert( item );
00217     m_startConstraints.removeAll( item );
00218 }
00219 
00220 void GraphicsItem::removeEndConstraint( ConstraintGraphicsItem* item )
00221 {
00222     assert( item );
00223     m_endConstraints.removeAll( item );
00224 }
00225 
00226 void GraphicsItem::updateConstraintItems()
00227 {
00228     { // Workaround for multiple definition error with MSVC6
00229     Q_FOREACH( ConstraintGraphicsItem* item, m_startConstraints ) {
00230         QPointF s = startConnector( item->constraint().relationType() );
00231         item->setStart( s );
00232     }}
00233     {// Workaround for multiple definition error with MSVC6
00234     Q_FOREACH( ConstraintGraphicsItem* item, m_endConstraints ) {
00235         QPointF e = endConnector( item->constraint().relationType() );
00236         item->setEnd( e );
00237     }}
00238 }
00239 
00240 void GraphicsItem::updateItem( const Span& rowGeometry, const QPersistentModelIndex& idx )
00241 {
00242     Updater updater( &m_isupdating );
00243     //qDebug() << "GraphicsItem::updateItem("<<rowGeometry<<idx<<")";
00244     if ( !idx.isValid() || idx.data( ItemTypeRole )==TypeMulti ) {
00245         setRect( QRectF() );
00246     hide();
00247         return;
00248     }
00249 
00250     Span s = scene()->grid()->mapToChart( idx );
00251     setPos( QPointF( s.start(), rowGeometry.start() ) );
00252     setRect( QRectF( 0., 0., s.length(), rowGeometry.length() ) );
00253     setIndex( idx );
00254     Span bs = scene()->itemDelegate()->itemBoundingSpan( getStyleOption(), index() );
00255     setBoundingRect( QRectF( bs.start(), 0., bs.length(), rowGeometry.length() ) );
00256     int maxh = scene()->rowController()->maximumItemHeight();
00257     if ( maxh < rowGeometry.length() ) {
00258         QRectF r = rect();
00259         Qt::Alignment align = getStyleOption().displayAlignment;
00260         if ( align & Qt::AlignTop ) {
00261             // Do nothing
00262         } else if ( align & Qt::AlignBottom ) {
00263             r.setY( rowGeometry.length()-maxh );
00264         } else {
00265             // Center
00266             r.setY( ( rowGeometry.length()-maxh ) / 2. );
00267         }
00268         r.setHeight( maxh );
00269         setRect( r );
00270     }
00271 
00272     scene()->setSceneRect( scene()->sceneRect().united( mapToScene( boundingRect() ).boundingRect() ) );
00273     updateConstraintItems();
00274 }
00275 
00276 QVariant GraphicsItem::itemChange( GraphicsItemChange change, const QVariant& value )
00277 {
00278     if ( !isUpdating() && change==ItemPositionChange && scene() ) {
00279         QPointF newPos=value.toPointF();
00280         if ( isEditable() ) {
00281             newPos.setY( pos().y() );
00282             return newPos;
00283         } else {
00284             return pos();
00285         }
00286     } else if ( change==QGraphicsItem::ItemSelectedChange ) {
00287         if ( value.toBool() ) {
00288             scene()->selectionModel()->select( index(), QItemSelectionModel::Select );
00289         } else {
00290             scene()->selectionModel()->select( index(), QItemSelectionModel::Deselect );
00291         }
00292     }
00293 
00294     return QGraphicsItem::itemChange( change, value );
00295 }
00296 
00297 void GraphicsItem::focusInEvent( QFocusEvent* event )
00298 {
00299     Q_UNUSED( event );
00300     scene()->selectionModel()->select( index(), QItemSelectionModel::SelectCurrent );
00301 }
00302 
00303 void GraphicsItem::updateModel()
00304 {
00305     //qDebug() << "GraphicsItem::updateModel("<<p<<")";
00306     if ( isEditable() ) {
00307         QAbstractItemModel* model = const_cast<QAbstractItemModel*>( index().model() );
00308         ConstraintModel* cmodel = scene()->constraintModel();
00309         assert( model );
00310         assert( cmodel );
00311         if ( model ) {
00312             //ItemType typ = static_cast<ItemType>( model->data( index(),
00313             //                                                   ItemTypeRole ).toInt() );
00314             const QModelIndex sourceIdx = scene()->summaryHandlingModel()->mapToSource( index() );
00315             QList<Constraint> constraints;
00316             for( QList<ConstraintGraphicsItem*>::iterator it1 = m_startConstraints.begin() ; it1 != m_startConstraints.end() ; ++it1 )
00317                 constraints.push_back((*it1)->proxyConstraint());
00318             for( QList<ConstraintGraphicsItem*>::iterator it2 = m_endConstraints.begin() ; it2 != m_endConstraints.end() ; ++it2 )
00319                 constraints.push_back((*it2)->proxyConstraint());
00320             if ( scene()->grid()->mapFromChart( Span( pos().x(), rect().width() ),
00321                                                 index(),
00322                                                 constraints ) ) {
00323                 scene()->updateRow( index().parent() );
00324             }
00325         }
00326     }
00327 }
00328 
00329 void GraphicsItem::hoverMoveEvent( QGraphicsSceneHoverEvent* event )
00330 {
00331     if (  !isEditable() ) return;
00332     StyleOptionGanttItem opt = getStyleOption();
00333     ItemDelegate::InteractionState istate = scene()->itemDelegate()->interactionStateFor( event->pos(), opt, index() );
00334     switch( istate ) {
00335     case ItemDelegate::State_ExtendLeft:
00336         setCursor( Qt::SizeHorCursor );
00337         scene()->itemEntered( index() );
00338         break;
00339     case ItemDelegate::State_ExtendRight:
00340         setCursor( Qt::SizeHorCursor );
00341         scene()->itemEntered( index() );
00342         break;
00343     case ItemDelegate::State_Move:
00344         setCursor( Qt::SplitHCursor );
00345         scene()->itemEntered( index() );
00346         break;
00347     default:
00348         unsetCursor();
00349     };
00350 }
00351 
00352 void GraphicsItem::hoverLeaveEvent( QGraphicsSceneHoverEvent* )
00353 {
00354     unsetCursor();
00355 }
00356 
00357 void GraphicsItem::mousePressEvent( QGraphicsSceneMouseEvent* event )
00358 {
00359     StyleOptionGanttItem opt = getStyleOption();
00360     m_istate = scene()->itemDelegate()->interactionStateFor( event->pos(), opt, index() );
00361     m_presspos = event->pos();
00362     m_pressscenepos = event->scenePos();
00363     scene()->itemPressed( index() );
00364 
00365     switch( m_istate ) {
00366     case ItemDelegate::State_ExtendLeft:
00367     case ItemDelegate::State_ExtendRight:
00368     default: /* None and Move */
00369         BASE::mousePressEvent( event );
00370         break;
00371     }
00372 }
00373 
00374 void GraphicsItem::mouseReleaseEvent( QGraphicsSceneMouseEvent* event )
00375 {
00376     if ( !m_presspos.isNull() ) {
00377         scene()->itemClicked( index() );
00378     }
00379     delete m_dragline; m_dragline = 0;
00380     if ( scene()->dragSource() ) {
00381         // Create a new constraint
00382         GraphicsItem* other = qgraphicsitem_cast<GraphicsItem*>( scene()->itemAt( event->scenePos() ) );
00383         if ( other && scene()->dragSource()!=other &&
00384              other->mapToScene( other->rect() ).boundingRect().contains( event->scenePos() )) {
00385             GraphicsView* view = qobject_cast<GraphicsView*>( event->widget()->parentWidget() );
00386             if ( view ) {
00387                 view->addConstraint( scene()->summaryHandlingModel()->mapToSource( scene()->dragSource()->index() ),
00388                                      scene()->summaryHandlingModel()->mapToSource( other->index() ), event->modifiers() );
00389             }
00390         }
00391         scene()->setDragSource( 0 );
00392     } else {
00393         updateItemFromMouse(event->scenePos());
00394         updateModel();
00395     }
00396 
00397     m_presspos = QPointF();
00398     BASE::mouseReleaseEvent( event );
00399 }
00400 
00401 void GraphicsItem::mouseDoubleClickEvent( QGraphicsSceneMouseEvent* event )
00402 {
00403     StyleOptionGanttItem opt = getStyleOption();
00404     ItemDelegate::InteractionState istate = scene()->itemDelegate()->interactionStateFor( event->pos(), opt, index() );
00405     if ( istate != ItemDelegate::State_None ) {
00406         scene()->itemDoubleClicked( index() );
00407     }
00408     BASE::mouseDoubleClickEvent( event );
00409 }
00410 
00411 void GraphicsItem::updateItemFromMouse( const QPointF& scenepos )
00412 {
00413     const QPointF p = scenepos - m_presspos;
00414     QRectF r = rect();
00415     QRectF br = boundingRect();
00416     switch( m_istate ) {
00417     case ItemDelegate::State_Move:
00418         setPos( p.x(), pos().y() );
00419         break;
00420     case ItemDelegate::State_ExtendLeft: {
00421         const qreal brr = br.right();
00422         const qreal rr = r.right();
00423         const qreal delta = pos().x()-p.x();
00424         setPos( p.x(), QGraphicsItem::pos().y() );
00425         br.setRight( brr+delta );
00426         r.setRight( rr+delta );
00427         break;
00428     }
00429     case ItemDelegate::State_ExtendRight: {
00430         const qreal rr = r.right();
00431         r.setRight( scenepos.x()-pos().x() );
00432         br.setWidth( br.width() + r.right()-rr );
00433         break;
00434     }
00435     default: return;
00436     }
00437     setRect( r );
00438     setBoundingRect( br );
00439 }
00440 
00441 void GraphicsItem::mouseMoveEvent( QGraphicsSceneMouseEvent* event )
00442 {
00443     if (  !isEditable() ) return;
00444     //qDebug() << "GraphicsItem::mouseMoveEvent("<<event<<"), m_istate="<< static_cast<ItemDelegate::InteractionState>( m_istate );
00445     QPointF pos = event->pos() - m_presspos;
00446     switch( m_istate ) {
00447     case ItemDelegate::State_ExtendLeft:
00448     case ItemDelegate::State_ExtendRight:
00449     case ItemDelegate::State_Move:
00450         // Check for constraint drag
00451       if ( qAbs( m_pressscenepos.x()-event->scenePos().x() ) < 10.
00452        && qAbs( m_pressscenepos.y()-event->scenePos().y() ) > 5. ) {
00453             m_istate = ItemDelegate::State_DragConstraint;
00454             m_dragline = new QGraphicsLineItem( this );
00455             m_dragline->setPen( QPen( Qt::DashLine ) );
00456             m_dragline->setLine(QLineF( rect().center(), event->pos() ));
00457             scene()->addItem( m_dragline );
00458             scene()->setDragSource( this );
00459             break;
00460         }
00461 
00462         scene()->selectionModel()->setCurrentIndex( index(), QItemSelectionModel::Current );
00463         updateItemFromMouse(event->scenePos());
00464         //BASE::mouseMoveEvent(event);
00465         break;
00466     case ItemDelegate::State_DragConstraint: {
00467         QLineF line = m_dragline->line();
00468         m_dragline->setLine( QLineF( line.p1(), event->pos() ) );
00469         //QGraphicsItem* item = scene()->itemAt( event->scenePos() );
00470         break;
00471     }
00472     }
00473 }

kdgantt

Skip menu "kdgantt"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal