diff --git a/src/workpackage/taskcompletiondialog.cpp b/src/workpackage/taskcompletiondialog.cpp index 7dadf1db..66cd2788 100644 --- a/src/workpackage/taskcompletiondialog.cpp +++ b/src/workpackage/taskcompletiondialog.cpp @@ -1,488 +1,488 @@ /* This file is part of the KDE project Copyright (C) 2009, 2011, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // clazy:excludeall=qstring-arg #include "taskcompletiondialog.h" #include "workpackage.h" #include "kptusedefforteditor.h" #include "kptcommand.h" #include "kptitemmodelbase.h" #include "kptaccountsmodel.h" // FIXME hack to get at i18n'ed header text #include #include #include #include "debugarea.h" using namespace KPlato; namespace KPlatoWork { TaskCompletionDialog::TaskCompletionDialog(WorkPackage &p, ScheduleManager *sm, QWidget *parent) : KoDialog(parent) { setCaption( i18n("Task Progress") ); setButtons( Ok|Cancel ); setDefaultButton( Ok ); showButtonSeparator( true ); m_panel = new TaskCompletionPanel( p, sm, this); setMainWidget(m_panel); enableButtonOk(false); connect(m_panel, &TaskCompletionPanel::changed, this, &TaskCompletionDialog::slotChanged); } void TaskCompletionDialog::slotChanged( bool ) { enableButtonOk( true ); } KUndo2Command *TaskCompletionDialog::buildCommand() { //debugPlanWork; return m_panel->buildCommand(); } TaskCompletionPanel::TaskCompletionPanel(WorkPackage &p, ScheduleManager *sm, QWidget *parent) : QWidget(parent), m_package( &p ) { //debugPlanWork; setupUi(this); addEntryBtn->setIcon(koIcon("list-add")); removeEntryBtn->setIcon(koIcon("list-remove")); CompletionEntryItemModel *m = new CompletionEntryItemModel( this ); entryTable->setItemDelegateForColumn ( 1, new ProgressBarDelegate( this ) ); entryTable->setItemDelegateForColumn ( 2, new DurationSpinBoxDelegate( this ) ); entryTable->setItemDelegateForColumn ( 3, new DurationSpinBoxDelegate( this ) ); entryTable->setCompletionModel( m ); Task *task = qobject_cast( p.node() ); m_completion = task->completion(); started->setChecked(m_completion.isStarted()); finished->setChecked(m_completion.isFinished()); startTime->setDateTime(m_completion.startTime()); finishTime->setDateTime(m_completion.finishTime()); finishTime->setMinimumDateTime( qMax( startTime->dateTime(), QDateTime(m_completion.entryDate(), QTime(), Qt::LocalTime) ) ); scheduledEffort = p.node()->estimate()->expectedValue(); if ( m_completion.usedEffortMap().isEmpty() || task->requests().isEmpty() ) { foreach ( ResourceGroupRequest *g, task->requests().requests() ) { foreach ( ResourceRequest *r, g->resourceRequests() ) { m_completion.addUsedEffort( r->resource() ); } } } enableWidgets(); started->setFocus(); m->setManager( sm ); m->setTask( task ); Resource *r = p.project()->findResource( task->workPackage().ownerId() ); - m->setSource( r, task ); + m->setSource( r, task, &m_completion ); entryTable->horizontalHeader()->swapSections( CompletionEntryItemModel::Property_PlannedEffort, CompletionEntryItemModel::Property_ActualAccumulated ); //FIXME when string freeze is lifted Duration pr = task->plannedEffort( r ); Duration tr = task->plannedEffort(); if ( pr == tr ) { ui_plannedFrame->hide(); } else { ui_plannedLabel->setText( m->headerData( CompletionEntryItemModel::Property_PlannedEffort, Qt::Horizontal ).toString() ); ui_labelResource->setText( r->name() ); ui_plannedResource->setText( pr.format() ); ui_labelTask->setText( Node::typeToString( Node::Type_Task, true ) ); ui_plannedTask->setText( tr.format() ); } if ( m->rowCount() > 0 ) { QModelIndex idx = m->index( m->rowCount() -1, 0 ); entryTable->scrollTo( idx ); } connect( addEntryBtn, &QAbstractButton::clicked, this, &TaskCompletionPanel::slotAddEntry ); connect( removeEntryBtn, &QAbstractButton::clicked, entryTable, &KPlato::CompletionEntryEditor::removeEntry ); connect( entryTable, &KPlato::CompletionEntryEditor::rowInserted, this, &TaskCompletionPanel::slotEntryAdded ); connect(entryTable, &KPlato::CompletionEntryEditor::changed, this, &TaskCompletionPanel::slotChanged ); connect(entryTable, &KPlato::CompletionEntryEditor::changed, this, &TaskCompletionPanel::slotEntryChanged ); connect(entryTable, &KPlato::CompletionEntryEditor::rowInserted, this, &TaskCompletionPanel::slotChanged ); connect(entryTable, &KPlato::CompletionEntryEditor::rowInserted, this, &TaskCompletionPanel::slotEntryChanged ); connect(entryTable, &KPlato::CompletionEntryEditor::rowRemoved, this, &TaskCompletionPanel::slotEntryChanged ); connect(entryTable, &KPlato::CompletionEntryEditor::selectedItemsChanged, this, &TaskCompletionPanel::slotSelectionChanged ); connect(started, &QAbstractButton::toggled, this, &TaskCompletionPanel::slotStartedChanged); connect(started, &QAbstractButton::toggled, this, &TaskCompletionPanel::slotChanged); connect(finished, &QAbstractButton::toggled, this, &TaskCompletionPanel::slotFinishedChanged); connect(finished, &QAbstractButton::toggled, this, &TaskCompletionPanel::slotChanged); connect(startTime, &QDateTimeEdit::dateTimeChanged, this, &TaskCompletionPanel::slotChanged); connect(startTime, &QDateTimeEdit::dateTimeChanged, this, &TaskCompletionPanel::slotStartTimeChanged); connect(finishTime, &QDateTimeEdit::dateTimeChanged, this, &TaskCompletionPanel::slotChanged); connect(finishTime, &QDateTimeEdit::dateTimeChanged, this, &TaskCompletionPanel::slotFinishTimeChanged); removeEntryBtn->setEnabled( false ); } QSize TaskCompletionPanel::sizeHint() const { return QWidget::sizeHint().expandedTo( QSize( 610, 0 ) ); } KUndo2Command *TaskCompletionPanel::buildCommand() { MacroCommand *cmd = new MacroCommand( kundo2_i18n("Modify task completion") ); Completion &org = m_package->task()->completion(); if ( org.entrymode() != m_completion.entrymode() ) { cmd->addCommand( new ModifyCompletionEntrymodeCmd(org, m_completion.entrymode() ) ); } if ( org.isStarted() != m_completion.isStarted() ) { cmd->addCommand( new ModifyCompletionStartedCmd(org, m_completion.isStarted() ) ); } if ( org.isFinished() != m_completion.isFinished() ) { cmd->addCommand( new ModifyCompletionFinishedCmd(org, m_completion.isFinished() ) ); } if ( org.startTime() != m_completion.startTime() ) { cmd->addCommand( new ModifyCompletionStartTimeCmd(org, m_completion.startTime() ) ); } if ( org.finishTime() != m_completion.finishTime() ) { cmd->addCommand( new ModifyCompletionFinishTimeCmd(org, m_completion.finishTime() ) ); } QList orgdates = org.entries().keys(); QList m_completiondates = m_completion.entries().keys(); foreach ( const QDate &d, orgdates ) { if ( m_completiondates.contains( d ) ) { if ( m_completion.entry( d ) == org.entry( d ) ) { continue; } Completion::Entry *e = new Completion::Entry( *( m_completion.entry( d ) ) ); cmd->addCommand( new ModifyCompletionEntryCmd(org, d, e ) ); } else { cmd->addCommand( new RemoveCompletionEntryCmd(org, d ) ); } } foreach ( const QDate &d, m_completiondates ) { if ( ! orgdates.contains( d ) ) { Completion::Entry *e = new Completion::Entry( * ( m_completion.entry( d ) ) ); cmd->addCommand( new AddCompletionEntryCmd(org, d, e ) ); } } if ( cmd->isEmpty() ) { delete cmd; return 0; } return cmd; } void TaskCompletionPanel::slotChanged() { emit changed( true ); //FIXME } void TaskCompletionPanel::slotStartedChanged(bool state) { m_completion.setStarted( state ); if (state) { m_completion.setStartTime( QDateTime::currentDateTime() ); startTime->setDateTime( m_completion.startTime() ); slotCalculateEffort(); } enableWidgets(); } void TaskCompletionPanel::setFinished() { finishTime->setDateTime( QDateTime::currentDateTime() ); slotFinishTimeChanged( finishTime->dateTime() ); } void TaskCompletionPanel::slotFinishedChanged(bool state) { debugPlanWork<node()->plannedEffort() ); m_completion.addEntry( m_completion.finishTime().date(), e ); entryTable->setCompletion( &m_completion ); debugPlanWork<<"Entry added:"<model()->rowCount() - 1; QModelIndex idx = entryTable->model()->index( row, CompletionEntryItemModel::Property_Completion ); entryTable->model()->setData( idx, 100 ); } } enableWidgets(); } void TaskCompletionPanel::slotFinishTimeChanged( const QDateTime &dt ) { m_completion.setFinishTime( dt ); } void TaskCompletionPanel::slotStartTimeChanged( const QDateTime &dt ) { m_completion.setStartTime( dt ); finishTime->setMinimumDateTime( qMax( startTime->dateTime(), QDateTime(m_completion.entryDate(), QTime(), Qt::LocalTime) ) ); } void TaskCompletionPanel::slotAddEntry() { CompletionEntryItemModel *m = static_cast( entryTable->model() ); int col = KPlato::CompletionEntryItemModel::Property_UsedEffort; entryTable->addEntry(); m_completion.setEntrymode( Completion::EnterEffortPerTask ); m->setFlags( col, Qt::ItemIsEditable ); } void TaskCompletionPanel::slotEntryChanged() { finishTime->setMinimumDateTime( qMax( startTime->dateTime(), QDateTime(m_completion.entryDate(), QTime(), Qt::LocalTime) ) ); if ( ! finished->isChecked() && ! m_completion.isFinished() && m_completion.percentFinished() == 100 ) { finished->setChecked( true ); } } void TaskCompletionPanel::enableWidgets() { started->setEnabled(!finished->isChecked()); finished->setEnabled(started->isChecked()); finishTime->setEnabled(finished->isChecked()); startTime->setEnabled(started->isChecked() && !finished->isChecked()); } void TaskCompletionPanel::slotPercentFinishedChanged( int ) { slotCalculateEffort(); } void TaskCompletionPanel::slotCalculateEffort() { } void TaskCompletionPanel::slotEntryAdded( const QDate& date ) { debugPlanWork<setEnabled( !sel.isEmpty() ); } void TaskCompletionPanel::slotEditmodeChanged( int index ) { Q_UNUSED( index ); } //------------------- CompletionEntryItemModel::CompletionEntryItemModel( QObject *parent ) : KPlato::CompletionEntryItemModel( parent ), m_calculate( false ), m_resource( 0 ), m_task( 0 ) { // FIXME after string freeze is lifted CostBreakdownItemModel m; m_headers << m.headerData( 2, Qt::Horizontal ).toString(); } -void CompletionEntryItemModel::setSource( Resource *resource, Task *task ) +void CompletionEntryItemModel::setSource( Resource *resource, Task *task, Completion *completion ) { m_resource = resource; m_task = task; - setCompletion( &(task->completion()) ); + setCompletion( completion ? completion : &(task->completion()) ); } int CompletionEntryItemModel::columnCount( const QModelIndex& ) const { return 6; } QVariant CompletionEntryItemModel::actualEffort ( int row, int role ) const { Completion::Entry *e = m_completion->entry( date( row ).toDate() ); if ( e == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: { Duration v = e->totalPerformed; if ( row > 0 ) { v -= m_completion->entry( date( row - 1 ).toDate() )->totalPerformed; } //debugPlanWork<name()<<": "<totalPerformed; if ( row > 0 ) { v -= m_completion->entry( date( row - 1 ).toDate() )->totalPerformed; } //debugPlanWork<name()<<": "<( Duration::Unit_h ); case Role::Minimum: return static_cast( Duration::Unit_h ); case Role::Maximum: return static_cast( Duration::Unit_h ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); default: break; } return QVariant(); } QVariant CompletionEntryItemModel::data( const QModelIndex &idx, int role ) const { if ( idx.column() == Property_PlannedEffort && m_resource ) { switch ( role ) { case Qt::DisplayRole: { Duration v = m_task->plannedEffortTo( m_resource, date( idx.row() ).toDate() ); return v.format(); } default: return QVariant(); } } else if ( idx.column() == Property_ActualAccumulated ) { switch ( role ) { case Qt::DisplayRole: { Duration v; Completion::Entry *e = m_completion->entry( date( idx.row() ).toDate() ); if ( e ) { v = e->totalPerformed; } return v.format(); } default: return QVariant(); } } return KPlato::CompletionEntryItemModel::data( idx, role ); } bool CompletionEntryItemModel::setData( const QModelIndex &idx, const QVariant &value, int role ) { //debugPlanWork; switch ( role ) { case Qt::EditRole: { if ( idx.column() == Property_Date ) { QDate od = date( idx.row() ).toDate(); removeEntry( od ); addEntry( value.toDate() ); // emit dataChanged( idx, idx ); m_calculate = true; return true; } if ( idx.column() == Property_Completion ) { Completion::Entry *e = m_completion->entry( date( idx.row() ).toDate() ); if ( e == 0 ) { return false; } e->percentFinished = value.toInt(); if ( m_calculate && m_node && idx.row() == rowCount() - 1 ) { // calculate used/remaining Duration est = m_node->plannedEffort( id(), ECCT_EffortWork ); e->totalPerformed = est * e->percentFinished / 100; e->remainingEffort = est - e->totalPerformed; } else if ( e->percentFinished == 100 && e->remainingEffort != 0 ) { e->remainingEffort = Duration::zeroDuration; } emit dataChanged( idx, createIndex( idx.row(), 3 ) ); return true; } if ( idx.column() == Property_ActualEffort ) { Completion::Entry *e = m_completion->entry( date( idx.row() ).toDate() ); if ( e == 0 ) { return false; } m_calculate = false; Duration prev; if ( idx.row() > 0 ) { Completion::Entry *pe = m_completion->entry( date( idx.row() - 1 ).toDate() ); if ( pe ) { prev = pe->totalPerformed; } } double v( value.toList()[0].toDouble() ); Duration::Unit unit = static_cast( value.toList()[1].toInt() ); Duration d = Estimate::scale( v, unit, scales() ); if ( d + prev == e->totalPerformed ) { return false; } e->totalPerformed = d + prev; emit dataChanged( idx, idx ); return true; } if ( idx.column() == Property_RemainigEffort ) { Completion::Entry *e = m_completion->entry( date( idx.row() ).toDate() ); if ( e == 0 ) { return false; } m_calculate = false; double v( value.toList()[0].toDouble() ); Duration::Unit unit = static_cast( value.toList()[1].toInt() ); Duration d = Estimate::scale( v, unit, scales() ); if ( d == e->remainingEffort ) { return false; } e->remainingEffort = d; debugPlanWork<remainingEffort.format(); emit dataChanged( idx, idx ); return true; } break; } default: break; } return false; } } //KPlatoWork namespace diff --git a/src/workpackage/taskcompletiondialog.h b/src/workpackage/taskcompletiondialog.h index a456dcc0..31ccffb0 100644 --- a/src/workpackage/taskcompletiondialog.h +++ b/src/workpackage/taskcompletiondialog.h @@ -1,136 +1,136 @@ /* This file is part of the KDE project Copyright (C) 2009, 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KPLATOWORK_TASKCOMPLETIONDIALOG_H #define KPLATOWORK_TASKCOMPLETIONDIALOG_H #include "planwork_export.h" #include "ui_taskcompletionpanel.h" #include "workpackage.h" #include "kptusedefforteditor.h" #include #include class KUndo2Command; namespace KPlato { class ScheduleManager; } namespace KPlatoWork { class TaskCompletionPanel; class PLANWORK_EXPORT TaskCompletionDialog : public KoDialog { Q_OBJECT public: explicit TaskCompletionDialog( WorkPackage &p, ScheduleManager *sm, QWidget *parent=0 ); KUndo2Command *buildCommand(); protected Q_SLOTS: void slotChanged( bool ); private: TaskCompletionPanel *m_panel; }; class PLANWORK_EXPORT TaskCompletionPanel : public QWidget, public Ui::TaskCompletionPanel { Q_OBJECT public: explicit TaskCompletionPanel( WorkPackage &p, ScheduleManager *sm, QWidget *parent=0 ); KUndo2Command *buildCommand(); void enableWidgets(); QSize sizeHint() const; Q_SIGNALS: void changed( bool ); public Q_SLOTS: void slotChanged(); void slotStartedChanged(bool state); void slotFinishedChanged(bool state); void slotPercentFinishedChanged(int value); void slotStartTimeChanged( const QDateTime &dt ); void slotFinishTimeChanged( const QDateTime &dt ); void slotAddEntry(); void slotEntryChanged(); void slotSelectionChanged( const QItemSelection &sel ); void slotEntryAdded( const QDate& date ); void slotEditmodeChanged( int ); protected Q_SLOTS: void slotCalculateEffort(); protected: void setFinished(); WorkPackage *m_package; Completion m_completion; int m_dayLength; Duration scheduledEffort; }; class CompletionEntryItemModel : public KPlato::CompletionEntryItemModel { Q_OBJECT public: enum Properties { Property_Date = KPlato::CompletionEntryItemModel::Property_Date, Property_Completion = KPlato::CompletionEntryItemModel::Property_Completion, Property_ActualEffort = KPlato::CompletionEntryItemModel::Property_UsedEffort, Property_RemainigEffort = KPlato::CompletionEntryItemModel::Property_RemainingEffort, Property_PlannedEffort = KPlato::CompletionEntryItemModel::Property_PlannedEffort, Property_ActualAccumulated }; explicit CompletionEntryItemModel(QObject *parent = 0); int columnCount( const QModelIndex &idx = QModelIndex() ) const; QVariant data( const QModelIndex &idx, int role ) const; bool setData( const QModelIndex &idx, const QVariant &value, int role ); - void setSource( Resource *resource, Task *task ); + void setSource( Resource *resource, Task *task, Completion *completion = 0 ); protected: virtual QVariant actualEffort( int row, int role ) const; private: bool m_calculate; // opens for calculating used-/remaining effort Resource *m_resource; Task *m_task; }; } //KPlatoWork namespace #endif