00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kptresourceview.h"
00021
00022 #include "kptcalendar.h"
00023 #include "kptduration.h"
00024 #include "kptresourceappointmentsview.h"
00025 #include "kptview.h"
00026 #include "kptnode.h"
00027 #include "kptproject.h"
00028 #include "kpttask.h"
00029 #include "kptresource.h"
00030 #include "kptdatetime.h"
00031 #include "kptcontext.h"
00032
00033 #include <QMenu>
00034 #include <QPainter>
00035 #include <QStyle>
00036 #include <QList>
00037 #include <QHeaderView>
00038 #include <QTreeWidget>
00039 #include <QStringList>
00040 #include <QVBoxLayout>
00041
00042 #include <klocale.h>
00043 #include <kglobal.h>
00044 #include <kprinter.h>
00045
00046 #include <kdebug.h>
00047
00048 namespace KPlato
00049 {
00050
00051 ResListView::ResListView( QWidget * parent )
00052 : QTreeWidget( parent )
00053 {
00054 setContextMenuPolicy( Qt::CustomContextMenu );
00055 connect( this, SIGNAL( customContextMenuRequested( const QPoint& ) ), SLOT( slotContextMenuRequested( const QPoint& ) ) );
00056 }
00057
00058 int ResListView::headerHeight() const
00059 {
00060 return header() ->height();
00061 }
00062 void ResListView::paintToPrinter( QPainter *p, int x, int y, int w, int h )
00063 {
00064 #if 0
00065 p->save();
00066 QColor bgc( 193, 223, 255 );
00067 QBrush bg( bgc );
00068 p->setBackgroundMode( Qt::OpaqueMode );
00069 p->setBackgroundColor( bgc );
00070 QHeaderView *head = header();
00071 int offset = 0;
00072 QRect sr;
00073
00074 for ( int s = 0; s < head->count(); ++s ) {
00075 sr = head->sectionRect( s );
00076 if ( offset > sr.x() )
00077 offset = sr.x();
00078 }
00079 for ( int s = 0; s < head->count(); ++s ) {
00080 sr = head->sectionRect( s );
00081 if ( offset != 0 ) {
00082 sr = QRect( sr.x() - offset, sr.y(), sr.width(), sr.height() );
00083 }
00084
00085 if ( sr.x() + sr.width() <= x || sr.x() >= x + w ) {
00086
00087 continue;
00088 }
00089 QRect tr = sr;
00090 if ( sr.x() < x ) {
00091 tr.setX( x );
00092
00093 }
00094 p->eraseRect( tr );
00095 p->drawText( tr, columnAlignment( s ) | Qt::AlignVCenter, head->label( s ), -1 );
00096 }
00097 p->restore();
00098 p->save();
00099 p->translate( 0, headerHeight() );
00100 drawAllContents( p, x, y, w, h );
00101 p->restore();
00102 #endif
00103 }
00104 int ResListView::calculateY( int ymin, int ymax ) const
00105 {
00106 #if 0
00107 QList<ResListView::DrawableItem*> drawables;
00108 QTreeWidgetItem *child = firstChild();
00109 int level = 0;
00110 int ypos = 0;
00111 for ( ; child; child = child->nextSibling() ) {
00112 ypos = buildDrawables( drawables, level, ypos, child, ymin, ymax );
00113 }
00114 int y = 0;
00115 if ( !drawables.isEmpty() ) {
00116 DrawableItem * item = drawables.last();
00117 if ( item ) {
00118 y = item->y + item->i->height();
00119 }
00120 }
00121
00122 while ( !drawables.isEmpty() ) {
00123 delete drawables.takeFirst();
00124 }
00125 return y;
00126 #endif
00127
00128 return 0;
00129 }
00130 int ResListView::buildDrawables( QList<ResListView::DrawableItem*> &lst, int level, int ypos, QTreeWidgetItem *item, int ymin, int ymax ) const
00131 {
00132 #if 0
00133 int y = ypos;
00134 int ih = item->height();
00135 if ( y < ymin && y + ih > ymin ) {
00136 y = ymin;
00137 }
00138 if ( y >= ymin && y + ih < ymax ) {
00139 ResListView::DrawableItem * dr = new ResListView::DrawableItem( level, y, item );
00140 lst.append( dr );
00141
00142 }
00143 y += ih;
00144 if ( item->isOpen() ) {
00145 QTreeWidgetItem * child = item->firstChild();
00146 for ( ; child; child = child->nextSibling() ) {
00147 y = buildDrawables( lst, level + 1, y, child, ymin, ymax );
00148 }
00149 }
00150 return y;
00151 #endif
00152
00153 return 0;
00154 }
00155
00156 void ResListView::drawAllContents( QPainter * p, int cx, int cy, int cw, int ch )
00157 {
00158 #if 0
00159 if ( columns() == 0 ) {
00160 paintEmptyArea( p, QRect( cx, cy, cw, ch ) );
00161 return ;
00162 }
00163
00164 QList<ResListView::DrawableItem*> drawables;
00165 QTreeWidgetItem *child = firstChild();
00166 int level = 0;
00167 int ypos = 0;
00168 for ( ; child; child = child->nextSibling() ) {
00169 ypos = buildDrawables( drawables, level, ypos, child, cy, cy + ch );
00170 }
00171
00172 p->setFont( font() );
00173
00174 QRect r;
00175 int fx = -1, x, fc = 0, lc = 0;
00176 int tx = -1;
00177 foreach ( ResListView::DrawableItem * current, drawables ) {
00178 int ih = current->i->height();
00179 int ith = current->i->totalHeight();
00180 int c;
00181 int cs;
00182
00183
00184 if ( ih > 0 && current->y < cy + ch && current->y + ih > cy ) {
00185
00186 if ( fx < 0 ) {
00187
00188 x = 0;
00189 c = 0;
00190 cs = header() ->cellSize( 0 );
00191 while ( x + cs <= cx && c < header() ->count() ) {
00192 x += cs;
00193 c++;
00194 if ( c < header() ->count() )
00195 cs = header() ->cellSize( c );
00196 }
00197 fx = x;
00198 fc = c;
00199 while ( x < cx + cw && c < header() ->count() ) {
00200 x += cs;
00201 c++;
00202 if ( c < header() ->count() )
00203 cs = header() ->cellSize( c );
00204 }
00205 lc = c;
00206 }
00207
00208 x = fx;
00209 c = fc;
00210
00211
00212 const QColorGroup &cg = ( palette().inactive() );
00213
00214 while ( c < lc && !drawables.isEmpty() ) {
00215 int i = header() ->mapToLogical( c );
00216 cs = header() ->cellSize( c );
00217 r.setRect( x, current->y - cy, cs, ih );
00218 if ( i == 0 )
00219 r.setLeft( r.left() + current->l * treeStepSize() );
00220
00221 p->save();
00222
00223 if ( !( r.width() == 0 || r.height() == 0 ) ) {
00224 p->translate( r.left(), r.top() );
00225 int ac = header() ->mapToLogical( c );
00226
00227
00228 int align = columnAlignment( ac );
00229 if ( align == Qt::AlignAuto )
00230 align = Qt::AlignLeft;
00231 bool sel = current->i->isSelected();
00232 if ( sel )
00233 current->i->setSelected( false );
00234 current->i->paintCell( p, cg, ac, r.width(), align );
00235 if ( sel )
00236 current->i->setSelected( sel );
00237 }
00238 p->restore();
00239 x += cs;
00240 c++;
00241 }
00242
00243 }
00244
00245 const int cell = header() ->mapToActual( 0 );
00246
00247 if ( tx < 0 )
00248 tx = header() ->cellPos( cell );
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 while ( !drawables.isEmpty() ) {
00284 delete drawables.takeFirst();
00285 }
00286 }
00287 #endif
00288 }
00289
00290 void ResListView::slotContextMenuRequested( const QPoint &p )
00291 {
00292 kDebug() << k_funcinfo << p << endl;
00293 emit contextMenuRequested( itemAt( p ), mapToGlobal( p ), 0 );
00294 }
00295
00296 class ResourceItemPrivate : public QTreeWidgetItem
00297 {
00298 public:
00299 ResourceItemPrivate( Resource *r, QTreeWidgetItem *parent )
00300 : QTreeWidgetItem( parent ),
00301 resource( r )
00302 {
00303 setText( 0, r->name() );
00304 }
00305
00306 Resource *resource;
00307
00308 virtual void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int align )
00309 {
00310 QColorGroup g = cg;
00311 if ( m_columns[ column ] == 1 ) {
00312 g.setColor( QColorGroup::Text, QColor( Qt::red ) );
00313 g.setColor( QColorGroup::HighlightedText, QColor( Qt::red ) );
00314 }
00315
00316
00317 }
00318 void setColumnState( int c, int state = 1 )
00319 {
00320 m_columns[ c ] = state;
00321 }
00322 private:
00323 QMap<int, int> m_columns;
00324 };
00325
00326 class NodeItemPrivate : public QTreeWidgetItem
00327 {
00328 public:
00329 NodeItemPrivate( Task *n, QTreeWidget *parent )
00330 : QTreeWidgetItem( parent ),
00331 node( n )
00332 {
00333 setText( 0, n->name() );
00334 init();
00335 }
00336
00337 NodeItemPrivate( QString name, QTreeWidget *parent )
00338 : QTreeWidgetItem( parent ),
00339 node( 0 )
00340 {
00341 setText( 0, name );
00342 init();
00343 }
00344
00345 void setPriority( int col, int prio )
00346 {
00347 if ( prioColors.contains( prio ) ) {
00348 columnPrio.insert( col, prio );
00349 } else {
00350 columnPrio.remove( col );
00351 }
00352 }
00353 int priority( int col )
00354 {
00355 if ( columnPrio.contains( col ) ) {
00356 return columnPrio[ col ];
00357 }
00358 return 0;
00359 }
00360
00361 virtual void paintCell ( QPainter * p, const QColorGroup & cg, int column, int width, int align )
00362 {
00363
00364 QColorGroup g = cg;
00365 if ( columnPrio.contains( column ) ) {
00366 g.setColor( QColorGroup::Base, prioColors[ columnPrio[ column ] ] );
00367 }
00368
00369 }
00370
00371 Task *node;
00372 private:
00373 void init()
00374 {
00375 prioColors.insert( 1, QColor( Qt::gray ) );
00376 prioColors.insert( 2, QColor( Qt::green ) );
00377 prioColors.insert( 3, QColor( Qt::yellow ) );
00378 prioColors.insert( 4, QColor( Qt::red ) );
00379 }
00380 QMap<int, QColor> prioColors;
00381 QMap<int, int> columnPrio;
00382 };
00383
00384 class AppointmentItem : public QTreeWidgetItem
00385 {
00386 public:
00387 AppointmentItem( Appointment *a, QDate &d, QTreeWidgetItem *parent )
00388 : QTreeWidgetItem( parent ),
00389 appointment( a ),
00390 date( d ) {}
00391
00392 Appointment *appointment;
00393 QDate date;
00394 };
00395
00396 QSize ResourceView::sizeHint() const
00397 {
00398 return minimumSizeHint();
00399 }
00400
00401
00402
00403 ResourceView::ResourceView( View *view, QWidget *parent )
00404 : ViewBase(view, parent),
00405 m_selectedItem( 0 ),
00406 m_currentNode( 0 )
00407 {
00408 QVBoxLayout *l = new QVBoxLayout( this );
00409 l->setMargin(0);
00410 m_splitter = new QSplitter( this );
00411 l->addWidget( m_splitter );
00412 m_splitter->setOrientation(Qt::Vertical);
00413
00414 m_resListView = new ResListView( m_splitter );
00415 QStringList sl;
00416 sl << i18n( "Name" )
00417 << i18n( "Type" )
00418 << i18n( "Initials" )
00419 << i18n( "Email" )
00420 << i18n( "Calendar Name" )
00421 << i18n( "Available From" )
00422 << i18n( "Available Until" )
00423 << i18n( "%" )
00424 << i18n( "Normal Rate" )
00425 << i18n( "Overtime Rate" );
00426 m_resListView->setHeaderLabels( sl );
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 m_showAppointments = false;
00452 m_appview = new ResourceAppointmentsView( view, m_splitter );
00453 m_appview->hide();
00454 draw( view->getProject() );
00455
00456 connect( m_resListView, SIGNAL( itemSelectionChanged() ), SLOT( resSelectionChanged() ) );
00457 connect( m_resListView, SIGNAL( itemActivated( QTreeWidgetItem*, int ) ), SLOT( slotItemActivated( QTreeWidgetItem* ) ) );
00458
00459 connect( m_resListView, SIGNAL( contextMenuRequested( QTreeWidgetItem*, const QPoint&, int ) ), SLOT( popupMenuRequested( QTreeWidgetItem*, const QPoint&, int ) ) );
00460
00461 }
00462
00463 void ResourceView::zoom( double )
00464 {}
00465
00466 Resource *ResourceView::currentResource()
00467 {
00468 if ( m_selectedItem )
00469 return m_selectedItem->resource;
00470 return 0;
00471 }
00472
00473 void ResourceView::draw( Project &project )
00474 {
00475
00476 m_resListView->clear();
00477 m_appview->clear();
00478 m_selectedItem = 0;
00479
00480 foreach ( ResourceGroup * gr, project.resourceGroups() ) {
00481 QTreeWidgetItem * item = new QTreeWidgetItem( m_resListView );
00482 item->setText( 0, gr->name() );
00483
00484 drawResources( project, item, gr );
00485 }
00486 if ( m_selectedItem ) {
00487 m_selectedItem->setSelected( true );
00488 } else {
00489 resSelectionChanged( m_selectedItem );
00490 }
00491 }
00492
00493
00494 void ResourceView::drawResources( const Project &proj, QTreeWidgetItem *parent, ResourceGroup *group )
00495 {
00496
00497 foreach ( Resource * r, group->resources() ) {
00498 ResourceItemPrivate * item = new ResourceItemPrivate( r, parent );
00499
00500 item->setColumnState( 0, 0 );
00501 item->setColumnState( 4, 0 );
00502 item->setColumnState( 5, 0 );
00503 item->setColumnState( 6, 0 );
00504 item->setColumnState( 7, 0 );
00505 if ( r->calendar() == 0 ) {
00506 item->setColumnState( 0, 1 );
00507 item->setColumnState( 4, 1 );
00508 }
00509 if ( proj.constraint() == Node::MustFinishOn ) {
00510 if ( proj.mustFinishOn() <= r->availableFrom() ) {
00511 item->setColumnState( 0, 1 );
00512 item->setColumnState( 5, 1 );
00513 }
00514 } else {
00515 if ( proj.mustStartOn() >= r->availableUntil() ) {
00516 item->setColumnState( 0, 1 );
00517 item->setColumnState( 6, 1 );
00518 }
00519 }
00520 if ( r->units() == 0 ) {
00521 item->setColumnState( 0, 1 );
00522 item->setColumnState( 7, 1 );
00523 }
00524
00525 item->setText( 0, r->name() );
00526 switch ( r->type() ) {
00527 case Resource::Type_Work:
00528 item->setText( 1, i18n( "Work" ) );
00529 break;
00530 case Resource::Type_Material:
00531 item->setText( 1, i18n( "Material" ) );
00532 break;
00533 default:
00534 item->setText( 1, i18n( "Undefined" ) );
00535 break;
00536 }
00537 item->setText( 2, r->initials() );
00538 item->setText( 3, r->email() );
00539 item->setText( 4, r->calendar() ? r->calendar() ->name() : i18n( "None" ) );
00540 item->setText( 5, KGlobal::locale() ->formatDateTime( r->availableFrom() ) );
00541 item->setText( 6, KGlobal::locale() ->formatDateTime( r->availableUntil() ) );
00542 item->setText( 7, QString().setNum( r->units() ) );
00543 item->setText( 8, KGlobal::locale() ->formatMoney( r->normalRate() ) );
00544 item->setText( 9, KGlobal::locale() ->formatMoney( r->overtimeRate() ) );
00545 if ( !m_selectedItem ) {
00546 m_selectedItem = item;
00547 }
00548 }
00549 }
00550
00551
00552 void ResourceView::resSelectionChanged()
00553 {
00554
00555 QTreeWidgetItem * i = 0;
00556 QList<QTreeWidgetItem*> sl = m_resListView->selectedItems();
00557 if ( !sl.isEmpty() )
00558 i = sl.first();
00559 resSelectionChanged( i );
00560 }
00561
00562 void ResourceView::resSelectionChanged( QTreeWidgetItem *item )
00563 {
00564
00565 ResourceItemPrivate * ritem = dynamic_cast<ResourceItemPrivate *>( item );
00566 if ( ritem ) {
00567 m_selectedItem = ritem;
00568 if ( m_showAppointments ) {
00569 m_appview->show();
00570 m_appview->draw( ritem->resource, m_mainview->getProject().startTime().date(), m_mainview->getProject().endTime().date() );
00571 } else {
00572 m_appview->hide();
00573 }
00574 return ;
00575 }
00576 m_selectedItem = 0;
00577 m_appview->clear();
00578 }
00579
00580
00581 void ResourceView::slotItemActivated( QTreeWidgetItem* )
00582 {
00583 emit itemDoubleClicked();
00584 }
00585
00586 void ResourceView::popupMenuRequested( QTreeWidgetItem *item, const QPoint & pos, int )
00587 {
00588 ResourceItemPrivate * ritem = dynamic_cast<ResourceItemPrivate *>( item );
00589 if ( ritem ) {
00590 if ( ritem != m_selectedItem )
00591 resSelectionChanged( ritem );
00592 QMenu *menu = m_mainview->popupMenu( "resource_popup" );
00593 if ( menu ) {
00594 menu->exec( pos );
00595
00596 } else
00597 kDebug() << k_funcinfo << "No menu!" << endl;
00598 }
00599 }
00600
00601 QList<int> ResourceView::listOffsets( int pageHeight ) const
00602 {
00603 QList<int> lst;
00604 #if 0
00605
00606 int hh = m_resListView->headerHeight();
00607 int ph = pageHeight - hh;
00608 int lh = m_resListView->contentsHeight() - hh;
00609 int ly = 0;
00610 kDebug() << k_funcinfo << ly << ", " << lh << endl;
00611 while ( ly < lh ) {
00612 lst << ly;
00613 ly = m_resListView->calculateY( ly + 1, ly + ph );
00614
00615 }
00616 #endif
00617 return lst;
00618 }
00619
00620 void ResourceView::print( KPrinter &printer )
00621 {
00622 #if 0
00623
00624 uint top, left, bottom, right;
00625 printer.margins( &top, &left, &bottom, &right );
00626
00627 QPainter p;
00628 p.begin( &printer );
00629 p.setViewport( left, top, printer.width() - left - right, printer.height() - top - bottom );
00630 p.setClipRect( left, top, printer.width() - left - right, printer.height() - top - bottom );
00631 QRect preg = p.clipRegion().boundingRect();
00632
00633
00634 int ch = m_resListView->contentsHeight();
00635 int cw = m_resListView->contentsWidth();
00636 double scale = ( double ) preg.width() / ( double ) ( cw );
00637
00638 if ( scale < 1.0 ) {
00639 p.scale( scale, scale );
00640 }
00641 int ph = preg.height() - m_resListView->headerHeight();
00642 Q3ValueList<int> lst = listOffsets( preg.height() );
00643 for ( int i = 0; i < lst.count(); ++i ) {
00644
00645 if ( i > 0 ) {
00646 printer.newPage();
00647 }
00648 m_resListView->paintToPrinter( &p, 0, lst[ i ], cw, ph );
00649 }
00650
00651 p.end();
00652 #endif
00653 }
00654
00655 bool ResourceView::setContext( Context::Resourceview & )
00656 {
00657
00658 return true;
00659 }
00660
00661 void ResourceView::getContext( Context::Resourceview & ) const
00662 {
00663
00664 }
00665
00666
00667 }
00668
00669 #include "kptresourceview.moc"