F:/KPlato/koffice/kplato/kpttaskeditor.cc

Aller à la documentation de ce fichier.
00001 /* This file is part of the KDE project
00002   Copyright (C) 2006 Dag Andersen <danders@get2net.dk>
00003 
00004   This library is free software; you can redistribute it and/or
00005   modify it under the terms of the GNU Library General Public
00006   License as published by the Free Software Foundation;
00007   version 2 of the License, or (at your option) any later version.
00008 
00009   This library is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012   Library General Public License for more details.
00013 
00014   You should have received a copy of the GNU Library General Public License
00015   along with this library; see the file COPYING.LIB.  If not, write to
00016   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017 * Boston, MA 02110-1301, USA.
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 &/* option */, const QModelIndex &/* index */) 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 &/* index */) const
00086 {
00087     kDebug()<<k_funcinfo<<editor<<": "<<option.rect<<", "<<editor->sizeHint()<<endl;
00088     QRect r = option.rect;
00089     //r.setHeight(r.height() + 50);
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; // Node type
00167             case 4: { // constraint start
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: { // constraint end
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     //kDebug()<<k_funcinfo<<index.internalPointer()<<": "<<index.row()<<", "<<index.column()<<endl;
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     // now get the internal pointer for the index
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     //TODO
00243     return false;
00244 }
00245 
00246 bool NodeItemModel::removeRows( int row, int count, const QModelIndex &parent )
00247 {
00248     //TODO
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 " "; //HACK to show focus
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 " "; //HACK to show focus
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                 // HACK to show focus in empty cells
00508                 result = " ";
00509             }
00510             return result;
00511         }
00512     }
00513     // define default action
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         //kDebug()<<k_funcinfo<<index.internalPointer()<<": "<<index.row()<<", "<<index.column()<<endl;
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     //setSelectionBehavior( QAbstractItemView::SelectItems );
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                         //HACK: Bug in qt??
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                         //HACK: Bug in qt??
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 /*    if ( event && event->type() == QEvent::KeyPress && selectionMode() == QAbstractItemView::ExtendedSelection ) {
00740         if ( static_cast<const QKeyEvent*>(event)->key() == Qt::Key_Space ) {
00741             Qt::KeyboardModifiers modifiers = QApplication::keyboardModifiers();
00742             QItemSelectionModel::SelectionFlags bflags = QItemSelectionModel::Rows;
00743             // 
00744             if ( modifiers && Qt::ShiftModifier ) {
00745                 return QItemSelectionModel::SelectCurrent|bflags;
00746             }
00747             // Toggle on Ctrl-Qt::Key_Space
00748             if ( modifiers & Qt::ControlModifier ) {
00749                 return QItemSelectionModel::Toggle|bflags;
00750             }
00751             // Select on Space alone
00752             return QItemSelectionModel::ClearAndSelect|bflags;
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 ) // slot
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 } // namespace KPlato
00954 
00955 #include "kpttaskeditor.moc"

Généré le Wed Nov 22 23:40:58 2006 pour KPlato par  doxygen 1.5.1-p1