diff --git a/src/libs/models/kptcommonstrings.cpp b/src/libs/models/kptcommonstrings.cpp index 3bdfacf8..c3373f73 100644 --- a/src/libs/models/kptcommonstrings.cpp +++ b/src/libs/models/kptcommonstrings.cpp @@ -1,204 +1,198 @@ /* This file is part of the KDE project Copyright (C) 2009, 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ // clazy:excludeall=qstring-arg #include "kptcommonstrings.h" -#include - #include namespace KPlato { QString ToolTip::nodeName() { return xi18nc("@info:tooltip", "The name of the task"); } QString ToolTip::nodeType() { return xi18nc("@info:tooltip", "Task type"); } QString ToolTip::nodeResponsible() { return xi18nc("@info:tooltip", "The person responsible for this task"); } QString ToolTip::allocation() { return xi18nc("@info:tooltip", "List of resource allocations"); } QString ToolTip::nodeConstraint() { return xi18nc("@info:tooltip", "The timing constraint type"); } QString ToolTip::nodeConstraintStart() { return xi18nc("@info:tooltip", "Constraint start time"); } QString ToolTip::nodeConstraintEnd() { return xi18nc("@info:tooltip", "Constraint end time"); } QString ToolTip::nodeDescription() { return xi18nc("@info:tooltip", "Task notes"); } QString ToolTip::nodeWBS() { return xi18nc("@info:tooltip", "Work Breakdown Structure Code"); } QString ToolTip::nodeLevel() { return xi18nc("@info:tooltip", "Node level"); } QString ToolTip::nodeRisk() { return xi18nc("@info:tooltip", "Risk controls the PERT distribution used when calculating the actual estimate for this task"); } QString ToolTip::nodePriority() { return xi18nc("@info:tooltip", "Scheduling priority.Atm. only the TJ Scheduler supports priority."); } QString ToolTip::nodeRunningAccount() { return xi18nc("@info:tooltip", "Account for running costs"); } QString ToolTip::nodeStartupAccount() { return xi18nc("@info:tooltip", "Account for cost incurred at startup of the task"); } QString ToolTip::nodeStartupCost() { return xi18nc("@info:tooltip", "The cost incurred at startup of the task"); } QString ToolTip::nodeShutdownAccount() { return xi18nc("@info:tooltip", "Account for cost incurred at shutdown of the task"); } QString ToolTip::nodeShutdownCost() { return xi18nc("@info:tooltip", "The cost incurred at shutdown of the task"); } QString ToolTip::nodeStartTime() { return xi18nc("@info:tooltip", "Planned start time"); } QString ToolTip::nodeEndTime() { return xi18nc("@info:tooltip", "Planned finish time"); } QString ToolTip::nodeEarlyStart() { return xi18nc("@info:tooltip", "Earliest start time allowed by dependencies"); } QString ToolTip::nodeEarlyFinish() { return xi18nc("@info:tooltip", "Earliest finish time allowed by dependencies"); } QString ToolTip::nodeLateStart() { return xi18nc("@info:tooltip", "Latest start time allowed by dependencies"); } QString ToolTip::nodeLateFinish() { return xi18nc("@info:tooltip", "Latest finish time allowed by dependencies"); } QString ToolTip::nodeDuration() { return xi18nc("@info:tooltip", "The planned duration"); } QString ToolTip::nodeVarianceDuration() { return xi18nc("@info:tooltip", "The variance of the duration"); } QString ToolTip::nodeOptimisticDuration() { return xi18nc("@info:tooltip", "The optimistic duration"); } QString ToolTip::nodePessimisticDuration() { return xi18nc("@info:tooltip", "The pessimistic duration"); } QString ToolTip::nodePositiveFloat() { return xi18nc("@info:tooltip", "The duration by which a tasks start can be delayed without affecting the project completion time"); } QString ToolTip::nodeNegativeFloat() { return xi18nc("@info:tooltip", "The duration by which the duration of a task or path has to be reduced in order to fulfill a timing constraint"); } QString WhatsThis::nodeNegativeFloat() { return xi18nc("@info:whatsthis", "Negative float is the duration by which the duration of a task or path has to be reduced in order to fulfill a timing constraint."); } QString ToolTip::nodeFreeFloat() { return xi18nc("@info:tooltip", "The duration by which a task can be delayed or extended without affecting the start of any succeeding task"); } QString WhatsThis::nodeFreeFloat() { return xi18nc("@info:whatsthis", "Free float is the duration by which a task can be delayed or extended without affecting the start of any succeeding task."); } QString ToolTip::nodeStartFloat() { return xi18nc("@info:tooltip", "The duration from Early Start to Late Start"); } QString WhatsThis::nodeStartFloat() { return xi18nc("@info:whatsthis", "Start float is the duration from Early Start to Late Start."); } QString ToolTip::nodeFinishFloat() { return xi18nc("@info:tooltip", "The duration from Early Finish to Late Finish"); } QString WhatsThis::nodeFinishFloat() { return xi18nc("@info:whatsthis", "Finish float is the duration from Early Finish to Late Finish."); } QString ToolTip::nodeAssignment() { return xi18nc("@info:tooltip", "The resources assigned to the task"); } QString ToolTip::nodeStatus() { return xi18nc("@info:tooltip", "Task status"); } QString ToolTip::nodeCompletion() { return xi18nc("@info:tooltip", "Task completion"); } QString ToolTip::nodePlannedEffortTo() { return xi18nc("@info:tooltip", "Planned effort"); } QString ToolTip::nodeActualEffortTo() { return xi18nc("@info:tooltip", "Actual effort"); } QString ToolTip::nodeRemainingEffort() { return xi18nc("@info:tooltip", "Remaining effort"); } QString ToolTip::nodePlannedCostTo() { return xi18nc("@info:tooltip", "Planned cost"); } QString ToolTip::nodeActualCostTo() { return xi18nc("@info:tooltip", "Actual cost"); } QString ToolTip::completionStartedTime() { return xi18nc("@info:tooltip", "Time when task was actually started"); } QString ToolTip::completionStarted() { return xi18nc("@info:tooltip", "Shows if the task is started"); } QString ToolTip::completionFinishedTime() { return xi18nc("@info:tooltip", "Time when task was actually finished"); } QString ToolTip::completionFinished() { return xi18nc("@info:tooltip", "Shows if the task is finished"); } QString ToolTip::completionStatusNote() { return xi18nc("@info:tooltip", "Status Note"); } QString ToolTip::estimateExpected() { return xi18nc("@info:tooltip", "Calculated expected estimate"); } QString ToolTip::estimateVariance() { return xi18nc("@info:tooltip", "Calculated estimate variance"); } QString ToolTip::estimateOptimistic() { return xi18nc("@info:tooltip", "Optimistic estimate"); } QString ToolTip::estimatePessimistic() { return xi18nc("@info:tooltip", "Pessimistic estimate"); } QString ToolTip::estimateType() { return xi18nc("@info:tooltip", "Type of estimate"); } QString ToolTip::estimateCalendar() { return xi18nc("@info:tooltip", "The calendar used when estimate type is Duration"); } QString ToolTip::estimate() { return xi18nc("@info:tooltip", "The most likely estimate"); } QString ToolTip::optimisticRatio() { return xi18nc("@info:tooltip", "Optimistic estimate"); } QString ToolTip::pessimisticRatio() { return xi18nc("@info:tooltip", "Pessimistic estimate"); } QString ToolTip::riskType() { return xi18nc("@info:tooltip", "Type of risk"); } QString ToolTip::nodeSchedulingStatus() { return xi18nc("@info:tooltip", "Shows the tasks scheduling status"); } QString ToolTip::nodeNotScheduled() { return xi18nc("@info:tooltip", "The task has not been scheduled"); } QString ToolTip::nodeAssignmentMissing() { return i18n("An effort has been estimated, but no resource has been assigned"); } QString ToolTip::nodeResourceOverbooked() { return xi18nc("@info:tooltip", "A resource assigned to this task is overbooked"); } QString ToolTip::nodeResourceUnavailable() { return xi18nc("@info:tooltip", "A resource assigned to this task is not available"); } QString ToolTip::nodeConstraintsError() { return xi18nc("@info:tooltip", "A timing constraint could not be met"); } QString ToolTip::nodeEffortNotMet() { return xi18nc("@info:tooltip", "The assigned resource could not meet the estimated effort"); } QString ToolTip::nodeSchedulingError() { return xi18nc("@info:tooltip", "A scheduling error occurred"); } QString ToolTip::nodeBCWS() { return xi18nc("@info:tooltip", "Budgeted Cost of Work Scheduled"); } QString ToolTip::nodeBCWP() { return xi18nc("@info:tooltip", "Budgeted Cost of Work Performed"); } QString ToolTip::nodeACWP() { return xi18nc("@info:tooltip", "Actual Cost of Work Performed"); } QString ToolTip::nodePerformanceIndex() { return i18n("Schedule performance index (BCWP/BCWS)"); } QString ToolTip::resourceName() { return xi18nc("@info:tooltip", "The name of the resource"); } QString ToolTip::resourceOrigin() { return xi18nc("@info:tooltip", "The origin of the resource"); } QString ToolTip::resourceType() { return xi18nc("@info:tooltip", "The type of the resource"); } QString ToolTip::resourceInitials() { return xi18nc("@info:tooltip", "The initials of the resource"); } QString ToolTip::resourceEMail() { return xi18nc("@info:tooltip", "The e-mail address of the resource"); } QString ToolTip::resourceCalendar() { return xi18nc("@info:tooltip", "The calendar defines when the resource is working"); } QString ToolTip::resourceUnits() { return xi18nc("@info:tooltip", "The maximum load that can be assigned"); } QString ToolTip::resourceAvailableFrom() { return xi18nc("@info:tooltip", "Defines when the resource is available to the project"); } QString ToolTip::resourceAvailableUntil() { return xi18nc("@info:tooltip", "Defines when the resource is available to the project"); } QString ToolTip::resourceNormalRate() { return xi18nc("@info:tooltip", "The cost pr hour, normal hours"); } QString ToolTip::resourceOvertimeRate() { return xi18nc("@info:tooltip", "The cost pr hour, overtime hours"); } QString ToolTip::resourceFixedCost() { return xi18nc("@info:tooltip", "The fixed cost"); } QString ToolTip::resourceAccount() { return xi18nc("@info:tooltip", "The account where the resource cost is accumulated"); } QString ToolTip::resourceGroupName() { return xi18nc("@info:tooltip", "The name of the resource group"); } QString ToolTip::resourceGroupOrigin() { return xi18nc("@info:tooltip", "The origin of the resource group"); } QString ToolTip::resourceGroupType() { return xi18nc("@info:tooltip", "The type of the resource group"); } QString ToolTip::resourceGroupUnits() { return xi18nc("@info:tooltip", "The aggregated units for the resources in the resource group"); } QString ToolTip::resourceGroupCoordinator() { return xi18nc("@info:tooltip", "The coordinator of the resource group"); } QString ToolTip::accountName() { return xi18nc("@info:tooltip", "The name of the account"); } QString ToolTip::accountDescription() { return xi18nc("@info:tooltip", "The description of the account"); } QString ToolTip::scheduleName() { return xi18nc("@info:tooltip", "The name and scheduling mode of the schedule"); } QString ToolTip::scheduleState() { return xi18nc("@info:tooltip", "The schedules state"); } QString ToolTip::scheduleOverbooking() { return xi18nc("@info:tooltip", "Controls resource overbooking when scheduling"); } QString WhatsThis::scheduleOverbooking() { return xi18nc("@info:whatsthis", "Controls resource overbooking when scheduling." "If overbooking is allowed, a resource may be booked (on working days) to work more than it is available. This can happen if the resource is allocated to multiple tasks or are booked on other projects." "If overbooking is to be avoided, resources will not be booked more than they are available. On resource conflict, tasks will be delayed until the resource is available." ); } QString ToolTip::scheduleDistribution() { return xi18nc("@info:tooltip", "The distribution to be used during scheduling"); } QString WhatsThis::scheduleDistribution() { return xi18nc("@info:whatsthis", "The distribution to be used during scheduling" "If distribution is 'None', the tasks estimate is used as is during scheduling." "If distribution is 'PERT', the estimate used is calculated based on the entered optimistic- (O), pessimistic-(P) and most likely (M) estimate. The formula used for this is (O + 4 * M + P) / 6." ); } QString ToolTip::scheduleCalculate() { return xi18nc("@info:tooltip", "Defines the schedules to be calculated"); } QString ToolTip::scheduleStart() { return xi18nc("@info:tooltip", "The scheduled start time"); } QString ToolTip::scheduleFinish() { return xi18nc("@info:tooltip", "The scheduled finish time"); } QString ToolTip::schedulingDirection() { return xi18nc("@info:tooltip", "The scheduling direction"); } QString WhatsThis::schedulingDirection() { return xi18nc("@info:whatsthis", "The scheduling direction." "If direction is Forward, the project is scheduled starting at the projects earliest start time specified in the main project dialog." "If direction is Backward, the project is scheduled starting at the projects latest finish time specified in the main project dialog." ); } QString ToolTip::scheduleScheduler() { return xi18nc("@info:tooltip", "The scheduler used for calculating the project schedule"); } QString WhatsThis::scheduleScheduler() { return xi18nc("@info:whatsthis", "The scheduler used for calculating the project schedule." "The default built-in scheduler is the Network Scheduler." "Other schedulers presently available is RCPS if libRCPS is installed on your system. " "RCPS is a genetics based resource constrained project scheduler." ); } QString ToolTip::scheduleGranularity() { return xi18nc("@info:tooltip", "The granularity used when calculating the project schedule"); } QString ToolTip::scheduleMode() { return xi18nc("@info:tooltip", "The scheduling mode:" "" "Manual: Calculation must be initiated manually." "Auto: Calculation is initiated automatically." "" ""); } QString ToolTip::documentUrl() { return xi18nc("@info:tooltip", "The url of the document"); } QString ToolTip::documentType() { return xi18nc("@info:tooltip", "The type of the document"); } QString ToolTip::documentStatus() { return xi18nc("@info:tooltip", "The status of the document"); } QString ToolTip::documentSendAs() { return xi18nc("@info:tooltip", "Defines how this document is sent"); } QString ToolTip::calendarName() { return xi18nc("@info:tooltip", "The name of the calendar"); } QString ToolTip::calendarTimeZone() { return xi18nc("@info:tooltip", "The timezone of the calendar"); } QString ToolTip::relationParent() { return xi18nc("@info:tooltip", "The name of the required task"); } QString ToolTip::relationChild() { return xi18nc("@info:tooltip", "The name of the dependent task"); } QString ToolTip::relationType() { return xi18nc("@info:tooltip", "The type of relation"); } QString ToolTip::relationLag() { return xi18nc("@info:tooltip", "The relations time lag"); } - - // Work around string freeze - KUndo2MagicString UndoText::removeDocument() { return kundo2_i18n("Remove document"); } - } //namespace KPlato diff --git a/src/libs/models/kptcommonstrings.h b/src/libs/models/kptcommonstrings.h index 24640431..378736e8 100644 --- a/src/libs/models/kptcommonstrings.h +++ b/src/libs/models/kptcommonstrings.h @@ -1,179 +1,173 @@ /* This file is part of the KDE project Copyright (C) 2009, 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTCOMMONSTRINGS_H #define KPTCOMMONSTRINGS_H #include "planmodels_export.h" -class KUndo2MagicString; class QString; namespace KPlato { struct PLANMODELS_EXPORT ToolTip { static QString nodeName(); static QString nodeType(); static QString nodeResponsible(); static QString allocation(); static QString nodeConstraint(); static QString nodeConstraintStart(); static QString nodeConstraintEnd(); static QString nodeDescription(); static QString nodeWBS(); static QString nodeLevel(); static QString nodeRisk(); static QString nodePriority(); static QString nodeRunningAccount(); static QString nodeStartupAccount(); static QString nodeStartupCost(); static QString nodeShutdownAccount(); static QString nodeShutdownCost(); static QString nodeStartTime(); static QString nodeEndTime(); static QString nodeEarlyStart(); static QString nodeEarlyFinish(); static QString nodeLateStart(); static QString nodeLateFinish(); static QString nodeDuration(); static QString nodeVarianceDuration(); static QString nodeOptimisticDuration(); static QString nodePessimisticDuration(); static QString nodePositiveFloat(); static QString nodeNegativeFloat(); static QString nodeFreeFloat(); static QString nodeStartFloat(); static QString nodeFinishFloat(); static QString nodeAssignment(); static QString nodeStatus(); static QString nodeCompletion(); static QString nodePlannedEffortTo(); static QString nodeActualEffortTo(); static QString nodeRemainingEffort(); static QString nodePlannedCostTo(); static QString nodeActualCostTo(); static QString completionStartedTime(); static QString completionStarted(); static QString completionFinishedTime(); static QString completionFinished(); static QString completionStatusNote(); static QString estimateExpected(); static QString estimateVariance(); static QString estimateOptimistic(); static QString estimatePessimistic(); static QString estimateType(); static QString estimateCalendar(); static QString estimate(); static QString optimisticRatio(); static QString pessimisticRatio(); static QString riskType(); static QString nodeSchedulingStatus(); static QString nodeNotScheduled(); static QString nodeAssignmentMissing(); static QString nodeResourceOverbooked(); static QString nodeResourceUnavailable(); static QString nodeConstraintsError(); static QString nodeEffortNotMet(); static QString nodeSchedulingError(); static QString nodeBCWS(); static QString nodeBCWP(); static QString nodeACWP(); static QString nodePerformanceIndex(); static QString resourceName(); static QString resourceOrigin(); static QString resourceType(); static QString resourceInitials(); static QString resourceEMail(); static QString resourceCalendar(); static QString resourceUnits(); static QString resourceAvailableFrom(); static QString resourceAvailableUntil(); static QString resourceNormalRate(); static QString resourceOvertimeRate(); static QString resourceFixedCost(); static QString resourceAccount(); static QString resourceGroupName(); static QString resourceGroupOrigin(); static QString resourceGroupType(); static QString resourceGroupUnits(); static QString resourceGroupCoordinator(); static QString accountName(); static QString accountDescription(); static QString scheduleName(); static QString scheduleState(); static QString scheduleOverbooking(); static QString scheduleDistribution(); static QString scheduleCalculate(); static QString scheduleStart(); static QString scheduleFinish(); static QString schedulingDirection(); static QString scheduleScheduler(); static QString scheduleGranularity(); static QString scheduleMode(); static QString documentUrl(); static QString documentType(); static QString documentStatus(); static QString documentSendAs(); static QString calendarName(); static QString calendarTimeZone(); static QString relationParent(); static QString relationChild(); static QString relationType(); static QString relationLag(); }; //namespace ToolTip struct PLANMODELS_EXPORT WhatsThis { static QString nodeNegativeFloat(); static QString nodeFreeFloat(); static QString nodeStartFloat(); static QString nodeFinishFloat(); static QString scheduleOverbooking(); static QString scheduleDistribution(); static QString schedulingDirection(); static QString scheduleScheduler(); }; //namespace WhatsThis -struct PLANMODELS_EXPORT UndoText -{ - static KUndo2MagicString removeDocument(); -}; //namespace Undo - } //namespace KPlato #endif diff --git a/src/workpackage/view.cpp b/src/workpackage/view.cpp index 97a57a9c..4adb7d32 100644 --- a/src/workpackage/view.cpp +++ b/src/workpackage/view.cpp @@ -1,486 +1,485 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999, 2000 Torben Weis Copyright (C) 2002 - 2009, 2011, 2012 Dag Andersen Copyright (C) 2019 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ // clazy:excludeall=qstring-arg #include "view.h" #include "mainwindow.h" #include "taskworkpackageview.h" #include "workpackage.h" #include "taskcompletiondialog.h" #include "calligraplanworksettings.h" #include "kpttaskeditor.h" #include "kpttaskdescriptiondialog.h" #include "kptcommonstrings.h" #include "KoDocumentInfo.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "part.h" #include "factory.h" #include "kptviewbase.h" #include "kptdocumentseditor.h" #include "kptnode.h" #include "kptproject.h" #include "kpttask.h" #include "kptcommand.h" #include "kptdocuments.h" #include "kpttaskprogressdialog.h" #include "kptcalendar.h" #include #include "debugarea.h" namespace KPlatoWork { View::View(Part *part, QWidget *parent, KActionCollection *collection) : QStackedWidget(parent), m_part(part), m_scheduleActionGroup(new QActionGroup(this)), m_manager(0) { m_readWrite = part->isReadWrite(); debugPlanWork<addAction("package_remove_selected", actionRemoveSelectedPackages); connect(actionRemoveSelectedPackages, &QAction::triggered, this, &View::slotRemoveSelectedPackages); actionRemoveCurrentPackage = new QAction(koIcon("edit-delete"), i18n("Remove Package"), this); collection->addAction("package_remove_current", actionRemoveCurrentPackage); connect(actionRemoveCurrentPackage, &QAction::triggered, this, &View::slotRemoveCurrentPackage); actionViewList = new QAction(koIcon("view-list-tree"), i18n("List"), this); actionViewList->setToolTip(i18nc("@info:tooltip", "Select task list")); collection->addAction("view_list", actionViewList); connect(actionViewList, &QAction::triggered, this, &View::slotViewList); actionViewGantt = new QAction(koIcon("view-time-schedule"), i18n("Gantt"), this); actionViewGantt->setToolTip(i18nc("@info:tooltip", "Select timeline")); collection->addAction("view_gantt", actionViewGantt); connect(actionViewGantt, &QAction::triggered, this, &View::slotViewGantt); // actionTaskProgress = new QAction(koIcon("document-edit"), i18n("Progress..."), this); // collection->addAction("task_progress", actionTaskProgress); // connect(actionTaskProgress, SIGNAL(triggered(bool)), SLOT(slotTaskProgress())); //------ Settings actionConfigure = new QAction(koIcon("configure"), i18n("Configure PlanWork..."), this); collection->addAction("configure", actionConfigure); connect(actionConfigure, &QAction::triggered, this, &View::slotConfigure); //------ Popups actionEditDocument = new QAction(koIcon("document-edit"), i18n("Edit..."), this); collection->addAction("edit_document", actionEditDocument); connect(actionEditDocument, SIGNAL(triggered(bool)), SLOT(slotEditDocument())); actionViewDocument = new QAction(koIcon("document-preview"), i18nc("@verb", "View..."), this); collection->addAction("view_document", actionViewDocument); connect(actionViewDocument, &QAction::triggered, this, &View::slotViewDocument); - // FIXME remove UndoText::removeDocument() when string freeze is lifted - actionRemoveDocument = new QAction(koIcon("list-remove"), UndoText::removeDocument().toString(), this); + actionRemoveDocument = new QAction(koIcon("list-remove"), i18n("Remove document"), this); collection->addAction("remove_document", actionRemoveDocument); connect(actionRemoveDocument, &QAction::triggered, this, &View::slotRemoveDocument); actionSendPackage = new QAction(koIcon("mail-send"), i18n("Send Package..."), this); collection->addAction("edit_sendpackage", actionSendPackage); connect(actionSendPackage, &QAction::triggered, this, &View::slotSendPackage); actionTaskCompletion = new QAction(koIcon("document-edit"), i18n("Edit Progress..."), this); collection->addAction("task_progress", actionTaskCompletion); connect(actionTaskCompletion, &QAction::triggered, this, &View::slotTaskCompletion); actionViewDescription = new QAction(/*koIcon("document_view"),*/ i18n("View Description..."), this); collection->addAction("task_description", actionViewDescription); connect(actionViewDescription, &QAction::triggered, this, &View::slotTaskDescription); updateReadWrite(m_readWrite); //debugPlanWork<<" end"; loadContext(); slotCurrentChanged(currentIndex()); connect(this, &QStackedWidget::currentChanged, this, &View::slotCurrentChanged); slotSelectionChanged(); } View::~View() { saveContext(); } void View::slotCurrentChanged(int index) { actionViewList->setEnabled(index != 0); actionViewGantt->setEnabled(index != 1); saveContext(); } void View::slotViewList() { debugPlanWork; setCurrentIndex(0); } void View::slotViewGantt() { debugPlanWork; setCurrentIndex(1); } void View::createViews() { QWidget *v = createTaskWorkPackageView(); addWidget(v); v = createGanttView(); addWidget(v); } TaskWorkPackageView *View::createTaskWorkPackageView() { TaskWorkPackageView *v = new TaskWorkPackageView(part(), this); connect(v, &AbstractView::requestPopupMenu, this, &View::slotPopupMenu); connect(v, &AbstractView::selectionChanged, this, &View::slotSelectionChanged); v->updateReadWrite(m_readWrite); v->loadContext(); return v; } TaskWPGanttView *View::createGanttView() { TaskWPGanttView *v = new TaskWPGanttView(part(), this); connect(v, &AbstractView::requestPopupMenu, this, &View::slotPopupMenu); connect(v, &AbstractView::selectionChanged, this, &View::slotSelectionChanged); v->updateReadWrite(m_readWrite); v->loadContext(); return v; } void View::setupPrinter(QPrinter &/*printer*/, QPrintDialog &/*printDialog */) { //debugPlanWork; } void View::print(QPrinter &/*printer*/, QPrintDialog &/*printDialog*/) { } void View::slotSelectionChanged() { bool enable = ! currentView()->selectedNodes().isEmpty(); actionRemoveSelectedPackages->setEnabled(enable); actionRemoveCurrentPackage->setEnabled(enable); } void View::slotEditCut() { //debugPlanWork; } void View::slotEditCopy() { //debugPlanWork; } void View::slotEditPaste() { //debugPlanWork; } void View::slotProgressChanged(int) { } void View::slotConfigure() { } ScheduleManager *View::currentScheduleManager() const { WorkPackage *wp = m_part->findWorkPackage(currentNode()); return wp ? wp->project()->scheduleManagers().value(0) : nullptr; } void View::updateReadWrite(bool readwrite) { debugPlanWork<"<setEnabled(readwrite); emit sigUpdateReadWrite(readwrite); } Part *View::part() const { return m_part; } void View::slotPopupMenu(const QString& name, const QPoint & pos) { debugPlanWork<factory()); if (m_part->factory() == 0) { return; } QMenu *menu = ((QMenu*) m_part->factory() ->container(name, m_part)); if (menu == 0) { return; } QList lst; AbstractView *v = currentView(); if (v) { lst = v->contextActionList(); debugPlanWork<addSeparator(); foreach (QAction *a, lst) { menu->addAction(a); } } } menu->exec(pos); foreach (QAction *a, lst) { menu->removeAction(a); } } bool View::loadContext() { debugPlanWork; setCurrentIndex(PlanWorkSettings::self()->currentView()); return true; } void View::saveContext() const { debugPlanWork; PlanWorkSettings::self()->setCurrentView(currentIndex()); PlanWorkSettings::self()->save(); } void View::slotEditDocument() { slotEditDocument(currentDocument()); } void View::slotEditDocument(Document *doc) { debugPlanWork<type() != Document::Type_Product) { KMessageBox::error(0, i18n("This file is not editable")); return; } part()->editWorkpackageDocument(doc); } void View::slotViewDocument() { emit viewDocument(currentDocument()); } void View::slotRemoveDocument() { part()->removeDocument(currentDocument()); } void View::slotSendPackage() { Node *node = currentNode(); if (node == 0) { KMessageBox::error(0, i18n("No work package is selected")); return; } debugPlanWork<name(); WorkPackage *wp = part()->findWorkPackage(node); if (wp == 0) { KMessageBox::error(0, i18n("Cannot find work package")); return; } /* if (wp->isModified()) { int r = KMessageBox::questionYesNoCancel(0, i18n("This work package has been modified.\nDo you want to save it before sending?"), node->name()); switch (r) { case KMessageBox::Cancel: return; case KMessageBox::Yes: wp->saveToProjects(part()); break; default: break; } }*/ bool wasmodified = wp->isModified(); if (wp->sendUrl().isValid()) { QTemporaryFile temp(wp->sendUrl().toLocalFile() + QLatin1String("/calligraplanwork_XXXXXX") + QLatin1String(".planwork")); temp.setAutoRemove(false); if (! temp.open()) { KMessageBox::error(0, i18n("Could not open file. Sending is aborted.")); return; } wp->saveNativeFormat(part(), temp.fileName()); } else { QTemporaryFile temp(QDir::tempPath() + QLatin1String("/calligraplanwork_XXXXXX") + QLatin1String(".planwork")); temp.setAutoRemove(false); if (! temp.open()) { KMessageBox::error(0, i18n("Could not open temporary file. Sending is aborted.")); return; } wp->saveNativeFormat(part(), temp.fileName()); QStringList attachURLs; attachURLs << temp.fileName(); QString to = node->projectNode()->leader(); QString cc; QString bcc; QString subject = i18n("Work Package: %1", node->name()); QString body = node->projectNode()->name(); QString messageFile; KToolInvocation::invokeMailer(to, cc, bcc, subject, body, messageFile, attachURLs); } wp->setModified(wasmodified); } void View::slotTaskDescription() { Task *node = qobject_cast(currentNode()); if (node == 0) { return; } QPointer dlg = new TaskDescriptionDialog(*node, this, true); dlg->exec(); delete dlg; } AbstractView *View::currentView() const { return qobject_cast(currentWidget()); } Node *View::currentNode() const { AbstractView *v = currentView(); return v ? v->currentNode() : 0; } Document *View::currentDocument() const { AbstractView *v = currentView(); return v ? v->currentDocument() : 0; } void View::slotTaskProgress() { debugPlanWork; Task *n = qobject_cast(currentNode()); if (n == 0) { return; } StandardWorktime *w = qobject_cast(n->projectNode())->standardWorktime(); QPointer dlg = new TaskProgressDialog(*n, currentScheduleManager(), w, this); if (dlg->exec() == QDialog::Accepted && dlg) { KUndo2Command *cmd = dlg->buildCommand(); if (cmd) { cmd->redo(); //FIXME m_part->addCommand(cmd); } } } void View::slotTaskCompletion() { debugPlanWork; WorkPackage *wp = m_part->findWorkPackage(currentNode()); if (wp == 0) { return; } QPointer dlg = new TaskCompletionDialog(*wp, currentScheduleManager(), this); if (dlg->exec() == QDialog::Accepted && dlg) { KUndo2Command *cmd = dlg->buildCommand(); if (cmd) { m_part->addCommand(cmd); } } delete dlg; } void View::slotRemoveSelectedPackages() { debugPlanWork; QList lst = currentView()->selectedNodes(); if (lst.isEmpty()) { return; } m_part->removeWorkPackages(lst); } void View::slotRemoveCurrentPackage() { debugPlanWork; Node *n = currentNode(); if (n == 0) { return; } m_part->removeWorkPackage(n); } } //KPlatoWork namespace diff --git a/src/workpackage/workpackage.cpp b/src/workpackage/workpackage.cpp index 0cf464f2..f83434c8 100644 --- a/src/workpackage/workpackage.cpp +++ b/src/workpackage/workpackage.cpp @@ -1,861 +1,861 @@ /* This file is part of the KDE project Copyright (C) 2009, 2012 Dag Andersen Copyright (C) 2019 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // clazy:excludeall=qstring-arg #include "workpackage.h" #include "KPlatoXmlLoader.h" //NOTE: this file should probably be moved #include "part.h" #include "kptglobal.h" #include "kptnode.h" #include "kptproject.h" #include "kptdocuments.h" #include "kptcommand.h" #include "kptxmlloaderobject.h" #include "XmlSaveContext.h" #include "kptconfigbase.h" #include "kptcommonstrings.h" #include #include #include #include #include #include #include #include #include #include #include "debugarea.h" using namespace KPlato; namespace KPlatoWork { WorkPackage::WorkPackage(bool fromProjectStore) : m_project(new Project()), m_fromProjectStore(fromProjectStore), m_modified(false) { m_project->setConfig(&m_config); } WorkPackage::WorkPackage(Project *project, bool fromProjectStore) : m_project(project), m_fromProjectStore(fromProjectStore), m_modified(false) { Q_ASSERT(project); Q_ASSERT (project->childNode(0)); m_project->setConfig(&m_config); if (! project->scheduleManagers().isEmpty()) { // should be only one manager, so just get the first const QList &lst = m_project->scheduleManagers(); project->setCurrentSchedule(lst.first()->scheduleId()); } connect(project, &KPlato::Project::projectChanged, this, &WorkPackage::projectChanged); } WorkPackage::~WorkPackage() { delete m_project; qDeleteAll(m_childdocs); } void WorkPackage::setSettings(const WorkPackageSettings &settings) { if (m_settings != settings) { m_settings = settings; setModified(true); } } //TODO find a way to know when changes are undone void WorkPackage::projectChanged() { debugPlanWork; setModified(true); } bool WorkPackage::addChild(Part */*part*/, const Document *doc) { DocumentChild *ch = findChild(doc); if (ch) { if (ch->isOpen()) { KMessageBox::error(0, i18n("Document is already open")); return false; } } else { ch = new DocumentChild(this); if (! ch->setDoc(doc)) { delete ch; return false; } } if (! ch->editDoc()) { delete ch; return false; } if (! m_childdocs.contains(ch)) { m_childdocs.append(ch); connect(ch, &DocumentChild::fileModified, this, &WorkPackage::slotChildModified); } return true; } void WorkPackage::slotChildModified(bool mod) { debugPlanWork<documents().contains(doc) : false; } DocumentChild *WorkPackage::findChild(const Document *doc) const { foreach (DocumentChild *c, m_childdocs) { if (c->doc() == doc) { return c; } } return 0; } bool WorkPackage::loadXML(const KoXmlElement &element, XMLLoaderObject &status) { bool ok = false; QString wbsCode = "Unknown"; KoXmlNode n = element.firstChild(); for (; ! n.isNull(); n = n.nextSibling()) { if (! n.isElement()) { continue; } KoXmlElement e = n.toElement(); debugPlanWork<load(e, status))) { status.addMsg(XMLLoaderObject::Errors, "Loading of work package failed"); KMessageBox::error(0, i18n("Failed to load project: %1" , m_project->name())); } else { KoXmlElement te = e.namedItem("task").toElement(); if (!te.isNull()) { wbsCode = te.attribute("wbs", "empty"); } } } } if (ok) { KoXmlNode n = element.firstChild(); for (; ! n.isNull(); n = n.nextSibling()) { if (! n.isElement()) { continue; } KoXmlElement e = n.toElement(); debugPlanWork<(m_project->childNode(0)); t->workPackage().setOwnerName(e.attribute("owner")); t->workPackage().setOwnerId(e.attribute("owner-id")); m_sendUrl = QUrl(e.attribute("save-url")); m_fetchUrl = QUrl(e.attribute("load-url")); m_wbsCode = wbsCode; Resource *r = m_project->findResource(t->workPackage().ownerId()); if (r == 0) { debugPlanWork<<"Cannot find resource id!!"<workPackage().ownerId()<workPackage().ownerName(); } debugPlanWork<<"is this me?"<workPackage().ownerName(); KoXmlNode ch = e.firstChild(); for (; ! ch.isNull(); ch = ch.nextSibling()) { if (! ch.isElement()) { continue; } KoXmlElement el = ch.toElement(); debugPlanWork<scheduleManagers().isEmpty()) { // should be only one manager const QList &lst = m_project->scheduleManagers(); m_project->setCurrentSchedule(lst.first()->scheduleId()); } return ok; } bool WorkPackage::loadKPlatoXML(const KoXmlElement &element, XMLLoaderObject &status) { bool ok = false; KoXmlNode n = element.firstChild(); for (; ! n.isNull(); n = n.nextSibling()) { if (! n.isElement()) { continue; } KoXmlElement e = n.toElement(); debugPlanWork<name())); } } } if (ok) { KoXmlNode n = element.firstChild(); for (; ! n.isNull(); n = n.nextSibling()) { if (! n.isElement()) { continue; } KoXmlElement e = n.toElement(); debugPlanWork<(m_project->childNode(0)); t->workPackage().setOwnerName(e.attribute("owner")); t->workPackage().setOwnerId(e.attribute("owner-id")); Resource *r = m_project->findResource(t->workPackage().ownerId()); if (r == 0) { debugPlanWork<<"Cannot find resource id!!"<workPackage().ownerId()<workPackage().ownerName(); } debugPlanWork<<"is this me?"<workPackage().ownerName(); KoXmlNode ch = e.firstChild(); for (; ! ch.isNull(); ch = ch.nextSibling()) { if (! ch.isElement()) { continue; } KoXmlElement el = ch.toElement(); debugPlanWork<scheduleManagers().isEmpty()) { // should be only one manager const QList &lst = m_project->scheduleManagers(); m_project->setCurrentSchedule(lst.first()->scheduleId()); } return ok; } bool WorkPackage::saveToStream(QIODevice * dev) { QDomDocument doc = saveXML(); // Save to buffer QByteArray s = doc.toByteArray(); // utf8 already dev->open(QIODevice::WriteOnly); int nwritten = dev->write(s.data(), s.size()); if (nwritten != (int)s.size()) warnPlanWork << "wrote " << nwritten << "- expected" << s.size(); return nwritten == (int)s.size(); } bool WorkPackage::saveNativeFormat(Part */*part*/, const QString &path) { if (path.isEmpty()) { KMessageBox::error(0, i18n("Cannot save to empty filename")); return false; } debugPlanWork<name()<bad()) { KMessageBox::error(0, i18n("Could not create the file for saving")); delete store; return false; } if (store->open("root")) { KoStoreDevice dev(store); if (! saveToStream(&dev) || ! store->close()) { debugPlanWork << "saveToStream failed"; delete store; return false; } } else { KMessageBox::error(0, i18n("Not able to write '%1'. Partition full?", QString("maindoc.xml"))); delete store; return false; } if (!completeSaving(store)) { delete store; return false; } if (!store->finalize()) { delete store; return false; } // Success delete store; m_modified = false; return true; } bool WorkPackage::completeSaving(KoStore *store) { debugPlanWork; KoStore *oldstore = KoStore::createStore(filePath(), KoStore::Read, "", KoStore::Zip); if (oldstore->bad()) { KMessageBox::error(0, i18n("Failed to open store:\n %1", filePath())); return false; } if (oldstore->hasFile("documentinfo.xml")) { copyFile(oldstore, store, "documentinfo.xml"); } if (oldstore->hasFile("preview.png")) { copyFile(oldstore, store, "preview.png"); } // First get all open documents debugPlanWork<saveToStore(store)) { } } // Then get new files foreach (const Document *doc, node()->documents().documents()) { if (m_newdocs.contains(doc)) { store->addLocalFile(m_newdocs[ doc ].path(), doc->url().fileName()); m_newdocs.remove(doc); // TODO remove temp file ?? } } // Then get files from the old store copied to the new store foreach (Document *doc, node()->documents().documents()) { if (doc->sendAs() != Document::SendAs_Copy) { continue; } if (! store->hasFile(doc->url().fileName())) { copyFile(oldstore, store, doc->url().fileName()); } } return true; } QString WorkPackage::fileName(const Part *part) const { Q_UNUSED(part); if (m_project == 0) { warnPlanWork<<"No project in this package"; return QString(); } Node *n = node(); if (n == 0) { warnPlanWork<<"No node in this project"; return QString(); } QString projectName = m_project->name().remove(' '); // FIXME: workaround: KoResourcePaths::saveLocation("projects", projectName + '/'); const QString path = KoResourcePaths::saveLocation("appdata", "projects/" + projectName + '/'); QString wpName = n->name(); wpName = QString(wpName.remove(' ').replace('/', '_') + '_' + n->id() + ".planwork"); return path + wpName; } void WorkPackage::removeFile() { QFile file(m_filePath); if (! file.exists()) { warnPlanWork<<"No project in this package"; return; } file.remove(); } void WorkPackage::saveToProjects(Part *part) { debugPlanWork; QString path = fileName(part); debugPlanWork<name(); if (saveNativeFormat(part, path)) { m_fromProjectStore = true; m_filePath = path; } else { KMessageBox::error(0, i18n("Cannot save to projects store:\n%1" , path)); } return; } bool WorkPackage::isModified() const { if (m_modified) { return true; } foreach (DocumentChild *ch, m_childdocs) { if (ch->isModified() || ch->isFileModified()) { return true; } } return false; } QString WorkPackage::name() const { Task *t = task(); return t ? t->name() : QString(); } Node *WorkPackage::node() const { return m_project == 0 ? 0 : m_project->childNode(0); } Task *WorkPackage::task() const { Task *task = qobject_cast(node()); Q_ASSERT(task); return task; } bool WorkPackage::removeDocument(Part *part, Document *doc) { Node *n = node(); if (n == 0) { return false; } - part->addCommand(new DocumentRemoveCmd(n->documents(), doc, UndoText::removeDocument())); + part->addCommand(new DocumentRemoveCmd(n->documents(), doc, kundo2_i18n("Remove document"))); return true; } bool WorkPackage::copyFile(KoStore *from, KoStore *to, const QString &filename) { QByteArray data; if (! from->extractFile(filename , data)) { KMessageBox::error(0, i18n("Failed read file:\n %1", filename)); return false; } if (! to->addDataToFile(data, filename)) { KMessageBox::error(0, i18n("Failed write file:\n %1", filename)); return false; } debugPlanWork<<"Copied file:"<(node()); if (t) { wp.setAttribute("owner", t->workPackage().ownerName()); wp.setAttribute("owner-id", t->workPackage().ownerId()); } doc.appendChild(wp); m_project->save(doc, XmlSaveContext()); return document; } void WorkPackage::merge(Part *part, const WorkPackage *wp, KoStore *store) { debugPlanWork; const Node *from = wp->node(); Node *to = node(); MacroCommand *m = new MacroCommand(kundo2_i18n("Merge data")); if (m_wbsCode != wp->wbsCode()) { m->addCommand(new ModifyWbsCodeCmd(this, wp->wbsCode())); } if (to->name() != from->name()) { m->addCommand(new NodeModifyNameCmd(*to, from->name())); } if (to->description() != from->description()) { m->addCommand(new NodeModifyDescriptionCmd(*to, from->description())); } if (to->startTime() != from->startTime() && from->startTime().isValid()) { m->addCommand(new NodeModifyStartTimeCmd(*to, from->startTime())); } if (to->endTime() != from->endTime() && from->endTime().isValid()) { m->addCommand(new NodeModifyEndTimeCmd(*to, from->endTime())); } if (to->leader() != from->leader()) { m->addCommand(new NodeModifyLeaderCmd(*to, from->leader())); } if (from->type() == Node::Type_Task && from->type() == Node::Type_Task) { if (static_cast(to)->workPackage().ownerId() != static_cast(from)->workPackage().ownerId()) { debugPlanWork<<"merge:"<<"different owners"<(from)->workPackage().ownerName()<(to)->workPackage().ownerName(); if (static_cast(to)->workPackage().ownerId().isEmpty()) { //TODO cmd static_cast(to)->workPackage().setOwnerId(static_cast(from)->workPackage().ownerId()); static_cast(to)->workPackage().setOwnerName(static_cast(from)->workPackage().ownerName()); } } foreach (Document *doc, from->documents().documents()) { Document *org = to->documents().findDocument(doc->url()); if (org) { // TODO: also handle modified type, sendas // update ? what if open, modified ... if (doc->type() == Document::Type_Product) { //### FIXME. user feedback warnPlanWork<<"We do not update existing deliverables (except name change)"; if (doc->name() != org->name()) { m->addCommand(new DocumentModifyNameCmd(org, doc->name())); } } else { if (doc->name() != org->name()) { m->addCommand(new DocumentModifyNameCmd(org, doc->name())); } if (doc->sendAs() != org->sendAs()) { m->addCommand(new DocumentModifySendAsCmd(org, doc->sendAs())); } if (doc->sendAs() == Document::SendAs_Copy) { debugPlanWork<<"Update existing doc:"<url(); openNewDocument(org, store); } } } else { debugPlanWork<<"new document:"<typeToString(doc->type())<url(); Document *newdoc = new Document(*doc); m->addCommand(new DocumentAddCmd(to->documents(), newdoc)); if (doc->sendAs() == Document::SendAs_Copy) { debugPlanWork<<"Copy file"; openNewDocument(newdoc, store); } } } } const Project *fromProject = wp->project(); Project *toProject = m_project; const ScheduleManager *fromSm = fromProject->scheduleManagers().value(0); Q_ASSERT(fromSm); ScheduleManager *toSm = toProject->scheduleManagers().value(0); Q_ASSERT(toSm); if (fromSm->managerId() != toSm->managerId() || fromSm->scheduleId() != toSm->scheduleId()) { // rescheduled, update schedules m->addCommand(new CopySchedulesCmd(*fromProject, *toProject)); } if (m->isEmpty()) { delete m; } else { part->addCommand(m); } } void WorkPackage::openNewDocument(const Document *doc, KoStore *store) { const QUrl url = extractFile(doc, store); if (url.url().isEmpty()) { KMessageBox::error(0, i18n("Could not extract document from storage:
%1", doc->url().path())); return; } if (! url.isValid()) { KMessageBox::error(0, i18n("Invalid URL:
%1", url.path())); return; } m_newdocs.insert(doc, url); } int WorkPackage::queryClose(Part *part) { debugPlanWork<name(); QStringList lst; if (! m_childdocs.isEmpty()) { foreach (DocumentChild *ch, m_childdocs) { if (ch->isOpen() && ch->doc()->sendAs() == Document::SendAs_Copy) { lst << ch->doc()->url().fileName(); } } } if (! lst.isEmpty()) { KMessageBox::ButtonCode result = KMessageBox::warningContinueCancelList(0, i18np( "

