00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kpttaskeditor.h"
00021
00022 #include "kptglobal.h"
00023 #include "kptcommand.h"
00024 #include "kptfactory.h"
00025 #include "kptproject.h"
00026
00027 #include <QAbstractItemModel>
00028 #include <QApplication>
00029 #include <QComboBox>
00030 #include <QHeaderView>
00031 #include <QItemDelegate>
00032 #include <QItemSelectionModel>
00033 #include <QLineEdit>
00034 #include <QListWidget>
00035 #include <QMap>
00036 #include <QModelIndex>
00037 #include <QStyleOptionViewItem>
00038 #include <QTreeWidgetItem>
00039 #include <QVBoxLayout>
00040 #include <QWidget>
00041
00042 #include <kicon.h>
00043 #include <kaction.h>
00044 #include <kglobal.h>
00045 #include <klocale.h>
00046 #include <ktoggleaction.h>
00047 #include <kactionmenu.h>
00048 #include <kstdaction.h>
00049 #include <kstdaccel.h>
00050 #include <kaccelgen.h>
00051
00052 namespace KPlato
00053 {
00054
00055 EnumDelegate::EnumDelegate( QObject *parent )
00056 : QItemDelegate( parent )
00057 {
00058 }
00059
00060 QWidget *EnumDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const
00061 {
00062 QComboBox *editor = new QComboBox(parent);
00063 editor->installEventFilter(const_cast<EnumDelegate*>(this));
00064 return editor;
00065 }
00066
00067 void EnumDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
00068 {
00069 QStringList lst = index.model()->data( index, Role::EnumList ).toStringList();
00070 int value = index.model()->data(index, Role::EnumListValue).toInt();
00071
00072 QComboBox *box = static_cast<QComboBox*>(editor);
00073 box->addItems( lst );
00074 box->setCurrentIndex( value );
00075 }
00076
00077 void EnumDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
00078 const QModelIndex &index) const
00079 {
00080 QComboBox *box = static_cast<QComboBox*>(editor);
00081 int value = box->currentIndex();
00082 model->setData( index, value, Qt::EditRole );
00083 }
00084
00085 void EnumDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &) const
00086 {
00087 kDebug()<<k_funcinfo<<editor<<": "<<option.rect<<", "<<editor->sizeHint()<<endl;
00088 QRect r = option.rect;
00089
00090 editor->setGeometry(r);
00091 }
00092
00093
00094 ItemModelBase::ItemModelBase( Part *part, QObject *parent )
00095 : QAbstractItemModel( parent ),
00096 m_part(part),
00097 m_project(0),
00098 m_readWrite( part->isReadWrite() )
00099 {
00100 }
00101
00102 ItemModelBase::~ItemModelBase()
00103 {
00104 }
00105
00106 void ItemModelBase::setProject( Project *project )
00107 {
00108 m_project = project;
00109 }
00110
00111 void ItemModelBase::slotLayoutChanged()
00112 {
00113 kDebug()<<k_funcinfo<<endl;
00114 emit layoutChanged();
00115 }
00116
00117 void ItemModelBase::slotLayoutToBeChanged()
00118 {
00119 kDebug()<<k_funcinfo<<endl;
00120 emit layoutAboutToBeChanged();
00121 }
00122
00123
00124 NodeItemModel::NodeItemModel( Part *part, QObject *parent )
00125 : ItemModelBase( part, parent )
00126 {
00127 }
00128
00129 NodeItemModel::~NodeItemModel()
00130 {
00131 }
00132
00133 void NodeItemModel::setProject( Project *project )
00134 {
00135 if ( m_project ) {
00136 disconnect( m_project, SIGNAL( nodeChanged( Node* ) ), this, SLOT( slotNodeChanged( Node* ) ) );
00137 disconnect( m_project, SIGNAL( nodeToBeAdded( Node* ) ), this, SLOT( slotLayoutToBeChanged() ) );
00138 disconnect( m_project, SIGNAL( nodeToBeRemoved( Node* ) ), this, SLOT( slotLayoutToBeChanged() ) );
00139 disconnect( m_project, SIGNAL( nodeToBeMoved( Node* ) ), this, SLOT( slotLayoutToBeChanged() ) );
00140
00141 disconnect( m_project, SIGNAL( nodeAdded( Node* ) ), this, SLOT( slotLayoutChanged() ) );
00142 disconnect( m_project, SIGNAL( nodeRemoved( Node* ) ), this, SLOT( slotLayoutChanged() ) );
00143 disconnect( m_project, SIGNAL( nodeMoved( Node* ) ), this, SLOT( slotLayoutChanged() ) );
00144 }
00145 m_project = project;
00146 connect( m_project, SIGNAL( nodeChanged( Node* ) ), this, SLOT( slotNodeChanged( Node* ) ) );
00147
00148 connect( m_project, SIGNAL( nodeToBeAdded( Node* ) ), this, SLOT( slotLayoutToBeChanged() ) );
00149 connect( m_project, SIGNAL( nodeToBeRemoved( Node* ) ), this, SLOT( slotLayoutToBeChanged() ) );
00150 connect( m_project, SIGNAL( nodeToBeMoved( Node* ) ), this, SLOT( slotLayoutToBeChanged() ) );
00151
00152 connect( m_project, SIGNAL( nodeAdded( Node* ) ), this, SLOT( slotLayoutChanged() ) );
00153 connect( m_project, SIGNAL( nodeRemoved( Node* ) ), this, SLOT( slotLayoutChanged() ) );
00154 connect( m_project, SIGNAL( nodeMoved( Node* ) ), this, SLOT( slotLayoutChanged() ) );
00155 }
00156
00157 Qt::ItemFlags NodeItemModel::flags( const QModelIndex &index ) const
00158 {
00159 Qt::ItemFlags flags = QAbstractItemModel::flags( index );
00160 if ( !index.isValid() )
00161 return flags;
00162 if ( !m_readWrite ) {
00163 flags &= ~Qt::ItemIsEditable;
00164 } else {
00165 switch ( index.column() ) {
00166 case 1: break;
00167 case 4: {
00168 Node *n = node( index );
00169 if ( n == 0 )
00170 break;
00171 int c = n->constraint();
00172 if ( c == Node::MustStartOn || c == Node::StartNotEarlier || c == Node::FixedInterval ) {
00173 flags |= Qt::ItemIsEditable;
00174 }
00175 break;
00176 }
00177 case 5: {
00178 Node *n = node( index );
00179 if ( n == 0 )
00180 break;
00181 int c = n->constraint();
00182 if ( c == Node::MustFinishOn || c == Node::FinishNotLater || c == Node::FixedInterval ) {
00183 flags |= Qt::ItemIsEditable;
00184 }
00185 break;
00186 }
00187 default: flags |= Qt::ItemIsEditable;
00188 }
00189 }
00190 return flags;
00191 }
00192
00193
00194 QModelIndex NodeItemModel::parent( const QModelIndex &index ) const
00195 {
00196 if ( !index.isValid() ) {
00197 return QModelIndex();
00198 }
00199
00200 Node *p = node( index )->getParent();
00201 if ( p == 0 || p->type() == Node::Type_Project ) {
00202 return QModelIndex();
00203 }
00204 int row = p->getParent()->findChildNode( p );
00205 return createIndex( row, 0, p );
00206 }
00207
00208 bool NodeItemModel::hasChildren( const QModelIndex &parent ) const
00209 {
00210 Node *p = node( parent );
00211 return p->numChildren() > 0;
00212 }
00213
00214 QModelIndex NodeItemModel::index( int row, int column, const QModelIndex &parent ) const
00215 {
00216 if ( m_project == 0 || column < 0 || column >= columnCount() || row < 0 ) {
00217 return QModelIndex();
00218 }
00219 Node *p = node( parent );
00220 if ( row >= p->numChildren() ) {
00221 return QModelIndex();
00222 }
00223
00224 Node *n = p->childNode( row );
00225
00226 return createIndex(row, column, n);
00227 }
00228
00229 int NodeItemModel::columnCount( const QModelIndex &parent ) const
00230 {
00231 return 8;
00232 }
00233
00234 int NodeItemModel::rowCount( const QModelIndex &parent ) const
00235 {
00236 Node *p = node( parent );
00237 return p->numChildren();
00238 }
00239
00240 bool NodeItemModel::insertRows( int row, int count, const QModelIndex &parent )
00241 {
00242
00243 return false;
00244 }
00245
00246 bool NodeItemModel::removeRows( int row, int count, const QModelIndex &parent )
00247 {
00248
00249 return false;
00250 }
00251
00252 QVariant NodeItemModel::name( const Node *node, int role ) const
00253 {
00254 switch ( role ) {
00255 case Qt::DisplayRole:
00256 case Qt::EditRole:
00257 case Qt::ToolTipRole:
00258 return node->name();
00259 case Qt::StatusTipRole:
00260 case Qt::WhatsThisRole:
00261 return QVariant();
00262 }
00263 return QVariant();
00264 }
00265
00266 bool NodeItemModel::setName( Node *node, const QVariant &value, int role )
00267 {
00268 switch ( role ) {
00269 case Qt::EditRole:
00270 m_part->addCommand( new NodeModifyNameCmd( m_part, *node, value.toString(), "Modify task name" ) );
00271 return true;
00272 }
00273 return false;
00274 }
00275
00276 QVariant NodeItemModel::leader( const Node *node, int role ) const
00277 {
00278 switch ( role ) {
00279 case Qt::DisplayRole:
00280 case Qt::EditRole:
00281 case Qt::ToolTipRole:
00282 return node->leader();
00283 case Qt::StatusTipRole:
00284 case Qt::WhatsThisRole:
00285 return QVariant();
00286 }
00287 return QVariant();
00288 }
00289
00290 bool NodeItemModel::setLeader( Node *node, const QVariant &value, int role )
00291 {
00292 switch ( role ) {
00293 case Qt::EditRole:
00294 m_part->addCommand( new NodeModifyLeaderCmd( m_part, *node, value.toString(), "Modify task responsible" ) );
00295 return true;
00296 }
00297 return false;
00298 }
00299
00300 QVariant NodeItemModel::description( const Node *node, int role ) const
00301 {
00302 switch ( role ) {
00303 case Qt::DisplayRole:
00304 case Qt::EditRole:
00305 case Qt::ToolTipRole:
00306 return node->description();
00307 case Qt::StatusTipRole:
00308 case Qt::WhatsThisRole:
00309 return QVariant();
00310 }
00311 return QVariant();
00312 }
00313
00314 bool NodeItemModel::setDescription( Node *node, const QVariant &value, int role )
00315 {
00316 switch ( role ) {
00317 case Qt::EditRole:
00318 m_part->addCommand( new NodeModifyDescriptionCmd( m_part, *node, value.toString(), "Modify task description" ) );
00319 return true;
00320 }
00321 return false;
00322 }
00323
00324 QVariant NodeItemModel::type( const Node *node, int role ) const
00325 {
00326 switch ( role ) {
00327 case Qt::DisplayRole:
00328 case Qt::EditRole:
00329 case Qt::ToolTipRole:
00330 return node->typeToString( true );
00331 case Qt::TextAlignmentRole:
00332 return Qt::AlignRight;
00333 case Qt::StatusTipRole:
00334 case Qt::WhatsThisRole:
00335 return QVariant();
00336 }
00337 return QVariant();
00338 }
00339
00340 bool NodeItemModel::setType( Node *, const QVariant &, int )
00341 {
00342 return false;
00343 }
00344
00345 QVariant NodeItemModel::constraint( const Node *node, int role ) const
00346 {
00347 switch ( role ) {
00348 case Qt::DisplayRole:
00349 case Qt::EditRole:
00350 case Qt::ToolTipRole:
00351 return node->constraintToString( true );
00352 case Role::EnumList:
00353 return Node::constraintList( true );
00354 case Role::EnumListValue:
00355 return (int)node->constraint();
00356 case Qt::TextAlignmentRole:
00357 return Qt::AlignCenter;
00358 case Qt::StatusTipRole:
00359 case Qt::WhatsThisRole:
00360 return QVariant();
00361 }
00362 return QVariant();
00363 }
00364 bool NodeItemModel::setConstraint( Node *node, const QVariant &value, int role )
00365 {
00366 switch ( role ) {
00367 case Qt::EditRole:
00368 Node::ConstraintType v = Node::ConstraintType( value.toInt() );
00369 kDebug()<<k_funcinfo<<v<<endl;
00370 m_part->addCommand( new NodeModifyConstraintCmd( m_part, *node, v, "Modify constraint type" ) );
00371 return true;
00372 }
00373 return false;
00374 }
00375
00376 QVariant NodeItemModel::constraintStartTime( const Node *node, int role ) const
00377 {
00378 switch ( role ) {
00379 case Qt::DisplayRole: {
00380 int c = node->constraint();
00381 if ( ! ( c == Node::MustStartOn || c == Node::StartNotEarlier || c == Node::FixedInterval ) ) {
00382 return " ";
00383 }
00384 return KGlobal::locale()->formatDateTime( node->constraintStartTime() );
00385 }
00386 case Qt::ToolTipRole: {
00387 int c = node->constraint();
00388 if ( ! ( c == Node::MustStartOn || c == Node::StartNotEarlier || c == Node::FixedInterval ) ) {
00389 return QVariant();
00390 }
00391 return KGlobal::locale()->formatDateTime( node->constraintStartTime() );
00392 }
00393 case Qt::EditRole: {
00394 int c = node->constraint();
00395 if ( c == Node::MustStartOn || c == Node::StartNotEarlier || c == Node::FixedInterval ) {
00396 return node->constraintStartTime();
00397 }
00398 break;
00399 }
00400 case Qt::StatusTipRole:
00401 case Qt::WhatsThisRole:
00402 return QVariant();
00403 }
00404 return QVariant();
00405 }
00406
00407 bool NodeItemModel::setConstraintStartTime( Node *node, const QVariant &value, int role )
00408 {
00409 switch ( role ) {
00410 case Qt::EditRole:
00411 m_part->addCommand( new NodeModifyConstraintStartTimeCmd( m_part, *node, value.toDateTime(), "Modify constraint start time" ) );
00412 return true;
00413 }
00414 return false;
00415 }
00416
00417 QVariant NodeItemModel::constraintEndTime( const Node *node, int role ) const
00418 {
00419 switch ( role ) {
00420 case Qt::DisplayRole: {
00421 int c = node->constraint();
00422 if ( ! ( c == Node::FinishNotLater || c == Node::MustFinishOn || c == Node::FixedInterval ) ) {
00423 return " ";
00424 }
00425 return KGlobal::locale()->formatDateTime( node->constraintEndTime() );
00426 }
00427 case Qt::ToolTipRole: {
00428 int c = node->constraint();
00429 if ( ! ( c == Node::FinishNotLater || c == Node::MustFinishOn || c == Node::FixedInterval ) ) {
00430 return QVariant();
00431 }
00432 return KGlobal::locale()->formatDateTime( node->constraintEndTime() );
00433 }
00434 case Qt::EditRole: {
00435 int c = node->constraint();
00436 if ( c == Node::FinishNotLater || c == Node::MustFinishOn || c == Node::FixedInterval ) {
00437 return node->constraintEndTime();
00438 }
00439 break;
00440 }
00441 case Qt::StatusTipRole:
00442 case Qt::WhatsThisRole:
00443 return QVariant();
00444 }
00445 return QVariant();
00446 }
00447
00448 bool NodeItemModel::setConstraintEndTime( Node *node, const QVariant &value, int role )
00449 {
00450 switch ( role ) {
00451 case Qt::EditRole:
00452 m_part->addCommand( new NodeModifyConstraintEndTimeCmd( m_part, *node, value.toDateTime(), "Modify constraint end time" ) );
00453 return true;
00454 }
00455 return false;
00456 }
00457
00458 QVariant NodeItemModel::estimateType( const Node *node, int role ) const
00459 {
00460 switch ( role ) {
00461 case Qt::DisplayRole:
00462 case Qt::EditRole:
00463 case Qt::ToolTipRole:
00464 return node->effort()->typeToString( true );
00465 case Role::EnumList:
00466 return Effort::typeToStringList( true );
00467 case Role::EnumListValue:
00468 return (int)node->effort()->type();
00469 case Qt::StatusTipRole:
00470 case Qt::WhatsThisRole:
00471 return QVariant();
00472 }
00473 return QVariant();
00474 }
00475
00476 bool NodeItemModel::setEstimateType( Node *node, const QVariant &value, int role )
00477 {
00478 switch ( role ) {
00479 case Qt::EditRole:
00480 Effort::Type v = Effort::Type( value.toInt() );
00481 m_part->addCommand( new ModifyEffortTypeCmd( m_part, *node, node->effort()->type(), v, "Modify estimate type" ) );
00482 return true;
00483 }
00484 return false;
00485 }
00486
00487 QVariant NodeItemModel::data( const QModelIndex &index, int role ) const
00488 {
00489 QVariant result;
00490 Node *n = node( index );
00491 if ( n != 0 ) {
00492 switch ( index.column() ) {
00493 case 0: result = name( n, role ); break;
00494 case 1: result = type( n, role ); break;
00495 case 2: result = leader( n, role ); break;
00496 case 3: result = constraint( n, role ); break;
00497 case 4: result = constraintStartTime( n, role ); break;
00498 case 5: result = constraintEndTime( n, role ); break;
00499 case 6: result = estimateType( n, role ); break;
00500 case 7: result = description( n, role ); break;
00501 default:
00502 kDebug()<<k_funcinfo<<"data: invalid display value column "<<index.column()<<endl;;
00503 return QVariant();
00504 }
00505 if ( result.isValid() ) {
00506 if ( result.type() == QVariant::String && result.toString().isEmpty()) {
00507
00508 result = " ";
00509 }
00510 return result;
00511 }
00512 }
00513
00514
00515 return QVariant();
00516 }
00517
00518 bool NodeItemModel::setData( const QModelIndex &index, const QVariant &value, int role )
00519 {
00520 if ( ( flags(index) &Qt::ItemIsEditable ) == 0 || role != Qt::EditRole ) {
00521 return false;
00522 }
00523 Node *n = node( index );
00524 switch (index.column()) {
00525 case 0: return setName( n, value, role );
00526 case 1: return setType( n, value, role );
00527 case 2: return setLeader( n, value, role );
00528 case 3: return setConstraint( n, value, role );
00529 case 4: return setConstraintStartTime( n, value, role );
00530 case 5: return setConstraintEndTime( n, value, role );
00531 case 6: return setEstimateType( n, value, role );
00532 case 7: return setDescription( n, value, role );
00533 default:
00534 qWarning("data: invalid display value column %d", index.column());
00535 return false;
00536 }
00537 return false;
00538 }
00539
00540 QVariant NodeItemModel::headerData( int section, Qt::Orientation orientation, int role ) const
00541 {
00542 if ( orientation == Qt::Horizontal ) {
00543 if ( role == Qt::DisplayRole ) {
00544 switch ( section ) {
00545 case 0: return i18n( "Name" );
00546 case 1: return i18n( "Type" );
00547 case 2: return i18n( "Responsible" );
00548 case 3: return i18n( "Constraint" );
00549 case 4: return i18n( "Constraint Start" );
00550 case 5: return i18n( "Constraint End" );
00551 case 6: return i18n( "Estimate" );
00552 case 7: return i18n( "Description" );
00553 default: return QVariant();
00554 }
00555 } else if ( role == Qt::TextAlignmentRole ) {
00556 switch (section) {
00557 case 1: return Qt::AlignCenter;
00558 default: return QVariant();
00559 }
00560 }
00561 }
00562 if ( role == Qt::ToolTipRole ) {
00563 switch ( section ) {
00564 case 0: return ToolTip::NodeName;
00565 case 1: return ToolTip::NodeType;
00566 case 2: return ToolTip::NodeResponsible;
00567 case 3: return ToolTip::NodeConstraint;
00568 case 4: return ToolTip::NodeConstraintStart;
00569 case 5: return ToolTip::NodeConstraintEnd;
00570 case 6: return ToolTip::NodeEstimateType;
00571 case 7: return ToolTip::NodeDescription;
00572 default: return QVariant();
00573 }
00574 }
00575 return ItemModelBase::headerData(section, orientation, role);
00576 }
00577
00578 void NodeItemModel::sort( int column, Qt::SortOrder order )
00579 {
00580 }
00581
00582 QMimeData * NodeItemModel::mimeData( const QModelIndexList &indexes ) const
00583 {
00584 return 0;
00585 }
00586
00587 QStringList NodeItemModel::mimeTypes () const
00588 {
00589 return QStringList();
00590 }
00591
00592 Node *NodeItemModel::node( const QModelIndex &index ) const
00593 {
00594 Node *n = m_project;
00595 if ( index.isValid() ) {
00596 if ( index.internalPointer() == 0 ) {
00597
00598 }
00599
00600 n = static_cast<Node*>( index.internalPointer() );
00601 Q_ASSERT( n );
00602 }
00603 return n;
00604 }
00605
00606 void NodeItemModel::slotNodeChanged( Node *node )
00607 {
00608 int row = node->getParent()->findChildNode( node );
00609 emit dataChanged( createIndex( row, 0, node ), createIndex( row, columnCount(), node ) );
00610 }
00611
00612
00613 NodeTreeView::NodeTreeView( Part *part, QWidget *parent )
00614 : QTreeView( parent ),
00615 m_arrowKeyNavigation( true )
00616 {
00617 header()->setContextMenuPolicy( Qt::CustomContextMenu );
00618 setModel( new NodeItemModel( part ) );
00619 setSelectionModel( new QItemSelectionModel( model() ) );
00620
00621 setSelectionMode( QAbstractItemView::ExtendedSelection );
00622
00623 setItemDelegateForColumn( 3, new EnumDelegate( this ) );
00624 setItemDelegateForColumn( 6, new EnumDelegate( this ) );
00625
00626 connect( header(), SIGNAL( customContextMenuRequested ( const QPoint& ) ), this, SLOT( headerContextMenuRequested( const QPoint& ) ) );
00627 connect( this, SIGNAL( activated ( const QModelIndex ) ), this, SLOT( slotActivated( const QModelIndex ) ) );
00628
00629 }
00630
00631 void NodeTreeView::slotActivated( const QModelIndex index )
00632 {
00633 kDebug()<<k_funcinfo<<index.column()<<endl;
00634 }
00635
00636 void NodeTreeView::headerContextMenuRequested( const QPoint &pos )
00637 {
00638 kDebug()<<k_funcinfo<<header()->logicalIndexAt(pos)<<" at "<<pos<<endl;
00639 }
00640
00641 void NodeTreeView::selectionChanged( const QItemSelection &sel, const QItemSelection &desel )
00642 {
00643 kDebug()<<k_funcinfo<<sel.indexes().count()<<endl;
00644 foreach( QModelIndex i, selectionModel()->selectedIndexes() ) {
00645 kDebug()<<k_funcinfo<<i.row()<<", "<<i.column()<<endl;
00646 }
00647 QTreeView::selectionChanged( sel, desel );
00648 emit selectionChanged( selectionModel()->selectedIndexes() );
00649 }
00650
00651 void NodeTreeView::currentChanged( const QModelIndex & current, const QModelIndex & previous )
00652 {
00653 kDebug()<<k_funcinfo<<endl;
00654 QTreeView::currentChanged( current, previous );
00655 emit currentChanged( current );
00656 }
00657
00661 void NodeTreeView::keyPressEvent(QKeyEvent *event)
00662 {
00663 kDebug()<<k_funcinfo<<event->key()<<", "<<m_arrowKeyNavigation<<endl;
00664 if ( !m_arrowKeyNavigation ) {
00665 QTreeView::keyPressEvent( event );
00666 return;
00667 }
00668 QModelIndex current = currentIndex();
00669 if ( current.isValid() ) {
00670 switch (event->key()) {
00671 case Qt::Key_Right: {
00672 if ( current.column() < model()->columnCount() - 1 ) {
00673 QModelIndex i = model()->index( current.row(), current.column() + 1, current.parent() );
00674 selectionModel()->setCurrentIndex( i, QItemSelectionModel::NoUpdate );
00675 }
00676 event->accept();
00677 return;
00678 break;
00679 }
00680 case Qt::Key_Left: {
00681 if ( current.column() > 0 ) {
00682 QModelIndex i = model()->index( current.row(), current.column() - 1, current.parent() );
00683 selectionModel()->setCurrentIndex( i, QItemSelectionModel::NoUpdate );
00684 }
00685 event->accept();
00686 return;
00687 break;
00688 }
00689 case Qt::Key_Down: {
00690 QModelIndex i = indexBelow( current );
00691 if ( i.isValid() ) {
00692 i = model()->index( i.row(), current.column(), i.parent() );
00693 selectionModel()->setCurrentIndex( i, QItemSelectionModel::NoUpdate );
00694 }
00695 event->accept();
00696 return;
00697 break;
00698 }
00699 case Qt::Key_Up: {
00700 QModelIndex i = indexAbove( current );
00701 if ( i.isValid() ) {
00702 i = model()->index( i.row(), current.column(), i.parent() );
00703 selectionModel()->setCurrentIndex( i, QItemSelectionModel::NoUpdate );
00704 }
00705 event->accept();
00706 return;
00707 break;
00708 }
00709 case Qt::Key_Plus:
00710 if ( itemsExpandable()) {
00711 if ( model()->hasChildren( current ) ) {
00712 QTreeView::keyPressEvent( event );
00713
00714 selectionModel()->setCurrentIndex(current, QItemSelectionModel::NoUpdate);
00715 }
00716 event->accept();
00717 return;
00718 }
00719 break;
00720 case Qt::Key_Minus:
00721 if ( itemsExpandable() ) {
00722 if ( model()->hasChildren( current ) ) {
00723 QTreeView::keyPressEvent( event );
00724
00725 selectionModel()->setCurrentIndex(current, QItemSelectionModel::NoUpdate);
00726 }
00727 event->accept();
00728 return;
00729 }
00730 break;
00731 }
00732 }
00733 QTreeView::keyPressEvent(event);
00734 }
00735
00736 QItemSelectionModel::SelectionFlags NodeTreeView::selectionCommand(const QModelIndex &index,
00737 const QEvent *event) const
00738 {
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 return QTreeView::selectionCommand( index, event );
00756 }
00757
00758
00759 TaskEditor::TaskEditor( View *view, QWidget *parent )
00760 : ViewBase( view, parent )
00761 {
00762 setInstance(Factory::global());
00763 if ( view->getPart()->isReadWrite() ) {
00764 setXMLFile("kplato_taskeditor.rc");
00765 }
00766 setupGui();
00767
00768 QVBoxLayout * l = new QVBoxLayout( this );
00769 l->setMargin( 0 );
00770 m_editor = new NodeTreeView( view->getPart(), this );
00771 l->addWidget( m_editor );
00772 m_editor->setEditTriggers( m_editor->editTriggers() | QAbstractItemView::EditKeyPressed );
00773
00774 connect( m_editor, SIGNAL( currentChanged( QModelIndex ) ), this, SLOT ( slotCurrentChanged( QModelIndex ) ) );
00775
00776 connect( m_editor, SIGNAL( selectionChanged( const QModelIndexList ) ), this, SLOT ( slotSelectionChanged( const QModelIndexList ) ) );
00777 }
00778
00779 void TaskEditor::draw( Project &project )
00780 {
00781 m_editor->setProject( &project );
00782 }
00783
00784 void TaskEditor::draw()
00785 {
00786 }
00787
00788 void TaskEditor::setViewActive( bool activate, KXMLGUIFactory *factory )
00789 {
00790 if ( activate ) {
00791 addActions( factory );
00792 updateActionsEnabled( true );
00793 } else {
00794 removeActions();
00795 }
00796 if ( !m_editor->currentIndex().isValid() ) {
00797 m_editor->selectionModel()->setCurrentIndex(m_editor->model()->index( 0, 0 ), QItemSelectionModel::NoUpdate);
00798 }
00799 }
00800
00801 void TaskEditor::slotCurrentChanged( const QModelIndex &curr )
00802 {
00803 kDebug()<<k_funcinfo<<curr.row()<<", "<<curr.column()<<endl;
00804 slotEnableActions();
00805 }
00806
00807 void TaskEditor::slotSelectionChanged( const QModelIndexList list)
00808 {
00809 kDebug()<<k_funcinfo<<list.count()<<endl;
00810 slotEnableActions();
00811 }
00812
00813 int TaskEditor::selectedNodeCount() const
00814 {
00815 QItemSelectionModel* sm = m_editor->selectionModel();
00816 return sm->selectedRows().count();
00817 }
00818
00819 QList<Node*> TaskEditor::selectedNodes() const {
00820 QList<Node*> lst;
00821 QItemSelectionModel* sm = m_editor->selectionModel();
00822 if ( sm == 0 ) {
00823 return lst;
00824 }
00825 foreach ( QModelIndex i, sm->selectedRows() ) {
00826 Node * n = m_editor->itemModel()->node( i );
00827 if ( n != 0 && n->type() != Node::Type_Project ) {
00828 lst.append( n );
00829 }
00830 }
00831 return lst;
00832 }
00833
00834 Node *TaskEditor::selectedNode() const
00835 {
00836 QItemSelectionModel* sm = m_editor->selectionModel();
00837 if ( sm == 0 || sm->selectedRows().count() != 1 ) {
00838 return 0;
00839 }
00840 Node * n = m_editor->itemModel()->node( sm->selectedRows().first() );
00841 if ( n->type() == Node::Type_Project ) {
00842 return 0;
00843 }
00844 kDebug()<<k_funcinfo<<n->name()<<endl;
00845 return n;
00846 }
00847
00848 Node *TaskEditor::currentNode() const {
00849 Node * n = m_editor->itemModel()->node( m_editor->currentIndex() );
00850 if ( n->type() == Node::Type_Project ) {
00851 return 0;
00852 }
00853 return n;
00854 }
00855
00856 void TaskEditor::slotEnableActions()
00857 {
00858 updateActionsEnabled( true );
00859 }
00860
00861 void TaskEditor::updateActionsEnabled( bool on )
00862 {
00863 Project *p = m_editor->project();
00864
00865 bool o = ( on && p && selectedNodeCount() <= 1 );
00866 actionAddTask->setEnabled( o );
00867 actionAddMilestone->setEnabled( o );
00868
00869 actionDeleteTask->setEnabled( on && p && selectedNodeCount() > 0 );
00870
00871 o = ( on && p && selectedNodeCount() == 1 );
00872 Node *n = selectedNode();
00873
00874 actionAddSubtask->setEnabled( o );
00875 actionMoveTaskUp->setEnabled( o && p->canMoveTaskUp( n ) );
00876 actionMoveTaskDown->setEnabled( o && p->canMoveTaskDown( n ) );
00877 actionIndentTask->setEnabled( o && p->canIndentTask( n ) );
00878 actionUnindentTask->setEnabled( o && p->canUnindentTask( n ) );
00879 }
00880
00881 void TaskEditor::setupGui()
00882 {
00883 actionAddTask = new KAction( KIcon( "add_task" ), i18n( "Add Task..." ), actionCollection(), "add_task" );
00884 connect( actionAddTask, SIGNAL( triggered( bool ) ), SLOT( slotAddTask() ) );
00885 actionAddSubtask = new KAction( KIcon( "add_sub_task" ), i18n( "Add Sub-Task..." ), actionCollection(), "add_sub_task" );
00886 connect( actionAddSubtask, SIGNAL( triggered( bool ) ), SLOT( slotAddSubtask() ) );
00887 actionAddMilestone = new KAction( KIcon( "add_milestone" ), i18n( "Add Milestone..." ), actionCollection(), "add_milestone" );
00888 connect( actionAddMilestone, SIGNAL( triggered( bool ) ), SLOT( slotAddMilestone() ) );
00889 actionDeleteTask = new KAction( KIcon( "editdelete" ), i18n( "Delete Task" ), actionCollection(), "delete_task" );
00890 connect( actionDeleteTask, SIGNAL( triggered( bool ) ), SLOT( slotDeleteTask() ) );
00891
00892
00893 actionIndentTask = new KAction(KIcon("indent_task"), i18n("Indent Task"), actionCollection(), "indent_task");
00894 connect(actionIndentTask, SIGNAL(triggered(bool) ), SLOT(slotIndentTask()));
00895 actionUnindentTask = new KAction(KIcon("unindent_task"), i18n("Unindent Task"), actionCollection(), "unindent_task");
00896 connect(actionUnindentTask, SIGNAL(triggered(bool) ), SLOT(slotUnindentTask()));
00897 actionMoveTaskUp = new KAction(KIcon("move_task_up"), i18n("Move Up"), actionCollection(), "move_task_up");
00898 connect(actionMoveTaskUp, SIGNAL(triggered(bool) ), SLOT(slotMoveTaskUp()));
00899 actionMoveTaskDown = new KAction(KIcon("move_task_down"), i18n("Move Down"), actionCollection(), "move_task_down");
00900 connect(actionMoveTaskDown, SIGNAL(triggered(bool) ), SLOT(slotMoveTaskDown()));
00901
00902 }
00903
00904 void TaskEditor::slotAddTask()
00905 {
00906 kDebug()<<k_funcinfo<<endl;
00907 emit addTask();
00908 }
00909
00910 void TaskEditor::slotAddMilestone()
00911 {
00912 kDebug()<<k_funcinfo<<endl;
00913 emit addMilestone();
00914 }
00915
00916 void TaskEditor::slotAddSubtask()
00917 {
00918 kDebug()<<k_funcinfo<<endl;
00919 emit addSubtask();
00920 }
00921
00922 void TaskEditor::slotDeleteTask()
00923 {
00924 kDebug()<<k_funcinfo<<endl;
00925 emit deleteTaskList( selectedNodes() );
00926 }
00927
00928 void TaskEditor::slotIndentTask()
00929 {
00930 kDebug()<<k_funcinfo<<endl;
00931 emit indentTask();
00932 }
00933
00934 void TaskEditor::slotUnindentTask()
00935 {
00936 kDebug()<<k_funcinfo<<endl;
00937 emit unindentTask();
00938 }
00939
00940 void TaskEditor::slotMoveTaskUp()
00941 {
00942 kDebug()<<k_funcinfo<<endl;
00943 emit moveTaskUp();
00944 }
00945
00946 void TaskEditor::slotMoveTaskDown()
00947 {
00948 kDebug()<<k_funcinfo<<endl;
00949 emit moveTaskDown();
00950 }
00951
00952
00953 }
00954
00955 #include "kpttaskeditor.moc"