1
/****************************************************************************
2
** Copyright (C) 2001-2006 Klarälvdalens Datakonsult AB. All rights reserved.
4
** This file is part of the KD Gantt library.
6
** This file may be used under the terms of the GNU General Public
7
** License versions 2.0 or 3.0 as published by the Free Software
8
** Foundation and appearing in the files LICENSE.GPL2 and LICENSE.GPL3
9
** included in the packaging of this file. Alternatively you may (at
10
** your option) use any later version of the GNU General Public
11
** License if such license has been publicly approved by
12
** Klarälvdalens Datakonsult AB (or its successors, if any).
14
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
15
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
16
** A PARTICULAR PURPOSE. Klarälvdalens Datakonsult AB reserves all rights
17
** not expressly granted herein.
19
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
20
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22
**********************************************************************/
23
#include "kdganttgraphicsitem.h"
24
#include "kdganttgraphicsscene.h"
25
#include "kdganttgraphicsview.h"
26
#include "kdganttitemdelegate.h"
27
#include "kdganttconstraintgraphicsitem.h"
28
#include "kdganttconstraintmodel.h"
29
#include "kdganttconstraint.h"
30
#include "kdganttabstractgrid.h"
31
#include "kdganttabstractrowcontroller.h"
39
#include <QAbstractItemModel>
40
#include <QAbstractProxyModel>
41
#include <QItemSelectionModel>
42
#include <QGraphicsSceneMouseEvent>
43
#include <QGraphicsLineItem>
47
/*!\class KDGantt::GraphicsItem
51
using namespace KDGantt;
53
typedef QGraphicsItem BASE;
60
Updater( bool* u ) : u_ptr( u ), oldval( *u ) {
69
GraphicsItem::GraphicsItem( QGraphicsItem* parent, GraphicsScene* scene )
70
: BASE( parent, scene ), m_isupdating( false )
75
GraphicsItem::GraphicsItem( const QModelIndex& idx, QGraphicsItem* parent,
76
GraphicsScene* scene )
77
: BASE( parent, scene ), m_index( idx ), m_isupdating( false )
82
GraphicsItem::~GraphicsItem()
86
void GraphicsItem::init()
88
setFlags( ItemIsMovable|ItemIsSelectable|ItemIsFocusable );
89
setAcceptsHoverEvents( true );
90
setHandlesChildEvents( true );
95
int GraphicsItem::type() const
100
StyleOptionGanttItem GraphicsItem::getStyleOption() const
102
StyleOptionGanttItem opt;
103
opt.itemRect = rect();
104
opt.boundingRect = boundingRect();
105
opt.displayPosition = StyleOptionGanttItem::Right;
106
opt.displayAlignment = static_cast< Qt::Alignment >( m_index.model()->data( m_index, Qt::TextAlignmentRole ).toInt() );
107
opt.grid = scene()->grid();
108
opt.text = m_index.model()->data( m_index, Qt::DisplayRole ).toString();
109
if ( isEnabled() ) opt.state |= QStyle::State_Enabled;
110
if ( isSelected() ) opt.state |= QStyle::State_Selected;
111
if ( hasFocus() ) opt.state |= QStyle::State_HasFocus;
115
GraphicsScene* GraphicsItem::scene() const
117
return qobject_cast<GraphicsScene*>( QGraphicsItem::scene() );
120
void GraphicsItem::setRect( const QRectF& r )
122
prepareGeometryChange();
124
updateConstraintItems();
128
void GraphicsItem::setBoundingRect( const QRectF& r )
130
prepareGeometryChange();
135
bool GraphicsItem::isEditable() const
137
return !scene()->isReadOnly() && m_index.model()->flags( m_index ) & Qt::ItemIsEditable;
140
void GraphicsItem::paint( QPainter* painter, const QStyleOptionGraphicsItem* option,
144
if ( boundingRect().isValid() && scene() ) {
145
StyleOptionGanttItem opt = getStyleOption();
146
*static_cast<QStyleOption*>(&opt) = *static_cast<const QStyleOption*>( option );
147
scene()->itemDelegate()->paintGanttItem( painter, opt, index() );
151
void GraphicsItem::setIndex( const QPersistentModelIndex& idx )
157
QString GraphicsItem::ganttToolTip() const
159
return scene()->itemDelegate()->toolTip( index() );
162
QRectF GraphicsItem::boundingRect() const
164
return m_boundingrect;
167
QPointF GraphicsItem::startConnector( int relationType ) const
169
switch ( relationType ) {
170
case Constraint::StartStart:
171
case Constraint::StartFinish:
172
return mapToScene( m_rect.left(), m_rect.top()+m_rect.height()/2. );
176
return mapToScene( m_rect.right(), m_rect.top()+m_rect.height()/2. );
179
QPointF GraphicsItem::endConnector( int relationType ) const
181
switch ( relationType ) {
182
case Constraint::FinishFinish:
183
case Constraint::StartFinish:
184
return mapToScene( m_rect.right(), m_rect.top()+m_rect.height()/2. );
188
return mapToScene( m_rect.left(), m_rect.top()+m_rect.height()/2. );
192
void GraphicsItem::addStartConstraint( ConstraintGraphicsItem* item )
195
m_startConstraints << item;
196
item->setStart( startConnector( item->constraint().relationType() ) );
199
void GraphicsItem::addEndConstraint( ConstraintGraphicsItem* item )
202
m_endConstraints << item;
203
item->setEnd( endConnector( item->constraint().relationType() ) );
206
void GraphicsItem::removeStartConstraint( ConstraintGraphicsItem* item )
209
m_startConstraints.removeAll( item );
212
void GraphicsItem::removeEndConstraint( ConstraintGraphicsItem* item )
215
m_endConstraints.removeAll( item );
218
void GraphicsItem::updateConstraintItems()
220
{ // Workaround for multiple definition error with MSVC6
221
Q_FOREACH( ConstraintGraphicsItem* item, m_startConstraints ) {
222
QPointF s = startConnector( item->constraint().relationType() );
225
{// Workaround for multiple definition error with MSVC6
226
Q_FOREACH( ConstraintGraphicsItem* item, m_endConstraints ) {
227
QPointF e = endConnector( item->constraint().relationType() );
232
void GraphicsItem::updateItem( const Span& rowGeometry, const QPersistentModelIndex& idx )
234
Updater updater( &m_isupdating );
235
//qDebug() << "GraphicsItem::updateItem("<<rowGeometry<<idx<<")";
236
if ( !idx.isValid() || idx.data( ItemTypeRole )==TypeMulti ) {
242
Span s = scene()->grid()->mapToChart( idx );
243
setPos( QPointF( s.start(), rowGeometry.start() ) );
244
setRect( QRectF( 0., 0., s.length(), rowGeometry.length() ) );
246
Span bs = scene()->itemDelegate()->itemBoundingSpan( getStyleOption(), index() );
247
setBoundingRect( QRectF( bs.start(), 0., bs.length(), rowGeometry.length() ) );
248
int maxh = scene()->rowController()->maximumItemHeight();
249
if ( maxh < rowGeometry.length() ) {
251
Qt::Alignment align = getStyleOption().displayAlignment;
252
if ( align & Qt::AlignTop ) {
254
} else if ( align & Qt::AlignBottom ) {
255
r.setY( rowGeometry.length()-maxh );
258
r.setY( ( rowGeometry.length()-maxh ) / 2. );
264
scene()->setSceneRect( scene()->sceneRect().united( mapToScene( boundingRect() ).boundingRect() ) );
265
updateConstraintItems();
268
QVariant GraphicsItem::itemChange( GraphicsItemChange change, const QVariant& value )
270
if ( !isUpdating() && change==ItemPositionChange && scene() ) {
271
QPointF newPos=value.toPointF();
272
if ( isEditable() ) {
273
newPos.setY( pos().y() );
278
} else if ( change==QGraphicsItem::ItemSelectedChange ) {
279
if ( value.toBool() ) {
280
scene()->selectionModel()->select( index(), QItemSelectionModel::Select );
282
scene()->selectionModel()->select( index(), QItemSelectionModel::Deselect );
286
return QGraphicsItem::itemChange( change, value );
289
void GraphicsItem::focusInEvent( QFocusEvent* event )
292
scene()->selectionModel()->select( index(), QItemSelectionModel::SelectCurrent );
295
void GraphicsItem::updateModel()
297
//qDebug() << "GraphicsItem::updateModel("<<p<<")";
298
if ( isEditable() ) {
299
QAbstractItemModel* model = const_cast<QAbstractItemModel*>( index().model() );
300
ConstraintModel* cmodel = scene()->constraintModel();
304
//ItemType typ = static_cast<ItemType>( model->data( index(),
305
// ItemTypeRole ).toInt() );
306
const QModelIndex sourceIdx = scene()->summaryHandlingModel()->mapToSource( index() );
307
QList<Constraint> constraints;
308
for( QList<ConstraintGraphicsItem*>::iterator it1 = m_startConstraints.begin() ; it1 != m_startConstraints.end() ; ++it1 )
309
constraints.push_back((*it1)->proxyConstraint());
310
for( QList<ConstraintGraphicsItem*>::iterator it2 = m_endConstraints.begin() ; it2 != m_endConstraints.end() ; ++it2 )
311
constraints.push_back((*it2)->proxyConstraint());
312
if ( scene()->grid()->mapFromChart( Span( pos().x(), rect().width() ),
315
scene()->updateRow( index().parent() );
321
void GraphicsItem::hoverMoveEvent( QGraphicsSceneHoverEvent* event )
323
if ( !isEditable() ) return;
324
StyleOptionGanttItem opt = getStyleOption();
325
ItemDelegate::InteractionState istate = scene()->itemDelegate()->interactionStateFor( event->pos(), opt, index() );
327
case ItemDelegate::State_ExtendLeft:
328
setCursor( Qt::SizeHorCursor );
329
scene()->itemEntered( index() );
331
case ItemDelegate::State_ExtendRight:
332
setCursor( Qt::SizeHorCursor );
333
scene()->itemEntered( index() );
335
case ItemDelegate::State_Move:
336
setCursor( Qt::SplitHCursor );
337
scene()->itemEntered( index() );
344
void GraphicsItem::hoverLeaveEvent( QGraphicsSceneHoverEvent* )
349
void GraphicsItem::mousePressEvent( QGraphicsSceneMouseEvent* event )
351
StyleOptionGanttItem opt = getStyleOption();
352
m_istate = scene()->itemDelegate()->interactionStateFor( event->pos(), opt, index() );
353
m_presspos = event->pos();
354
m_pressscenepos = event->scenePos();
355
scene()->itemPressed( index() );
358
case ItemDelegate::State_ExtendLeft:
359
case ItemDelegate::State_ExtendRight:
360
default: /* None and Move */
361
BASE::mousePressEvent( event );
366
void GraphicsItem::mouseReleaseEvent( QGraphicsSceneMouseEvent* event )
368
if ( !m_presspos.isNull() ) {
369
scene()->itemClicked( index() );
371
delete m_dragline; m_dragline = 0;
372
if ( scene()->dragSource() ) {
373
// Create a new constraint
374
GraphicsItem* other = qgraphicsitem_cast<GraphicsItem*>( scene()->itemAt( event->scenePos() ) );
375
if ( other && scene()->dragSource()!=other &&
376
other->mapToScene( other->rect() ).boundingRect().contains( event->scenePos() )) {
377
GraphicsView* view = qobject_cast<GraphicsView*>( event->widget()->parentWidget() );
379
view->addConstraint( scene()->summaryHandlingModel()->mapToSource( scene()->dragSource()->index() ),
380
scene()->summaryHandlingModel()->mapToSource( other->index() ), event->modifiers() );
383
scene()->setDragSource( 0 );
385
updateItemFromMouse(event->scenePos());
389
m_presspos = QPointF();
390
BASE::mouseReleaseEvent( event );
393
void GraphicsItem::mouseDoubleClickEvent( QGraphicsSceneMouseEvent* event )
395
StyleOptionGanttItem opt = getStyleOption();
396
ItemDelegate::InteractionState istate = scene()->itemDelegate()->interactionStateFor( event->pos(), opt, index() );
397
if ( istate != ItemDelegate::State_None ) {
398
scene()->itemDoubleClicked( index() );
400
BASE::mouseDoubleClickEvent( event );
403
void GraphicsItem::updateItemFromMouse( const QPointF& scenepos )
405
const QPointF p = scenepos - m_presspos;
407
QRectF br = boundingRect();
409
case ItemDelegate::State_Move:
410
setPos( p.x(), pos().y() );
412
case ItemDelegate::State_ExtendLeft: {
413
const qreal brr = br.right();
414
const qreal rr = r.right();
415
const qreal delta = pos().x()-p.x();
416
setPos( p.x(), QGraphicsItem::pos().y() );
417
br.setRight( brr+delta );
418
r.setRight( rr+delta );
421
case ItemDelegate::State_ExtendRight: {
422
const qreal rr = r.right();
423
r.setRight( scenepos.x()-pos().x() );
424
br.setWidth( br.width() + r.right()-rr );
430
setBoundingRect( br );
433
void GraphicsItem::mouseMoveEvent( QGraphicsSceneMouseEvent* event )
435
if ( !isEditable() ) return;
436
//qDebug() << "GraphicsItem::mouseMoveEvent("<<event<<"), m_istate="<< static_cast<ItemDelegate::InteractionState>( m_istate );
438
case ItemDelegate::State_ExtendLeft:
439
case ItemDelegate::State_ExtendRight:
440
case ItemDelegate::State_Move:
441
// Check for constraint drag
442
if ( qAbs( m_pressscenepos.x()-event->scenePos().x() ) < 10.
443
&& qAbs( m_pressscenepos.y()-event->scenePos().y() ) > 5. ) {
444
m_istate = ItemDelegate::State_DragConstraint;
445
m_dragline = new QGraphicsLineItem( this );
446
m_dragline->setPen( QPen( Qt::DashLine ) );
447
m_dragline->setLine(QLineF( rect().center(), event->pos() ));
448
scene()->addItem( m_dragline );
449
scene()->setDragSource( this );
453
scene()->selectionModel()->setCurrentIndex( index(), QItemSelectionModel::Current );
454
updateItemFromMouse(event->scenePos());
455
//BASE::mouseMoveEvent(event);
457
case ItemDelegate::State_DragConstraint: {
458
QLineF line = m_dragline->line();
459
m_dragline->setLine( QLineF( line.p1(), event->pos() ) );
460
//QGraphicsItem* item = scene()->itemAt( event->scenePos() );