The work package '%2' has an open document.

Data may be lost if you continue.

", "

The work package '%2' has open documents.

Data may be lost if you continue.

", lst.count(), name), lst); switch (result) { case KMessageBox::Continue: { debugPlanWork<<"Continue"; break; } default: // case KMessageBox::Cancel : debugPlanWork<<"Cancel"; return KMessageBox::Cancel; break; } } if (! isModified()) { return KMessageBox::Yes; } KMessageBox::ButtonCode res = KMessageBox::warningYesNoCancel(0, i18n("

The work package '%1' has been modified.

Do you want to save it?

", name), QString(), KStandardGuiItem::save(), KStandardGuiItem::discard()); switch (res) { case KMessageBox::Yes: { debugPlanWork<<"Yes"; saveToProjects(part); break; } case KMessageBox::No: debugPlanWork<<"No"; break; default: // case KMessageBox::Cancel : debugPlanWork<<"Cancel"; break; } return res; } QUrl WorkPackage::extractFile(const Document *doc) { KoStore *store = KoStore::createStore(m_filePath, KoStore::Read, "", KoStore::Zip); if (store->bad()) { KMessageBox::error(0, i18n("

Work package '%1'

Could not open store:

%2

", node()->name(), m_filePath)); delete store; return QUrl(); } const QUrl url = extractFile(doc, store); delete store; return url; } QUrl WorkPackage::extractFile(const Document *doc, KoStore *store) { //FIXME: should use a special tmp dir QString tmp = QDir::tempPath() + QLatin1Char('/') + doc->url().fileName(); const QUrl url = QUrl::fromLocalFile(tmp); debugPlanWork<<"Extract: "<url().fileName()<<" -> "<extractFile(doc->url().fileName(), url.path())) { KMessageBox::error(0, i18n("

