kdganttview.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 distributed and/or modified under the terms of the
00007  ** GNU General Public License version 2 as published by the Free Software
00008  ** Foundation and appearing in the file LICENSE.GPL included in the
00009  ** packaging of this file.
00010  **
00011  ** Licensees holding valid commercial KD Gantt licenses may use this file in
00012  ** accordance with the KD Gantt Commercial License Agreement provided with
00013  ** the Software.
00014  **
00015  ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00016  ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00017  **
00018  ** See http://www.kdab.net/kdgantt for
00019  **   information about KD Gantt Commercial License Agreements.
00020  **
00021  ** Contact info@kdab.net if any conditions of this
00022  ** licensing are not clear to you.
00023  **
00024  **********************************************************************/
00025 #include "kdganttview.h"
00026 #include "kdganttview_p.h"
00027 
00028 #include "kdganttitemdelegate.h"
00029 #include "kdganttgraphicsitem.h"
00030 
00031 #include <QAbstractItemModel>
00032 #include <QHeaderView>
00033 #include <QVBoxLayout>
00034 #include <QGraphicsItem>
00035 #include <QGraphicsRectItem>
00036 #include <QScrollBar>
00037 #include <QPaintEvent>
00038 
00039 #include <QDebug>
00040 
00041 #include <cassert>
00042 
00043 using namespace KDGantt;
00044 
00045 namespace {
00046     class HeaderView : public QHeaderView {
00047     public:
00048         explicit HeaderView( QWidget* parent=0 ) : QHeaderView( Qt::Horizontal, parent ) {
00049         }
00050 
00051         QSize sizeHint() const { QSize s = QHeaderView::sizeHint(); s.rheight() *= 2; return s; }
00052     };
00053 }
00054 
00055 KDGanttTreeView::KDGanttTreeView( QAbstractProxyModel* proxy, QWidget* parent )
00056     : QTreeView( parent ),
00057       m_controller( this, proxy )
00058 {
00059     setHeader( new HeaderView );
00060 }
00061 
00062 KDGanttTreeView::~KDGanttTreeView()
00063 {
00064 }
00065 
00066 View::Private::Private(View* v)
00067     : q(v),
00068       splitter(v),
00069       rowController(0),
00070       gfxview(&splitter),
00071       model(0)
00072 {
00073     //init();
00074 }
00075 
00076 View::Private::~Private()
00077 {
00078 }
00079 
00080 void View::Private::init()
00081 {
00082     KDGanttTreeView* tw = new KDGanttTreeView( &ganttProxyModel, &splitter );
00083     tw->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00084     tw->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
00085 
00086     q->setLeftView( tw );
00087     q->setRowController( tw->rowController() );
00088 
00089     gfxview.setAlignment(Qt::AlignTop|Qt::AlignLeft);
00090     //gfxview.setRenderHints( QPainter::Antialiasing );
00091 
00092     tw->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
00093     gfxview.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
00094 
00095     QVBoxLayout* layout = new QVBoxLayout(q);
00096     layout->setMargin(0);
00097     layout->addWidget(&splitter);
00098     q->setLayout(layout);
00099 
00100     constraintProxy.setProxyModel( &ganttProxyModel );
00101     constraintProxy.setDestinationModel( &mappedConstraintModel );
00102     gfxview.setSelectionModel( leftWidget->selectionModel() );
00103     gfxview.setConstraintModel( &mappedConstraintModel );
00104 }
00105 
00106 void View::Private::updateScene()
00107 {
00108     gfxview.clearItems();
00109     if( !model) return;
00110 
00111     if( QTreeView* tw = qobject_cast<QTreeView*>(leftWidget)) {
00112       QModelIndex idx = ganttProxyModel.mapFromSource( model->index( 0, 0, leftWidget->rootIndex() ) );
00113       do {
00114         gfxview.updateRow( idx );
00115       } while ( ( idx = tw->indexBelow( idx ) ) != QModelIndex() &&
00116                 gfxview.rowController()->isRowVisible(idx) );
00117       gfxview.updateSceneRect();
00118     } else {
00119       const QModelIndex rootidx = ganttProxyModel.mapFromSource( leftWidget->rootIndex() );
00120       for( int r = 0; r < ganttProxyModel.rowCount(rootidx); ++r ) {
00121         gfxview.updateRow( ganttProxyModel.index( r, 0, rootidx ) );
00122       }
00123     }
00124 }
00125 
00126 void View::Private::slotCollapsed(const QModelIndex& _idx)
00127 {
00128     QTreeView* tw = qobject_cast<QTreeView*>(leftWidget);
00129     if(!tw) return;
00130 
00131     bool blocked = gfxview.blockSignals( true );
00132 
00133     QModelIndex idx( _idx );
00134     const QAbstractItemModel* model = leftWidget->model();
00135     const QModelIndex pidx = ganttProxyModel.mapFromSource(idx);
00136     bool isMulti = false;
00137     for( QModelIndex treewalkidx = pidx; treewalkidx.isValid(); treewalkidx = treewalkidx.parent() ) {
00138         if ( treewalkidx.data( ItemTypeRole ).toInt() == TypeMulti
00139              && !gfxview.rowController()->isRowExpanded( treewalkidx ) ) {
00140             isMulti = true;
00141             break;
00142         }
00143     }
00144 
00145     if ( !isMulti ) {
00146         for ( int i = 0; i < model->rowCount( idx ); ++i ) {
00147             gfxview.deleteSubtree( ganttProxyModel.index( i, 0, pidx ) );
00148         }
00149     } else {
00150         gfxview.updateRow(pidx);
00151     }
00152     //qDebug() << "Looking to update from " << idx;
00153     while ( ( idx=tw->indexBelow( idx ) ) != QModelIndex() &&
00154             gfxview.rowController()->isRowVisible( ganttProxyModel.mapFromSource(idx) ) ) {
00155         const QModelIndex proxyidx( ganttProxyModel.mapFromSource( idx ) );
00156         gfxview.updateRow(proxyidx);
00157     }
00158     gfxview.blockSignals( blocked );
00159     gfxview.updateSceneRect();
00160 }
00161 
00162 void View::Private::slotExpanded(const QModelIndex& _idx)
00163 {
00164     QModelIndex idx( ganttProxyModel.mapFromSource( _idx ) );
00165     do {
00166         //qDebug() << "Updating row" << idx << idx.data( Qt::DisplayRole ).toString();
00167         gfxview.updateRow(idx);
00168     } while( ( idx=gfxview.rowController()->indexBelow( idx ) ) != QModelIndex()
00169              && gfxview.rowController()->isRowVisible( idx ) );
00170     gfxview.updateSceneRect();
00171 }
00172 
00173 void View::Private::slotVerticalScrollValueChanged( int val )
00174 {
00175 #if 0
00176     qDebug() << "View::Private::slotVerticalScrollValueChanged("<<val<<")="
00177              << val/gfxview.verticalScrollBar()->singleStep();
00178 #endif
00179     leftWidget->verticalScrollBar()->setValue( val/gfxview.verticalScrollBar()->singleStep() );
00180 }
00181 
00182 void View::Private::slotLeftWidgetVerticalRangeChanged(int min, int max )
00183 {
00184     //qDebug() << "View::Private::slotLeftWidgetVerticalRangeChanged("<<min<<max<<")";
00185     gfxview.verticalScrollBar()->setRange( min, max );
00186     gfxview.updateSceneRect();
00187 }
00188 
00189 void View::Private::slotGfxViewVerticalRangeChanged( int min, int max )
00190 {
00191     //qDebug() << "View::Private::slotGfxViewVerticalRangeChanged("<<min<<max<<")";
00192     int leftMin = leftWidget->verticalScrollBar()->minimum();
00193     int leftMax = leftWidget->verticalScrollBar()->maximum();
00194     bool blocked = gfxview.verticalScrollBar()->blockSignals( true );
00195     gfxview.verticalScrollBar()->setRange( qMax( min, leftMin ), qMax( max, leftMax ) );
00196     gfxview.verticalScrollBar()->blockSignals( blocked );
00197 }
00198 
00212 View::View(QWidget* parent)
00213     : QWidget(parent),
00214       _d(new Private(this))
00215 {
00216    _d->init();
00217 }
00218 
00219 View::~View()
00220 {
00221     delete _d;
00222 }
00223 
00224 #define d d_func()
00225 
00231 void View::setLeftView( QAbstractItemView* aiv )
00232 {
00233     assert( aiv );
00234     if ( aiv==d->leftWidget ) return;
00235     if ( !d->leftWidget.isNull() ) {
00236         d->leftWidget->disconnect( this );
00237         d->leftWidget->hide();
00238         d->leftWidget->verticalScrollBar()->disconnect( d->gfxview.verticalScrollBar() );
00239         d->gfxview.verticalScrollBar()->disconnect( d->leftWidget->verticalScrollBar() );
00240     }
00241 
00242     d->leftWidget = aiv;
00243     d->splitter.insertWidget( 0, d->leftWidget );
00244 
00245     if( qobject_cast<QTreeView*>(d->leftWidget) ) {
00246       connect( d->leftWidget,  SIGNAL( collapsed( const QModelIndex& ) ),
00247                this, SLOT( slotCollapsed( const QModelIndex& ) ) );
00248       connect( d->leftWidget,  SIGNAL( expanded( const QModelIndex& ) ),
00249                this, SLOT( slotExpanded( const QModelIndex& ) ) );
00250     }
00251 
00252     connect( d->gfxview.verticalScrollBar(), SIGNAL( valueChanged( int ) ),
00253              d->leftWidget->verticalScrollBar(), SLOT( setValue( int ) ) );
00254     connect( d->leftWidget->verticalScrollBar(), SIGNAL( valueChanged( int ) ),
00255              d->gfxview.verticalScrollBar(), SLOT( setValue( int ) ) );
00256     connect( d->leftWidget->verticalScrollBar(), SIGNAL( rangeChanged( int, int ) ),
00257              this, SLOT( slotLeftWidgetVerticalRangeChanged( int, int ) ) );
00258     connect( d->gfxview.verticalScrollBar(), SIGNAL( rangeChanged( int, int ) ),
00259              this, SLOT( slotGfxViewVerticalRangeChanged( int, int ) ) );
00260 }
00261 
00267 void View::setRowController( AbstractRowController* ctrl )
00268 {
00269     if ( ctrl == d->rowController ) return;
00270     d->rowController = ctrl;
00271     d->gfxview.setRowController( d->rowController );
00272 }
00273 
00277 AbstractRowController* View::rowController()
00278 {
00279     return d->rowController;
00280 }
00281 
00284 const AbstractRowController* View::rowController() const
00285 {
00286     return d->rowController;
00287 }
00288 
00293 const QAbstractItemView* View::leftView() const
00294 {
00295     return d->leftWidget;
00296 }
00297 
00301 QAbstractItemView* View::leftView()
00302 {
00303     return d->leftWidget;
00304 }
00305 
00309 const GraphicsView* View::graphicsView() const
00310 {
00311     return &d->gfxview;
00312 }
00313 
00317 GraphicsView* View::graphicsView()
00318 {
00319     return &d->gfxview;
00320 }
00321 
00325 const QSplitter* View::splitter() const
00326 {
00327     return &d->splitter;
00328 }
00329 
00333 QSplitter* View::splitter()
00334 {
00335     return &d->splitter;
00336 }
00337 
00338 
00341 QAbstractItemModel* View::model() const
00342 {
00343     return leftView()->model();
00344 }
00345 
00351 void View::setModel( QAbstractItemModel* model )
00352 {
00353     leftView()->setModel( model );
00354     d->ganttProxyModel.setSourceModel( model );
00355     d->gfxview.setModel( &d->ganttProxyModel );
00356 }
00357 
00360 QItemSelectionModel* View::selectionModel() const
00361 {
00362     return leftView()->selectionModel();
00363 }
00364 
00368 void View::setSelectionModel( QItemSelectionModel* smodel )
00369 {
00370     leftView()->setSelectionModel( smodel );
00371     d->gfxview.setSelectionModel( new QItemSelectionModel( &( d->ganttProxyModel ),this ) );
00372 }
00373 
00379 void View::setGrid( AbstractGrid* grid )
00380 {
00381     d->gfxview.setGrid( grid );
00382 }
00383 
00386 AbstractGrid* View::grid() const
00387 {
00388     return d->gfxview.grid();
00389 }
00390 
00393 QModelIndex View::rootIndex() const
00394 {
00395     return leftView()->rootIndex();
00396 }
00397 
00401 void View::setRootIndex( const QModelIndex& idx )
00402 {
00403     leftView()->setRootIndex( idx );
00404     d->gfxview.setRootIndex( idx );
00405 }
00406 
00409 ItemDelegate* View::itemDelegate() const
00410 {
00411     return d->gfxview.itemDelegate();
00412 }
00413 
00417 void View::setItemDelegate( ItemDelegate* delegate )
00418 {
00419     leftView()->setItemDelegate( delegate );
00420     d->gfxview.setItemDelegate( delegate );
00421 }
00422 
00426 void View::setConstraintModel( ConstraintModel* cm )
00427 {
00428     d->constraintProxy.setSourceModel( cm );
00429     d->gfxview.setConstraintModel( &d->mappedConstraintModel );
00430 }
00431 
00434 ConstraintModel* View::constraintModel() const
00435 {
00436     return d->constraintProxy.sourceModel();
00437 }
00438 
00439 const QAbstractProxyModel* View::ganttProxyModel() const
00440 {
00441     return &( d->ganttProxyModel );
00442 }
00443 
00444 QAbstractProxyModel* View::ganttProxyModel()
00445 {
00446     return &( d->ganttProxyModel );
00447 }
00448 
00449 void View::resizeEvent(QResizeEvent*ev)
00450 {
00451     QWidget::resizeEvent(ev);
00452 }
00453 
00460 QModelIndex View::indexAt( const QPoint& pos ) const
00461 {
00462     return d->gfxview.indexAt( pos );
00463 }
00464 
00471 void View::print( QPrinter* printer, bool drawRowLabels )
00472 {
00473     graphicsView()->print( printer, drawRowLabels );
00474 }
00475 
00486 void View::print( QPrinter* printer, qreal start, qreal end, bool drawRowLabels )
00487 {
00488     graphicsView()->print( printer, start, end, drawRowLabels );
00489 }
00490 
00495 void View::print( QPainter* painter, const QRectF& target, bool drawRowLabels)
00496 {
00497     d->gfxview.print( painter,
00498                       target,
00499                       drawRowLabels);
00500 }
00501 
00510 void View::print( QPainter* painter, qreal start, qreal end, const QRectF& target, bool drawRowLabels)
00511 {
00512     d->gfxview.print( painter,
00513                       start, end,
00514                       target,
00515                       drawRowLabels);
00516 }
00517 
00518 
00519 #include "moc_kdganttview.cpp"
00520 
00521 #ifndef KDAB_NO_UNIT_TESTS
00522 #include "unittest/test.h"
00523 
00524 #include "kdganttlistviewrowcontroller.h"
00525 #include <QApplication>
00526 #include <QTimer>
00527 #include <QPixmap>
00528 #include <QListView>
00529 
00530 namespace {
00531     std::ostream& operator<<( std::ostream& os, const QImage& img )
00532     {
00533         os << "QImage[ size=("<<img.width()<<", "<<img.height()<<")]";
00534         return os;
00535     }
00536 }
00537 
00538 KDAB_SCOPED_UNITTEST_SIMPLE( KDGantt, View, "test" ) {
00539     View view( 0 );
00540 #if 0 // GUI tests do not work well on the server
00541     QTimer::singleShot( 1000, qApp, SLOT( quit() ) );
00542     view.show();
00543 
00544     qApp->exec();
00545     QPixmap screenshot1 = QPixmap::grabWidget( &view );
00546 
00547     QTreeView* tv = new QTreeView;
00548     view.setLeftView( tv );
00549     view.setRowController( new TreeViewRowController(tv,view.ganttProxyModel()) );
00550 
00551     QTimer::singleShot( 1000, qApp, SLOT( quit() ) );
00552 
00553     qApp->exec();
00554     QPixmap screenshot2 = QPixmap::grabWidget( &view );
00555 
00556     assertEqual( screenshot1.toImage(),  screenshot2.toImage() );
00557 
00558     QListView* lv = new QListView;
00559     view.setLeftView(lv);
00560     view.setRowController( new ListViewRowController(lv,view.ganttProxyModel()));
00561     view.show();
00562     QTimer::singleShot( 1000, qApp, SLOT( quit() ) );
00563     qApp->exec();
00564 #endif
00565 }
00566 #endif /* KDAB_NO_UNIT_TESTS */

Generated on Thu Mar 4 23:19:13 2010 for KD Chart 2 by  doxygen 1.5.4