1 | /* This file is part of the KDE project |
2 | Copyright (C) 2007, 2011, 2012 Dag Andersen danders@get2net> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Library General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2 of the License, or (at your option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Library General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to |
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | * Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "kptresourceappointmentsmodel.h" |
21 | |
22 | #include "kptglobal.h" |
23 | #include "kptcommonstrings.h" |
24 | #include "kptappointment.h" |
25 | #include "kptcommand.h" |
26 | #include "kpteffortcostmap.h" |
27 | #include "kptitemmodelbase.h" |
28 | #include "kptcalendar.h" |
29 | #include "kptduration.h" |
30 | #include "kptnode.h" |
31 | #include "kptproject.h" |
32 | #include "kpttask.h" |
33 | #include "kptresource.h" |
34 | #include "kptdatetime.h" |
35 | #include "kptdebug.h" |
36 | |
37 | #include <QDate> |
38 | #include <QList> |
39 | #include <QObject> |
40 | #include <QStringList> |
41 | |
42 | |
43 | #include <kglobal.h> |
44 | #include <klocale.h> |
45 | |
46 | #include "kdganttglobal.h" |
47 | |
48 | |
49 | namespace KPlato |
50 | { |
51 | |
52 | ResourceAppointmentsItemModel::ResourceAppointmentsItemModel( QObject *parent ) |
53 | : ItemModelBase( parent ), |
54 | m_group( 0 ), |
55 | m_resource( 0 ), |
56 | m_showInternal( true ), |
57 | m_showExternal( true ) |
58 | { |
59 | } |
60 | |
61 | ResourceAppointmentsItemModel::~ResourceAppointmentsItemModel() |
62 | { |
63 | } |
64 | |
65 | void ResourceAppointmentsItemModel::slotResourceToBeInserted( const ResourceGroup *group, int row ) |
66 | { |
67 | kDebug(planDbg())<<group->name()<<row; |
68 | Q_ASSERT( m_group == 0 ); |
69 | m_group = const_cast<ResourceGroup*>(group); |
70 | QModelIndex i = index( group ); |
71 | beginInsertRows( i, row, row ); |
72 | } |
73 | |
74 | void ResourceAppointmentsItemModel::slotResourceInserted( const Resource *r ) |
75 | { |
76 | kDebug(planDbg())<<r->name(); |
77 | Q_ASSERT( r->parentGroup() == m_group ); |
78 | endInsertRows(); |
79 | m_group = 0; |
80 | refresh(); |
81 | connect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); |
82 | connect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); |
83 | connect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); |
84 | connect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); |
85 | connect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); |
86 | } |
87 | |
88 | void ResourceAppointmentsItemModel::slotResourceToBeRemoved( const Resource *r ) |
89 | { |
90 | kDebug(planDbg())<<r->name(); |
91 | int row = r->parentGroup()->indexOf( r ); |
92 | beginRemoveRows( index( r->parentGroup() ), row, row ); |
93 | disconnect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); |
94 | disconnect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); |
95 | disconnect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); |
96 | disconnect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); |
97 | disconnect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); |
98 | |
99 | } |
100 | |
101 | void ResourceAppointmentsItemModel::slotResourceRemoved( const Resource *resource ) |
102 | { |
103 | Q_UNUSED(resource); |
104 | //kDebug(planDbg())<<resource->name(); |
105 | endRemoveRows(); |
106 | refresh(); |
107 | } |
108 | |
109 | void ResourceAppointmentsItemModel::slotResourceGroupToBeInserted( const ResourceGroup *group, int row ) |
110 | { |
111 | //kDebug(planDbg())<<group->name()<<endl; |
112 | Q_ASSERT( m_group == 0 ); |
113 | m_group = const_cast<ResourceGroup*>(group); |
114 | beginInsertRows( QModelIndex(), row, row ); |
115 | } |
116 | |
117 | void ResourceAppointmentsItemModel::slotResourceGroupInserted( const ResourceGroup *group ) |
118 | { |
119 | //kDebug(planDbg())<<group->name()<<endl; |
120 | Q_ASSERT( group == m_group ); Q_UNUSED( group ); |
121 | endInsertRows(); |
122 | m_group = 0; |
123 | } |
124 | |
125 | void ResourceAppointmentsItemModel::slotResourceGroupToBeRemoved( const ResourceGroup *group ) |
126 | { |
127 | //kDebug(planDbg())<<group->name()<<endl; |
128 | Q_ASSERT( m_group == 0 ); |
129 | m_group = const_cast<ResourceGroup*>(group); |
130 | int row = index( group ).row(); |
131 | beginRemoveRows( QModelIndex(), row, row ); |
132 | } |
133 | |
134 | void ResourceAppointmentsItemModel::slotResourceGroupRemoved( const ResourceGroup *group ) |
135 | { |
136 | //kDebug(planDbg())<<group->name()<<endl; |
137 | Q_ASSERT( group == m_group ); Q_UNUSED( group ); |
138 | endRemoveRows(); |
139 | m_group = 0; |
140 | } |
141 | |
142 | void ResourceAppointmentsItemModel::slotAppointmentToBeInserted( Resource *r, int row ) |
143 | { |
144 | Q_UNUSED(r); |
145 | Q_UNUSED(row); |
146 | } |
147 | |
148 | void ResourceAppointmentsItemModel::slotAppointmentInserted( Resource *r, Appointment *a ) |
149 | { |
150 | Q_UNUSED(r); |
151 | Q_UNUSED(a); |
152 | refreshData(); |
153 | reset(); |
154 | } |
155 | |
156 | void ResourceAppointmentsItemModel::slotAppointmentToBeRemoved( Resource *r, int row ) |
157 | { |
158 | Q_UNUSED(r); |
159 | Q_UNUSED(row); |
160 | } |
161 | |
162 | void ResourceAppointmentsItemModel::slotAppointmentRemoved() |
163 | { |
164 | refreshData(); |
165 | reset(); |
166 | } |
167 | |
168 | void ResourceAppointmentsItemModel::slotAppointmentChanged( Resource *r, Appointment *a ) |
169 | { |
170 | int row = rowNumber( r, a ); |
171 | Q_ASSERT( row >= 0 ); |
172 | refreshData(); |
173 | emit dataChanged( createExternalAppointmentIndex( row, 0, a ), createExternalAppointmentIndex( row, columnCount() - 1, a ) ); |
174 | } |
175 | |
176 | void ResourceAppointmentsItemModel::slotProjectCalculated( ScheduleManager *sm ) |
177 | { |
178 | if ( sm == m_manager ) { |
179 | setScheduleManager( sm ); |
180 | } |
181 | } |
182 | |
183 | int ResourceAppointmentsItemModel::rowNumber( Resource *res, Appointment *a ) const |
184 | { |
185 | int r = 0; |
186 | if ( m_showInternal ) { |
187 | r = res->appointments( id() ).indexOf( a ); |
188 | if ( r > -1 ) { |
189 | return r; |
190 | } |
191 | r = res->numAppointments(); |
192 | } |
193 | if ( m_showExternal ) { |
194 | int rr = res->externalAppointmentList().indexOf( a ); |
195 | if ( rr > -1 ) { |
196 | return r + rr; |
197 | } |
198 | } |
199 | return -1; |
200 | } |
201 | |
202 | void ResourceAppointmentsItemModel::setShowInternalAppointments( bool show ) |
203 | { |
204 | if ( m_showInternal == show ) { |
205 | return; |
206 | } |
207 | m_showInternal = show; |
208 | refreshData(); |
209 | reset(); |
210 | } |
211 | |
212 | void ResourceAppointmentsItemModel::setShowExternalAppointments( bool show ) |
213 | { |
214 | if ( m_showExternal == show ) { |
215 | return; |
216 | } |
217 | m_showExternal = show; |
218 | refreshData(); |
219 | reset(); |
220 | } |
221 | |
222 | void ResourceAppointmentsItemModel::setProject( Project *project ) |
223 | { |
224 | kDebug(planDbg()); |
225 | if ( m_project ) { |
226 | disconnect( m_project, SIGNAL(resourceChanged(Resource*)), this, SLOT(slotResourceChanged(Resource*)) ); |
227 | disconnect( m_project, SIGNAL(resourceGroupChanged(ResourceGroup*)), this, SLOT(slotResourceGroupChanged(ResourceGroup*)) ); |
228 | |
229 | disconnect( m_project, SIGNAL(resourceGroupToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const ResourceGroup*,int)) ); |
230 | |
231 | disconnect( m_project, SIGNAL(resourceGroupToBeRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const ResourceGroup*)) ); |
232 | |
233 | disconnect( m_project, SIGNAL(resourceToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const ResourceGroup*,int)) ); |
234 | |
235 | disconnect( m_project, SIGNAL(resourceToBeRemoved(const Resource*)), this, SLOT(slotResourceToBeRemoved(const Resource*)) ); |
236 | |
237 | disconnect( m_project, SIGNAL(resourceGroupAdded(const ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const ResourceGroup*)) ); |
238 | |
239 | disconnect( m_project, SIGNAL(resourceGroupRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const ResourceGroup*)) ); |
240 | |
241 | disconnect( m_project, SIGNAL(resourceAdded(const Resource*)), this, SLOT(slotResourceInserted(const Resource*)) ); |
242 | |
243 | disconnect( m_project, SIGNAL(resourceRemoved(const Resource*)), this, SLOT(slotResourceRemoved(const Resource*)) ); |
244 | |
245 | disconnect( m_project, SIGNAL(defaultCalendarChanged(Calendar*)), this, SLOT(slotCalendarChanged(Calendar*)) ); |
246 | |
247 | disconnect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); |
248 | |
249 | disconnect( m_project, SIGNAL(scheduleManagerChanged(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); |
250 | |
251 | foreach ( Resource *r, m_project->resourceList() ) { |
252 | disconnect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); |
253 | disconnect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); |
254 | disconnect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); |
255 | disconnect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); |
256 | disconnect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); |
257 | } |
258 | } |
259 | m_project = project; |
260 | if ( m_project ) { |
261 | connect( m_project, SIGNAL(resourceChanged(Resource*)), this, SLOT(slotResourceChanged(Resource*)) ); |
262 | connect( m_project, SIGNAL(resourceGroupChanged(ResourceGroup*)), this, SLOT(slotResourceGroupChanged(ResourceGroup*)) ); |
263 | |
264 | connect( m_project, SIGNAL(resourceGroupToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const ResourceGroup*,int)) ); |
265 | |
266 | connect( m_project, SIGNAL(resourceGroupToBeRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const ResourceGroup*)) ); |
267 | |
268 | connect( m_project, SIGNAL(resourceToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const ResourceGroup*,int)) ); |
269 | |
270 | connect( m_project, SIGNAL(resourceToBeRemoved(const Resource*)), this, SLOT(slotResourceToBeRemoved(const Resource*)) ); |
271 | |
272 | connect( m_project, SIGNAL(resourceGroupAdded(const ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const ResourceGroup*)) ); |
273 | |
274 | connect( m_project, SIGNAL(resourceGroupRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const ResourceGroup*)) ); |
275 | |
276 | connect( m_project, SIGNAL(resourceAdded(const Resource*)), this, SLOT(slotResourceInserted(const Resource*)) ); |
277 | |
278 | connect( m_project, SIGNAL(resourceRemoved(const Resource*)), this, SLOT(slotResourceRemoved(const Resource*)) ); |
279 | |
280 | connect( m_project, SIGNAL(defaultCalendarChanged(Calendar*)), this, SLOT(slotCalendarChanged(Calendar*)) ); |
281 | |
282 | connect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); |
283 | |
284 | connect( m_project, SIGNAL(scheduleManagerChanged(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); |
285 | |
286 | foreach ( Resource *r, m_project->resourceList() ) { |
287 | connect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); |
288 | connect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); |
289 | connect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); |
290 | connect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); |
291 | connect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); |
292 | } |
293 | } |
294 | refreshData(); |
295 | reset(); |
296 | emit refreshed(); |
297 | } |
298 | |
299 | QDate ResourceAppointmentsItemModel::startDate() const |
300 | { |
301 | if ( m_project && m_manager ) { |
302 | return m_project->startTime( id() ).date(); |
303 | } |
304 | return QDate::currentDate(); |
305 | } |
306 | |
307 | QDate ResourceAppointmentsItemModel::endDate() const |
308 | { |
309 | if ( m_project && m_manager ) { |
310 | return m_project->endTime( id() ).date(); |
311 | } |
312 | return QDate::currentDate(); |
313 | } |
314 | |
315 | void ResourceAppointmentsItemModel::setScheduleManager( ScheduleManager *sm ) |
316 | { |
317 | kDebug(planDbg())<<sm; |
318 | m_manager = sm; |
319 | refreshData(); |
320 | reset(); |
321 | emit refreshed(); |
322 | } |
323 | |
324 | long ResourceAppointmentsItemModel::id() const |
325 | { |
326 | return m_manager == 0 ? -1 : m_manager->scheduleId(); |
327 | } |
328 | |
329 | Qt::ItemFlags ResourceAppointmentsItemModel::flags( const QModelIndex &index ) const |
330 | { |
331 | Qt::ItemFlags flags = ItemModelBase::flags( index ); |
332 | return flags &= ~Qt::ItemIsEditable; |
333 | } |
334 | |
335 | |
336 | QModelIndex ResourceAppointmentsItemModel::parent( const QModelIndex &idx ) const |
337 | { |
338 | if ( !idx.isValid() || m_project == 0 || m_manager == 0 ) { |
339 | kWarning()<<"No data " <<idx; |
340 | return QModelIndex(); |
341 | } |
342 | |
343 | QModelIndex p; |
344 | if ( ! p.isValid() ) { |
345 | Resource *r = resource( idx ); |
346 | if ( r ) { |
347 | int row = m_project->indexOf( r->parentGroup() ); |
348 | p = createGroupIndex( row, 0, r->parentGroup() ); |
349 | //kDebug(planDbg())<<"Parent:"<<p<<r->parentGroup()->name(); |
350 | Q_ASSERT( p.isValid() ); |
351 | } |
352 | } |
353 | if ( ! p.isValid() && m_showInternal ) { |
354 | Appointment *a = appointment( idx ); |
355 | if ( a && a->resource() && a->resource()->resource() ) { |
356 | Resource *r = a->resource()->resource(); |
357 | int row = r->parentGroup()->indexOf( r ); |
358 | p = createResourceIndex( row, 0, r ); |
359 | //kDebug(planDbg())<<"Parent:"<<p<<r->name(); |
360 | Q_ASSERT( p.isValid() ); |
361 | } |
362 | } |
363 | if ( ! p.isValid() && m_showExternal ) { |
364 | Appointment *a = externalAppointment( idx ); |
365 | Resource *r = parent( a ); |
366 | if ( r ) { |
367 | int row = r->parentGroup()->indexOf( r ); |
368 | p = createResourceIndex( row, 0, r ); |
369 | } |
370 | } |
371 | if ( ! p.isValid() ) { |
372 | //kDebug(planDbg())<<"Parent:"<<p; |
373 | } |
374 | //kDebug(planDbg())<<"Child :"<<idx; |
375 | return p; |
376 | } |
377 | |
378 | Resource *ResourceAppointmentsItemModel::parent( const Appointment *a ) const |
379 | { |
380 | if ( a == 0 || m_project == 0 ) { |
381 | return 0; |
382 | } |
383 | foreach ( Resource *r, m_project->resourceList() ) { |
384 | if ( r->appointments( id() ).contains( const_cast<Appointment*>( a ) ) ) { |
385 | return r; |
386 | } |
387 | if ( r->externalAppointmentList().contains( const_cast<Appointment*>( a ) ) ) { |
388 | return r; |
389 | } |
390 | } |
391 | return 0; |
392 | } |
393 | |
394 | QModelIndex ResourceAppointmentsItemModel::index( int row, int column, const QModelIndex &parent ) const |
395 | { |
396 | if ( m_project == 0 || m_manager == 0 ) { |
397 | return QModelIndex(); |
398 | } |
399 | if ( ! parent.isValid() ) { |
400 | if ( row < m_project->numResourceGroups() ) { |
401 | //kDebug(planDbg())<<"Group: "<<m_project->resourceGroupAt( row )<<endl; |
402 | return createGroupIndex( row, column, m_project->resourceGroupAt( row ) ); |
403 | } |
404 | return QModelIndex(); |
405 | } |
406 | ResourceGroup *g = resourcegroup( parent ); |
407 | if ( g ) { |
408 | if ( row < g->numResources() ) { |
409 | //kDebug(planDbg())<<"Resource: "<<g->resourceAt( row )<<endl; |
410 | return createResourceIndex( row, column, g->resourceAt( row ) ); |
411 | } |
412 | return QModelIndex(); |
413 | } |
414 | Resource *r = resource( parent ); |
415 | if ( r && ( m_showInternal || m_showExternal ) ) { |
416 | int num = m_showInternal ? r->numAppointments( id() ) : 0; |
417 | if ( row < num ) { |
418 | //kDebug(planDbg())<<"Appointment: "<<r->appointmentAt( row, m_manager->scheduleId() ); |
419 | return createAppointmentIndex( row, column, r->appointmentAt( row, id() ) ); |
420 | } |
421 | int extRow = row - num; |
422 | //kDebug(planDbg())<<"Appointment: "<<r->externalAppointmentList().value( extRow ); |
423 | Q_ASSERT( extRow >= 0 && extRow < r->externalAppointmentList().count() ); |
424 | return createExternalAppointmentIndex( row, column, r->externalAppointmentList().value( extRow ) ); |
425 | } |
426 | return QModelIndex(); |
427 | } |
428 | |
429 | QModelIndex ResourceAppointmentsItemModel::index( const Resource *resource ) const |
430 | { |
431 | if ( m_project == 0 || resource == 0 ) { |
432 | return QModelIndex(); |
433 | } |
434 | Resource *r = const_cast<Resource*>(resource); |
435 | int row = -1; |
436 | ResourceGroup *par = r->parentGroup(); |
437 | if ( par ) { |
438 | row = par->indexOf( r ); |
439 | return createResourceIndex( row, 0, r ); |
440 | } |
441 | return QModelIndex(); |
442 | } |
443 | |
444 | QModelIndex ResourceAppointmentsItemModel::index( const ResourceGroup *group ) const |
445 | { |
446 | if ( m_project == 0 || group == 0 ) { |
447 | return QModelIndex(); |
448 | } |
449 | ResourceGroup *g = const_cast<ResourceGroup*>(group); |
450 | int row = m_project->indexOf( g ); |
451 | return createGroupIndex( row, 0, g ); |
452 | |
453 | } |
454 | |
455 | void ResourceAppointmentsItemModel::refresh() |
456 | { |
457 | refreshData(); |
458 | emit refreshed(); |
459 | } |
460 | |
461 | void ResourceAppointmentsItemModel::refreshData() |
462 | { |
463 | long id = m_manager == 0 ? -1 : m_manager->scheduleId(); |
464 | //kDebug(planDbg())<<"Schedule id: "<<id<<endl; |
465 | QDate start; |
466 | QDate end; |
467 | QMap<const Appointment*, EffortCostMap> ec; |
468 | QMap<const Appointment*, EffortCostMap> extEff; |
469 | foreach ( Resource *r, m_project->resourceList() ) { |
470 | foreach (Appointment* a, r->appointments( id )) { |
471 | QDate s = a->startTime().date(); |
472 | QDate e = a->endTime().date(); |
473 | ec[ a ] = a->plannedPrDay( s, e ); |
474 | if ( ! start.isValid() || s < start ) { |
475 | start = s; |
476 | } |
477 | if ( ! end.isValid() || e > end ) { |
478 | end = e; |
479 | } |
480 | //kDebug(planDbg())<<a->node()->node()->name()<<": "<<s<<e<<": "<<m_effortMap[ a ].totalEffort().toDouble(Duration::Unit_h); |
481 | } |
482 | // add external appointments |
483 | foreach (Appointment* a, r->externalAppointmentList() ) { |
484 | extEff[ a ] = a->plannedPrDay( startDate(), endDate() ); |
485 | //kDebug(planDbg())<<r->name()<<a->auxcilliaryInfo()<<": "<<extEff[ a ].totalEffort().toDouble(Duration::Unit_h); |
486 | //kDebug(planDbg())<<r->name()<<a->auxcilliaryInfo()<<": "<<extEff[ a ].startDate()<<extEff[ a ].endDate(); |
487 | } |
488 | } |
489 | m_effortMap.clear(); |
490 | m_externalEffortMap.clear(); |
491 | m_effortMap = ec; |
492 | m_externalEffortMap = extEff; |
493 | return; |
494 | } |
495 | |
496 | int ResourceAppointmentsItemModel::columnCount( const QModelIndex &/*parent*/ ) const |
497 | { |
498 | return 3 + startDate().daysTo( endDate() ); |
499 | } |
500 | |
501 | int ResourceAppointmentsItemModel::rowCount( const QModelIndex &parent ) const |
502 | { |
503 | if ( m_project == 0 || m_manager == 0 ) { |
504 | return 0; |
505 | } |
506 | //kDebug(planDbg())<<parent.row()<<", "<<parent.column()<<endl; |
507 | if ( ! parent.isValid() ) { |
508 | //kDebug(planDbg())<<m_project->name()<<": "<<m_project->numResourceGroups()<<endl; |
509 | return m_project->numResourceGroups(); |
510 | } |
511 | ResourceGroup *g = resourcegroup( parent ); |
512 | if ( g ) { |
513 | //kDebug(planDbg())<<g->name()<<": "<<g->numResources()<<endl; |
514 | return g->numResources(); |
515 | } |
516 | Resource *r = resource( parent ); |
517 | if ( r ) { |
518 | int rows = m_showInternal ? r->numAppointments( id() ) : 0; |
519 | rows += m_showExternal ? r->numExternalAppointments() : 0; |
520 | return rows; |
521 | } |
522 | return 0; |
523 | } |
524 | |
525 | QVariant ResourceAppointmentsItemModel::name( const Resource *res, int role ) const |
526 | { |
527 | switch ( role ) { |
528 | case Qt::DisplayRole: |
529 | case Qt::EditRole: |
530 | case Qt::ToolTipRole: |
531 | return res->name(); |
532 | break; |
533 | case Qt::StatusTipRole: |
534 | case Qt::WhatsThisRole: |
535 | return QVariant(); |
536 | } |
537 | return QVariant(); |
538 | } |
539 | |
540 | QVariant ResourceAppointmentsItemModel::name( const ResourceGroup *res, int role ) const |
541 | { |
542 | switch ( role ) { |
543 | case Qt::DisplayRole: |
544 | case Qt::EditRole: |
545 | case Qt::ToolTipRole: |
546 | return res->name(); |
547 | break; |
548 | case Qt::StatusTipRole: |
549 | case Qt::WhatsThisRole: |
550 | return QVariant(); |
551 | } |
552 | return QVariant(); |
553 | } |
554 | |
555 | QVariant ResourceAppointmentsItemModel::name( const Node *node, int role ) const |
556 | { |
557 | switch ( role ) { |
558 | case Qt::DisplayRole: |
559 | case Qt::EditRole: |
560 | case Qt::ToolTipRole: |
561 | return node->name(); |
562 | break; |
563 | case Qt::StatusTipRole: |
564 | case Qt::WhatsThisRole: |
565 | return QVariant(); |
566 | } |
567 | return QVariant(); |
568 | } |
569 | |
570 | QVariant ResourceAppointmentsItemModel::name( const Appointment *app, int role ) const |
571 | { |
572 | switch ( role ) { |
573 | case Qt::DisplayRole: |
574 | case Qt::EditRole: |
575 | return app->auxcilliaryInfo(); |
576 | case Qt::ToolTipRole: |
577 | return i18n( "External project: %1" , app->auxcilliaryInfo() ); |
578 | case Qt::StatusTipRole: |
579 | case Qt::WhatsThisRole: |
580 | return QVariant(); |
581 | case Qt::ForegroundRole: |
582 | if ( m_externalEffortMap.contains( app ) ) { |
583 | return QVariant( Qt::blue ); |
584 | } |
585 | break; |
586 | } |
587 | return QVariant(); |
588 | } |
589 | |
590 | |
591 | QVariant ResourceAppointmentsItemModel::total( const Resource *res, int role ) const |
592 | { |
593 | switch ( role ) { |
594 | case Qt::DisplayRole: { |
595 | Duration d; |
596 | if ( m_showInternal ) { |
597 | QList<Appointment*> lst = res->appointments( m_manager->scheduleId() ); |
598 | foreach ( Appointment *a, lst ) { |
599 | if ( m_effortMap.contains( a ) ) { |
600 | d += m_effortMap[ a ].totalEffort(); |
601 | } |
602 | } |
603 | } |
604 | if ( m_showExternal ) { |
605 | QList<Appointment*> lst = res->externalAppointmentList(); |
606 | foreach ( Appointment *a, lst ) { |
607 | if ( m_externalEffortMap.contains( a ) ) { |
608 | d += m_externalEffortMap[ a ].totalEffort(); |
609 | } |
610 | } |
611 | } |
612 | return KGlobal::locale()->formatNumber( d.toDouble( Duration::Unit_h ), 1 ); |
613 | } |
614 | case Qt::EditRole: |
615 | case Qt::ToolTipRole: |
616 | case Qt::StatusTipRole: |
617 | case Qt::WhatsThisRole: |
618 | return QVariant(); |
619 | case Qt::TextAlignmentRole: |
620 | return (int)(Qt::AlignRight|Qt::AlignVCenter); |
621 | } |
622 | return QVariant(); |
623 | } |
624 | |
625 | QVariant ResourceAppointmentsItemModel::total( const Resource *res, const QDate &date, int role ) const |
626 | { |
627 | switch ( role ) { |
628 | case Qt::DisplayRole: { |
629 | Duration d; |
630 | if ( m_showInternal ) { |
631 | QList<Appointment*> lst = res->appointments( id() ); |
632 | foreach ( Appointment *a, lst ) { |
633 | if ( m_effortMap.contains( a ) ) { |
634 | d += m_effortMap[ a ].effortOnDate( date ); |
635 | } |
636 | } |
637 | } |
638 | if ( m_showExternal ) { |
639 | QList<Appointment*> lst = res->externalAppointmentList(); |
640 | foreach ( Appointment *a, lst ) { |
641 | if ( m_externalEffortMap.contains( a ) ) { |
642 | d += m_externalEffortMap[ a ].effortOnDate( date ); |
643 | } |
644 | } |
645 | } |
646 | QString ds = KGlobal::locale()->formatNumber( d.toDouble( Duration::Unit_h ), 1 ); |
647 | Duration avail = res->effort( 0, DateTime( date, QTime(0,0,0) ), Duration( 1.0, Duration::Unit_d ) ); |
648 | QString avails = KGlobal::locale()->formatNumber( avail.toDouble( Duration::Unit_h ), 1 ); |
649 | return QString( "%1(%2)" ).arg( ds).arg( avails ); |
650 | } |
651 | case Qt::EditRole: |
652 | case Qt::ToolTipRole: |
653 | return i18n( "The total booking on %1, along with the maximum hours for the resource" , KGlobal::locale()->formatDate( date ) ); |
654 | case Qt::StatusTipRole: |
655 | case Qt::WhatsThisRole: |
656 | return QVariant(); |
657 | case Qt::TextAlignmentRole: |
658 | return (int)(Qt::AlignRight|Qt::AlignVCenter); |
659 | case Qt::BackgroundRole: { |
660 | if ( res->calendar() && res->calendar()->state( date ) != CalendarDay::Working ) { |
661 | QColor c( 0xf0f0f0 ); |
662 | return QVariant::fromValue( c ); |
663 | //return QVariant( Qt::cyan ); |
664 | } |
665 | break; |
666 | } |
667 | } |
668 | return QVariant(); |
669 | } |
670 | |
671 | QVariant ResourceAppointmentsItemModel::total( const Appointment *a, int role ) const |
672 | { |
673 | switch ( role ) { |
674 | case Qt::DisplayRole: { |
675 | Duration d; |
676 | if ( m_effortMap.contains( a ) ) { |
677 | d = m_effortMap[ a ].totalEffort(); |
678 | } else if ( m_externalEffortMap.contains( a ) ) { |
679 | d = m_externalEffortMap[ a ].totalEffort(); |
680 | } |
681 | return KGlobal::locale()->formatNumber( d.toDouble( Duration::Unit_h ), 1 ); |
682 | } |
683 | case Qt::ToolTipRole: { |
684 | if ( m_effortMap.contains( a ) ) { |
685 | return i18n( "Total booking by this task" ); |
686 | } else if ( m_externalEffortMap.contains( a ) ) { |
687 | return i18n( "Total booking by the external project" ); |
688 | } |
689 | return QVariant(); |
690 | } |
691 | case Qt::EditRole: |
692 | case Qt::StatusTipRole: |
693 | case Qt::WhatsThisRole: |
694 | return QVariant(); |
695 | case Qt::TextAlignmentRole: |
696 | return (int)(Qt::AlignRight|Qt::AlignVCenter); |
697 | case Qt::ForegroundRole: |
698 | if ( m_externalEffortMap.contains( a ) ) { |
699 | return QVariant( Qt::blue ); |
700 | } |
701 | break; |
702 | } |
703 | return QVariant(); |
704 | } |
705 | |
706 | |
707 | QVariant ResourceAppointmentsItemModel::assignment( const Appointment *a, const QDate &date, int role ) const |
708 | { |
709 | switch ( role ) { |
710 | case Qt::DisplayRole: { |
711 | Duration d; |
712 | if ( m_effortMap.contains( a ) ) { |
713 | if ( date < m_effortMap[ a ].startDate() || date > m_effortMap[ a ].endDate() ) { |
714 | return QVariant(); |
715 | } |
716 | d = m_effortMap[ a ].effortOnDate( date ); |
717 | return KGlobal::locale()->formatNumber( d.toDouble( Duration::Unit_h ), 1 ); |
718 | } else if ( m_externalEffortMap.contains( a ) ) { |
719 | if ( date < m_externalEffortMap[ a ].startDate() || date > m_externalEffortMap[ a ].endDate() ) { |
720 | return QVariant(); |
721 | } |
722 | d = m_externalEffortMap[ a ].effortOnDate( date ); |
723 | return KGlobal::locale()->formatNumber( d.toDouble( Duration::Unit_h ), 1 ); |
724 | } |
725 | return QVariant(); |
726 | } |
727 | case Qt::EditRole: |
728 | case Qt::ToolTipRole: { |
729 | if ( m_effortMap.contains( a ) ) { |
730 | return i18n( "Booking by this task on %1" , KGlobal::locale()->formatDate( date ) ); |
731 | } else if ( m_externalEffortMap.contains( a ) ) { |
732 | return i18n( "Booking by external project on %1" ,KGlobal::locale()->formatDate( date ) ); |
733 | } |
734 | return QVariant(); |
735 | } |
736 | case Qt::StatusTipRole: |
737 | case Qt::WhatsThisRole: |
738 | return QVariant(); |
739 | case Qt::TextAlignmentRole: |
740 | return (int)(Qt::AlignRight|Qt::AlignVCenter); |
741 | case Qt::ForegroundRole: |
742 | if ( m_externalEffortMap.contains( a ) ) { |
743 | return QVariant( Qt::blue ); |
744 | } |
745 | break; |
746 | case Qt::BackgroundRole: { |
747 | Resource *r = parent( a ); |
748 | if ( r && r->calendar() && r->calendar()->state( date ) != CalendarDay::Working ) { |
749 | QColor c( 0xf0f0f0 ); |
750 | return QVariant::fromValue( c ); |
751 | //return QVariant( Qt::cyan ); |
752 | } |
753 | break; |
754 | } |
755 | } |
756 | return QVariant(); |
757 | } |
758 | |
759 | QVariant ResourceAppointmentsItemModel::notUsed( const ResourceGroup *, int role ) const |
760 | { |
761 | switch ( role ) { |
762 | case Qt::DisplayRole: |
763 | return QString(" " ); |
764 | case Qt::TextAlignmentRole: |
765 | return Qt::AlignCenter; |
766 | case Qt::EditRole: |
767 | case Qt::ToolTipRole: |
768 | case Qt::StatusTipRole: |
769 | case Qt::WhatsThisRole: |
770 | return QVariant(); |
771 | } |
772 | return QVariant(); |
773 | } |
774 | |
775 | QVariant ResourceAppointmentsItemModel::data( const QModelIndex &index, int role ) const |
776 | { |
777 | if ( m_project == 0 || m_manager == 0 ) { |
778 | return QVariant(); |
779 | } |
780 | QVariant result; |
781 | if ( index.column() >= columnCount() ) { |
782 | kDebug(planDbg())<<"invalid display value column " <<index; |
783 | return result; |
784 | } |
785 | if ( ! index.isValid() ) { |
786 | kDebug(planDbg())<<"Invalid index:" <<index; |
787 | return result; |
788 | } |
789 | if ( role == Qt::TextAlignmentRole ) { |
790 | return headerData( index.column(), Qt::Horizontal, role ); |
791 | } |
792 | Resource *r = resource( index ); |
793 | if ( r ) { |
794 | switch ( index.column() ) { |
795 | case 0: result = name( r, role ); break; |
796 | case 1: result = total( r, role ); break; |
797 | default: |
798 | QDate d = startDate().addDays( index.column() - 2 ); |
799 | result = total( r, d, role ); |
800 | break; |
801 | } |
802 | if ( result.isValid() ) { |
803 | if ( role == Qt::DisplayRole && result.type() == QVariant::String && result.toString().isEmpty()) { |
804 | // HACK to show focus in empty cells |
805 | result = ' '; |
806 | } |
807 | return result; |
808 | } |
809 | return QVariant(); |
810 | } |
811 | ResourceGroup *g = resourcegroup( index ); |
812 | if ( g ) { |
813 | switch ( index.column() ) { |
814 | case 0: result = name( g, role ); break; |
815 | default: |
816 | result = notUsed( g, role ); |
817 | break; |
818 | } |
819 | if ( result.isValid() ) { |
820 | if ( role == Qt::DisplayRole && result.type() == QVariant::String && result.toString().isEmpty()) { |
821 | // HACK to show focus in empty cells |
822 | result = ' '; |
823 | } |
824 | return result; |
825 | } |
826 | return QVariant(); |
827 | } |
828 | Appointment *a = appointment( index ); |
829 | if ( a ) { |
830 | switch ( index.column() ) { |
831 | case 0: result = name( a->node()->node(), role ); break; |
832 | case 1: result = total( a, role ); break; |
833 | default: { |
834 | QDate d = startDate().addDays( index.column()-2 ); |
835 | result = assignment( a, d, role ); |
836 | break; |
837 | } |
838 | } |
839 | if ( result.isValid() ) { |
840 | if ( role == Qt::DisplayRole && result.type() == QVariant::String && result.toString().isEmpty()) { |
841 | // HACK to show focus in empty cells |
842 | result = ' '; |
843 | } |
844 | return result; |
845 | } |
846 | return QVariant(); |
847 | } |
848 | a = externalAppointment( index ); |
849 | if ( a ) { |
850 | //kDebug(planDbg())<<"external"<<a->auxcilliaryInfo()<<index; |
851 | switch ( index.column() ) { |
852 | case 0: result = name( a, role ); break; |
853 | case 1: result = total( a, role ); break; |
854 | default: { |
855 | QDate d = startDate().addDays( index.column()-2 ); |
856 | result = assignment( a, d, role ); |
857 | break; |
858 | } |
859 | } |
860 | if ( result.isValid() ) { |
861 | if ( role == Qt::DisplayRole && result.type() == QVariant::String && result.toString().isEmpty()) { |
862 | // HACK to show focus in empty cells |
863 | result = ' '; |
864 | } |
865 | return result; |
866 | } |
867 | return QVariant(); |
868 | } |
869 | kDebug(planDbg())<<"Could not find ptr:" <<index; |
870 | return QVariant(); |
871 | } |
872 | |
873 | bool ResourceAppointmentsItemModel::setData( const QModelIndex &index, const QVariant &value, int role ) |
874 | { |
875 | if ( ! index.isValid() ) { |
876 | return ItemModelBase::setData( index, value, role ); |
877 | } |
878 | if ( ( flags( index ) &Qt::ItemIsEditable ) == 0 || role != Qt::EditRole ) { |
879 | return false; |
880 | } |
881 | Resource *r = resource( index ); |
882 | if ( r ) { |
883 | switch (index.column()) { |
884 | default: |
885 | qWarning("data: invalid display value column %d" , index.column()); |
886 | break; |
887 | } |
888 | return false; |
889 | } |
890 | ResourceGroup *g = resourcegroup( index ); |
891 | if ( g ) { |
892 | switch (index.column()) { |
893 | default: |
894 | qWarning("data: invalid display value column %d" , index.column()); |
895 | break; |
896 | } |
897 | return false; |
898 | } |
899 | return false; |
900 | } |
901 | |
902 | QVariant ResourceAppointmentsItemModel::( int section, Qt::Orientation orientation, int role ) const |
903 | { |
904 | if ( orientation == Qt::Horizontal ) { |
905 | if ( role == Qt::DisplayRole ) { |
906 | switch ( section ) { |
907 | case 0: return i18n( "Name" ); |
908 | case 1: return i18n( "Total" ); |
909 | default: { |
910 | //kDebug(planDbg())<<section<<", "<<startDate()<<endDate(); |
911 | if ( section < columnCount() ) { |
912 | QDate d = startDate().addDays( section - 2 ); |
913 | if ( d <= endDate() ) { |
914 | return d; |
915 | } |
916 | } |
917 | return QVariant(); |
918 | } |
919 | } |
920 | } else if ( role == Qt::ToolTipRole ) { |
921 | switch ( section ) { |
922 | case 0: return i18n( "Name" ); |
923 | case 1: return i18n( "The total hours booked" ); |
924 | default: { |
925 | //kDebug(planDbg())<<section<<", "<<startDate()<<endDate(); |
926 | QDate d = startDate().addDays( section - 2 ); |
927 | return i18n( "Bookings on %1" , KGlobal::locale()->formatDate( d ) ); |
928 | } |
929 | return QVariant(); |
930 | } |
931 | } else if ( role == Qt::TextAlignmentRole ) { |
932 | switch (section) { |
933 | case 0: return QVariant(); |
934 | default: return (int)(Qt::AlignRight|Qt::AlignVCenter); |
935 | } |
936 | } |
937 | } |
938 | if ( role == Qt::ToolTipRole ) { |
939 | switch ( section ) { |
940 | default: return QVariant(); |
941 | } |
942 | } |
943 | return ItemModelBase::headerData(section, orientation, role); |
944 | } |
945 | |
946 | QObject *ResourceAppointmentsItemModel::object( const QModelIndex &index ) const |
947 | { |
948 | QObject *o = 0; |
949 | if ( index.isValid() ) { |
950 | o = dynamic_cast<QObject*>( resource( index ) ); |
951 | if ( o ) { |
952 | return o; |
953 | } |
954 | o = dynamic_cast<QObject*>( resourcegroup( index ) ); |
955 | } |
956 | return o; |
957 | } |
958 | |
959 | Node *ResourceAppointmentsItemModel::node( const QModelIndex &index ) const |
960 | { |
961 | Appointment *a = appointment( index ); |
962 | if ( a == 0 ) { |
963 | return 0; |
964 | } |
965 | return a->node()->node(); |
966 | } |
967 | |
968 | Appointment *ResourceAppointmentsItemModel::appointment( const QModelIndex &index ) const |
969 | { |
970 | if ( m_project == 0 || m_manager == 0 ) { |
971 | return 0; |
972 | } |
973 | foreach ( Resource *r, m_project->resourceList() ) { |
974 | foreach ( Appointment *a, r->appointments( id() ) ) { |
975 | if ( a == index.internalPointer() ) { |
976 | return a; |
977 | } |
978 | } |
979 | } |
980 | return 0; |
981 | } |
982 | |
983 | Appointment *ResourceAppointmentsItemModel::externalAppointment( const QModelIndex &index ) const |
984 | { |
985 | if ( m_project == 0 || m_manager == 0 ) { |
986 | return 0; |
987 | } |
988 | foreach ( Resource *r, m_project->resourceList() ) { |
989 | foreach ( Appointment *a, r->externalAppointmentList() ) { |
990 | if ( a == index.internalPointer() ) { |
991 | return a; |
992 | } |
993 | } |
994 | } |
995 | return 0; |
996 | } |
997 | |
998 | QModelIndex ResourceAppointmentsItemModel::createAppointmentIndex( int row, int col, void *ptr ) const |
999 | { |
1000 | return createIndex( row, col, ptr ); |
1001 | } |
1002 | |
1003 | QModelIndex ResourceAppointmentsItemModel::createExternalAppointmentIndex( int row, int col, void *ptr ) const |
1004 | { |
1005 | if ( m_project == 0 || m_manager == 0 ) { |
1006 | return QModelIndex(); |
1007 | } |
1008 | QModelIndex i = createIndex( row, col, ptr ); |
1009 | //kDebug(planDbg())<<i; |
1010 | return i; |
1011 | } |
1012 | |
1013 | Resource *ResourceAppointmentsItemModel::resource( const QModelIndex &index ) const |
1014 | { |
1015 | if ( m_project == 0 ) { |
1016 | return 0; |
1017 | } |
1018 | foreach ( Resource *r, m_project->resourceList() ) { |
1019 | if ( r == index.internalPointer() ) { |
1020 | return r; |
1021 | } |
1022 | } |
1023 | return 0; |
1024 | } |
1025 | |
1026 | QModelIndex ResourceAppointmentsItemModel::createResourceIndex( int row, int col, void *ptr ) const |
1027 | { |
1028 | return createIndex( row, col, ptr ); |
1029 | } |
1030 | |
1031 | ResourceGroup *ResourceAppointmentsItemModel::resourcegroup( const QModelIndex &index ) const |
1032 | { |
1033 | if ( m_project == 0 ) { |
1034 | return 0; |
1035 | } |
1036 | foreach ( ResourceGroup *r, m_project->resourceGroups() ) { |
1037 | if ( r == index.internalPointer() ) { |
1038 | return r; |
1039 | } |
1040 | } |
1041 | return 0; |
1042 | } |
1043 | |
1044 | QModelIndex ResourceAppointmentsItemModel::createGroupIndex( int row, int col, void *ptr ) const |
1045 | { |
1046 | return createIndex( row, col, ptr ); |
1047 | } |
1048 | |
1049 | void ResourceAppointmentsItemModel::slotCalendarChanged( Calendar* ) |
1050 | { |
1051 | foreach ( Resource *r, m_project->resourceList() ) { |
1052 | if ( r->calendar( true ) == 0 ) { |
1053 | slotResourceChanged( r ); |
1054 | } |
1055 | } |
1056 | } |
1057 | |
1058 | void ResourceAppointmentsItemModel::slotResourceChanged( Resource *res ) |
1059 | { |
1060 | ResourceGroup *g = res->parentGroup(); |
1061 | if ( g ) { |
1062 | int row = g->indexOf( res ); |
1063 | emit dataChanged( createResourceIndex( row, 0, res ), createResourceIndex( row, columnCount() - 1, res ) ); |
1064 | return; |
1065 | } |
1066 | } |
1067 | |
1068 | void ResourceAppointmentsItemModel::slotResourceGroupChanged( ResourceGroup *res ) |
1069 | { |
1070 | Project *p = res->project(); |
1071 | if ( p ) { |
1072 | int row = p->resourceGroups().indexOf( res ); |
1073 | emit dataChanged( createGroupIndex( row, 0, res ), createGroupIndex( row, columnCount() - 1, res ) ); |
1074 | } |
1075 | } |
1076 | |
1077 | //------------------------------------------------------- |
1078 | class ResourceAppointmentsRowModel::Private |
1079 | { |
1080 | public: |
1081 | Private( Private *par=0, void *p=0, KPlato::ObjectType t=OT_None ) : parent( par ), ptr( p ), type( t ), internalCached( false ), externalCached( false ), intervalRow( -1 ) |
1082 | {} |
1083 | ~Private() |
1084 | { |
1085 | qDeleteAll( intervals ); |
1086 | } |
1087 | |
1088 | QVariant data( int column, long id = -1, int role = Qt::DisplayRole ) const; |
1089 | |
1090 | Private *parent; |
1091 | void *ptr; |
1092 | KPlato::ObjectType type; |
1093 | bool internalCached; |
1094 | bool externalCached; |
1095 | |
1096 | Private *intervalAt( int row ) const; |
1097 | // used by interval |
1098 | AppointmentInterval interval; |
1099 | |
1100 | protected: |
1101 | QVariant groupData( int column, int role ) const; |
1102 | QVariant resourceData( int column, long id, int role ) const; |
1103 | QVariant appointmentData( int column, int role ) const; |
1104 | QVariant externalData( int column, int role ) const; |
1105 | QVariant intervalData( int column, int role ) const; |
1106 | |
1107 | private: |
1108 | // used by resource |
1109 | Appointment internal; |
1110 | Appointment external; |
1111 | |
1112 | // used by appointment |
1113 | int intervalRow; |
1114 | mutable QMap<int, Private*> intervals; |
1115 | }; |
1116 | |
1117 | QVariant ResourceAppointmentsRowModel::Private::data( int column, long id, int role ) const |
1118 | { |
1119 | if ( role == Role::ObjectType ) { |
1120 | return (int)type; |
1121 | } |
1122 | switch ( type ) { |
1123 | case OT_ResourceGroup: return groupData( column, role ); |
1124 | case OT_Resource: return resourceData( column, id, role ); |
1125 | case OT_Appointment: return appointmentData( column, role ); |
1126 | case OT_External: return externalData( column, role ); |
1127 | case OT_Interval: return intervalData( column, role ); |
1128 | default: break; |
1129 | } |
1130 | return QVariant(); |
1131 | } |
1132 | |
1133 | QVariant ResourceAppointmentsRowModel::Private::groupData( int column, int role ) const |
1134 | { |
1135 | ResourceGroup *g = static_cast<ResourceGroup*>( ptr ); |
1136 | if ( role == Qt::DisplayRole ) { |
1137 | switch ( column ) { |
1138 | case ResourceAppointmentsRowModel::Name: return g->name(); |
1139 | case ResourceAppointmentsRowModel::Type: return g->typeToString( true ); |
1140 | case ResourceAppointmentsRowModel::StartTime: return " " ; |
1141 | case ResourceAppointmentsRowModel::EndTime: return " " ; |
1142 | case ResourceAppointmentsRowModel::Load: return " " ; |
1143 | } |
1144 | } else if ( role == Role::Maximum ) { |
1145 | return g->units(); //TODO: Maximum Load |
1146 | } |
1147 | return QVariant(); |
1148 | } |
1149 | |
1150 | QVariant ResourceAppointmentsRowModel::Private::resourceData( int column, long id, int role ) const |
1151 | { |
1152 | KPlato::Resource *r = static_cast<KPlato::Resource*>( ptr ); |
1153 | if ( role == Qt::DisplayRole ) { |
1154 | switch ( column ) { |
1155 | case ResourceAppointmentsRowModel::Name: return r->name(); |
1156 | case ResourceAppointmentsRowModel::Type: return r->typeToString( true ); |
1157 | case ResourceAppointmentsRowModel::StartTime: return " " ; |
1158 | case ResourceAppointmentsRowModel::EndTime: return " " ; |
1159 | case ResourceAppointmentsRowModel::Load: return " " ; |
1160 | } |
1161 | } else if ( role == Role::Maximum ) { |
1162 | return r->units(); //TODO: Maximum Load |
1163 | } else if ( role == Role::InternalAppointments ) { |
1164 | if ( ! internalCached ) { |
1165 | Resource *r = static_cast<Resource*>( ptr ); |
1166 | const_cast<Private*>( this )->internal.clear(); |
1167 | foreach ( Appointment *a, r->appointments( id ) ) { |
1168 | const_cast<Private*>( this )->internal += *a; |
1169 | } |
1170 | const_cast<Private*>( this )->internalCached = true; |
1171 | } |
1172 | return QVariant::fromValue( (void*)(&internal) ); |
1173 | } else if ( role == Role::ExternalAppointments ) { |
1174 | if ( ! externalCached ) { |
1175 | Resource *r = static_cast<Resource*>( ptr ); |
1176 | const_cast<Private*>( this )->external.clear(); |
1177 | foreach ( Appointment *a, r->externalAppointmentList() ) { |
1178 | Appointment e; |
1179 | e.setIntervals( a->intervals( r->startTime( id ), r->endTime( id ) ) ); |
1180 | const_cast<Private*>( this )->external += e; |
1181 | } |
1182 | const_cast<Private*>( this )->externalCached = true; |
1183 | } |
1184 | return QVariant::fromValue( (void*)(&external) ); |
1185 | } |
1186 | return QVariant(); |
1187 | } |
1188 | |
1189 | QVariant ResourceAppointmentsRowModel::Private::appointmentData( int column, int role ) const |
1190 | { |
1191 | KPlato::Appointment *a = static_cast<KPlato::Appointment*>( ptr ); |
1192 | if ( role == Qt::DisplayRole ) { |
1193 | switch ( column ) { |
1194 | case ResourceAppointmentsRowModel::Name: return a->node()->node()->name(); |
1195 | case ResourceAppointmentsRowModel::Type: return a->node()->node()->typeToString( true ); |
1196 | case ResourceAppointmentsRowModel::StartTime: return KGlobal::locale()->formatDateTime( a->startTime() ); |
1197 | case ResourceAppointmentsRowModel::EndTime: return KGlobal::locale()->formatDateTime( a->endTime() ); |
1198 | case ResourceAppointmentsRowModel::Load: return " " ; |
1199 | } |
1200 | } else if ( role == Qt::ToolTipRole ) { |
1201 | Node *n = a->node()->node(); |
1202 | return i18nc( "@info:tooltip" , "%1: %2<nl/>%3: %4" , |
1203 | n->wbsCode(), |
1204 | n->name(), |
1205 | KGlobal::locale()->formatDateTime( a->startTime() ), |
1206 | KGlobal::locale()->formatDuration( ( a->endTime() - a->startTime() ).milliseconds() ) |
1207 | ); |
1208 | } else if ( role == Role::Maximum ) { |
1209 | return a->resource()->resource()->units(); //TODO: Maximum Load |
1210 | } |
1211 | return QVariant(); |
1212 | } |
1213 | |
1214 | QVariant ResourceAppointmentsRowModel::Private::externalData( int column, int role ) const |
1215 | { |
1216 | KPlato::Appointment *a = static_cast<KPlato::Appointment*>( ptr ); |
1217 | if ( role == Qt::DisplayRole ) { |
1218 | switch ( column ) { |
1219 | case ResourceAppointmentsRowModel::Name: return a->auxcilliaryInfo(); |
1220 | case ResourceAppointmentsRowModel::Type: return i18n( "Project" ); |
1221 | case ResourceAppointmentsRowModel::StartTime: return KGlobal::locale()->formatDateTime( a->startTime() ); |
1222 | case ResourceAppointmentsRowModel::EndTime: return KGlobal::locale()->formatDateTime( a->endTime() ); |
1223 | case ResourceAppointmentsRowModel::Load: return " " ; |
1224 | } |
1225 | } else if ( role == Qt::ForegroundRole ) { |
1226 | return QColor( Qt::blue ); |
1227 | } else if ( role == Role::Maximum ) { |
1228 | KPlato::Resource *r = static_cast<KPlato::Resource*>( parent->ptr ); |
1229 | return r->units(); //TODO: Maximum Load |
1230 | } |
1231 | return QVariant(); |
1232 | } |
1233 | |
1234 | ResourceAppointmentsRowModel::Private *ResourceAppointmentsRowModel::Private::intervalAt( int row ) const |
1235 | { |
1236 | Q_ASSERT( type == OT_Appointment || type == OT_External ); |
1237 | Private *p = intervals.value( row ); |
1238 | if ( p ) { |
1239 | return p; |
1240 | } |
1241 | Appointment *a = static_cast<Appointment*>( ptr ); |
1242 | p = new Private( const_cast<Private*>( this ), 0, OT_Interval ); |
1243 | p->intervalRow = row; |
1244 | p->interval = a->intervalAt( row ); |
1245 | intervals.insert( row, p ); |
1246 | return p; |
1247 | } |
1248 | |
1249 | |
1250 | QVariant ResourceAppointmentsRowModel::Private::intervalData( int column, int role ) const |
1251 | { |
1252 | if ( role == Qt::DisplayRole ) { |
1253 | switch ( column ) { |
1254 | case ResourceAppointmentsRowModel::Name: return QVariant(); |
1255 | case ResourceAppointmentsRowModel::Type: return i18n( "Interval" ); |
1256 | case ResourceAppointmentsRowModel::StartTime: return KGlobal::locale()->formatDateTime( interval.startTime() ); |
1257 | case ResourceAppointmentsRowModel::EndTime: return KGlobal::locale()->formatDateTime( interval.endTime() ); |
1258 | case ResourceAppointmentsRowModel::Load: return interval.load(); |
1259 | } |
1260 | } else if ( role == Qt::ToolTipRole ) { |
1261 | Appointment *a = static_cast<Appointment*>( parent->ptr ); |
1262 | Node *n = a->node()->node(); |
1263 | return i18nc( "@info:tooltip" , "%1: %2<nl/>%3: %4<nl/>Assigned: %5<nl/>Available: %6" , |
1264 | n->wbsCode(), |
1265 | n->name(), |
1266 | KGlobal::locale()->formatDateTime( a->startTime() ), |
1267 | KGlobal::locale()->formatDuration( ( a->endTime() - a->startTime() ).milliseconds() ), |
1268 | interval.load(), |
1269 | a->resource()->resource()->units() |
1270 | ); |
1271 | } else if ( role == Role::Maximum ) { |
1272 | return parent->appointmentData( column, role ); |
1273 | } |
1274 | return QVariant(); |
1275 | } |
1276 | |
1277 | int ResourceAppointmentsRowModel::sortRole( int column ) const |
1278 | { |
1279 | switch ( column ) { |
1280 | case ResourceAppointmentsRowModel::StartTime: |
1281 | case ResourceAppointmentsRowModel::EndTime: |
1282 | return Qt::EditRole; |
1283 | default: |
1284 | break; |
1285 | } |
1286 | return Qt::DisplayRole; |
1287 | } |
1288 | |
1289 | #ifndef QT_NO_DEBUG_STREAM |
1290 | QDebug operator<<( QDebug dbg, KPlato::ObjectType t) |
1291 | { |
1292 | switch(t){ |
1293 | case KPlato::OT_None: dbg << "None" ; break; |
1294 | case KPlato::OT_ResourceGroup: dbg << "Group" ; break; |
1295 | case KPlato::OT_Resource: dbg << "Resource" ; break; |
1296 | case KPlato::OT_Appointment: dbg << "Appointment" ; break; |
1297 | case KPlato::OT_External: dbg << "External" ; break; |
1298 | case KPlato::OT_Interval: dbg << "Interval" ; break; |
1299 | default: dbg << "Unknown" ; |
1300 | } |
1301 | return dbg; |
1302 | } |
1303 | QDebug operator<<( QDebug dbg, const ResourceAppointmentsRowModel::Private& s ) |
1304 | { |
1305 | dbg <<&s; |
1306 | return dbg; |
1307 | } |
1308 | QDebug operator<<( QDebug dbg, const ResourceAppointmentsRowModel::Private* s ) |
1309 | { |
1310 | if ( s == 0 ) { |
1311 | dbg<<"ResourceAppointmentsRowModel::Private[ (" <<(void*)s<<") ]" ; |
1312 | } else { |
1313 | dbg << "ResourceAppointmentsRowModel::Private[ (" <<(void*)s<<") Type=" <<s->type<<" parent=" ; |
1314 | switch( s->type ) { |
1315 | case KPlato::OT_ResourceGroup: |
1316 | dbg<<static_cast<ResourceGroup*>(s->ptr)->project()<<static_cast<ResourceGroup*>(s->ptr)->project()->name(); |
1317 | dbg<<" ptr=" <<static_cast<ResourceGroup*>(s->ptr)<<static_cast<ResourceGroup*>(s->ptr)->name(); |
1318 | break; |
1319 | case KPlato::OT_Resource: |
1320 | dbg<<static_cast<ResourceGroup*>(s->parent->ptr)<<static_cast<ResourceGroup*>(s->parent->ptr)->name(); |
1321 | dbg<<" ptr=" <<static_cast<Resource*>(s->ptr)<<static_cast<Resource*>(s->ptr)->name(); |
1322 | break; |
1323 | case KPlato::OT_Appointment: |
1324 | case KPlato::OT_External: |
1325 | dbg<<static_cast<Resource*>(s->parent->ptr)<<static_cast<Resource*>(s->parent->ptr)->name(); |
1326 | dbg<<" ptr=" <<static_cast<Appointment*>(s->ptr); |
1327 | break; |
1328 | case KPlato::OT_Interval: |
1329 | dbg<<static_cast<Appointment*>(s->parent->ptr)<<" ptr=" <<static_cast<AppointmentInterval*>(s->ptr); |
1330 | break; |
1331 | default: |
1332 | dbg<<s->parent<<" ptr=" <<s->ptr; |
1333 | break; |
1334 | } |
1335 | dbg<<" ]" ; |
1336 | } |
1337 | |
1338 | return dbg; |
1339 | } |
1340 | #endif |
1341 | |
1342 | ResourceAppointmentsRowModel::ResourceAppointmentsRowModel( QObject *parent ) |
1343 | : ItemModelBase( parent ), |
1344 | m_schedule( 0 ) |
1345 | { |
1346 | } |
1347 | |
1348 | ResourceAppointmentsRowModel::~ResourceAppointmentsRowModel() |
1349 | { |
1350 | qDeleteAll( m_datamap ); |
1351 | } |
1352 | |
1353 | void ResourceAppointmentsRowModel::setProject( Project *project ) |
1354 | { |
1355 | //kDebug(planDbg())<<project; |
1356 | if ( m_project ) { |
1357 | disconnect( m_project, SIGNAL(resourceGroupToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const ResourceGroup*,int)) ); |
1358 | |
1359 | disconnect( m_project, SIGNAL(resourceGroupToBeRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const ResourceGroup*)) ); |
1360 | |
1361 | disconnect( m_project, SIGNAL(resourceToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const ResourceGroup*,int)) ); |
1362 | |
1363 | disconnect( m_project, SIGNAL(resourceToBeRemoved(const Resource*)), this, SLOT(slotResourceToBeRemoved(const Resource*)) ); |
1364 | |
1365 | disconnect( m_project, SIGNAL(resourceGroupAdded(const ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const ResourceGroup*)) ); |
1366 | |
1367 | disconnect( m_project, SIGNAL(resourceGroupRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const ResourceGroup*)) ); |
1368 | |
1369 | disconnect( m_project, SIGNAL(resourceAdded(const Resource*)), this, SLOT(slotResourceInserted(const Resource*)) ); |
1370 | |
1371 | disconnect( m_project, SIGNAL(resourceRemoved(const Resource*)), this, SLOT(slotResourceRemoved(const Resource*)) ); |
1372 | |
1373 | disconnect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); |
1374 | |
1375 | foreach ( Resource *r, m_project->resourceList() ) { |
1376 | disconnect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); |
1377 | disconnect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); |
1378 | disconnect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); |
1379 | disconnect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); |
1380 | disconnect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); |
1381 | } |
1382 | } |
1383 | m_project = project; |
1384 | if ( m_project ) { |
1385 | connect( m_project, SIGNAL(resourceGroupToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const ResourceGroup*,int)) ); |
1386 | |
1387 | connect( m_project, SIGNAL(resourceGroupToBeRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const ResourceGroup*)) ); |
1388 | |
1389 | connect( m_project, SIGNAL(resourceToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const ResourceGroup*,int)) ); |
1390 | |
1391 | connect( m_project, SIGNAL(resourceToBeRemoved(const Resource*)), this, SLOT(slotResourceToBeRemoved(const Resource*)) ); |
1392 | |
1393 | connect( m_project, SIGNAL(resourceGroupAdded(const ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const ResourceGroup*)) ); |
1394 | |
1395 | connect( m_project, SIGNAL(resourceGroupRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const ResourceGroup*)) ); |
1396 | |
1397 | connect( m_project, SIGNAL(resourceAdded(const Resource*)), this, SLOT(slotResourceInserted(const Resource*)) ); |
1398 | |
1399 | connect( m_project, SIGNAL(resourceRemoved(const Resource*)), this, SLOT(slotResourceRemoved(const Resource*)) ); |
1400 | |
1401 | connect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); |
1402 | |
1403 | foreach ( Resource *r, m_project->resourceList() ) { |
1404 | connect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); |
1405 | connect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); |
1406 | connect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); |
1407 | connect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); |
1408 | connect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); |
1409 | } |
1410 | } |
1411 | reset(); |
1412 | } |
1413 | |
1414 | void ResourceAppointmentsRowModel::setScheduleManager( ScheduleManager *sm ) |
1415 | { |
1416 | kDebug(planDbg())<<"ResourceAppointmentsRowModel::setScheduleManager:" <<sm; |
1417 | if ( sm == 0 || sm != m_manager || sm->expected() != m_schedule ) { |
1418 | m_manager = sm; |
1419 | m_schedule = sm ? sm->expected() : 0; |
1420 | qDeleteAll( m_datamap ); |
1421 | m_datamap.clear(); |
1422 | reset(); |
1423 | } |
1424 | } |
1425 | |
1426 | long ResourceAppointmentsRowModel::id() const |
1427 | { |
1428 | return m_manager ? m_manager->scheduleId() : -1; |
1429 | } |
1430 | |
1431 | const QMetaEnum ResourceAppointmentsRowModel::columnMap() const |
1432 | { |
1433 | return metaObject()->enumerator( metaObject()->indexOfEnumerator("Properties" ) ); |
1434 | } |
1435 | |
1436 | int ResourceAppointmentsRowModel::columnCount( const QModelIndex & /*parent */) const |
1437 | { |
1438 | return columnMap().keyCount(); |
1439 | } |
1440 | |
1441 | int ResourceAppointmentsRowModel::rowCount( const QModelIndex & parent ) const |
1442 | { |
1443 | if ( m_project == 0 ) { |
1444 | return 0; |
1445 | } |
1446 | if ( ! parent.isValid() ) { |
1447 | return m_project->numResourceGroups(); |
1448 | } |
1449 | if ( ResourceGroup *g = resourcegroup( parent ) ) { |
1450 | return g->numResources(); |
1451 | } |
1452 | if ( m_manager == 0 ) { |
1453 | return 0; |
1454 | } |
1455 | if ( Resource *r = resource( parent ) ) { |
1456 | return r->numAppointments( id() ) + r->numExternalAppointments(); // number of tasks there are appointments with + external projects |
1457 | } |
1458 | if ( Appointment *a = appointment( parent ) ) { |
1459 | return a->count(); // number of appointment intervals |
1460 | } |
1461 | return 0; |
1462 | } |
1463 | |
1464 | QVariant ResourceAppointmentsRowModel::data( const QModelIndex &index, int role ) const |
1465 | { |
1466 | //kDebug(planDbg())<<index<<role; |
1467 | if ( ! index.isValid() ) { |
1468 | return QVariant(); |
1469 | } |
1470 | if ( role == Qt::TextAlignmentRole ) { |
1471 | return headerData( index.column(), Qt::Horizontal, role ); |
1472 | } |
1473 | return static_cast<Private*>(index.internalPointer() )->data( index.column(), id(), role ); |
1474 | } |
1475 | |
1476 | QVariant ResourceAppointmentsRowModel::( int section, Qt::Orientation orientation, int role ) const |
1477 | { |
1478 | if ( orientation == Qt::Vertical ) { |
1479 | return QVariant(); |
1480 | } |
1481 | if ( role == Qt::DisplayRole ) { |
1482 | switch ( section ) { |
1483 | case Name: return i18n( "Name" ); |
1484 | case Type: return i18n( "Type" ); |
1485 | case StartTime: return i18n( "Start Time" ); |
1486 | case EndTime: return i18n( "End Time" ); |
1487 | case Load: return i18nc( "@title:column noun" , "Load" ); |
1488 | } |
1489 | } |
1490 | if ( role == Qt::TextAlignmentRole ) { |
1491 | switch ( section ) { |
1492 | case Name: |
1493 | case Type: |
1494 | case StartTime: |
1495 | case EndTime: |
1496 | return (int)(Qt::AlignLeft|Qt::AlignVCenter);; |
1497 | case Load: |
1498 | return (int)(Qt::AlignRight|Qt::AlignVCenter); |
1499 | } |
1500 | } |
1501 | return ItemModelBase::headerData( section, orientation, role ); |
1502 | } |
1503 | |
1504 | QModelIndex ResourceAppointmentsRowModel::parent( const QModelIndex &idx ) const |
1505 | { |
1506 | if ( !idx.isValid() || m_project == 0 ) { |
1507 | kWarning(planDbg())<<"No data " <<idx; |
1508 | return QModelIndex(); |
1509 | } |
1510 | |
1511 | QModelIndex p; |
1512 | if ( resourcegroup( idx ) ) { |
1513 | // ResourceGroup, no parent |
1514 | return QModelIndex(); |
1515 | } |
1516 | if ( ResourceGroup *pg = parentGroup( idx ) ) { |
1517 | // Resource, parent is ResourceGroup |
1518 | int row = m_project->indexOf( pg ); |
1519 | p = const_cast<ResourceAppointmentsRowModel*>( this )->createGroupIndex( row, 0, m_project ); |
1520 | //kDebug(planDbg())<<"Parent:"<<p<<r->parentGroup()->name(); |
1521 | Q_ASSERT( p.isValid() ); |
1522 | return p; |
1523 | } |
1524 | if ( Resource *pr = parentResource( idx ) ) { |
1525 | // Appointment, parent is Resource |
1526 | int row = pr->parentGroup()->indexOf( pr ); |
1527 | p = const_cast<ResourceAppointmentsRowModel*>( this )->createResourceIndex( row, 0, pr->parentGroup() ); |
1528 | //kDebug(planDbg())<<"Parent:"<<p<<r->parentGroup()->name(); |
1529 | Q_ASSERT( p.isValid() ); |
1530 | return p; |
1531 | } |
1532 | if ( Appointment *a = parentAppointment( idx ) ) { |
1533 | // AppointmentInterval, parent is Appointment |
1534 | Private *pi = static_cast<Private*>( idx.internalPointer() ); |
1535 | if ( pi->parent->type == OT_Appointment ) { |
1536 | Q_ASSERT( a->resource()->id() == id() ); |
1537 | if ( a->resource() && a->resource()->resource() ) { |
1538 | Resource *r = a->resource()->resource(); |
1539 | int row = r->indexOf( a, id() ); |
1540 | Q_ASSERT( row >= 0 ); |
1541 | p = const_cast<ResourceAppointmentsRowModel*>( this )->createAppointmentIndex( row, 0, r ); |
1542 | //kDebug(planDbg())<<"Parent:"<<p<<r->name(); |
1543 | Q_ASSERT( p.isValid() ); |
1544 | } |
1545 | } else if ( pi->parent->type == OT_External ) { |
1546 | Resource *r = static_cast<Resource*>( pi->parent->parent->ptr ); |
1547 | int row = r->externalAppointmentList().indexOf( a ); |
1548 | Q_ASSERT( row >= 0 ); |
1549 | row += r->numAppointments( id() ); |
1550 | p = const_cast<ResourceAppointmentsRowModel*>( this )->createAppointmentIndex( row, 0, r ); |
1551 | } |
1552 | return p; |
1553 | } |
1554 | return QModelIndex(); |
1555 | } |
1556 | |
1557 | QModelIndex ResourceAppointmentsRowModel::index( ResourceGroup *g ) const |
1558 | { |
1559 | if ( m_project == 0 || g == 0 ) { |
1560 | return QModelIndex(); |
1561 | } |
1562 | return const_cast<ResourceAppointmentsRowModel*>( this )->createGroupIndex( m_project->indexOf( g ), 0, m_project ); |
1563 | } |
1564 | |
1565 | QModelIndex ResourceAppointmentsRowModel::index( Resource *r ) const |
1566 | { |
1567 | if ( m_project == 0 || r == 0 ) { |
1568 | return QModelIndex(); |
1569 | } |
1570 | return const_cast<ResourceAppointmentsRowModel*>( this )->createResourceIndex( r->parentGroup()->indexOf( r ), 0, r->parentGroup() ); |
1571 | } |
1572 | |
1573 | QModelIndex ResourceAppointmentsRowModel::index( Appointment *a ) const |
1574 | { |
1575 | if ( m_project == 0 || m_manager == 0 || a == 0 || a->resource()->resource() ) { |
1576 | return QModelIndex(); |
1577 | } |
1578 | Resource *r = a->resource()->resource(); |
1579 | return const_cast<ResourceAppointmentsRowModel*>( this )->createAppointmentIndex( r->indexOf( a, id() ), 0, r ); |
1580 | } |
1581 | |
1582 | QModelIndex ResourceAppointmentsRowModel::index( int row, int column, const QModelIndex &parent ) const |
1583 | { |
1584 | if ( m_project == 0 || row < 0 || column < 0 ) { |
1585 | return QModelIndex(); |
1586 | } |
1587 | if ( ! parent.isValid() ) { |
1588 | if ( row < m_project->numResourceGroups() ) { |
1589 | //kDebug(planDbg())<<"Group: "<<m_project->resourceGroupAt( row ); |
1590 | return const_cast<ResourceAppointmentsRowModel*>( this )->createGroupIndex( row, column, m_project ); |
1591 | } |
1592 | return QModelIndex(); |
1593 | } |
1594 | if ( ResourceGroup *g = resourcegroup( parent ) ) { |
1595 | if ( row < g->numResources() ) { |
1596 | //kDebug(planDbg())<<"Resource: "<<g->resourceAt( row )<<static_cast<Private*>( parent.internalPointer() ); |
1597 | return const_cast<ResourceAppointmentsRowModel*>( this )->createResourceIndex( row, column, g ); |
1598 | } |
1599 | return QModelIndex(); |
1600 | } |
1601 | if ( m_manager == 0 ) { |
1602 | return QModelIndex(); |
1603 | } |
1604 | if ( Resource *r = resource( parent ) ) { |
1605 | int num = r->numAppointments( id() ) + r->numExternalAppointments(); |
1606 | if ( row < num ) { |
1607 | //kDebug(planDbg())<<"Appointment: "<<r->appointmentAt( row, m_manager->scheduleId() )<<static_cast<Private*>( parent.internalPointer() ); |
1608 | return const_cast<ResourceAppointmentsRowModel*>( this )->createAppointmentIndex( row, column, r ); |
1609 | } |
1610 | return QModelIndex(); |
1611 | } |
1612 | if ( Appointment *a = appointment( parent ) ) { |
1613 | int num = a->count(); |
1614 | if ( row < num ) { |
1615 | //kDebug(planDbg())<<"Appointment interval at: "<<row<<static_cast<Private*>( parent.internalPointer() ); |
1616 | return const_cast<ResourceAppointmentsRowModel*>( this )->createIntervalIndex( row, column, a ); |
1617 | } |
1618 | return QModelIndex(); |
1619 | } |
1620 | return QModelIndex(); |
1621 | } |
1622 | |
1623 | QModelIndex ResourceAppointmentsRowModel::createGroupIndex( int row, int column, Project *project ) |
1624 | { |
1625 | ResourceGroup *group = project->resourceGroupAt( row ); |
1626 | Private *p = m_datamap.value( (void*)group ); |
1627 | if ( p == 0 ) { |
1628 | p = new Private( 0, group, OT_ResourceGroup ); |
1629 | m_datamap.insert( group, p ); |
1630 | } |
1631 | QModelIndex idx = createIndex( row, column, p ); |
1632 | Q_ASSERT( idx.isValid() ); |
1633 | return idx; |
1634 | } |
1635 | |
1636 | QModelIndex ResourceAppointmentsRowModel::createResourceIndex( int row, int column, ResourceGroup *g ) |
1637 | { |
1638 | Resource *res = g->resourceAt( row ); |
1639 | Private *p = m_datamap.value( (void*)res ); |
1640 | if ( p == 0 ) { |
1641 | Private *pg = m_datamap.value( g ); |
1642 | Q_ASSERT( pg ); |
1643 | p = new Private( pg, res, OT_Resource ); |
1644 | m_datamap.insert( res, p ); |
1645 | } |
1646 | QModelIndex idx = createIndex( row, column, p ); |
1647 | Q_ASSERT( idx.isValid() ); |
1648 | return idx; |
1649 | } |
1650 | |
1651 | QModelIndex ResourceAppointmentsRowModel::createAppointmentIndex( int row, int column, Resource *r ) |
1652 | { |
1653 | Private *p = 0; |
1654 | KPlato::ObjectType type; |
1655 | Appointment *a = 0; |
1656 | if ( row < r->numAppointments( id() ) ) { |
1657 | a = r->appointmentAt( row, id() ); |
1658 | type = OT_Appointment; |
1659 | } else { |
1660 | a = r->externalAppointmentList().value( row - r->numAppointments( id() ) ); |
1661 | type = OT_External; |
1662 | } |
1663 | Q_ASSERT( a ); |
1664 | p = m_datamap.value( (void*)a ); |
1665 | if ( p == 0 ) { |
1666 | Private *pr = m_datamap.value( r ); |
1667 | Q_ASSERT( pr ); |
1668 | p = new Private( pr, a, type ); |
1669 | m_datamap.insert( a, p ); |
1670 | } |
1671 | QModelIndex idx = createIndex( row, column, p ); |
1672 | Q_ASSERT( idx.isValid() ); |
1673 | return idx; |
1674 | } |
1675 | |
1676 | QModelIndex ResourceAppointmentsRowModel::createIntervalIndex( int row, int column, Appointment *a ) |
1677 | { |
1678 | AppointmentInterval i = a->intervalAt( row ); |
1679 | Private *pr = m_datamap.value( a ); |
1680 | Q_ASSERT( pr ); |
1681 | Private *p = pr->intervalAt( row ); |
1682 | Q_ASSERT( p ); |
1683 | |
1684 | QModelIndex idx = createIndex( row, column, p ); |
1685 | Q_ASSERT( idx.isValid() ); |
1686 | return idx; |
1687 | } |
1688 | |
1689 | void ResourceAppointmentsRowModel::slotResourceToBeInserted( const ResourceGroup *group, int row ) |
1690 | { |
1691 | kDebug(planDbg())<<group->name()<<row; |
1692 | QModelIndex i = index( const_cast<ResourceGroup*>( group ) ); |
1693 | beginInsertRows( i, row, row ); |
1694 | } |
1695 | |
1696 | void ResourceAppointmentsRowModel::slotResourceInserted( const Resource *r ) |
1697 | { |
1698 | kDebug(planDbg())<<r->name(); |
1699 | endInsertRows(); |
1700 | |
1701 | connect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); |
1702 | connect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); |
1703 | connect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); |
1704 | connect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); |
1705 | connect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); |
1706 | } |
1707 | |
1708 | void ResourceAppointmentsRowModel::slotResourceToBeRemoved( const Resource *r ) |
1709 | { |
1710 | kDebug(planDbg())<<r->name(); |
1711 | int row = r->parentGroup()->indexOf( r ); |
1712 | |
1713 | beginRemoveRows( index( r->parentGroup() ), row, row ); |
1714 | disconnect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); |
1715 | disconnect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); |
1716 | disconnect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); |
1717 | disconnect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); |
1718 | disconnect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); |
1719 | |
1720 | Private *p = 0; |
1721 | foreach ( Appointment *a, r->appointments( id() ) ) { |
1722 | // remove appointment |
1723 | p = m_datamap.value( a ); |
1724 | if ( p ) { |
1725 | m_datamap.remove( a ); |
1726 | delete p; |
1727 | } |
1728 | } |
1729 | foreach ( Appointment *a, r->externalAppointmentList() ) { |
1730 | // remove appointment |
1731 | p = m_datamap.value( a ); |
1732 | if ( p ) { |
1733 | m_datamap.remove( a ); |
1734 | delete p; |
1735 | } |
1736 | } |
1737 | // remove resource |
1738 | p = m_datamap.value( (void*)r ); |
1739 | if ( p ) { |
1740 | m_datamap.remove( const_cast<Resource*>( r ) ); |
1741 | delete p; |
1742 | } |
1743 | } |
1744 | |
1745 | void ResourceAppointmentsRowModel::slotResourceRemoved( const Resource *resource ) |
1746 | { |
1747 | Q_UNUSED(resource); |
1748 | //kDebug(planDbg())<<resource->name(); |
1749 | endRemoveRows(); |
1750 | } |
1751 | |
1752 | void ResourceAppointmentsRowModel::slotResourceGroupToBeInserted( const ResourceGroup *group, int row ) |
1753 | { |
1754 | Q_UNUSED(group); |
1755 | beginInsertRows( QModelIndex(), row, row ); |
1756 | } |
1757 | |
1758 | void ResourceAppointmentsRowModel::slotResourceGroupInserted( const ResourceGroup*/*group*/ ) |
1759 | { |
1760 | endInsertRows(); |
1761 | } |
1762 | |
1763 | void ResourceAppointmentsRowModel::slotResourceGroupToBeRemoved( const ResourceGroup *group ) |
1764 | { |
1765 | //kDebug(planDbg())<<group->name()<<endl; |
1766 | int row = m_project->indexOf( const_cast<ResourceGroup*>( group ) ); |
1767 | beginRemoveRows( QModelIndex(), row, row ); |
1768 | |
1769 | Private *p = m_datamap.value( const_cast<ResourceGroup*>( group ) ); |
1770 | if ( p ) { |
1771 | m_datamap.remove( const_cast<ResourceGroup*>( group ) ); |
1772 | delete p; |
1773 | } |
1774 | } |
1775 | |
1776 | void ResourceAppointmentsRowModel::slotResourceGroupRemoved( const ResourceGroup *group ) |
1777 | { |
1778 | Q_UNUSED(group); |
1779 | //kDebug(planDbg())<<group->name(); |
1780 | endRemoveRows(); |
1781 | } |
1782 | |
1783 | void ResourceAppointmentsRowModel::slotAppointmentToBeInserted( Resource *r, int row ) |
1784 | { |
1785 | Q_UNUSED(r); |
1786 | Q_UNUSED(row); |
1787 | // external appointments only, (Internal handled in slotProjectCalculated) |
1788 | } |
1789 | |
1790 | void ResourceAppointmentsRowModel::slotAppointmentInserted( Resource *r, Appointment *a ) |
1791 | { |
1792 | Q_UNUSED(a); |
1793 | // external appointments only, (Internal handled in slotProjectCalculated) |
1794 | Private *p = m_datamap.value( r ); |
1795 | if ( p ) { |
1796 | p->externalCached = false; |
1797 | } |
1798 | reset(); |
1799 | } |
1800 | |
1801 | void ResourceAppointmentsRowModel::slotAppointmentToBeRemoved( Resource *r, int row ) |
1802 | { |
1803 | Q_UNUSED(row); |
1804 | // external appointments only, (Internal handled in slotProjectCalculated) |
1805 | Private *p = m_datamap.value( r ); |
1806 | if ( p ) { |
1807 | p->externalCached = false; |
1808 | } |
1809 | } |
1810 | |
1811 | void ResourceAppointmentsRowModel::slotAppointmentRemoved() |
1812 | { |
1813 | // external appointments only, (Internal handled in slotProjectCalculated) |
1814 | reset(); |
1815 | } |
1816 | |
1817 | void ResourceAppointmentsRowModel::slotAppointmentChanged( Resource *r, Appointment *a ) |
1818 | { |
1819 | Q_UNUSED(r); |
1820 | Q_UNUSED(a); |
1821 | // external appointments only, (Internal handled in slotProjectCalculated) |
1822 | // will not happen atm |
1823 | } |
1824 | |
1825 | void ResourceAppointmentsRowModel::slotProjectCalculated( ScheduleManager *sm ) |
1826 | { |
1827 | if ( sm == m_manager ) { |
1828 | setScheduleManager( sm ); |
1829 | } |
1830 | } |
1831 | |
1832 | ResourceGroup *ResourceAppointmentsRowModel::parentGroup( const QModelIndex &index ) const |
1833 | { |
1834 | if ( m_project == 0 ) { |
1835 | return 0; |
1836 | } |
1837 | Private *ch = static_cast<Private*>( index.internalPointer() ); |
1838 | if ( ch && ch->type == OT_Resource ) { |
1839 | return static_cast<ResourceGroup*>( ch->parent->ptr ); |
1840 | } |
1841 | return 0; |
1842 | } |
1843 | |
1844 | ResourceGroup *ResourceAppointmentsRowModel::resourcegroup( const QModelIndex &index ) const |
1845 | { |
1846 | if ( m_project == 0 ) { |
1847 | return 0; |
1848 | } |
1849 | Private *p = static_cast<Private*>( index.internalPointer() ); |
1850 | if ( p && p->type == OT_ResourceGroup ) { |
1851 | return static_cast<ResourceGroup*>( p->ptr ); |
1852 | } |
1853 | return 0; |
1854 | } |
1855 | |
1856 | Resource *ResourceAppointmentsRowModel::parentResource( const QModelIndex &index ) const |
1857 | { |
1858 | if ( m_project == 0 ) { |
1859 | return 0; |
1860 | } |
1861 | Private *ch = static_cast<Private*>( index.internalPointer() ); |
1862 | if ( ch && ( ch->type == OT_Appointment || ch->type == OT_External ) ) { |
1863 | return static_cast<Resource*>( ch->parent->ptr ); |
1864 | } |
1865 | return 0; |
1866 | } |
1867 | |
1868 | |
1869 | Resource *ResourceAppointmentsRowModel::resource( const QModelIndex &index ) const |
1870 | { |
1871 | if ( m_project == 0 ) { |
1872 | return 0; |
1873 | } |
1874 | Private *p = static_cast<Private*>( index.internalPointer() ); |
1875 | if ( p && p->type == OT_Resource ) { |
1876 | return static_cast<Resource*>( p->ptr ); |
1877 | } |
1878 | return 0; |
1879 | } |
1880 | |
1881 | Appointment *ResourceAppointmentsRowModel::parentAppointment( const QModelIndex &index ) const |
1882 | { |
1883 | if ( m_project == 0 || m_manager == 0 ) { |
1884 | return 0; |
1885 | } |
1886 | Private *ch = static_cast<Private*>( index.internalPointer() ); |
1887 | if ( ch && ch->type == OT_Interval ) { |
1888 | return static_cast<Appointment*>( ch->parent->ptr ); |
1889 | } |
1890 | return 0; |
1891 | } |
1892 | |
1893 | Appointment *ResourceAppointmentsRowModel::appointment( const QModelIndex &index ) const |
1894 | { |
1895 | if ( m_project == 0 || m_manager == 0 || ! index.isValid() ) { |
1896 | return 0; |
1897 | } |
1898 | Private *p = static_cast<Private*>( index.internalPointer() ); |
1899 | if ( p && ( p->type == OT_Appointment || p->type == OT_External ) ) { |
1900 | return static_cast<Appointment*>( p->ptr ); |
1901 | } |
1902 | return 0; |
1903 | } |
1904 | |
1905 | AppointmentInterval *ResourceAppointmentsRowModel::interval( const QModelIndex &index ) const |
1906 | { |
1907 | if ( m_project == 0 || m_manager == 0 ) { |
1908 | return 0; |
1909 | } |
1910 | Private *p = static_cast<Private*>( index.internalPointer() ); |
1911 | if ( p && p->type == OT_Interval ) { |
1912 | return &( p->interval ); |
1913 | } |
1914 | return 0; |
1915 | } |
1916 | |
1917 | Node *ResourceAppointmentsRowModel::node( const QModelIndex &idx ) const |
1918 | { |
1919 | Appointment *a = appointment( idx ); |
1920 | return ( a && a->node() ? a->node()->node() : 0 ); |
1921 | } |
1922 | |
1923 | |
1924 | //--------------------------------------------- |
1925 | ResourceAppointmentsGanttModel::ResourceAppointmentsGanttModel( QObject *parent ) |
1926 | : ResourceAppointmentsRowModel( parent ) |
1927 | { |
1928 | } |
1929 | |
1930 | ResourceAppointmentsGanttModel::~ResourceAppointmentsGanttModel() |
1931 | { |
1932 | } |
1933 | |
1934 | QVariant ResourceAppointmentsGanttModel::data( const ResourceGroup *g, int column, int role ) const |
1935 | { |
1936 | Q_UNUSED(column); |
1937 | switch( role ) { |
1938 | case KDGantt::ItemTypeRole: return KDGantt::TypeSummary; |
1939 | case KDGantt::StartTimeRole: return g->startTime( id() ); |
1940 | case KDGantt::EndTimeRole: return g->endTime( id() ); |
1941 | } |
1942 | return QVariant(); |
1943 | } |
1944 | |
1945 | QVariant ResourceAppointmentsGanttModel::data( const Resource *r, int column, int role ) const |
1946 | { |
1947 | Q_UNUSED(column); |
1948 | switch( role ) { |
1949 | case KDGantt::ItemTypeRole: return KDGantt::TypeSummary; |
1950 | case KDGantt::StartTimeRole: return r->startTime( id() ); |
1951 | case KDGantt::EndTimeRole: return r->endTime( id() ); |
1952 | } |
1953 | return QVariant(); |
1954 | } |
1955 | |
1956 | QVariant ResourceAppointmentsGanttModel::data( const Appointment *a, int column, int role ) const |
1957 | { |
1958 | Q_UNUSED(column); |
1959 | switch( role ) { |
1960 | case KDGantt::ItemTypeRole: return KDGantt::TypeMulti; |
1961 | case KDGantt::StartTimeRole: return a->startTime(); |
1962 | case KDGantt::EndTimeRole: return a->endTime(); |
1963 | } |
1964 | return QVariant(); |
1965 | } |
1966 | |
1967 | QVariant ResourceAppointmentsGanttModel::data( const AppointmentInterval *a, int column, int role ) const |
1968 | { |
1969 | Q_UNUSED(column); |
1970 | switch( role ) { |
1971 | case KDGantt::ItemTypeRole: return KDGantt::TypeTask; |
1972 | case KDGantt::StartTimeRole: return a->startTime(); |
1973 | case KDGantt::EndTimeRole: return a->endTime(); |
1974 | } |
1975 | return QVariant(); |
1976 | } |
1977 | |
1978 | QVariant ResourceAppointmentsGanttModel::data( const QModelIndex &index, int role ) const |
1979 | { |
1980 | //kDebug(planDbg())<<index<<role; |
1981 | if ( m_project == 0 || ! index.isValid() ) { |
1982 | return QVariant(); |
1983 | } |
1984 | if ( role == KDGantt::ItemTypeRole || |
1985 | role == KDGantt::StartTimeRole || |
1986 | role == KDGantt::EndTimeRole || |
1987 | role == KDGantt::TaskCompletionRole ) |
1988 | { |
1989 | if ( ResourceGroup *g = resourcegroup( index ) ) { |
1990 | return data( g, index.column(), role ); |
1991 | } |
1992 | if ( Resource *r = resource( index ) ) { |
1993 | return data( r, index.column(), role ); |
1994 | } |
1995 | if ( m_manager == 0 ) { |
1996 | return QVariant(); |
1997 | } |
1998 | if ( Appointment *a = appointment( index ) ) { |
1999 | return data( a, index.column(), role ); |
2000 | } |
2001 | if ( AppointmentInterval *i = interval( index ) ) { |
2002 | return data( i, index.column(), role ); |
2003 | } |
2004 | return QVariant(); |
2005 | } |
2006 | return ResourceAppointmentsRowModel::data( index, role ); |
2007 | } |
2008 | |
2009 | } // namespace KPlato |
2010 | |
2011 | #include "kptresourceappointmentsmodel.moc" |
2012 | |