Work package '%1'

Could not extract file:

%2

", node()->name(), doc->url().fileName())); return QUrl(); } return url; } QString WorkPackage::id() const { QString id; if (node()) { id = m_project->id() + node()->id(); } return id; } //-------------------------------- PackageRemoveCmd::PackageRemoveCmd(Part *part, WorkPackage *value, const KUndo2MagicString& name) : NamedCommand(name), m_part(part), m_value(value), m_mine(false) { } PackageRemoveCmd::~PackageRemoveCmd() { if (m_mine) { m_value->removeFile(); delete m_value; } } void PackageRemoveCmd::execute() { m_part->removeWorkPackage(m_value); m_mine = true; } void PackageRemoveCmd::unexecute() { m_part->addWorkPackage(m_value); m_mine = false; } //--------------------- CopySchedulesCmd::CopySchedulesCmd(const Project &fromProject, Project &toProject, const KUndo2MagicString &name) : NamedCommand(name), m_project(toProject) { QDomDocument olddoc; QDomElement e = olddoc.createElement("old"); olddoc.appendChild(e); toProject.save(e, XmlSaveContext()); m_olddoc = olddoc.toString(); QDomDocument newdoc; e = newdoc.createElement("new"); newdoc.appendChild(e); fromProject.save(e, XmlSaveContext()); m_newdoc = newdoc.toString(); } void CopySchedulesCmd::execute() { load(m_newdoc); } void CopySchedulesCmd::unexecute() { load(m_olddoc); } void CopySchedulesCmd::load(const QString &doc) { clearSchedules(); KoXmlDocument d; d.setContent(doc); KoXmlElement proj = d.documentElement().namedItem("project").toElement(); Q_ASSERT(! proj.isNull()); KoXmlElement task = proj.namedItem("task").toElement(); Q_ASSERT(! task.isNull()); KoXmlElement ts = task.namedItem("schedules").namedItem("schedule").toElement(); Q_ASSERT(! ts.isNull()); KoXmlElement ps = proj.namedItem("schedules").namedItem("plan").toElement(); Q_ASSERT(! ps.isNull()); XMLLoaderObject status; status.setProject(&m_project); status.setVersion(PLAN_FILE_SYNTAX_VERSION); // task first NodeSchedule *ns = new NodeSchedule(); if (ns->loadXML(ts, status)) { debugPlanWork<name()<type()<id(); ns->setNode(m_project.childNode(0)); m_project.childNode(0)->addSchedule(ns); } else { Q_ASSERT(false); delete ns; } // schedule manager next (includes main schedule and resource schedule) ScheduleManager *sm = new ScheduleManager(m_project); if (sm->loadXML(ps, status)) { m_project.addScheduleManager(sm); } else { Q_ASSERT(false); delete sm; } if (sm) { m_project.setCurrentSchedule(sm->scheduleId()); } m_project.childNode(0)->changed(); } void CopySchedulesCmd::clearSchedules() { foreach (Schedule *s, m_project.schedules()) { m_project.takeSchedule(s); } foreach (Schedule *s, m_project.childNode(0)->schedules()) { foreach (Appointment *a, s->appointments()) { if (a->resource() && a->resource()->resource()) { a->resource()->resource()->takeSchedule(a->resource()); } } m_project.childNode(0)->takeSchedule(s); } foreach (ScheduleManager *sm, m_project.scheduleManagers()) { m_project.takeScheduleManager(sm); delete sm; } } //--------------------- ModifyWbsCodeCmd::ModifyWbsCodeCmd(WorkPackage *wp, QString wbsCode, const KUndo2MagicString &name) : NamedCommand(name) , m_wp(wp) , m_old(wp->wbsCode()) , m_new(wbsCode) { } void ModifyWbsCodeCmd::execute() { m_wp->setWbsCode(m_new); } void ModifyWbsCodeCmd::unexecute() { m_wp->setWbsCode(m_old); } } //KPlatoWork namespace QDebug operator<<(QDebug dbg, const KPlatoWork::WorkPackage *wp) { if (!wp) { return dbg.noquote() << "WorkPackage[0x0]"; } return dbg << *wp; } QDebug operator<<(QDebug dbg, const KPlatoWork::WorkPackage &wp) { dbg.noquote() << "WorkPackage["; dbg << wp.id(); dbg << wp.name(); dbg << ']'; return dbg; }