kplato

kptresourcespanel.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2003 Thomas Zander <zander@kde.org>
3 Copyright (C) 2004, 2005 Dag Andersen <danders@get2net.dk>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19*/
20
21#include "kptresourcespanel.h"
22#include "kptproject.h"
23#include "kptresourcedialog.h"
24#include "kptcommand.h"
25
26#include <kdebug.h>
27#include <tdelistview.h>
28#include <tdemessagebox.h>
29#include <tdelocale.h>
30#include <tdeabc/addressee.h>
31#include <tdeabc/addresseedialog.h>
32
33#include <tqgroupbox.h>
34#include <tqheader.h>
35#include <tqlistbox.h>
36#include <tqlineedit.h>
37#include <tqlistview.h>
38#include <tqpushbutton.h>
39
41
42namespace KPlato
43{
44
45class GroupItem;
46class ResourcesPanelGroupLVItem;
47class ResourcesPanelResourceItem;
48class Part;
49
50class ResourcesPanelResourceItem {
51public:
52 enum State {None, Modified, New};
53
54 ResourcesPanelResourceItem(Resource *res, State state = None)
55 : m_originalResource(0),
56 m_state(state) {
57 if (state == New) {
58 m_resource = res;
59 } else {
60 m_originalResource = res;
61 m_resource = new Resource(res);
62 }
63 //kdDebug()<<k_funcinfo<<"("<<this<<")"<<" orgres="<<m_originalResource<<" newres="<<m_resource<<endl;
64 }
65 ~ResourcesPanelResourceItem() {
66 //kdDebug()<<k_funcinfo<<"("<<this<<") state="<<m_state<<endl;
67 delete m_resource;
68 }
69 void setState(State s) {
70 if (m_state == New)
71 return; // A new is allways new
72 m_state = s;
73 }
74 TQString name() { return m_resource->name(); }
75 void setName(const TQString &newName) {
76 m_resource->setName(newName);
77 setState(Modified);
78 }
79 Resource *takeResource() {
80 Resource *r = m_resource;
81 m_resource = 0;
82 return r;
83 }
84 KCommand *saveResource(Part *part, ResourceGroup *group);
85
86 Resource *m_originalResource;
87 Resource *m_resource; // work on a local copy
88 State m_state;
89};
90KCommand *ResourcesPanelResourceItem::saveResource(Part *part, ResourceGroup *group) {
91 KMacroCommand *m=0;
92 if (m_state == New) {
93 //kdDebug()<<k_funcinfo<<"Add resource: "<<m_resource->name()<<endl;
94 if (!m) m = new KMacroCommand("Add resource");
95 m->addCommand(new AddResourceCmd(part, group, takeResource()));
96 } else if (m_state == Modified) {
97 //kdDebug()<<k_funcinfo<<"Modify resource: "<<m_originalResource->name()<<endl;
98 KCommand *cmd = ResourceDialog::buildCommand(m_originalResource, *m_resource, part);
99 if (cmd) {
100 if (!m) m = new KMacroCommand("Modify resource");
101 m->addCommand(cmd);
102 }
103 }
104 return m;
105}
106
107class ResourceLBItem : public TQListBoxText {
108public:
109 ResourceLBItem(ResourcesPanelResourceItem *item) {
110 m_resourceItem = item; setText(item->name());
111 }
112 TQString name() { return m_resourceItem->name(); }
113 void setName(const TQString &newName) {
114 setText(newName);
115 m_resourceItem->setName(newName);
116 }
117
118 ResourcesPanelResourceItem *m_resourceItem;
119};
120
121
122//-------------------
123class GroupItem {
124public:
125 enum State {None=0, Modified=1, New=2}; //bitmap
126
127 GroupItem(ResourceGroup *group, State state = None) {
128 m_group = group;
129 m_name = group->name();
130 m_state = state;
131 m_resourceItems.setAutoDelete(true);
132 m_deletedItems.setAutoDelete(true);
133 //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
134 }
135 ~GroupItem() {
136 //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
137 if (m_state & New) {
138 delete m_group;
139 }
140 }
141 void setState(State s) { m_state |= s; }
142 void setName(const TQString &newName) {
143 m_name = newName;
144 if (m_state & New)
145 m_group->setName(newName);
146 setState(Modified);
147 //kdDebug()<<k_funcinfo<<"New name: '"<<newName<<"', group name: '"<<m_group->name()<<"' state="<<m_state<<endl;
148 }
149 void addResource(ResourcesPanelResourceItem *item) {
150 //kdDebug()<<k_funcinfo<<" add: "<<(item?item->name():"")<<" ("<<item<<")"<<endl;
151 m_resourceItems.append(item);
152 }
153 void deleteResource(ResourcesPanelResourceItem *item) {
154 //kdDebug()<<k_funcinfo<<" Deleted: "<<item->m_name<<" ("<<item<<")"<<endl;
155 m_resourceItems.take(m_resourceItems.findRef(item));
156 if (item->m_state == ResourcesPanelResourceItem::New)
157 delete item;
158 else
159 m_deletedItems.append(item);
160 //kdDebug()<<k_funcinfo<<"No of items now="<<m_resourceItems.count()<<", no of deleted items="<<m_deletedItems.count()<<endl;
161 }
162 ResourceGroup *takeGroup() {
163 //kdDebug()<<k_funcinfo<<"("<<m_group<<")"<<endl;
164 ResourceGroup *g = m_group;
165 m_group = 0;
166 return g;
167 }
168 void saveResources() {
169 ResourcesPanelResourceItem *item = m_resourceItems.first();
170 while ((item = m_resourceItems.take())) {
171 //kdDebug()<<k_funcinfo<<item->m_resource->name()<<endl;
172 m_group->addResource(item->takeResource(), 0);
173 delete item;
174 }
175 }
176 ResourceGroup *m_group;
177 TQString m_name;
178 TQPtrList<ResourcesPanelResourceItem> m_resourceItems;
179 TQPtrList<ResourcesPanelResourceItem> m_deletedItems;
180 int m_state;
181};
182
183class ResourcesPanelGroupLVItem : public TDEListViewItem {
184public:
185 ResourcesPanelGroupLVItem(ResourcesPanel &pan, TDEListView *lv, GroupItem *item)
186 : TDEListViewItem(lv, item->m_name),
187 m_group(item),
188 panel(pan) {
189
190 setRenameEnabled(0, false);
191 //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
192 }
193 ~ResourcesPanelGroupLVItem() {
194 //kdDebug()<<k_funcinfo<<"("<<this<<")"<<endl;
195 }
196 void setName(const TQString &newName) {
197 setText(0, newName);
198 m_group->setName(newName);
199 }
200 void deleteGroup() {
201 delete m_group;
202 m_group = 0;
203 }
204 GroupItem *takeGroup() {
205 //kdDebug()<<k_funcinfo<<"("<<m_group<<")"<<endl;
206 GroupItem *g = m_group;
207 m_group = 0;
208 return g;
209 }
210 GroupItem *m_group;
211 ResourcesPanel &panel;
212 TQString oldText;
213
214protected:
215 virtual void cancelRename(int col) {
216 //kdDebug()<<k_funcinfo<<endl;
217 if (col == 0 && oldText.isEmpty()){
218 return;
219 }
220 panel.renameStopped(this);
221 TDEListViewItem::cancelRename(col);
222 setRenameEnabled(col, false);
223 }
224};
225
227
228ResourcesPanel::ResourcesPanel(TQWidget *parent, Project *p) : ResourcesPanelBase(parent) {
229 project = p;
230 m_groupItem = 0;
231 m_blockResourceRename = false;
232 m_renameItem = 0;
233
234 bEditResource->setEnabled(false);
235 bRemoveResource->setEnabled(false);
236 resourceName->setEnabled(false);
237
238 listOfGroups->header()->setStretchEnabled(true, 0);
239 listOfGroups->setSorting(0);
240 listOfGroups->setShowSortIndicator(true);
241 listOfGroups->setDefaultRenameAction (TQListView::Accept);
242 bAdd->setEnabled(true);
243
244 m_groupItems.setAutoDelete(true);
245 m_deletedGroupItems.setAutoDelete(true);
246
247 TQPtrListIterator<ResourceGroup> git(project->resourceGroups());
248 for(; git.current(); ++git) {
249 ResourceGroup *grp = git.current();
250 GroupItem *groupItem = new GroupItem(grp);
251 //kdDebug()<<k_funcinfo<<" Added group: "<<groupItem->m_name<<" ("<<groupItem<<")"<<endl;
252 TQPtrListIterator<Resource> rit(grp->resources());
253 for(; rit.current(); ++rit) {
254 Resource *res = rit.current();
255 ResourcesPanelResourceItem *ritem = new ResourcesPanelResourceItem(res);
256 groupItem->addResource(ritem);
257 //kdDebug()<<k_funcinfo<<" Added resource: "<<ritem->m_name<<" ("<<ritem<<")"<<endl;
258 }
259 m_groupItems.append(groupItem);
260 new ResourcesPanelGroupLVItem(*this, listOfGroups, groupItem);
261 }
262 listOfGroups->setSelected(listOfGroups->firstChild(), true);
263 slotGroupChanged();
264
265 connect(bAdd, TQ_SIGNAL(clicked()), TQ_SLOT(slotAddGroup()));
266 connect(bRemove, TQ_SIGNAL(clicked()), TQ_SLOT(slotDeleteGroup()));
267 connect(listOfGroups, TQ_SIGNAL(selectionChanged()), TQ_SLOT(slotGroupChanged()));
268 connect(listOfGroups, TQ_SIGNAL(doubleClicked(TQListViewItem*, const TQPoint&, int)), TQ_SLOT(slotListDoubleClicked(TQListViewItem*, const TQPoint&, int)));
269 connect(listOfGroups, TQ_SIGNAL(itemRenamed(TQListViewItem*, int)), TQ_SLOT(slotItemRenamed(TQListViewItem*, int)));
270
271 connect(bAddResource, TQ_SIGNAL( clicked() ), this, TQ_SLOT ( slotAddResource() ));
272 connect(bEditResource, TQ_SIGNAL( clicked() ), this, TQ_SLOT ( slotEditResource() ));
273 connect(bRemoveResource, TQ_SIGNAL( clicked() ), this, TQ_SLOT ( slotDeleteResource() ));
274 connect(listOfResources, TQ_SIGNAL(selectionChanged(TQListBoxItem*)), TQ_SLOT(slotResourceChanged(TQListBoxItem*)));
275 connect(listOfResources, TQ_SIGNAL(currentChanged(TQListBoxItem*)), TQ_SLOT(slotCurrentChanged(TQListBoxItem*)));
276 connect(resourceName, TQ_SIGNAL(textChanged(const TQString&)), TQ_SLOT(slotResourceRename(const TQString&)));
277
278
279 // Internal hacks, to get renaming to behave
280 // Uses signals to not get in the way of TQListView
281 connect(this, TQ_SIGNAL(renameStarted(TQListViewItem*, int)), TQ_SLOT(slotRenameStarted(TQListViewItem*, int)));
282 connect(this, TQ_SIGNAL(startRename(TQListViewItem*, int)), TQ_SLOT(slotStartRename(TQListViewItem*, int)));
283 connect(this, TQ_SIGNAL(selectionChanged()), TQ_SLOT(slotGroupChanged()));
284}
285
286void ResourcesPanel::slotAddGroup() {
287 //kdDebug()<<k_funcinfo<<endl;
288 ResourceGroup *r = new ResourceGroup(project);
289 GroupItem *gitem = new GroupItem(r, GroupItem::New);
290 m_groupItems.append(gitem);
291 ResourcesPanelGroupLVItem *groupItem = new ResourcesPanelGroupLVItem(*this, listOfGroups, gitem);
292
293 slotListDoubleClicked(groupItem, TQPoint(), 0);
294}
295
296void ResourcesPanel::slotDeleteGroup() {
297 //kdDebug()<<k_funcinfo<<endl;
298 ResourcesPanelGroupLVItem *groupLVItem = dynamic_cast<ResourcesPanelGroupLVItem*> (listOfGroups->selectedItem());
299 if (groupLVItem == 0)
300 return;
301
302 listOfResources->clear();
303
304 listOfGroups->takeItem(groupLVItem); // remove from listbox
305 m_groupItems.take(m_groupItems.findRef(groupLVItem->m_group)); // remove GroupItem from active list
306 m_deletedGroupItems.append(groupLVItem->takeGroup()); // remove GroupItem from GroupLVItem and add to deleted list
307
308 //kdDebug()<<k_funcinfo<<" No of deleted groups="<<m_deletedGroupItems.count()<<", now "<<m_groupItems.count()<<" groups left"<<endl;
309
310 delete groupLVItem; // delete GroupLVItem (but not GroupItem)
311 emit changed();
312}
313
314void ResourcesPanel::slotAddResource() {
315 if (!m_groupItem) {
316 KMessageBox::sorry(this, i18n("Resources belong to resource groups, select the group first to add a new resource to"));
317 return;
318 }
319 listOfResources->setSelected(listOfResources->selectedItem(), false);
320 Resource *r = new Resource(project);
321 ResourceDialog *dia = new ResourceDialog(*project, r);
322 if (dia->exec()) {
323 KCommand *cmd = dia->buildCommand();
324 if (cmd) {
325 cmd->execute(); // modifications -> r
326 delete cmd;
327 }
328 ResourcesPanelResourceItem *resourceItem = new ResourcesPanelResourceItem(r, ResourcesPanelResourceItem::New);
329 m_groupItem->m_group->addResource(resourceItem);
330 ResourceLBItem *item = new ResourceLBItem(resourceItem);
331 listOfResources->insertItem(item);
332 resourceName->clear();
333 listOfResources->setSelected(item, true);
334 emit changed();
335 //kdDebug()<<k_funcinfo<<" Added: "<<resourceItem->name()<<" to "<<m_groupItem->m_group->m_name<<endl;
336 } else {
337 delete r;
338 }
339 delete dia;
340}
341
342void ResourcesPanel::slotEditResource() {
343 //kdDebug()<<k_funcinfo<<endl;
344 ResourceLBItem *item = dynamic_cast<ResourceLBItem*> (listOfResources->selectedItem());
345 if(item == 0) return;
346 Resource *r = item->m_resourceItem->m_resource;
347 ResourceDialog *dia = new ResourceDialog(*project, r);
348 if (dia->exec()) {
349 KCommand *cmd = dia->buildCommand();
350 if (cmd) {
351 cmd->execute(); // modifications -> r
352 delete cmd;
353 }
354 resourceName->setText(r->name());
355 item->m_resourceItem->setState(ResourcesPanelResourceItem::Modified);
356 item->setName(r->name()); // refresh list
357 listOfResources->triggerUpdate(false);
358 emit changed();
359 }
360 delete dia;
361}
362
363void ResourcesPanel::slotDeleteResource() {
364 //kdDebug()<<k_funcinfo<<endl;
365 ResourceLBItem *item = dynamic_cast<ResourceLBItem*> (listOfResources->selectedItem());
366 if(item == 0) return;
367
368 //Can't delete resource from unselected group
369 if(m_groupItem == 0) return;
370
371 m_groupItem->m_group->deleteResource(item->m_resourceItem);
372 listOfResources->removeItem(listOfResources->currentItem());
373
374 emit changed();
375}
376
377/* Select another resource */
378void ResourcesPanel::slotResourceChanged( TQListBoxItem *item) {
379 if (!item) {
380 resourceName->setEnabled(false);
381 bEditResource->setEnabled(false);
382 bRemoveResource->setEnabled(false);
383 return;
384 }
385 resourceName->setText( ((ResourceLBItem *)item)->name());
386 resourceName->setEnabled(true);
387 bEditResource->setEnabled(true);
388 bRemoveResource->setEnabled(true);
389}
390
391/* Select another resource */
392void ResourcesPanel::slotCurrentChanged( TQListBoxItem *item) {
393 if (item && !item->isSelected()) {
394 listOfResources->setSelected(item, true);
395 }
396}
397
398void ResourcesPanel::slotResourceRename( const TQString &newName) {
399 TQListBoxItem *item = listOfResources->selectedItem();
400 if(!item || m_blockResourceRename) return;
401
402 ResourceLBItem *i = dynamic_cast<ResourceLBItem *>(item);
403 if (i->name() == newName) return;
404
405 i->setName(newName);
406 listOfResources->triggerUpdate(false);
407
408 emit changed();
409}
410
411bool ResourcesPanel::ok() {
412 return true;
413}
414
415KCommand *ResourcesPanel::buildCommand(Part *part) {
416 KMacroCommand *m=0;
417 GroupItem *gitem;
418
419 TQString cmdName = "Modify resourcegroups";
420 TQPtrListIterator<GroupItem> dgit(m_deletedGroupItems);
421 for (; (gitem = dgit.current()) != 0; ++dgit) {
422 if (!(gitem->m_state & GroupItem::New)) {
423 if (!m) m = new KMacroCommand(cmdName);
424 //kdDebug()<<k_funcinfo<<"Remove group: '"<<gitem->m_name<<"'"<<endl;
425 m->addCommand(new RemoveResourceGroupCmd(part, gitem->takeGroup()));
426 }
427 }
428
429 TQPtrListIterator<GroupItem> git(m_groupItems);
430 for (; (gitem = git.current()) != 0; ++git) {
431 //kdDebug()<<k_funcinfo<<"Group: "<<gitem->m_name<<" has "<<gitem->m_resourceItems.count()<<" resources"<<" and "<<gitem->m_deletedItems.count()<<" deleted resources"<<endl;
432 //First remove deleted resources from group
433 TQPtrListIterator<ResourcesPanelResourceItem> dit(gitem->m_deletedItems);
434 ResourcesPanelResourceItem *ditem;
435 for (; (ditem = dit.current()) != 0; ++dit) {
436 if (!m) m = new KMacroCommand(cmdName);
437 //kdDebug()<<k_funcinfo<<" Deleting resource: '"<<ditem->m_originalResource->name()<<"'"<<endl;
438 m->addCommand(new RemoveResourceCmd(part, gitem->m_group, ditem->m_originalResource));
439 }
440 // Now add/modify group/resources
441 if (gitem->m_state & GroupItem::New) {
442 if (!m) m = new KMacroCommand(cmdName);
443 //kdDebug()<<k_funcinfo<<" Adding group: '"<<gitem->m_name<<"'"<<endl;
444 gitem->saveResources();
445 m->addCommand(new AddResourceGroupCmd(part, gitem->takeGroup()));
446 continue;
447 }
448 ResourceGroup *rg = gitem->takeGroup();
449 if (gitem->m_state & GroupItem::Modified) {
450 if (gitem->m_name != rg->name()) {
451 if (!m) m = new KMacroCommand(cmdName);
452 //kdDebug()<<k_funcinfo<<" Modifying group: '"<<gitem->m_name<<"'"<<endl;
453 m->addCommand(new ModifyResourceGroupNameCmd(part, rg, gitem->m_name));
454 }
455 }
456 TQPtrListIterator<ResourcesPanelResourceItem> it(gitem->m_resourceItems);
457 for (; it.current() != 0; ++it) {
458 KCommand *cmd = it.current()->saveResource(part, rg);
459 if (cmd) {
460 if (!m) m = new KMacroCommand(cmdName);
461 m->addCommand(cmd);
462 }
463 }
464 }
465 return m;
466}
467
468void ResourcesPanel::slotGroupChanged() {
469 slotGroupChanged(listOfGroups->selectedItem());
470}
471
472void ResourcesPanel::slotGroupChanged(TQListViewItem *itm) {
473 ResourcesPanelGroupLVItem *item = static_cast<ResourcesPanelGroupLVItem*>(itm);
474 if (!item) {
475 bAdd->setEnabled(true);
476 bRemove->setEnabled(false);
477 listOfResources->clear();
478 resourceName->clear();
479 resourceGroupBox->setEnabled(false);
480 return;
481 }
482 m_blockResourceRename = true;
483 resourceName->clear();
484 resourceName->setEnabled(false);
485 m_blockResourceRename = false;
486
487 m_groupItem = item;
488 listOfResources->clear();
489
490 TQPtrListIterator<ResourcesPanelResourceItem> it(m_groupItem->m_group->m_resourceItems);
491 for ( ; it.current(); ++it ) {
492 listOfResources->insertItem(new ResourceLBItem(it.current()));
493 //kdDebug()<<k_funcinfo<<"Insert resource item: "<<it.current()->name()<<endl;
494 }
495 bAdd->setEnabled(true);
496 bRemove->setEnabled(true);
497 slotResourceChanged(0);
498 resourceGroupBox->setEnabled(true);
499}
500
501void ResourcesPanel::slotListDoubleClicked(TQListViewItem* item, const TQPoint&, int col) {
502 //kdDebug()<<k_funcinfo<<(item?item->text(0):"")<<endl;
503 if (m_renameItem)
504 return;
505 slotStartRename(item, col);
506}
507
508void ResourcesPanel::slotItemRenamed(TQListViewItem *item, int col) {
509 //kdDebug()<<k_funcinfo<<item->text(0)<<endl;
510 item->setRenameEnabled(col, false);
511 m_renameItem = 0;
512 if (col != 0) {
513 renameStopped(item);
514 emit changed();
515 return;
516 }
517 if (item->text(0).isEmpty()) {
518 item->setText(0, static_cast<ResourcesPanelGroupLVItem*>(item)->oldText); // keep the old name
519 }
520 if (item->text(0).isEmpty()) {
521 // Not allowed
522 //kdDebug()<<k_funcinfo<<"name empty"<<endl;
523 emit startRename(item, 0);
524 return;
525 }
526 static_cast<ResourcesPanelGroupLVItem*>(item)->setName(item->text(0));
527 bRemove->setEnabled(listOfGroups->selectedItem());
528 bAdd->setEnabled(listOfGroups->selectedItem());
529 renameStopped(item);
530 emit changed();
531}
532
533void ResourcesPanel::slotRenameStarted(TQListViewItem */*item*/, int /*col*/) {
534 //kdDebug()<<k_funcinfo<<(item?item->text(0):"")<<endl;
535 if (listOfGroups->isRenaming()) {
536 bRemove->setEnabled(false);
537 bAdd->setEnabled(false);
538 }
539}
540
541void ResourcesPanel::slotStartRename(TQListViewItem *item, int col) {
542 //kdDebug()<<k_funcinfo<<(item?item->text(0):"")<<endl;
543 static_cast<ResourcesPanelGroupLVItem*>(item)->oldText = item->text(col);
544 item->setRenameEnabled(col, true);
545 item->startRename(col);
546 m_renameItem = item;
547
548 emit renameStarted(item, col);
549}
550
551// We don't get notified when rename is cancelled, this is called from the item
552void ResourcesPanel::renameStopped(TQListViewItem *) {
553 //kdDebug()<<k_funcinfo<<endl;
554 m_renameItem = 0;
555 emit selectionChanged();
556}
557
558
559} //KPlato namespace
560
561#include "kptresourcespanel.moc"
Project is the main node in a project, it contains child nodes and possibly sub-projects.
Definition kptproject.h:52
This class represents a group of similar resources to be assigned to a task e.g.
Definition kptresource.h:66