diff --git a/src/kptview.cpp b/src/kptview.cpp index a7c6166e..f9b10917 100644 --- a/src/kptview.cpp +++ b/src/kptview.cpp @@ -1,3315 +1,3325 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999, 2000 Torben Weis Copyright (C) 2002 - 2011 Dag Andersen Copyright (C) 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ // clazy:excludeall=qstring-arg #include "kptview.h" #include #include #include "KoDocumentInfo.h" #include "KoMainWindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kptlocale.h" #include "kptviewbase.h" #include "kptaccountsview.h" #include "kptaccountseditor.h" #include "kptcalendareditor.h" #include "kptfactory.h" #include "kptmilestoneprogressdialog.h" #include "kpttaskdescriptiondialog.h" #include "kptdocumentsdialog.h" #include "kptnode.h" #include "kptmaindocument.h" #include "kptproject.h" #include "kptmainprojectdialog.h" #include "kpttask.h" #include "kptsummarytaskdialog.h" #include "kpttaskdialog.h" #include "kpttaskprogressdialog.h" #include "kptganttview.h" #include "kpttaskeditor.h" #include "kptdependencyeditor.h" #include "kptperteditor.h" #include "kptdatetime.h" #include "kptcommand.h" #include "kptrelation.h" #include "kptrelationdialog.h" #include "kptresourceappointmentsview.h" #include "kptresourceeditor.h" #include "kptscheduleeditor.h" #include "kptresourcedialog.h" #include "kptresource.h" #include "kptstandardworktimedialog.h" #include "kptwbsdefinitiondialog.h" #include "kptresourceassignmentview.h" #include "kpttaskstatusview.h" #include "kptsplitterview.h" #include "kptpertresult.h" #include "ConfigProjectPanel.h" #include "ConfigWorkVacationPanel.h" #include "kpttaskdefaultpanel.h" #include "kptworkpackageconfigpanel.h" #include "kptcolorsconfigpanel.h" #include "kptinsertfiledlg.h" #include "kptloadsharedprojectsdialog.h" #include "kpthtmlview.h" #include "about/aboutpage.h" #include "kptlocaleconfigmoneydialog.h" #include "kptflatproxymodel.h" #include "kpttaskstatusmodel.h" #include "performance/PerformanceStatusView.h" #include "performance/ProjectStatusView.h" #include "reportsgenerator/ReportsGeneratorView.h" #ifdef PLAN_USE_KREPORT #include "reports/reportview.h" #include "reports/reportdata.h" #endif #include "kptviewlistdialog.h" #include "kptviewlistdocker.h" #include "kptviewlist.h" #include "kptschedulesdocker.h" #include "kptpart.h" #include "kptdebug.h" #include "calligraplansettings.h" #include "kptprintingcontrolprivate.h" // #include "KPtViewAdaptor.h" #include namespace KPlato { //------------------------------- ConfigDialog::ConfigDialog(QWidget *parent, const QString& name, KConfigSkeleton *config ) : KConfigDialog( parent, name, config ), m_config( config ) { KConfigDialogManager::changedMap()->insert("KRichTextWidget", SIGNAL(textChanged()) ); } bool ConfigDialog::hasChanged() { QRegExp kcfg( "kcfg_*" ); foreach ( KRichTextWidget *w, findChildren( kcfg ) ) { KConfigSkeletonItem *item = m_config->findItem( w->objectName().mid(5) ); if ( ! item->isEqual( w->toHtml() ) ) { return true; } } return false; } void ConfigDialog::updateSettings() { bool changed = false; QRegExp kcfg( "kcfg_*" ); foreach ( KRichTextWidget *w, findChildren( kcfg ) ) { KConfigSkeletonItem *item = m_config->findItem( w->objectName().mid(5) ); if ( ! item ) { warnPlan << "The setting '" << w->objectName().mid(5) << "' has disappeared!"; continue; } if ( ! item->isEqual( QVariant( w->toHtml() ) ) ) { item->setProperty( QVariant( w->toHtml() ) ); changed = true; } } if ( changed ) { m_config->save(); } } void ConfigDialog::updateWidgets() { QRegExp kcfg( "kcfg_*" ); foreach ( KRichTextWidget *w, findChildren( kcfg ) ) { KConfigSkeletonItem *item = m_config->findItem( w->objectName().mid(5) ); if ( ! item ) { warnPlan << "The setting '" << w->objectName().mid(5) << "' has disappeared!"; continue; } if ( ! item->isEqual( QVariant( w->toHtml() ) ) ) { w->setHtml( item->property().toString() ); } } } void ConfigDialog::updateWidgetsDefault() { bool usedefault = m_config->useDefaults( true ); updateWidgets(); m_config->useDefaults( usedefault ); } bool ConfigDialog::isDefault() { bool bUseDefaults = m_config->useDefaults(true); bool result = !hasChanged(); m_config->useDefaults(bUseDefaults); return result; } //------------------------------------ View::View(KoPart *part, MainDocument *doc, QWidget *parent) : KoView(part, doc, parent), m_currentEstimateType( Estimate::Use_Expected ), m_scheduleActionGroup( new QActionGroup( this ) ), m_readWrite( false ), m_defaultView(1), m_partpart (part) { //debugPlan; doc->registerView( this ); setComponentName(Factory::global().componentName(), Factory::global().componentDisplayName()); if ( !doc->isReadWrite() ) setXMLFile( "calligraplan_readonly.rc" ); else setXMLFile( "calligraplan.rc" ); // new ViewAdaptor( this ); m_sp = new QSplitter( this ); QVBoxLayout *layout = new QVBoxLayout( this ); layout->setMargin(0); layout->addWidget( m_sp ); ViewListDocker *docker = 0; if ( mainWindow() == 0 ) { // Don't use docker if embedded m_viewlist = new ViewListWidget(doc, m_sp); m_viewlist->setProject( &( getProject() ) ); connect( m_viewlist, &ViewListWidget::selectionChanged, this, &View::slotSelectionChanged); connect( this, &View::currentScheduleManagerChanged, m_viewlist, &ViewListWidget::setSelectedSchedule); connect( m_viewlist, &ViewListWidget::updateViewInfo, this, &View::slotUpdateViewInfo); } else { ViewListDockerFactory vl(this); docker = static_cast(mainWindow()->createDockWidget(&vl)); if (docker->view() != this) { docker->setView(this); } m_viewlist = docker->viewList(); #if 0 //SchedulesDocker SchedulesDockerFactory sdf; SchedulesDocker *sd = dynamic_cast( createDockWidget( &sdf ) ); Q_ASSERT( sd ); sd->setProject( &getProject() ); connect(sd, SIGNAL(selectionChanged(KPlato::ScheduleManager*)), SLOT(slotSelectionChanged(KPlato::ScheduleManager*))); connect(this, &View::currentScheduleManagerChanged, sd, SLOT(setSelectedSchedule(KPlato::ScheduleManager*))); #endif } m_tab = new QStackedWidget( m_sp ); //////////////////////////////////////////////////////////////////////////////////////////////////// // Add sub views createIntroductionView(); // The menu items // ------ File /* actionCreateTemplate = new QAction( i18n( "&Create Template From Document..." ), this ); actionCollection()->addAction("file_createtemplate", actionCreateTemplate ); connect( actionCreateTemplate, SIGNAL(triggered(bool)), SLOT(slotCreateTemplate()) ); */ actionCreateNewProject = new QAction( i18n( "&Create New Project..." ), this ); actionCollection()->addAction("file_createnewproject", actionCreateNewProject ); connect( actionCreateNewProject, &QAction::triggered, this, &View::slotCreateNewProject ); // ------ Edit actionCut = actionCollection()->addAction(KStandardAction::Cut, "edit_cut", this, SLOT(slotEditCut())); actionCopy = actionCollection()->addAction(KStandardAction::Copy, "edit_copy", this, SLOT(slotEditCopy())); actionPaste = actionCollection()->addAction(KStandardAction::Paste, "edit_paste", this, SLOT(slotEditPaste())); // ------ View actionCollection()->addAction( KStandardAction::Redisplay, "view_refresh" , this, SLOT(slotRefreshView()) ); actionViewSelector = new KToggleAction(i18n("Show Selector"), this); actionCollection()->addAction("view_show_selector", actionViewSelector ); connect( actionViewSelector, &QAction::triggered, this, &View::slotViewSelector ); // ------ Insert // ------ Project actionEditMainProject = new QAction(koIcon("view-time-schedule-edit"), i18n("Edit Main Project..."), this); actionCollection()->addAction("project_edit", actionEditMainProject ); connect( actionEditMainProject, &QAction::triggered, this, &View::slotProjectEdit ); actionEditStandardWorktime = new QAction(koIcon("configure"), i18n("Define Estimate Conversions..."), this); actionCollection()->addAction("project_worktime", actionEditStandardWorktime ); connect( actionEditStandardWorktime, &QAction::triggered, this, &View::slotProjectWorktime ); // ------ Tools actionDefineWBS = new QAction(koIcon("configure"), i18n("Define WBS Pattern..."), this); actionCollection()->addAction("tools_define_wbs", actionDefineWBS ); connect( actionDefineWBS, &QAction::triggered, this, &View::slotDefineWBS ); actionInsertFile = new QAction(koIcon("document-import"), i18n("Insert Project File..."), this); actionCollection()->addAction("insert_file", actionInsertFile ); connect( actionInsertFile, &QAction::triggered, this, &View::slotInsertFile ); actionLoadSharedProjects = new QAction(koIcon("document-import"), i18n("Load Shared Projects..."), this); actionCollection()->addAction("load_shared_projects", actionLoadSharedProjects ); connect( actionLoadSharedProjects, &QAction::triggered, this, &View::slotLoadSharedProjects ); // ------ Settings actionConfigure = new QAction(koIcon("configure"), i18n("Configure Plan..."), this); actionCollection()->addAction("configure", actionConfigure ); connect( actionConfigure, &QAction::triggered, this, &View::slotConfigure ); actionCurrencyConfig = new QAction(koIcon("configure"), i18n("Define Currency..."), this); actionCollection()->addAction( "config_currency", actionCurrencyConfig ); connect( actionCurrencyConfig, &QAction::triggered, this, &View::slotCurrencyConfig ); #ifdef PLAN_USE_KREPORT actionOpenReportFile = new QAction(koIcon("document-open"), i18n("Open Report Definition File..."), this); actionCollection()->addAction( "reportdesigner_open_file", actionOpenReportFile ); connect( actionOpenReportFile, QAction::triggered, this, &View::slotOpenReportFile); #endif // ------ Help actionIntroduction = new QAction(koIcon("dialog-information"), i18n("Introduction to Plan"), this); actionCollection()->addAction("plan_introduction", actionIntroduction ); connect( actionIntroduction, &QAction::triggered, this, &View::slotIntroduction ); // ------ Popup actionOpenNode = new QAction(koIcon("document-edit"), i18n("Edit..."), this); actionCollection()->addAction("node_properties", actionOpenNode ); connect( actionOpenNode, &QAction::triggered, this, &View::slotOpenCurrentNode ); actionTaskProgress = new QAction(koIcon("document-edit"), i18n("Progress..."), this); actionCollection()->addAction("task_progress", actionTaskProgress ); connect( actionTaskProgress, &QAction::triggered, this, &View::slotTaskProgress ); actionDeleteTask = new QAction(koIcon("edit-delete"), i18n("Delete Task"), this); actionCollection()->addAction("delete_task", actionDeleteTask ); connect( actionDeleteTask, &QAction::triggered, this, &View::slotDeleteCurrentTask ); actionTaskDescription = new QAction(koIcon("document-edit"), i18n("Description..."), this); actionCollection()->addAction("task_description", actionTaskDescription ); connect( actionTaskDescription, &QAction::triggered, this, &View::slotTaskDescription ); actionDocuments = new QAction(koIcon("document-edit"), i18n("Documents..."), this); actionCollection()->addAction("task_documents", actionDocuments ); connect( actionDocuments, &QAction::triggered, this, &View::slotDocuments ); actionIndentTask = new QAction(koIcon("format-indent-more"), i18n("Indent Task"), this); actionCollection()->addAction("indent_task", actionIndentTask ); connect( actionIndentTask, &QAction::triggered, this, &View::slotIndentTask ); actionUnindentTask= new QAction(koIcon("format-indent-less"), i18n("Unindent Task"), this); actionCollection()->addAction("unindent_task", actionUnindentTask ); connect( actionUnindentTask, &QAction::triggered, this, &View::slotUnindentTask ); actionMoveTaskUp = new QAction(koIcon("arrow-up"), i18n("Move Task Up"), this); actionCollection()->addAction("move_task_up", actionMoveTaskUp ); connect( actionMoveTaskUp, &QAction::triggered, this, &View::slotMoveTaskUp ); actionMoveTaskDown = new QAction(koIcon("arrow-down"), i18n("Move Task Down"), this); actionCollection()->addAction("move_task_down", actionMoveTaskDown ); connect( actionMoveTaskDown, &QAction::triggered, this, &View::slotMoveTaskDown ); actionEditResource = new QAction(koIcon("document-edit"), i18n("Edit Resource..."), this); actionCollection()->addAction("edit_resource", actionEditResource ); connect( actionEditResource, &QAction::triggered, this, &View::slotEditCurrentResource ); actionEditRelation = new QAction(koIcon("document-edit"), i18n("Edit Dependency..."), this); actionCollection()->addAction("edit_dependency", actionEditRelation ); connect( actionEditRelation, &QAction::triggered, this, &View::slotModifyCurrentRelation ); actionDeleteRelation = new QAction(koIcon("edit-delete"), i18n("Delete Dependency"), this); actionCollection()->addAction("delete_dependency", actionDeleteRelation ); connect( actionDeleteRelation, &QAction::triggered, this, &View::slotDeleteRelation ); // Viewlist popup connect( m_viewlist, &ViewListWidget::createView, this, &View::slotCreateView ); m_estlabel = new QLabel( "", 0 ); if ( statusBar() ) { addStatusBarItem( m_estlabel, 0, true ); } connect( &getProject(), &Project::scheduleManagerAdded, this, &View::slotScheduleAdded ); connect( &getProject(), &Project::scheduleManagerRemoved, this, &View::slotScheduleRemoved ); + connect( &getProject(), &Project::scheduleManagersSwapped, this, &View::slotScheduleSwapped ); connect( &getProject(), &Project::sigCalculationFinished, this, &View::slotScheduleCalculated ); slotPlugScheduleActions(); connect( doc, &MainDocument::changed, this, &View::slotUpdate ); connect( m_scheduleActionGroup, &QActionGroup::triggered, this, &View::slotViewSchedule ); connect( getPart(), &MainDocument::workPackageLoaded, this, &View::slotWorkPackageLoaded ); // views take time for large projects QTimer::singleShot(0, this, &View::initiateViews); const QList pluginFactories = KoPluginLoader::instantiatePluginFactories(QStringLiteral("calligraplan/extensions")); foreach (KPluginFactory* factory, pluginFactories) { QObject *object = factory->create(this, QVariantList()); KXMLGUIClient *clientPlugin = dynamic_cast(object); if (clientPlugin) { insertChildClient(clientPlugin); } else { // not our/valid plugin, so delete the created object object->deleteLater(); } } // do not watch task module changes if we are editing one if (!doc->isTaskModule()) { QString dir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); if (!dir.isEmpty()) { dir += "/taskmodules"; m_dirwatch.addDir(dir, KDirWatch::WatchFiles); QStringList modules = KoResourcePaths::findAllResources( "calligraplan_taskmodules", "*.plan", KoResourcePaths::NoDuplicates|KoResourcePaths::Recursive ); for (const QString &f : modules) { m_dirwatch.addFile(f); } connect(&m_dirwatch, &KDirWatch::created, this, &View::taskModuleFileChanged); connect(&m_dirwatch, &KDirWatch::deleted, this, &View::taskModuleFileChanged); } } //debugPlan<<" end"; } View::~View() { // Disconnect and delete so we do not get called by destroyd() signal const QMap map = m_scheduleActions; // clazy:exclude=qmap-with-pointer-key QMap::const_iterator it; for (it = map.constBegin(); it != map.constEnd(); ++it) { disconnect(it.key(), &QObject::destroyed, this, &View::slotActionDestroyed); m_scheduleActionGroup->removeAction(it.key()); delete it.key(); } ViewBase *view = currentView(); if (view) { // deactivate view to remove dockers etc slotGuiActivated(view, false); } /* removeStatusBarItem( m_estlabel ); delete m_estlabel;*/ } void View::initiateViews() { QApplication::setOverrideCursor( Qt::WaitCursor ); createViews(); connect( m_viewlist, &ViewListWidget::activated, this, &View::slotViewActivated ); // after createViews() !! connect( m_viewlist, &ViewListWidget::viewListItemRemoved, this, &View::slotViewListItemRemoved ); // after createViews() !! connect( m_viewlist, &ViewListWidget::viewListItemInserted, this, &View::slotViewListItemInserted ); ViewListDocker *docker = qobject_cast( m_viewlist->parent() ); if ( docker ) { // after createViews() !! connect( m_viewlist, &ViewListWidget::modified, docker, &ViewListDocker::slotModified); connect( m_viewlist, &ViewListWidget::modified, getPart(), &MainDocument::slotViewlistModified); connect(getPart(), &MainDocument::viewlistModified, docker, &ViewListDocker::updateWindowTitle); } connect( m_tab, &QStackedWidget::currentChanged, this, &View::slotCurrentChanged ); slotSelectDefaultView(); loadContext(); QApplication::restoreOverrideCursor(); } void View::slotCreateNewProject() { debugPlan; if ( KMessageBox::Continue == KMessageBox::warningContinueCancel( this, xi18nc( "@info", "This action cannot be undone." "Create a new Project from the current project " "with new project- and task identities." "Resource- and calendar identities are not changed." "All scheduling information is removed." "Do you want to continue?" ) ) ) { emit currentScheduleManagerChanged(0); getPart()->createNewProject(); slotOpenNode( &getProject() ); } } void View::createViews() { Context *ctx = getPart()->context(); if ( ctx && ctx->isLoaded() ) { debugPlan<<"isLoaded"; KoXmlNode n = ctx->context().namedItem( "categories" ); if ( n.isNull() ) { warnPlan<<"No categories"; } else { n = n.firstChild(); for ( ; ! n.isNull(); n = n.nextSibling() ) { if ( ! n.isElement() ) { continue; } KoXmlElement e = n.toElement(); if (e.tagName() != "category") { continue; } debugPlan<<"category: "<addCategory( ct, cn ); KoXmlNode n1 = e.firstChild(); for ( ; ! n1.isNull(); n1 = n1.nextSibling() ) { if ( ! n1.isElement() ) { continue; } KoXmlElement e1 = n1.toElement(); if (e1.tagName() != "view") { continue; } ViewBase *v = 0; QString type = e1.attribute( "viewtype" ); QString tag = e1.attribute( "tag" ); QString name = e1.attribute( "name" ); QString tip = e1.attribute( "tooltip" ); v = createView( cat, type, tag, name, tip ); //KoXmlNode settings = e1.namedItem( "settings " ); ???? KoXmlNode settings = e1.firstChild(); for ( ; ! settings.isNull(); settings = settings.nextSibling() ) { if ( settings.nodeName() == "settings" ) { break; } } if ( v && settings.isElement() ) { debugPlan<<" settings"; v->loadContext( settings.toElement() ); } } } } } else { debugPlan<<"Default"; ViewBase *v = 0; ViewListItem *cat; QString ct = "Editors"; cat = m_viewlist->addCategory( ct, defaultCategoryInfo( ct ).name ); createCalendarEditor( cat, "CalendarEditor", QString(), TIP_USE_DEFAULT_TEXT ); createAccountsEditor( cat, "AccountsEditor", QString(), TIP_USE_DEFAULT_TEXT ); v = createResourceEditor( cat, "ResourceEditor", QString(), TIP_USE_DEFAULT_TEXT ); v = createTaskEditor( cat, "TaskEditor", QString(), TIP_USE_DEFAULT_TEXT ); m_defaultView = m_tab->count() - 1; v->showColumns(QList() << NodeModel::NodeName << NodeModel::NodeType << NodeModel::NodePriority << NodeModel::NodeAllocation << NodeModel::NodeEstimateCalendar << NodeModel::NodeEstimate << NodeModel::NodeOptimisticRatio << NodeModel::NodePessimisticRatio << NodeModel::NodeRisk << NodeModel::NodeResponsible << NodeModel::NodeDescription ); v = createTaskEditor( cat, "TaskConstraintEditor", i18n("Task Constraints"), i18n("Edit task scheduling constraints") ); v->showColumns(QList() << NodeModel::NodeName << NodeModel::NodeType << NodeModel::NodeConstraint << NodeModel::NodeConstraintStart << NodeModel::NodeConstraintEnd << NodeModel::NodeDescription ); v = createTaskEditor( cat, "TaskCostEditor", i18n("Task Cost"), i18n("Edit task cost") ); v->showColumns(QList() << NodeModel::NodeName << NodeModel::NodeType << NodeModel::NodeRunningAccount << NodeModel::NodeStartupAccount << NodeModel::NodeStartupCost << NodeModel::NodeShutdownAccount << NodeModel::NodeShutdownCost << NodeModel::NodeDescription ); createDependencyEditor( cat, "DependencyEditor", QString(), TIP_USE_DEFAULT_TEXT ); // Do not show by default // createPertEditor( cat, "PertEditor", QString(), TIP_USE_DEFAULT_TEXT ); createScheduleHandler( cat, "ScheduleHandlerView", QString(), TIP_USE_DEFAULT_TEXT ); ct = "Views"; cat = m_viewlist->addCategory( ct, defaultCategoryInfo( ct ).name ); createGanttView( cat, "GanttView", QString(), TIP_USE_DEFAULT_TEXT ); createMilestoneGanttView( cat, "MilestoneGanttView", QString(), TIP_USE_DEFAULT_TEXT ); createResourceAppointmentsView( cat, "ResourceAppointmentsView", QString(), TIP_USE_DEFAULT_TEXT ); createResourceAppointmentsGanttView( cat, "ResourceAppointmentsGanttView", QString(), TIP_USE_DEFAULT_TEXT ); createAccountsView( cat, "AccountsView", QString(), TIP_USE_DEFAULT_TEXT ); ct = "Execution"; cat = m_viewlist->addCategory( ct, defaultCategoryInfo( ct ).name ); createProjectStatusView( cat, "ProjectStatusView", QString(), TIP_USE_DEFAULT_TEXT ); createPerformanceStatusView( cat, "PerformanceStatusView", QString(), TIP_USE_DEFAULT_TEXT ); v = createTaskStatusView( cat, "TaskStatusView", QString(), TIP_USE_DEFAULT_TEXT ); v = createTaskView( cat, "TaskView", QString(), TIP_USE_DEFAULT_TEXT ); v = createTaskWorkPackageView( cat, "TaskWorkPackageView", QString(), TIP_USE_DEFAULT_TEXT ); ct = "Reports"; cat = m_viewlist->addCategory(ct, defaultCategoryInfo(ct).name); createReportsGeneratorView(cat, "ReportsGeneratorView", i18n("Generate reports"), TIP_USE_DEFAULT_TEXT); #ifdef PLAN_USE_KREPORT // Let user add reports explicitly, we prefer reportsgenerator now // A little hack to get the user started... #if 0 ReportView *rv = qobject_cast( createReportView( cat, "ReportView", i18n( "Task Status Report" ), TIP_USE_DEFAULT_TEXT ) ); if ( rv ) { QDomDocument doc; doc.setContent( standardTaskStatusReport() ); rv->loadXML( doc ); } #endif #endif } } ViewBase *View::createView( ViewListItem *cat, const QString &type, const QString &tag, const QString &name, const QString &tip, int index ) { ViewBase *v = 0; //NOTE: type is the same as classname (so if it is changed...) if ( type == "CalendarEditor" ) { v = createCalendarEditor( cat, tag, name, tip, index ); } else if ( type == "AccountsEditor" ) { v = createAccountsEditor( cat, tag, name, tip, index ); } else if ( type == "ResourceEditor" ) { v = createResourceEditor( cat, tag, name, tip, index ); } else if ( type == "TaskEditor" ) { v = createTaskEditor( cat, tag, name, tip, index ); } else if ( type == "DependencyEditor" ) { v = createDependencyEditor( cat, tag, name, tip, index ); } else if ( type == "PertEditor" ) { v = createPertEditor( cat, tag, name, tip, index ); } else if ( type == "ScheduleEditor" ) { v = createScheduleEditor( cat, tag, name, tip, index ); } else if ( type == "ScheduleHandlerView" ) { v = createScheduleHandler( cat, tag, name, tip, index ); } else if ( type == "ProjectStatusView" ) { v = createProjectStatusView( cat, tag, name, tip, index ); } else if ( type == "TaskStatusView" ) { v = createTaskStatusView( cat, tag, name, tip, index ); } else if ( type == "TaskView" ) { v = createTaskView( cat, tag, name, tip, index ); } else if ( type == "TaskWorkPackageView" ) { v = createTaskWorkPackageView( cat, tag, name, tip, index ); } else if ( type == "GanttView" ) { v = createGanttView( cat, tag, name, tip, index ); } else if ( type == "MilestoneGanttView" ) { v = createMilestoneGanttView( cat, tag, name, tip, index ); } else if ( type == "ResourceAppointmentsView" ) { v = createResourceAppointmentsView( cat, tag, name, tip, index ); } else if ( type == "ResourceAppointmentsGanttView" ) { v = createResourceAppointmentsGanttView( cat, tag, name, tip, index ); } else if ( type == "AccountsView" ) { v = createAccountsView( cat, tag, name, tip, index ); } else if ( type == "PerformanceStatusView" ) { v = createPerformanceStatusView( cat, tag, name, tip, index ); } else if ( type == "ReportsGeneratorView" ) { v = createReportsGeneratorView(cat, tag, name, tip, index); } else if ( type == "ReportView" ) { #ifdef PLAN_USE_KREPORT v = createReportView( cat, tag, name, tip, index ); #endif } else { warnPlan<<"Unknown viewtype: "<type() == ViewListItem::ItemType_SubView ) { itm->setViewInfo( defaultViewInfo( itm->viewType() ) ); } else if ( itm->type() == ViewListItem::ItemType_Category ) { ViewInfo vi = defaultCategoryInfo( itm->tag() ); itm->setViewInfo( vi ); } } ViewInfo View::defaultViewInfo( const QString &type ) const { ViewInfo vi; if ( type == "CalendarEditor" ) { vi.name = i18n( "Work & Vacation" ); vi.tip = xi18nc( "@info:tooltip", "Edit working- and vacation days for resources" ); } else if ( type == "AccountsEditor" ) { vi.name = i18n( "Cost Breakdown Structure" ); vi.tip = xi18nc( "@info:tooltip", "Edit cost breakdown structure." ); } else if ( type == "ResourceEditor" ) { vi.name = i18n( "Resources" ); vi.tip = xi18nc( "@info:tooltip", "Edit resource breakdown structure" ); } else if ( type == "TaskEditor" ) { vi.name = i18n( "Tasks" ); vi.tip = xi18nc( "@info:tooltip", "Edit work breakdown structure" ); } else if ( type == "DependencyEditor" ) { vi.name = i18n( "Dependencies (Graphic)" ); vi.tip = xi18nc( "@info:tooltip", "Edit task dependencies" ); } else if ( type == "PertEditor" ) { vi.name = i18n( "Dependencies (List)" ); vi.tip = xi18nc( "@info:tooltip", "Edit task dependencies" ); } else if ( type == "ScheduleEditor" ) { // This view is not used stand-alone atm vi.name = i18n( "Schedules" ); } else if ( type == "ScheduleHandlerView" ) { vi.name = i18n( "Schedules" ); vi.tip = xi18nc( "@info:tooltip", "Calculate and analyze project schedules" ); } else if ( type == "ProjectStatusView" ) { vi.name = i18n( "Project Performance Chart" ); vi.tip = xi18nc( "@info:tooltip", "View project status information" ); } else if ( type == "TaskStatusView" ) { vi.name = i18n( "Task Status" ); vi.tip = xi18nc( "@info:tooltip", "View task progress information" ); } else if ( type == "TaskView" ) { vi.name = i18n( "Task Execution" ); vi.tip = xi18nc( "@info:tooltip", "View task execution information" ); } else if ( type == "TaskWorkPackageView" ) { vi.name = i18n( "Work Package View" ); vi.tip = xi18nc( "@info:tooltip", "View task work package information" ); } else if ( type == "GanttView" ) { vi.name = i18n( "Gantt" ); vi.tip = xi18nc( "@info:tooltip", "View Gantt chart" ); } else if ( type == "MilestoneGanttView" ) { vi.name = i18n( "Milestone Gantt" ); vi.tip = xi18nc( "@info:tooltip", "View milestone Gantt chart" ); } else if ( type == "ResourceAppointmentsView" ) { vi.name = i18n( "Resource Assignments" ); vi.tip = xi18nc( "@info:tooltip", "View resource assignments in a table" ); } else if ( type == "ResourceAppointmentsGanttView" ) { vi.name = i18n( "Resource Assignments (Gantt)" ); vi.tip = xi18nc( "@info:tooltip", "View resource assignments in Gantt chart" ); } else if ( type == "AccountsView" ) { vi.name = i18n( "Cost Breakdown" ); vi.tip = xi18nc( "@info:tooltip", "View planned and actual cost" ); } else if ( type == "PerformanceStatusView" ) { vi.name = i18n( "Tasks Performance Chart" ); vi.tip = xi18nc( "@info:tooltip", "View tasks performance status information" ); } else if ( type == "ReportsGeneratorView" ) { vi.name = i18n( "Reports Generator" ); vi.tip = xi18nc( "@info:tooltip", "Generate reports" ); } else if ( type == "ReportView" ) { vi.name = i18n( "Report" ); vi.tip = xi18nc( "@info:tooltip", "View report" ); } else { warnPlan<<"Unknown viewtype: "<count()-1) : m_visitedViews.at(m_visitedViews.count() - 2); debugPlan<<"Prev:"<setCurrentIndex(view); return; } if ( url.url().startsWith( QLatin1String( "about:plan" ) ) ) { getPart()->aboutPage().generatePage( v->htmlPart(), url ); return; } } if ( url.scheme() == QLatin1String("help") ) { KHelpClient::invokeHelp( "", url.fileName() ); return; } // try to open the url debugPlan<htmlPart().setJScriptEnabled(false); v->htmlPart().setJavaEnabled(false); v->htmlPart().setMetaRefreshEnabled(false); v->htmlPart().setPluginsEnabled(false); slotOpenUrlRequest( v, QUrl( "about:plan/main" ) ); connect( v, &HtmlView::openUrlRequest, this, &View::slotOpenUrlRequest ); m_tab->addWidget( v ); return v; } ViewBase *View::createResourceAppointmentsGanttView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { ResourceAppointmentsGanttView *v = new ResourceAppointmentsGanttView(getKoPart(), getPart(), m_tab ); m_tab->addWidget( v ); ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "ResourceAppointmentsGanttView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( this, &View::currentScheduleManagerChanged, v, &ResourceAppointmentsGanttView::setScheduleManager); connect( v, &ResourceAppointmentsGanttView::requestPopupMenu, this, &View::slotPopupMenuRequested); v->setProject( &( getProject() ) ); v->setScheduleManager( currentScheduleManager() ); v->updateReadWrite( m_readWrite ); return v; } ViewBase *View::createResourceAppointmentsView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { ResourceAppointmentsView *v = new ResourceAppointmentsView(getKoPart(), getPart(), m_tab ); m_tab->addWidget( v ); ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "ResourceAppointmentsView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( this, &View::currentScheduleManagerChanged, v, &ResourceAppointmentsView::setScheduleManager); connect( v, &ResourceAppointmentsView::requestPopupMenu, this, &View::slotPopupMenuRequested); v->setProject( &( getProject() ) ); v->setScheduleManager( currentScheduleManager() ); v->updateReadWrite( m_readWrite ); return v; } ViewBase *View::createResourceEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { ResourceEditor *resourceeditor = new ResourceEditor(getKoPart(), getPart(), m_tab ); resourceeditor->setViewSplitMode(false); m_tab->addWidget( resourceeditor ); resourceeditor->setProject( &(getProject()) ); ViewListItem *i = m_viewlist->addView( cat, tag, name, resourceeditor, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "ResourceEditor" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } connect( resourceeditor, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( resourceeditor, &ResourceEditor::deleteObjectList, this, &View::slotDeleteResourceObjects ); connect( resourceeditor, &ResourceEditor::requestPopupMenu, this, &View::slotPopupMenuRequested); resourceeditor->updateReadWrite( m_readWrite ); return resourceeditor; } ViewBase *View::createTaskEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { TaskEditor *taskeditor = new TaskEditor(getKoPart(), getPart(), m_tab ); taskeditor->setViewSplitMode(false); m_tab->addWidget( taskeditor ); ViewListItem *i = m_viewlist->addView( cat, tag, name, taskeditor, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "TaskEditor" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } taskeditor->setProject( &(getProject()) ); taskeditor->setScheduleManager( currentScheduleManager() ); connect( this, &View::currentScheduleManagerChanged, taskeditor, &TaskEditor::setScheduleManager); connect( taskeditor, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( taskeditor, &TaskEditor::addTask, this, &View::slotAddTask ); connect( taskeditor, &TaskEditor::addMilestone, this, &View::slotAddMilestone ); connect( taskeditor, &TaskEditor::addSubtask, this, &View::slotAddSubTask ); connect( taskeditor, &TaskEditor::addSubMilestone, this, &View::slotAddSubMilestone ); connect(taskeditor, &TaskEditor::deleteTaskList, this, &View::slotDeleteTaskList); connect( taskeditor, &TaskEditor::moveTaskUp, this, &View::slotMoveTaskUp ); connect( taskeditor, &TaskEditor::moveTaskDown, this, &View::slotMoveTaskDown ); connect( taskeditor, &TaskEditor::indentTask, this, &View::slotIndentTask ); connect( taskeditor, &TaskEditor::unindentTask, this, &View::slotUnindentTask ); connect(taskeditor, &TaskEditor::saveTaskModule, this, &View::saveTaskModule); connect(taskeditor, &TaskEditor::removeTaskModule, this, &View::removeTaskModule); connect(taskeditor, &ViewBase::openDocument, static_cast(m_partpart), &Part::openTaskModule); connect(this, &View::taskModulesChanged, taskeditor, &TaskEditor::setTaskModules); connect( taskeditor, &TaskEditor::requestPopupMenu, this, &View::slotPopupMenuRequested); taskeditor->updateReadWrite( m_readWrite ); // last: QStringList modules = KoResourcePaths::findAllResources( "calligraplan_taskmodules", "*.plan", KoResourcePaths::NoDuplicates|KoResourcePaths::Recursive ); debugPlan<setTaskModules( modules ); return taskeditor; } ViewBase *View::createAccountsEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { AccountsEditor *ae = new AccountsEditor(getKoPart(), getPart(), m_tab ); m_tab->addWidget( ae ); ViewListItem *i = m_viewlist->addView( cat, tag, name, ae, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "AccountsEditor" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } ae->draw( getProject() ); connect( ae, &ViewBase::guiActivated, this, &View::slotGuiActivated ); ae->updateReadWrite( m_readWrite ); return ae; } ViewBase *View::createCalendarEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { CalendarEditor *calendareditor = new CalendarEditor(getKoPart(), getPart(), m_tab ); m_tab->addWidget( calendareditor ); ViewListItem *i = m_viewlist->addView( cat, tag, name, calendareditor, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "CalendarEditor" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } calendareditor->draw( getProject() ); connect( calendareditor, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( calendareditor, &CalendarEditor::requestPopupMenu, this, &View::slotPopupMenuRequested); calendareditor->updateReadWrite( m_readWrite ); return calendareditor; } ViewBase *View::createScheduleHandler( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { ScheduleHandlerView *handler = new ScheduleHandlerView(getKoPart(), getPart(), m_tab ); m_tab->addWidget( handler ); ViewListItem *i = m_viewlist->addView( cat, tag, name, handler, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "ScheduleHandlerView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } connect( handler->scheduleEditor(), &ScheduleEditor::addScheduleManager, this, &View::slotAddScheduleManager ); connect( handler->scheduleEditor(), &ScheduleEditor::deleteScheduleManager, this, &View::slotDeleteScheduleManager ); connect( handler->scheduleEditor(), &ScheduleEditor::moveScheduleManager, this, &View::slotMoveScheduleManager); connect( handler->scheduleEditor(), &ScheduleEditor::calculateSchedule, this, &View::slotCalculateSchedule ); connect( handler->scheduleEditor(), &ScheduleEditor::baselineSchedule, this, &View::slotBaselineSchedule ); connect( handler, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( this, &View::currentScheduleManagerChanged, handler, &ScheduleHandlerView::currentScheduleManagerChanged ); connect( handler, &ScheduleHandlerView::requestPopupMenu, this, &View::slotPopupMenuRequested); connect(handler, &ScheduleHandlerView::editNode, this, &View::slotOpenNode); connect(handler, &ScheduleHandlerView::editResource, this, &View::slotEditResource); handler->draw( getProject() ); handler->updateReadWrite( m_readWrite ); return handler; } ScheduleEditor *View::createScheduleEditor( QWidget *parent ) { ScheduleEditor *scheduleeditor = new ScheduleEditor(getKoPart(), getPart(), parent ); connect( scheduleeditor, &ScheduleEditor::addScheduleManager, this, &View::slotAddScheduleManager ); connect( scheduleeditor, &ScheduleEditor::deleteScheduleManager, this, &View::slotDeleteScheduleManager ); connect( scheduleeditor, &ScheduleEditor::calculateSchedule, this, &View::slotCalculateSchedule ); connect( scheduleeditor, &ScheduleEditor::baselineSchedule, this, &View::slotBaselineSchedule ); scheduleeditor->updateReadWrite( m_readWrite ); return scheduleeditor; } ViewBase *View::createScheduleEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { ScheduleEditor *scheduleeditor = new ScheduleEditor(getKoPart(), getPart(), m_tab ); m_tab->addWidget( scheduleeditor ); ViewListItem *i = m_viewlist->addView( cat, tag, name, scheduleeditor, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "ScheduleEditor" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } scheduleeditor->setProject( &( getProject() ) ); connect( scheduleeditor, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( scheduleeditor, &ScheduleEditor::addScheduleManager, this, &View::slotAddScheduleManager ); connect( scheduleeditor, &ScheduleEditor::deleteScheduleManager, this, &View::slotDeleteScheduleManager ); connect( scheduleeditor, &ScheduleEditor::calculateSchedule, this, &View::slotCalculateSchedule ); connect( scheduleeditor, &ScheduleEditor::baselineSchedule, this, &View::slotBaselineSchedule ); scheduleeditor->updateReadWrite( m_readWrite ); return scheduleeditor; } ViewBase *View::createDependencyEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { DependencyEditor *editor = new DependencyEditor(getKoPart(), getPart(), m_tab ); m_tab->addWidget( editor ); ViewListItem *i = m_viewlist->addView( cat, tag, name, editor, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "DependencyEditor" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } editor->draw( getProject() ); connect( editor, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( editor, &DependencyEditor::addRelation, this, &View::slotAddRelation); connect( editor, &DependencyEditor::modifyRelation, this, &View::slotModifyRelation); connect( editor, &DependencyEditor::editRelation, this, &View::slotEditRelation); connect( editor, &DependencyEditor::editNode, this, &View::slotOpenNode); connect( editor, &DependencyEditor::addTask, this, &View::slotAddTask ); connect( editor, &DependencyEditor::addMilestone, this, &View::slotAddMilestone ); connect( editor, &DependencyEditor::addSubMilestone, this, &View::slotAddSubMilestone ); connect( editor, &DependencyEditor::addSubtask, this, &View::slotAddSubTask ); connect( editor, &DependencyEditor::deleteTaskList, this, &View::slotDeleteTaskList); connect( this, &View::currentScheduleManagerChanged, editor, &DependencyEditor::setScheduleManager); connect( editor, &DependencyEditor::requestPopupMenu, this, &View::slotPopupMenuRequested); editor->updateReadWrite( m_readWrite ); editor->setScheduleManager( currentScheduleManager() ); return editor; } ViewBase *View::createPertEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { PertEditor *perteditor = new PertEditor(getKoPart(), getPart(), m_tab ); m_tab->addWidget( perteditor ); ViewListItem *i = m_viewlist->addView( cat, tag, name, perteditor, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "PertEditor" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } perteditor->draw( getProject() ); connect( perteditor, &ViewBase::guiActivated, this, &View::slotGuiActivated ); m_updatePertEditor = true; perteditor->updateReadWrite( m_readWrite ); return perteditor; } ViewBase *View::createProjectStatusView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { ProjectStatusView *v = new ProjectStatusView(getKoPart(), getPart(), m_tab ); m_tab->addWidget( v ); ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "ProjectStatusView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( this, &View::currentScheduleManagerChanged, v, &ProjectStatusView::setScheduleManager); v->updateReadWrite( m_readWrite ); v->setProject( &getProject() ); v->setScheduleManager( currentScheduleManager() ); return v; } ViewBase *View::createPerformanceStatusView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { PerformanceStatusView *v = new PerformanceStatusView(getKoPart(), getPart(), m_tab ); m_tab->addWidget( v ); ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "PerformanceStatusView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( this, &View::currentScheduleManagerChanged, v, &PerformanceStatusView::setScheduleManager); connect( v, &PerformanceStatusView::requestPopupMenu, this, &View::slotPopupMenuRequested); v->updateReadWrite( m_readWrite ); v->setProject( &getProject() ); v->setScheduleManager( currentScheduleManager() ); return v; } ViewBase *View::createTaskStatusView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { TaskStatusView *taskstatusview = new TaskStatusView(getKoPart(), getPart(), m_tab ); taskstatusview->setViewSplitMode(false); m_tab->addWidget( taskstatusview ); ViewListItem *i = m_viewlist->addView( cat, tag, name, taskstatusview, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "TaskStatusView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } connect( taskstatusview, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( this, &View::currentScheduleManagerChanged, taskstatusview, &TaskStatusView::setScheduleManager); connect( taskstatusview, &TaskStatusView::requestPopupMenu, this, &View::slotPopupMenuRequested); taskstatusview->updateReadWrite( m_readWrite ); taskstatusview->draw( getProject() ); taskstatusview->setScheduleManager( currentScheduleManager() ); return taskstatusview; } ViewBase *View::createTaskView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { TaskView *v = new TaskView(getKoPart(), getPart(), m_tab ); v->setViewSplitMode(false); m_tab->addWidget( v ); ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "TaskView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } v->draw( getProject() ); v->setScheduleManager( currentScheduleManager() ); connect( this, &View::currentScheduleManagerChanged, v, &TaskView::setScheduleManager); connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( v, &TaskView::requestPopupMenu, this, &View::slotPopupMenuRequested); v->updateReadWrite( m_readWrite ); return v; } ViewBase *View::createTaskWorkPackageView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { TaskWorkPackageView *v = new TaskWorkPackageView(getKoPart(), getPart(), m_tab ); v->setViewSplitMode(false); m_tab->addWidget( v ); ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "TaskWorkPackageView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } v->setProject( &getProject() ); v->setScheduleManager( currentScheduleManager() ); connect( this, &View::currentScheduleManagerChanged, v, &TaskWorkPackageView::setScheduleManager); connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( v, &TaskWorkPackageView::requestPopupMenu, this, &View::slotPopupMenuRequested); connect( v, &TaskWorkPackageView::mailWorkpackage, this, &View::slotMailWorkpackage ); connect( v, &TaskWorkPackageView::mailWorkpackages, this, &View::slotMailWorkpackages ); connect(v, &TaskWorkPackageView::checkForWorkPackages, getPart(), &MainDocument::checkForWorkPackages); v->updateReadWrite( m_readWrite ); return v; } ViewBase *View::createGanttView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { GanttView *ganttview = new GanttView(getKoPart(), getPart(), m_tab, koDocument()->isReadWrite() ); m_tab->addWidget( ganttview ); ViewListItem *i = m_viewlist->addView( cat, tag, name, ganttview, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "GanttView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } ganttview->setProject( &( getProject() ) ); ganttview->setScheduleManager( currentScheduleManager() ); connect( ganttview, &ViewBase::guiActivated, this, &View::slotGuiActivated ); /* TODO: Review these connect( ganttview, SIGNAL(addRelation(KPlato::Node*,KPlato::Node*,int)), SLOT(slotAddRelation(KPlato::Node*,KPlato::Node*,int)) ); connect( ganttview, SIGNAL(modifyRelation(KPlato::Relation*,int)), SLOT(slotModifyRelation(KPlato::Relation*,int)) ); connect( ganttview, SIGNAL(modifyRelation(KPlato::Relation*)), SLOT(slotModifyRelation(KPlato::Relation*)) ); connect( ganttview, SIGNAL(itemDoubleClicked()), SLOT(slotOpenNode()) ); connect( ganttview, SIGNAL(itemRenamed(KPlato::Node*,QString)), this, SLOT(slotRenameNode(KPlato::Node*,QString)) );*/ connect( this, &View::currentScheduleManagerChanged, ganttview, &GanttView::setScheduleManager); connect( ganttview, &GanttView::requestPopupMenu, this, &View::slotPopupMenuRequested); ganttview->updateReadWrite( m_readWrite ); return ganttview; } ViewBase *View::createMilestoneGanttView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { MilestoneGanttView *ganttview = new MilestoneGanttView(getKoPart(), getPart(), m_tab, koDocument()->isReadWrite() ); m_tab->addWidget( ganttview ); ViewListItem *i = m_viewlist->addView( cat, tag, name, ganttview, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "MilestoneGanttView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } ganttview->setProject( &( getProject() ) ); ganttview->setScheduleManager( currentScheduleManager() ); connect( ganttview, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( this, &View::currentScheduleManagerChanged, ganttview, &MilestoneGanttView::setScheduleManager); connect( ganttview, &MilestoneGanttView::requestPopupMenu, this, &View::slotPopupMenuRequested); ganttview->updateReadWrite( m_readWrite ); return ganttview; } ViewBase *View::createAccountsView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { AccountsView *accountsview = new AccountsView(getKoPart(), &getProject(), getPart(), m_tab ); m_tab->addWidget( accountsview ); ViewListItem *i = m_viewlist->addView( cat, tag, name, accountsview, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "AccountsView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } accountsview->setScheduleManager( currentScheduleManager() ); connect( this, &View::currentScheduleManagerChanged, accountsview, &AccountsView::setScheduleManager); connect( accountsview, &ViewBase::guiActivated, this, &View::slotGuiActivated ); accountsview->updateReadWrite( m_readWrite ); return accountsview; } ViewBase *View::createResourceAssignmentView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { ResourceAssignmentView *resourceAssignmentView = new ResourceAssignmentView(getKoPart(), getPart(), m_tab ); m_tab->addWidget( resourceAssignmentView ); m_updateResourceAssignmentView = true; ViewListItem *i = m_viewlist->addView( cat, tag, name, resourceAssignmentView, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "ResourceAssignmentView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } resourceAssignmentView->draw( getProject() ); connect( resourceAssignmentView, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( resourceAssignmentView, &ResourceAssignmentView::requestPopupMenu, this, &View::slotPopupMenuRequested); resourceAssignmentView->updateReadWrite( m_readWrite ); return resourceAssignmentView; } ViewBase *View::createReportsGeneratorView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index) { ReportsGeneratorView *v = new ReportsGeneratorView(getKoPart(), getPart(), m_tab ); m_tab->addWidget( v ); ViewListItem *i = m_viewlist->addView(cat, tag, name, v, getPart(), "", index); ViewInfo vi = defaultViewInfo( "ReportsGeneratorView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } v->setProject( &getProject() ); connect( this, &View::currentScheduleManagerChanged, v, &ViewBase::setScheduleManager ); connect( this, &View::currentScheduleManagerChanged, v, &ViewBase::slotRefreshView); v->setScheduleManager( currentScheduleManager() ); connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated ); connect( v, &ReportsGeneratorView::requestPopupMenu, this, &View::slotPopupMenuRequested); v->updateReadWrite( m_readWrite ); return v; } ViewBase *View::createReportView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { #ifdef PLAN_USE_KREPORT ReportView *v = new ReportView(getKoPart(), getPart(), m_tab ); m_tab->addWidget( v ); ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "ReportView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } v->setProject( &getProject() ); connect( this, &View::currentScheduleManagerChanged, v, &ReportView::setScheduleManager); connect( this, &View::currentScheduleManagerChanged, v, SLOT(slotRefreshView())); v->setScheduleManager( currentScheduleManager() ); connect( v, &ReportView::guiActivated, this, &View::slotGuiActivated); v->updateReadWrite( m_readWrite ); return v; #else Q_UNUSED(cat) Q_UNUSED(tag) Q_UNUSED(name) Q_UNUSED(tip) Q_UNUSED(index) return 0; #endif } Project& View::getProject() const { return getPart() ->getProject(); } KoPrintJob * View::createPrintJob() { KoView *v = qobject_cast( canvas() ); if ( v == 0 ) { return 0; } return v->createPrintJob(); } ViewBase *View::currentView() const { return qobject_cast( m_tab->currentWidget() ); } void View::slotEditCut() { ViewBase *v = currentView(); if ( v ) { v->slotEditCut(); } } void View::slotEditCopy() { ViewBase *v = currentView(); if ( v ) { v->slotEditCopy(); } } void View::slotEditPaste() { ViewBase *v = currentView(); if ( v ) { v->slotEditPaste(); } } void View::slotRefreshView() { ViewBase *v = currentView(); if ( v ) { debugPlan<slotRefreshView(); } } void View::slotViewSelector( bool show ) { //debugPlan; m_viewlist->setVisible( show ); } void View::slotInsertResourcesFile(const QString &file, const QUrl &projects) { getPart()->insertResourcesFile(QUrl(file), projects); } void View::slotInsertFile() { InsertFileDialog *dlg = new InsertFileDialog( getProject(), currentTask(), this ); connect(dlg, &QDialog::finished, this, &View::slotInsertFileFinished); dlg->show(); dlg->raise(); dlg->activateWindow(); } void View::slotInsertFileFinished( int result ) { InsertFileDialog *dlg = qobject_cast( sender() ); if ( dlg == 0 ) { return; } if ( result == QDialog::Accepted ) { getPart()->insertFile( dlg->url(), dlg->parentNode(), dlg->afterNode() ); } dlg->deleteLater(); } void View::slotLoadSharedProjects() { LoadSharedProjectsDialog *dlg = new LoadSharedProjectsDialog( getProject(), getPart()->url(), this ); connect(dlg, &QDialog::finished, this, &View::slotLoadSharedProjectsFinished); dlg->show(); dlg->raise(); dlg->activateWindow(); } void View::slotLoadSharedProjectsFinished( int result ) { LoadSharedProjectsDialog *dlg = qobject_cast( sender() ); if ( dlg == 0 ) { return; } if ( result == QDialog::Accepted ) { getPart()->insertSharedProjects(dlg->urls()); } dlg->deleteLater(); } void View::slotProjectEdit() { slotOpenNode( &getProject() ); } void View::slotProjectWorktime() { StandardWorktimeDialog *dia = new StandardWorktimeDialog( getProject(), this ); connect(dia, &QDialog::finished, this, &View::slotProjectWorktimeFinished); dia->show(); dia->raise(); dia->activateWindow(); } void View::slotProjectWorktimeFinished( int result ) { StandardWorktimeDialog *dia = qobject_cast( sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { KUndo2Command * cmd = dia->buildCommand(); if ( cmd ) { //debugPlan<<"Modifying calendar(s)"; getPart() ->addCommand( cmd ); //also executes } } dia->deleteLater(); } void View::slotSelectionChanged( ScheduleManager *sm ) { debugPlan<setChecked( true ); // this doesn't trigger QActionGroup slotViewSchedule( a ); } QList View::sortedActionList() { QMap lst; const QMap map = m_scheduleActions; // clazy:exclude=qmap-with-pointer-key QMap::const_iterator it; for (it = map.constBegin(); it != map.constEnd(); ++it) { lst.insert(it.key()->objectName(), it.key()); } return lst.values(); } +void View::slotScheduleSwapped(ScheduleManager *from, ScheduleManager *to) +{ + if (currentScheduleManager() == from) { + QAction *a = m_scheduleActions.key(to); + if (a) { + a->setChecked(true); + } + } +} + void View::slotScheduleRemoved( const ScheduleManager *sch ) { debugPlan<name(); QAction *a = 0; QAction *checked = m_scheduleActionGroup->checkedAction(); QMapIterator i( m_scheduleActions ); while (i.hasNext()) { i.next(); if ( i.value() == sch ) { a = i.key(); break; } } if ( a ) { unplugActionList( "view_schedule_list" ); delete a; plugActionList( "view_schedule_list", sortedActionList() ); if ( checked && checked != a ) { checked->setChecked( true ); } else if ( ! m_scheduleActions.isEmpty() ) { m_scheduleActions.firstKey()->setChecked( true ); } } slotViewSchedule( m_scheduleActionGroup->checkedAction() ); } void View::slotScheduleAdded( const ScheduleManager *sch ) { ScheduleManager *s = const_cast( sch ); QAction *checked = m_scheduleActionGroup->checkedAction(); unplugActionList( "view_schedule_list" ); QAction *act = addScheduleAction( s ); plugActionList( "view_schedule_list", sortedActionList() ); if (!currentScheduleManager()) { if ( act ) { act->setChecked( true ); } else if ( ! m_scheduleActions.isEmpty() ) { m_scheduleActions.firstKey()->setChecked( true ); } slotViewSchedule( m_scheduleActionGroup->checkedAction() ); } } void View::slotScheduleCalculated(Project *project, ScheduleManager *manager) { Q_UNUSED(project); if (manager == currentScheduleManager()) { slotViewScheduleManager(manager); } } QAction *View::addScheduleAction( ScheduleManager *sch ) { QAction *act = 0; QString n = sch->name(); act = new KToggleAction( n, this); actionCollection()->addAction(n, act ); m_scheduleActions.insert( act, sch ); m_scheduleActionGroup->addAction( act ); //debugPlan<<"Add:"<name(); m_scheduleActions.remove( static_cast( o ) ); } void View::slotPlugScheduleActions() { ScheduleManager *current = currentScheduleManager(); unplugActionList( "view_schedule_list" ); const QMap map = m_scheduleActions; // clazy:exclude=qmap-with-pointer-key QMap::const_iterator it; for (it = map.constBegin(); it != map.constEnd(); ++it) { m_scheduleActionGroup->removeAction(it.key()); delete it.key(); } m_scheduleActions.clear(); QAction *ca = 0; foreach( ScheduleManager *sm, getProject().allScheduleManagers() ) { QAction *act = addScheduleAction(sm); if (sm == current) { ca = act; } } plugActionList( "view_schedule_list", sortedActionList() ); if ( ca == 0 && m_scheduleActionGroup->actions().count() > 0 ) { ca = m_scheduleActionGroup->actions().constFirst(); } if ( ca ) { ca->setChecked( true ); } slotViewSchedule( ca ); } void View::slotCalculateSchedule( Project *project, ScheduleManager *sm ) { if ( project == 0 || sm == 0 ) { return; } if ( sm->parentManager() && ! sm->parentManager()->isScheduled() ) { // the parent must be scheduled return; } CalculateScheduleCmd *cmd = new CalculateScheduleCmd( *project, sm, kundo2_i18nc("@info:status 1=schedule name", "Calculate %1", sm->name() ) ); getPart() ->addCommand( cmd ); slotUpdate(); } void View::slotRemoveCommands() { while ( ! m_undocommands.isEmpty() ) { m_undocommands.last()->undo(); delete m_undocommands.takeLast(); } } void View::slotBaselineSchedule( Project *project, ScheduleManager *sm ) { if ( project == 0 || sm == 0 ) { return; } if ( ! sm->isBaselined() && project->isBaselined() ) { KMessageBox::sorry( this, i18n( "Cannot baseline. The project is already baselined." ) ); return; } KUndo2Command *cmd; if ( sm->isBaselined() ) { KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel( this, i18n( "This schedule is baselined. Do you want to remove the baseline?" ) ); if ( res == KMessageBox::Cancel ) { return; } cmd = new ResetBaselineScheduleCmd( *sm, kundo2_i18n( "Reset baseline %1", sm->name() ) ); } else { cmd = new BaselineScheduleCmd( *sm, kundo2_i18n( "Baseline %1", sm->name() ) ); } getPart() ->addCommand( cmd ); } void View::slotAddScheduleManager( Project *project ) { if ( project == 0 ) { return; } ScheduleManager *sm = project->createScheduleManager(); AddScheduleManagerCmd *cmd = new AddScheduleManagerCmd( *project, sm, -1, kundo2_i18n( "Add schedule %1", sm->name() ) ); getPart() ->addCommand( cmd ); } void View::slotDeleteScheduleManager( Project *project, ScheduleManager *sm ) { if ( project == 0 || sm == 0) { return; } DeleteScheduleManagerCmd *cmd = new DeleteScheduleManagerCmd( *project, sm, kundo2_i18n( "Delete schedule %1", sm->name() ) ); getPart() ->addCommand( cmd ); } void View::slotMoveScheduleManager( ScheduleManager *sm, ScheduleManager *parent, int index ) { if ( sm == 0 ) { return; } MoveScheduleManagerCmd *cmd = new MoveScheduleManagerCmd( sm, parent, index, kundo2_i18n( "Move schedule %1", sm->name() ) ); getPart() ->addCommand( cmd ); } void View::slotAddSubTask() { Task * node = getProject().createTask( getPart() ->config().taskDefaults() ); SubTaskAddDialog *dia = new SubTaskAddDialog( getProject(), *node, currentNode(), getProject().accounts(), this ); connect(dia, &QDialog::finished, this, &View::slotAddSubTaskFinished); dia->show(); dia->raise(); dia->activateWindow(); } void View::slotAddSubTaskFinished( int result ) { SubTaskAddDialog *dia = qobject_cast( sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { KUndo2Command *m = dia->buildCommand(); getPart() ->addCommand( m ); // add task to project } dia->deleteLater(); } void View::slotAddTask() { Task * node = getProject().createTask( getPart() ->config().taskDefaults() ); TaskAddDialog *dia = new TaskAddDialog( getProject(), *node, currentNode(), getProject().accounts(), this ); connect(dia, &QDialog::finished, this, &View::slotAddTaskFinished); dia->show(); dia->raise(); dia->activateWindow(); } void View::slotAddTaskFinished( int result ) { TaskAddDialog *dia = qobject_cast( sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { KUndo2Command *m = dia->buildCommand(); getPart() ->addCommand( m ); // add task to project } dia->deleteLater(); } void View::slotAddMilestone() { Task * node = getProject().createTask(); node->estimate() ->clear(); TaskAddDialog *dia = new TaskAddDialog( getProject(), *node, currentNode(), getProject().accounts(), this ); connect(dia, &QDialog::finished, this, &View::slotAddMilestoneFinished); dia->show(); dia->raise(); dia->activateWindow(); } void View::slotAddMilestoneFinished( int result ) { TaskAddDialog *dia = qobject_cast( sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { MacroCommand *c = new MacroCommand( kundo2_i18n( "Add milestone" ) ); c->addCommand( dia->buildCommand() ); getPart() ->addCommand( c ); // add task to project } dia->deleteLater(); } void View::slotAddSubMilestone() { Task * node = getProject().createTask(); node->estimate() ->clear(); SubTaskAddDialog *dia = new SubTaskAddDialog( getProject(), *node, currentNode(), getProject().accounts(), this ); connect(dia, &QDialog::finished, this, &View::slotAddSubMilestoneFinished); dia->show(); dia->raise(); dia->activateWindow(); } void View::slotAddSubMilestoneFinished( int result ) { SubTaskAddDialog *dia = qobject_cast( sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { MacroCommand *c = new MacroCommand( kundo2_i18n( "Add sub-milestone" ) ); c->addCommand( dia->buildCommand() ); getPart() ->addCommand( c ); // add task to project } dia->deleteLater(); } void View::slotDefineWBS() { //debugPlan; Project &p = getProject(); WBSDefinitionDialog *dia = new WBSDefinitionDialog( p, p.wbsDefinition(), this ); connect(dia, &QDialog::finished, this, &View::slotDefineWBSFinished); dia->show(); dia->raise(); dia->activateWindow(); } void View::slotDefineWBSFinished( int result ) { //debugPlan; WBSDefinitionDialog *dia = qobject_cast( sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted ) { KUndo2Command *cmd = dia->buildCommand(); if ( cmd ) { getPart()->addCommand( cmd ); } } dia->deleteLater(); } void View::slotConfigure() { //debugPlan; if( KConfigDialog::showDialog("Plan Settings") ) { return; } ConfigDialog *dialog = new ConfigDialog( this, "Plan Settings", KPlatoSettings::self() ); dialog->addPage(new ConfigProjectPanel(), i18n("Project Defaults"), koIconName("calligraplan") ); dialog->addPage(new ConfigWorkVacationPanel(), i18n("Work & Vacation"), koIconName("view-calendar") ); dialog->addPage(new TaskDefaultPanel(), i18n("Task Defaults"), koIconName("view-task") ); dialog->addPage(new ColorsConfigPanel(), i18n("Task Colors"), koIconName("fill-color") ); dialog->addPage(new WorkPackageConfigPanel(), i18n("Work Package"), koIconName("calligraplanwork") ); dialog->show(); } void View::slotIntroduction() { m_tab->setCurrentIndex(0); } Calendar *View::currentCalendar() { ViewBase *v = dynamic_cast( m_tab->currentWidget() ); if ( v == 0 ) { return 0; } return v->currentCalendar(); } Node *View::currentNode() const { ViewBase *v = dynamic_cast( m_tab->currentWidget() ); if ( v == 0 ) { return 0; } Node * task = v->currentNode(); if ( 0 != task ) { return task; } return &( getProject() ); } Task *View::currentTask() const { ViewBase *v = dynamic_cast( m_tab->currentWidget() ); if ( v == 0 ) { return 0; } Node * task = v->currentNode(); if ( task ) { return dynamic_cast( task ); } return 0; } Resource *View::currentResource() { ViewBase *v = dynamic_cast( m_tab->currentWidget() ); if ( v == 0 ) { return 0; } return v->currentResource(); } ResourceGroup *View::currentResourceGroup() { ViewBase *v = dynamic_cast( m_tab->currentWidget() ); if ( v == 0 ) { return 0; } return v->currentResourceGroup(); } void View::slotOpenCurrentNode() { //debugPlan; Node * node = currentNode(); slotOpenNode( node ); } void View::slotOpenNode( Node *node ) { //debugPlan; if ( !node ) return ; switch ( node->type() ) { case Node::Type_Project: { Project * project = static_cast( node ); MainProjectDialog *dia = new MainProjectDialog( *project, this ); connect(dia, &MainProjectDialog::dialogFinished, this, &View::slotProjectEditFinished); connect(dia, &MainProjectDialog::sigLoadSharedResources, this, &View::slotInsertResourcesFile); connect(dia, &MainProjectDialog::loadResourceAssignments, getPart(), &MainDocument::loadResourceAssignments); connect(dia, &MainProjectDialog::clearResourceAssignments, getPart(), &MainDocument::clearResourceAssignments); dia->show(); dia->raise(); dia->activateWindow(); break; } case Node::Type_Subproject: //TODO break; case Node::Type_Task: { Task *task = static_cast( node ); TaskDialog *dia = new TaskDialog( getProject(), *task, getProject().accounts(), this ); connect(dia, &QDialog::finished, this, &View::slotTaskEditFinished); dia->show(); dia->raise(); dia->activateWindow(); break; } case Node::Type_Milestone: { // Use the normal task dialog for now. // Maybe milestone should have it's own dialog, but we need to be able to // enter a duration in case we accidentally set a tasks duration to zero // and hence, create a milestone Task *task = static_cast( node ); TaskDialog *dia = new TaskDialog( getProject(), *task, getProject().accounts(), this ); connect(dia, &QDialog::finished, this, &View::slotTaskEditFinished); dia->show(); dia->raise(); dia->activateWindow(); break; } case Node::Type_Summarytask: { Task *task = dynamic_cast( node ); Q_ASSERT( task ); SummaryTaskDialog *dia = new SummaryTaskDialog( *task, this ); connect(dia, &QDialog::finished, this, &View::slotSummaryTaskEditFinished); dia->show(); dia->raise(); dia->activateWindow(); break; } default: break; // avoid warnings } } void View::slotProjectEditFinished( int result ) { MainProjectDialog *dia = qobject_cast( sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { KUndo2Command * cmd = dia->buildCommand(); if ( cmd ) { getPart() ->addCommand( cmd ); } } dia->deleteLater(); } void View::slotTaskEditFinished( int result ) { TaskDialog *dia = qobject_cast( sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { KUndo2Command * cmd = dia->buildCommand(); if ( cmd ) { getPart() ->addCommand( cmd ); } } dia->deleteLater(); } void View::slotSummaryTaskEditFinished( int result ) { SummaryTaskDialog *dia = qobject_cast( sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { KUndo2Command * cmd = dia->buildCommand(); if ( cmd ) { getPart() ->addCommand( cmd ); } } dia->deleteLater(); } ScheduleManager *View::currentScheduleManager() const { return m_scheduleActions.value( m_scheduleActionGroup->checkedAction() ); } long View::activeScheduleId() const { ScheduleManager *s = m_scheduleActions.value( m_scheduleActionGroup->checkedAction() ); return s == nullptr || s->expected() == nullptr ? -1 : s->expected()->id(); } void View::setActiveSchedule( long id ) { if ( id != -1 ) { QMap::const_iterator it = m_scheduleActions.constBegin(); for (; it != m_scheduleActions.constEnd(); ++it ) { int mid = it.value()->expected() == nullptr ? -1 : it.value()->expected()->id(); if (mid == id) { it.key()->setChecked( true ); slotViewSchedule( it.key() ); // signal not emitted from group, so trigger it here break; } } } } void View::slotTaskProgress() { //debugPlan; Node * node = currentNode(); if ( !node ) return ; switch ( node->type() ) { case Node::Type_Project: { break; } case Node::Type_Subproject: //TODO break; case Node::Type_Task: { Task *task = dynamic_cast( node ); Q_ASSERT( task ); TaskProgressDialog *dia = new TaskProgressDialog( *task, currentScheduleManager(), getProject().standardWorktime(), this ); connect(dia, &QDialog::finished, this, &View::slotTaskProgressFinished); dia->show(); dia->raise(); dia->activateWindow(); break; } case Node::Type_Milestone: { Task *task = dynamic_cast( node ); Q_ASSERT( task ); MilestoneProgressDialog *dia = new MilestoneProgressDialog( *task, this ); connect(dia, &QDialog::finished, this, &View::slotMilestoneProgressFinished); dia->show(); dia->raise(); dia->activateWindow(); break; } case Node::Type_Summarytask: { // TODO break; } default: break; // avoid warnings } } void View::slotTaskProgressFinished( int result ) { TaskProgressDialog *dia = qobject_cast(sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { KUndo2Command * m = dia->buildCommand(); if ( m ) { getPart() ->addCommand( m ); } } dia->deleteLater(); } void View::slotMilestoneProgressFinished( int result ) { MilestoneProgressDialog *dia = qobject_cast(sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { KUndo2Command * m = dia->buildCommand(); if ( m ) { getPart() ->addCommand( m ); } } dia->deleteLater(); } void View::slotTaskDescription() { //debugPlan; Node * node = currentNode(); if ( !node ) return ; - qInfo()<type() ) { case Node::Type_Subproject: //TODO break; case Node::Type_Project: case Node::Type_Task: case Node::Type_Milestone: case Node::Type_Summarytask: { TaskDescriptionDialog *dia = new TaskDescriptionDialog( *node, this ); connect(dia, &QDialog::finished, this, &View::slotTaskDescriptionFinished); dia->show(); dia->raise(); dia->activateWindow(); break; } default: break; // avoid warnings } } void View::slotTaskDescriptionFinished( int result ) { TaskDescriptionDialog *dia = qobject_cast(sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { KUndo2Command * m = dia->buildCommand(); if ( m ) { getPart() ->addCommand( m ); } } dia->deleteLater(); } void View::slotDocuments() { //debugPlan; Node * node = currentNode(); if ( !node ) { return ; } switch ( node->type() ) { case Node::Type_Subproject: //TODO break; case Node::Type_Project: case Node::Type_Summarytask: case Node::Type_Task: case Node::Type_Milestone: { DocumentsDialog *dia = new DocumentsDialog(*node, this); connect(dia, &QDialog::finished, this, &View::slotDocumentsFinished); dia->show(); dia->raise(); dia->activateWindow(); break; } default: break; // avoid warnings } } void View::slotDocumentsFinished( int result ) { DocumentsDialog *dia = qobject_cast(sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { KUndo2Command * m = dia->buildCommand(); if ( m ) { getPart()->addCommand( m ); } } dia->deleteLater(); } void View::slotDeleteTaskList( QList lst ) { //debugPlan; foreach ( Node *n, lst ) { if ( n->isScheduled() ) { KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel( this, i18n( "A task that has been scheduled will be deleted. This will invalidate the schedule." ) ); if ( res == KMessageBox::Cancel ) { return; } break; } } if ( lst.count() == 1 ) { getPart()->addCommand( new NodeDeleteCmd( lst.takeFirst(), kundo2_i18n( "Delete task" ) ) ); return; } int num = 0; MacroCommand *cmd = new MacroCommand( kundo2_i18np( "Delete task", "Delete tasks", lst.count() ) ); while ( !lst.isEmpty() ) { Node *node = lst.takeFirst(); if ( node == 0 || node->parentNode() == 0 ) { debugPlan << ( node ?"Task is main project" :"No current task" ); continue; } bool del = true; foreach ( Node *n, lst ) { if ( node->isChildOf( n ) ) { del = false; // node is going to be deleted when we delete n break; } } if ( del ) { //debugPlan<name(); cmd->addCommand( new NodeDeleteCmd( node, kundo2_i18n( "Delete task" ) ) ); num++; } } if ( num > 0 ) { getPart()->addCommand( cmd ); } else { delete cmd; } } void View::slotDeleteTask( Node *node ) { //debugPlan; if ( node == 0 || node->parentNode() == 0 ) { debugPlan << ( node ?"Task is main project" :"No current task" ); return ; } if ( node->isScheduled() ) { KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel( this, i18n( "This task has been scheduled. This will invalidate the schedule." ) ); if ( res == KMessageBox::Cancel ) { return; } } NodeDeleteCmd *cmd = new NodeDeleteCmd( node, kundo2_i18n( "Delete task" ) ); getPart() ->addCommand( cmd ); } void View::slotDeleteCurrentTask() { //debugPlan; return slotDeleteTask( currentNode() ); } void View::slotIndentTask() { //debugPlan; Node * node = currentNode(); if ( node == 0 || node->parentNode() == 0 ) { debugPlan << ( node ?"Task is main project" :"No current task" ); return ; } if ( getProject().canIndentTask( node ) ) { NodeIndentCmd * cmd = new NodeIndentCmd( *node, kundo2_i18n( "Indent task" ) ); getPart() ->addCommand( cmd ); } } void View::slotUnindentTask() { //debugPlan; Node * node = currentNode(); if ( node == 0 || node->parentNode() == 0 ) { debugPlan << ( node ?"Task is main project" :"No current task" ); return ; } if ( getProject().canUnindentTask( node ) ) { NodeUnindentCmd * cmd = new NodeUnindentCmd( *node, kundo2_i18n( "Unindent task" ) ); getPart() ->addCommand( cmd ); } } void View::slotMoveTaskUp() { //debugPlan; Node * task = currentNode(); if ( 0 == task ) { // is always != 0. At least we would get the Project, but you never know who might change that // so better be careful errorPlan << "No current task" << endl; return ; } if ( Node::Type_Project == task->type() ) { debugPlan <<"The root node cannot be moved up"; return ; } if ( getProject().canMoveTaskUp( task ) ) { NodeMoveUpCmd * cmd = new NodeMoveUpCmd( *task, kundo2_i18n( "Move task up" ) ); getPart() ->addCommand( cmd ); } } void View::slotMoveTaskDown() { //debugPlan; Node * task = currentNode(); if ( 0 == task ) { // is always != 0. At least we would get the Project, but you never know who might change that // so better be careful return ; } if ( Node::Type_Project == task->type() ) { debugPlan <<"The root node cannot be moved down"; return ; } if ( getProject().canMoveTaskDown( task ) ) { NodeMoveDownCmd * cmd = new NodeMoveDownCmd( *task, kundo2_i18n( "Move task down" ) ); getPart() ->addCommand( cmd ); } } void View::openRelationDialog( Node *par, Node *child ) { //debugPlan; Relation * rel = new Relation( par, child ); AddRelationDialog *dia = new AddRelationDialog( getProject(), rel, this ); connect(dia, &QDialog::finished, this, &View::slotAddRelationFinished); dia->show(); dia->raise(); dia->activateWindow(); } void View::slotAddRelationFinished( int result ) { AddRelationDialog *dia = qobject_cast(sender() ); if ( dia == 0 ) { return; } if ( result == QDialog::Accepted) { KUndo2Command * m = dia->buildCommand(); if ( m ) { getPart() ->addCommand( m ); } } dia->deleteLater(); } void View::slotAddRelation( Node *par, Node *child, int linkType ) { //debugPlan; if ( linkType == Relation::FinishStart || linkType == Relation::StartStart || linkType == Relation::FinishFinish ) { Relation * rel = new Relation( par, child, static_cast( linkType ) ); getPart() ->addCommand( new AddRelationCmd( getProject(), rel, kundo2_i18n( "Add task dependency" ) ) ); } else { openRelationDialog( par, child ); } } void View::slotEditRelation( Relation *rel ) { //debugPlan; ModifyRelationDialog *dia = new ModifyRelationDialog( getProject(), rel, this ); connect(dia, &QDialog::finished, this, &View::slotModifyRelationFinished); dia->show(); dia->raise(); dia->activateWindow(); } void View::slotModifyRelationFinished( int result ) { ModifyRelationDialog *dia = qobject_cast( sender() ); if ( dia == 0 ) { return ; } if ( result == QDialog::Accepted) { KUndo2Command *cmd = dia->buildCommand(); if ( cmd ) { getPart() ->addCommand( cmd ); } } dia->deleteLater(); } void View::slotModifyRelation( Relation *rel, int linkType ) { //debugPlan; if ( linkType == Relation::FinishStart || linkType == Relation::StartStart || linkType == Relation::FinishFinish ) { getPart() ->addCommand( new ModifyRelationTypeCmd( rel, static_cast( linkType ) ) ); } else { slotEditRelation( rel ); } } void View::slotModifyCurrentRelation() { ViewBase *v = dynamic_cast( m_tab->currentWidget() ); if ( v == 0 ) { return; } Relation *rel = v->currentRelation(); if ( rel ) { slotEditRelation( rel ); } } void View::slotDeleteRelation() { ViewBase *v = dynamic_cast( m_tab->currentWidget() ); if ( v == 0 ) { return; } Relation *rel = v->currentRelation(); if ( rel ) { getPart()->addCommand( new DeleteRelationCmd( getProject(), rel, kundo2_i18n( "Delete task dependency" ) ) ); } } void View::slotEditCurrentResource() { //debugPlan; slotEditResource( currentResource() ); } void View::slotEditResource( Resource *resource ) { if ( resource == 0 ) { return ; } ResourceDialog *dia = new ResourceDialog( getProject(), resource, this ); connect(dia, &QDialog::finished, this, &View::slotEditResourceFinished); dia->show(); dia->raise(); dia->activateWindow(); } void View::slotEditResourceFinished( int result ) { //debugPlan; ResourceDialog *dia = qobject_cast( sender() ); if ( dia == 0 ) { return ; } if ( result == QDialog::Accepted) { KUndo2Command * cmd = dia->buildCommand(); if ( cmd ) getPart() ->addCommand( cmd ); } dia->deleteLater(); } void View::slotDeleteResource( Resource *resource ) { getPart()->addCommand( new RemoveResourceCmd( resource->parentGroup(), resource, kundo2_i18n( "Delete resource" ) ) ); } void View::slotDeleteResourceGroup( ResourceGroup *group ) { getPart()->addCommand( new RemoveResourceGroupCmd( group->project(), group, kundo2_i18n( "Delete resourcegroup" ) ) ); } void View::slotDeleteResourceObjects( QObjectList lst ) { //debugPlan; foreach ( QObject *o, lst ) { Resource *r = qobject_cast( o ); if ( r && r->isScheduled() ) { KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel( this, i18n( "A resource that has been scheduled will be deleted. This will invalidate the schedule." ) ); if ( res == KMessageBox::Cancel ) { return; } break; } ResourceGroup *g = qobject_cast( o ); if ( g && g->isScheduled() ) { KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel( this, i18n( "A resource that has been scheduled will be deleted. This will invalidate the schedule." ) ); if ( res == KMessageBox::Cancel ) { return; } break; } } if ( lst.count() == 1 ) { Resource *r = qobject_cast( lst.first() ); if ( r ) { slotDeleteResource( r ); } else { ResourceGroup *g = qobject_cast( lst.first() ); if ( g ) { slotDeleteResourceGroup( g ); } } return; } // int num = 0; MacroCommand *cmd = 0, *rc = 0, *gc = 0; foreach ( QObject *o, lst ) { Resource *r = qobject_cast( o ); if ( r ) { if ( rc == 0 ) rc = new MacroCommand( KUndo2MagicString() ); rc->addCommand( new RemoveResourceCmd( r->parentGroup(), r ) ); continue; } ResourceGroup *g = qobject_cast( o ); if ( g ) { if ( gc == 0 ) gc = new MacroCommand( KUndo2MagicString() ); gc->addCommand( new RemoveResourceGroupCmd( g->project(), g ) ); } } if ( rc || gc ) { KUndo2MagicString s; if ( rc && gc ) { s = kundo2_i18n( "Delete resourcegroups and resources" ); } else if ( rc ) { s = kundo2_i18np( "Delete resource", "Delete resources", lst.count() ); } else { s = kundo2_i18np( "Delete resourcegroup", "Delete resourcegroups", lst.count() ); } cmd = new MacroCommand( s ); } if ( rc ) cmd->addCommand( rc ); if ( gc ) cmd->addCommand( gc ); if ( cmd ) getPart()->addCommand( cmd ); } void View::updateReadWrite( bool readwrite ) { m_readWrite = readwrite; m_viewlist->setReadWrite( readwrite ); } MainDocument *View::getPart() const { return ( MainDocument * ) koDocument(); } KoPart *View::getKoPart() const { return m_partpart; } void View::slotConnectNode() { //debugPlan; /* NodeItem *curr = ganttview->currentItem(); if (curr) { debugPlan<<"node="<getNode().name(); }*/ } QMenu * View::popupMenu( const QString& name ) { //debugPlan; if ( factory() ) { return ( ( QMenu* ) factory() ->container( name, this ) ); } debugPlan<<"No factory"; return 0L; } void View::slotUpdate() { //debugPlan<<"calculate="<currentWidget() ); } void View::slotGuiActivated( ViewBase *view, bool activate ) { //FIXME: Avoid unplug if possible, it flashes the gui // always unplug, in case they already are plugged foreach( const QString &name, view->actionListNames() ) { unplugActionList( name ); } if ( activate ) { foreach( const QString &name, view->actionListNames() ) { plugActionList( name, view->actionList( name ) ); } foreach ( DockWidget *ds, view->dockers() ) { m_dockers.append( ds ); ds->activate( mainWindow() ); } if (!m_dockers.isEmpty()) {debugPlan<<"Added dockers:"<deactivate( mainWindow() ); } } } void View::guiActivateEvent( bool activated ) { if ( activated ) { // plug my own actionlists, they may be gone slotPlugScheduleActions(); } // propagate to sub-view ViewBase *v = dynamic_cast( m_tab->currentWidget() ); if ( v ) { v->setGuiActive( activated ); } } void View::slotViewListItemRemoved( ViewListItem *item ) { getPart()->removeViewListItem( this, item ); } void View::removeViewListItem( const ViewListItem *item ) { if ( item == 0 ) { return; } ViewListItem *itm = m_viewlist->findItem( item->tag() ); if ( itm == 0 ) { return; } m_viewlist->removeViewListItem( itm ); return; } void View::slotViewListItemInserted( ViewListItem *item, ViewListItem *parent, int index ) { getPart()->insertViewListItem( this, item, parent, index ); } void View::addViewListItem( const ViewListItem *item, const ViewListItem *parent, int index ) { if ( item == 0 ) { return; } if ( parent == 0 ) { if ( item->type() != ViewListItem::ItemType_Category ) { return; } m_viewlist->blockSignals( true ); ViewListItem *cat = m_viewlist->addCategory( item->tag(), item->text( 0 ) ); cat->setToolTip( 0, item->toolTip( 0 ) ); m_viewlist->blockSignals( false ); return; } ViewListItem *cat = m_viewlist->findCategory( parent->tag() ); if ( cat == 0 ) { return; } m_viewlist->blockSignals( true ); createView( cat, item->viewType(), item->tag(), item->text( 0 ), item->toolTip( 0 ), index ); m_viewlist->blockSignals( false ); } void View::createReportView(const QDomDocument &doc) { #ifdef PLAN_USE_KREPORT QPointer vd = new ViewListReportsDialog( this, *m_viewlist, doc, this ); vd->exec(); // FIXME make non-crash delete vd; #else Q_UNUSED(doc) #endif } void View::slotOpenReportFile() { #ifdef PLAN_USE_KREPORT QFileDialog *dlg = new QFileDialog(this); connect(dlg, &QDialog::finished, &View::slotOpenReportFileFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); #endif } void View::slotOpenReportFileFinished( int result ) { #ifdef PLAN_USE_KREPORT QFileDialog *fdlg = qobject_cast( sender() ); if ( fdlg == 0 || result != QDialog::Accepted ) { return; } QString fn = fdlg->selectedFiles().value(0); if ( fn.isEmpty() ) { return; } QFile file( fn ); if ( ! file.open( QIODevice::ReadOnly | QIODevice::Text ) ) { KMessageBox::sorry( this, xi18nc( "@info", "Cannot open file:
%1", fn ) ); return; } QDomDocument doc; doc.setContent( &file ); createReportView(doc); #else Q_UNUSED(result) #endif } void View::slotReportDesignFinished( int /*result */) { #ifdef PLAN_USE_KREPORT if ( sender() ) { sender()->deleteLater(); } #endif } void View::slotCreateView() { ViewListDialog *dlg = new ViewListDialog( this, *m_viewlist, this ); connect(dlg, &QDialog::finished, this, &View::slotCreateViewFinished); dlg->show(); dlg->raise(); dlg->activateWindow(); } void View::slotCreateViewFinished( int ) { if ( sender() ) { sender()->deleteLater(); } } void View::slotViewActivated( ViewListItem *item, ViewListItem *prev ) { QApplication::setOverrideCursor( Qt::WaitCursor ); if ( prev && prev->type() == ViewListItem::ItemType_Category && m_viewlist->previousViewItem() ) { // A view is shown anyway... ViewBase *v = qobject_cast( m_viewlist->previousViewItem()->view() ); if ( v ) { v->setGuiActive( false ); } } else if ( prev && prev->type() == ViewListItem::ItemType_SubView ) { ViewBase *v = qobject_cast( prev->view() ); if ( v ) { v->setGuiActive( false ); } } if ( item && item->type() == ViewListItem::ItemType_SubView ) { //debugPlan<<"Activate:"<setCurrentWidget( item->view() ); // Add sub-view specific gui ViewBase *v = dynamic_cast( m_tab->currentWidget() ); if ( v ) { v->setGuiActive( true ); } } QApplication::restoreOverrideCursor(); } QWidget *View::canvas() const { return m_tab->currentWidget();//KoView::canvas(); } KoPageLayout View::pageLayout() const { return currentView()->pageLayout(); } void View::setPageLayout(const KoPageLayout &pageLayout) { currentView()->setPageLayout(pageLayout); } QPrintDialog *View::createPrintDialog( KoPrintJob *printJob, QWidget *parent ) { debugPlan<( printJob ); if ( ! job ) { return 0; } QPrintDialog *dia = KoView::createPrintDialog( job, parent ); PrintingDialog *j = dynamic_cast( job ); if ( j ) { new PrintingControlPrivate( j, dia ); } return dia; } void View::slotCurrentChanged( int view ) { m_visitedViews << view; ViewListItem *item = m_viewlist->findItem( qobject_cast( m_tab->currentWidget() ) ); m_viewlist->setCurrentItem( item ); } void View::slotSelectDefaultView() { m_tab->setCurrentIndex(qMin(m_defaultView, m_tab->count()-1)); } void View::updateView( QWidget * ) { QApplication::setOverrideCursor( Qt::WaitCursor ); //setScheduleActionsEnabled(); QWidget *widget2; widget2 = m_viewlist->findView( "ResourceAssignmentView" ); if ( widget2 && m_updateResourceAssignmentView ) static_cast( widget2 ) ->draw( getProject() ); m_updateResourceAssignmentView = false; QApplication::restoreOverrideCursor(); } void View::slotRenameNode( Node *node, const QString& name ) { //debugPlan<type() ) { case Node::Type_Task: s = kundo2_i18n( "Modify task name" ); break; case Node::Type_Milestone: s = kundo2_i18n( "Modify milestone name" ); break; case Node::Type_Summarytask: s = kundo2_i18n( "Modify summarytask name" ); break; case Node::Type_Project: s = kundo2_i18n( "Modify project name" ); break; } NodeModifyNameCmd * cmd = new NodeModifyNameCmd( *node, name, s ); getPart() ->addCommand( cmd ); } } void View::slotPopupMenuRequested( const QString& menuname, const QPoint & pos ) { QMenu * menu = this->popupMenu( menuname ); if ( menu ) { //debugPlan<actions().count(); ViewBase *v = qobject_cast( m_tab->currentWidget() ); //debugPlan< lst; if ( v ) { lst = v->contextActionList(); debugPlan<addSeparator(); foreach ( QAction *a, lst ) { menu->addAction( a ); } } } menu->exec( pos ); foreach ( QAction *a, lst ) { menu->removeAction( a ); } } } void View::slotPopupMenu( const QString& menuname, const QPoint &pos, ViewListItem *item ) { //debugPlan<context(); if ( ctx == 0 || ! ctx->isLoaded() ) { return false; } KoXmlElement n = ctx->context(); QString cv = n.attribute( "current-view" ); if ( ! cv.isEmpty() ) { m_viewlist->setSelected( m_viewlist->findItem( cv ) ); } else debugPlan<<"No current view"; long id = n.attribute( "current-schedule", "-1" ).toLong(); if ( id != -1 ) { setActiveSchedule( id ); } else debugPlan<<"No current schedule"; return true; } void View::saveContext( QDomElement &me ) const { //debugPlan; long id = activeScheduleId(); if ( id != -1 ) { me.setAttribute( "current-schedule", QString::number((qlonglong)id) ); } ViewListItem *item = m_viewlist->findItem( qobject_cast( m_tab->currentWidget() ) ); if ( item ) { me.setAttribute("current-view", item->tag() ); } m_viewlist->save( me ); } bool View::loadWorkPackage( Project &project, const QUrl &url ) { return getPart()->loadWorkPackage( project, url ); } void View::setLabel( ScheduleManager *sm ) { //debugPlan; Schedule *s = sm == 0 ? 0 : sm->expected(); if ( s && !s->isDeleted() && s->isScheduled() ) { m_estlabel->setText( sm->name() ); return; } m_estlabel->setText( xi18nc( "@info:status", "Not scheduled" ) ); } void View::slotWorkPackageLoaded() { debugPlan<workPackages(); } void View::slotMailWorkpackage( Node *node, Resource *resource ) { debugPlan; QTemporaryFile tmpfile(QDir::tempPath() + QLatin1String("/calligraplanwork_XXXXXX") + QLatin1String( ".planwork" )); tmpfile.setAutoRemove( false ); if ( ! tmpfile.open() ) { debugPlan<<"Failed to open file"; KMessageBox::error(0, i18n("Failed to open temporary file" ) ); return; } QUrl url = QUrl::fromLocalFile( tmpfile.fileName() ); if ( ! getPart()->saveWorkPackageUrl( url, node, activeScheduleId(), resource ) ) { debugPlan<<"Failed to save to file"; KMessageBox::error(0, xi18nc( "@info", "Failed to save to temporary file:
%1", url.url() ) ); return; } QStringList attachURLs; attachURLs << url.url(); QString to = resource == 0 ? node->leader() : ( resource->name() + " <" + resource->email() + '>' ); QString cc; QString bcc; QString subject = i18n( "Work Package: %1", node->name() ); QString body = i18nc( "1=project name, 2=task name", "%1\n%2", getProject().name(), node->name() ); QString messageFile; KToolInvocation::invokeMailer( to, cc, bcc, subject, body, messageFile, attachURLs ); } void View::slotMailWorkpackages( const QList &nodes, Resource *resource ) { debugPlan; if ( resource == 0 ) { warnPlan<<"No resource, we don't handle node->leader() yet"; return; } QString to = resource->name() + " <" + resource->email() + '>'; QString subject = i18n( "Work Package for project: %1", getProject().name() ); QString body; QStringList attachURLs; foreach ( Node *n, nodes ) { QTemporaryFile tmpfile(QDir::tempPath() + QLatin1String("/calligraplanwork_XXXXXX") + QLatin1String( ".planwork" )); tmpfile.setAutoRemove( false ); if ( ! tmpfile.open() ) { debugPlan<<"Failed to open file"; KMessageBox::error(0, i18n("Failed to open temporary file" ) ); return; } QUrl url = QUrl::fromLocalFile( tmpfile.fileName() ); if ( ! getPart()->saveWorkPackageUrl( url, n, activeScheduleId(), resource ) ) { debugPlan<<"Failed to save to file"; KMessageBox::error(0, xi18nc( "@info", "Failed to save to temporary file:
%1", url.url() ) ); return; } attachURLs << url.url(); body += n->name() + '\n'; } QString cc; QString bcc; QString messageFile; KToolInvocation::invokeMailer( to, cc, bcc, subject, body, messageFile, attachURLs ); } void View::slotCurrencyConfig() { LocaleConfigMoneyDialog *dlg = new LocaleConfigMoneyDialog( getProject().locale(), this ); connect(dlg, &QDialog::finished, this, &View::slotCurrencyConfigFinished); dlg->show(); dlg->raise(); dlg->activateWindow(); } void View::slotCurrencyConfigFinished( int result ) { LocaleConfigMoneyDialog *dlg = qobject_cast( sender() ); if ( dlg == 0 ) { return; } if ( result == QDialog::Accepted ) { KUndo2Command *c = dlg->buildCommand( getProject() ); if ( c ) { getPart()->addCommand( c ); } } dlg->deleteLater(); } void View::saveTaskModule( const QUrl &url, Project *project ) { // NOTE: workaround: KoResourcePaths::saveLocation( "calligraplan_taskmodules" ); does not work const QString dir = KoResourcePaths::saveLocation( "appdata", "taskmodules/" ); debugPlan<<"dir="<setDocument( doc ); doc->disconnect(); // doc shall not handle feedback from openUrl() doc->setAutoSave( 0 ); //disable doc->insertProject( *project, 0, 0 ); // FIXME: destroys project, find better way doc->getProject().setName( project->name() ); doc->getProject().setLeader( project->leader() ); doc->getProject().setDescription( project->description() ); doc->saveNativeFormat( dir + url.fileName() ); part->deleteLater(); // also deletes document debugPlan<" "" "" "%1" "" "" "predefined" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "") .arg( i18n( "Report" ), i18nc( "Project manager", "Manager:" ), i18n( "Project:" ), i18n( "Task Status Report" ), i18nc( "As in: Page 1 of 2", "of" ), i18n( "Page" ), i18nc( "Task name", "Name" ), i18nc( "Task completion", "Completion (%)" ) ); #endif return s; } } //KPlato namespace diff --git a/src/kptview.h b/src/kptview.h index c8e5bf68..5ca2d29a 100644 --- a/src/kptview.h +++ b/src/kptview.h @@ -1,456 +1,457 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999, 2000 Torben Weis Copyright (C) 2002 - 2010 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 KPTVIEW_H #define KPTVIEW_H #include "plan_export.h" #include #include "kptcontext.h" #include "kptviewbase.h" #include #include #include #include #include class QMenu; class QPrintDialog; class QStackedWidget; class QSplitter; class QUrl; class KUndo2Command; class QAction; class KToggleAction; class QLabel; class KConfigSkeleton; class KConfigSkeletonItem; class KoView; namespace KPlato { class View; class ViewBase; class ViewListItem; class ViewListWidget; struct ViewInfo; class AccountsView; class ResourceCoverageView; class GanttView; class PertEditor; class AccountsEditor; class TaskEditor; class CalendarEditor; class ScheduleEditor; class ScheduleManager; class CalculateScheduleCmd; class ResourceAssignmentView; class TaskStatusView; class Calendar; class MainDocument; class Part; class Node; class Project; class Task; class MainSchedule; class Schedule; class Resource; class ResourceGroup; class Relation; class Context; class ViewAdaptor; class HtmlView; class ReportView; class ReportDesignDialog; class DockWidget; class ConfigDialog : public KConfigDialog { Q_OBJECT public: ConfigDialog( QWidget *parent, const QString &name, KConfigSkeleton *config ); protected Q_SLOTS: /// Return true if any widget has changed virtual bool hasChanged(); /** * Update the settings from the dialog. * Virtual function for custom additions. * * Example use: User clicks Ok or Apply button in a configure dialog. */ virtual void updateSettings(); /** * Update the dialog based on the settings. * Virtual function for custom additions. * * Example use: Initialisation of dialog. * Example use: User clicks Reset button in a configure dialog. */ virtual void updateWidgets(); /** * Update the dialog based on the default settings. * Virtual function for custom additions. * * Example use: User clicks Defaults button in a configure dialog. */ virtual void updateWidgetsDefault(); /** * Returns whether the current state of the dialog is * the same as the default configuration. */ virtual bool isDefault(); private: KConfigSkeleton *m_config; QMap m_signalsmap; QMap m_itemmap; QMap m_propertymap; }; //------------- class PLAN_EXPORT View : public KoView { Q_OBJECT public: explicit View(KoPart *part, MainDocument *doc, QWidget *parent = 0); ~View(); MainDocument *getPart() const; KoPart *getKoPart() const; Project& getProject() const; QMenu *popupMenu( const QString& name ); virtual bool loadContext(); virtual void saveContext( QDomElement &context ) const; /// Load the workpackage from @p url into @p project. Return true if successful, else false. bool loadWorkPackage( Project &project, const QUrl &url ); QWidget *canvas() const; KoPageLayout pageLayout() const; void setPageLayout(const KoPageLayout &pageLayout); ScheduleManager *currentScheduleManager() const; long activeScheduleId() const; void setActiveSchedule( long id ); /// Returns the default view information like standard name and tooltip for view type @p type ViewInfo defaultViewInfo( const QString &type ) const; /// Returns the default category information like standard name and tooltip for category type @p type ViewInfo defaultCategoryInfo( const QString &type ) const; ViewBase *createTaskEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createResourceEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createAccountsEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createCalendarEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createScheduleHandler( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ScheduleEditor *createScheduleEditor( QWidget *parent ); ViewBase *createScheduleEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createDependencyEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createPertEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createProjectStatusView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createPerformanceStatusView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createTaskStatusView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createTaskView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createTaskWorkPackageView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createGanttView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createMilestoneGanttView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createResourceAppointmentsView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createResourceAppointmentsGanttView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createAccountsView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createResourceAssignmentView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createChartView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createReportView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createReportsGeneratorView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); KoPrintJob * createPrintJob(); QPrintDialog* createPrintDialog(KoPrintJob*, QWidget*); Q_SIGNALS: void currentScheduleManagerChanged(KPlato::ScheduleManager *sm); void taskModulesChanged(const QStringList &modules); public Q_SLOTS: void slotUpdate(); void slotCreateNewProject(); void slotEditCurrentResource(); void slotEditResource(KPlato::Resource *resource); void slotEditCut(); void slotEditCopy(); void slotEditPaste(); void slotRefreshView(); void slotViewSelector( bool show ); void slotAddTask(); void slotAddSubTask(); void slotAddMilestone(); void slotAddSubMilestone(); void slotProjectEdit(); void slotDefineWBS(); void slotCurrencyConfig(); void slotCreateView(); void slotConfigure(); void slotIntroduction(); void openRelationDialog(KPlato::Node *par, KPlato::Node *child); void slotEditRelation(KPlato::Relation *rel); void slotAddRelation(KPlato::Node *par, KPlato::Node *child, int linkType); void slotModifyRelation(KPlato::Relation *rel, int linkType); void slotModifyCurrentRelation(); void slotDeleteRelation(); void slotRenameNode(KPlato::Node *node, const QString& name); void slotPopupMenuRequested( const QString& menuname, const QPoint &pos ); void slotPopupMenu( const QString& menuname, const QPoint &pos, KPlato::ViewListItem *item ); void addViewListItem(const KPlato::ViewListItem *item, const KPlato::ViewListItem *parent, int index); void removeViewListItem(const KPlato::ViewListItem *item); void slotOpenReportFile(); void slotSelectionChanged(KPlato::ScheduleManager *sm); void slotUpdateViewInfo(KPlato::ViewListItem *itm); protected Q_SLOTS: void slotGuiActivated(KPlato::ViewBase *view, bool); void slotViewActivated(KPlato::ViewListItem*, KPlato::ViewListItem*); void slotPlugScheduleActions(); void slotViewSchedule( QAction *act ); void slotScheduleAdded(const KPlato::ScheduleManager*); void slotScheduleRemoved( const KPlato::ScheduleManager*); + void slotScheduleSwapped(KPlato::ScheduleManager *from, KPlato::ScheduleManager *to); void slotScheduleCalculated(KPlato::Project *project, KPlato::ScheduleManager *manager); void slotAddScheduleManager(KPlato::Project *project); void slotDeleteScheduleManager(KPlato::Project *project, KPlato::ScheduleManager *sm); void slotMoveScheduleManager(KPlato::ScheduleManager *sm, KPlato::ScheduleManager *parent, int index); void slotCalculateSchedule(KPlato::Project*, KPlato::ScheduleManager*); void slotBaselineSchedule(KPlato::Project *project, KPlato::ScheduleManager *sm); void slotProjectWorktime(); void slotOpenCurrentNode(); void slotOpenNode(KPlato::Node *node); void slotTaskProgress(); void slotTaskDescription(); void slotDocuments(); void slotDeleteTaskList(QList lst); void slotDeleteTask(KPlato::Node *node); void slotDeleteCurrentTask(); void slotIndentTask(); void slotUnindentTask(); void slotMoveTaskUp(); void slotMoveTaskDown(); void slotConnectNode(); void slotDeleteResource(KPlato::Resource *resource); void slotDeleteResourceGroup(KPlato::ResourceGroup *group); void slotDeleteResourceObjects( QObjectList ); void slotCurrentChanged( int ); void slotSelectDefaultView(); void slotInsertResourcesFile(const QString&, const QUrl &projects); void slotInsertFile(); void slotLoadSharedProjects(); void slotWorkPackageLoaded(); void slotMailWorkpackage(KPlato::Node *node, KPlato::Resource *resource = 0); void slotMailWorkpackages(const QList &nodes, KPlato::Resource *resource = 0 ); void slotOpenUrlRequest(KPlato::HtmlView *v, const QUrl &url); void createReportView(const QDomDocument &doc); void saveTaskModule(const QUrl &url, KPlato::Project *project); void removeTaskModule( const QUrl &url ); void taskModuleFileChanged(const QString &path); protected: virtual void guiActivateEvent( bool activated ); virtual void updateReadWrite( bool readwrite ); QList sortedActionList(); QAction *addScheduleAction( ScheduleManager *sch ); void setLabel( ScheduleManager *sm = 0 ); Task *currentTask() const; Node *currentNode() const; Resource *currentResource(); ResourceGroup *currentResourceGroup(); Calendar *currentCalendar(); void updateView( QWidget *widget ); ViewBase *currentView() const; ViewBase *createIntroductionView(); private Q_SLOTS: void slotActionDestroyed( QObject *o ); void slotViewListItemRemoved(KPlato::ViewListItem *item); void slotViewListItemInserted(KPlato::ViewListItem *item, KPlato::ViewListItem *parent, int index); void slotProjectEditFinished( int result ); void slotTaskEditFinished( int result ); void slotSummaryTaskEditFinished( int result ); void slotEditResourceFinished( int result ); void slotProjectWorktimeFinished( int result ); void slotDefineWBSFinished( int result ); void slotCurrencyConfigFinished( int result ); void slotInsertFileFinished( int result ); void slotAddSubTaskFinished( int result ); void slotAddTaskFinished( int result ); void slotAddSubMilestoneFinished( int result ); void slotAddMilestoneFinished( int result ); void slotTaskProgressFinished( int result ); void slotMilestoneProgressFinished( int result ); void slotTaskDescriptionFinished( int result ); void slotDocumentsFinished(int result); void slotAddRelationFinished( int result ); void slotModifyRelationFinished( int result ); void slotReportDesignFinished( int result ); void slotOpenReportFileFinished( int result ); void slotCreateViewFinished( int result ); void slotLoadSharedProjectsFinished( int result ); void slotRemoveCommands(); void initiateViews(); void slotViewScheduleManager(KPlato::ScheduleManager *sm); private: void createViews(); ViewBase *createView( ViewListItem *cat, const QString &type, const QString &tag, const QString &name, const QString &tip, int index = -1 ); QString standardTaskStatusReport() const; private: QSplitter *m_sp; QStackedWidget *m_tab; ViewListWidget *m_viewlist; ViewListItem *m_viewlistItem; // requested popupmenu item //QDockWidget *m_toolbox; int m_viewGrp; int m_defaultFontSize; int m_currentEstimateType; bool m_updateAccountsview; bool m_updateResourceAssignmentView; bool m_updatePertEditor; QLabel *m_estlabel; ViewAdaptor* m_dbus; QActionGroup *m_scheduleActionGroup; QMap m_scheduleActions; QMultiMap m_calculationcommands; QList m_undocommands; bool m_readWrite; int m_defaultView; QList m_visitedViews; QList m_dockers; // ------ File QAction *actionCreateTemplate; QAction *actionCreateNewProject; // ------ Edit QAction *actionCut; QAction *actionCopy; QAction *actionPaste; // ------ View KToggleAction *actionViewSelector; // ------ Insert // ------ Project QAction *actionEditMainProject; // ------ Tools QAction *actionEditStandardWorktime; QAction *actionDefineWBS; QAction *actionInsertFile; QAction *actionCurrencyConfig; QAction *actionLoadSharedProjects; QAction *actionOpenReportFile; // ------ Settings QAction *actionConfigure; // ------ Help QAction *actionIntroduction; // ------ Popup QAction *actionOpenNode; QAction *actionTaskProgress; QAction *actionTaskDescription; QAction *actionDocuments; QAction *actionDeleteTask; QAction *actionIndentTask; QAction *actionUnindentTask; QAction *actionMoveTaskUp; QAction *actionMoveTaskDown; QAction *actionEditResource; QAction *actionEditRelation; QAction *actionDeleteRelation; //Test QAction *actNoInformation; QMap m_reportActionMap; KoPart *m_partpart; KDirWatch m_dirwatch; }; } //Kplato namespace #endif diff --git a/src/libs/kernel/kptcommand.cpp b/src/libs/kernel/kptcommand.cpp index f4a4caf0..ea45677d 100644 --- a/src/libs/kernel/kptcommand.cpp +++ b/src/libs/kernel/kptcommand.cpp @@ -1,3776 +1,3817 @@ /* This file is part of the KDE project Copyright (C) 2004 - 2007 Dag Andersen Copyright (C) 2011 Dag Andersen Copyright (C) 2016 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 "kptcommand.h" #include "kptaccount.h" #include "kptappointment.h" #include "kptproject.h" #include "kpttask.h" #include "kptcalendar.h" #include "kptrelation.h" #include "kptresource.h" #include "kptdocuments.h" #include "kptlocale.h" #include "kptdebug.h" #include const QLoggingCategory &PLANCMDINSPROJECT_LOG() { static const QLoggingCategory category("calligra.plan.command.insertProject"); return category; } #define debugPlanInsertProject qCDebug(PLANCMDINSPROJECT_LOG) #define warnPlanInsertProject qCWarning(PLANCMDINSPROJECT_LOG) #define errorPlanInsertProject qCCritical(PLANCMDINSPROJECT_LOG) namespace KPlato { void NamedCommand::setSchScheduled() { QHash::ConstIterator it; for ( it = m_schedules.constBegin(); it != m_schedules.constEnd(); ++it ) { //debugPlan << it.key() ->name() <<":" << it.value(); it.key() ->setScheduled( it.value() ); } } void NamedCommand::setSchScheduled( bool state ) { QHash::ConstIterator it; for ( it = m_schedules.constBegin(); it != m_schedules.constEnd(); ++it ) { //debugPlan << it.key() ->name() <<":" << state; it.key() ->setScheduled( state ); } } void NamedCommand::addSchScheduled( Schedule *sch ) { //debugPlan << sch->id() <<":" << sch->isScheduled(); m_schedules.insert( sch, sch->isScheduled() ); foreach ( Appointment * a, sch->appointments() ) { if ( a->node() == sch ) { m_schedules.insert( a->resource(), a->resource() ->isScheduled() ); } else if ( a->resource() == sch ) { m_schedules.insert( a->node(), a->node() ->isScheduled() ); } } } //--------- MacroCommand::~MacroCommand() { while ( ! cmds.isEmpty() ) { delete cmds.takeLast(); } } void MacroCommand::addCommand( KUndo2Command *cmd ) { cmds.append( cmd ); } void MacroCommand::execute() { foreach ( KUndo2Command *c, cmds ) { c->redo(); } } void MacroCommand::unexecute() { for (int i = cmds.count() - 1; i >= 0; --i) { cmds.at( i )->undo(); } } //------------------------------------------------- CalendarAddCmd::CalendarAddCmd( Project *project, Calendar *cal, int pos, Calendar *parent, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ), m_cal( cal ), m_pos( pos ), m_parent( parent ), m_mine( true ) { //debugPlan<name(); Q_ASSERT( project != 0 ); } CalendarAddCmd::~CalendarAddCmd() { if ( m_mine ) delete m_cal; } void CalendarAddCmd::execute() { if ( m_project ) { m_project->addCalendar( m_cal, m_parent, m_pos ); m_mine = false; } //debugPlan<name()<<" added to:"<name(); } void CalendarAddCmd::unexecute() { if ( m_project ) { m_project->takeCalendar( m_cal ); m_mine = true; } //debugPlan<name(); } CalendarRemoveCmd::CalendarRemoveCmd( Project *project, Calendar *cal, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ), m_parent( cal->parentCal() ), m_cal( cal ), m_index( -1 ), m_mine( false ), m_cmd( new MacroCommand(KUndo2MagicString()) ) { Q_ASSERT( project != 0 ); m_index = m_parent ? m_parent->indexOf( cal ) : project->indexOf( cal ); foreach ( Resource *r, project->resourceList() ) { if ( r->calendar( true ) == cal ) { m_cmd->addCommand( new ModifyResourceCalendarCmd( r, 0 ) ); } } if ( project->defaultCalendar() == cal ) { m_cmd->addCommand( new ProjectModifyDefaultCalendarCmd( project, 0 ) ); } foreach ( Calendar *c, cal->calendars() ) { m_cmd->addCommand( new CalendarRemoveCmd( project, c ) ); } } CalendarRemoveCmd::~CalendarRemoveCmd() { delete m_cmd; if ( m_mine ) delete m_cal; } void CalendarRemoveCmd::execute() { m_cmd->execute(); m_project->takeCalendar( m_cal ); m_mine = true; } void CalendarRemoveCmd::unexecute() { m_project->addCalendar( m_cal, m_parent, m_index ); m_cmd->unexecute(); m_mine = false; } CalendarMoveCmd::CalendarMoveCmd( Project *project, Calendar *cal, int position, Calendar *parent, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ), m_cal( cal ), m_newpos( position ), m_newparent( parent ), m_oldparent( cal->parentCal() ) { //debugPlan<name(); Q_ASSERT( project != 0 ); m_oldpos = m_oldparent ? m_oldparent->indexOf( cal ) : project->indexOf( cal ); } void CalendarMoveCmd::execute() { m_project->takeCalendar( m_cal ); m_project->addCalendar( m_cal, m_newparent, m_newpos ); } void CalendarMoveCmd::unexecute() { m_project->takeCalendar( m_cal ); m_project->addCalendar( m_cal, m_oldparent, m_oldpos ); } CalendarModifyNameCmd::CalendarModifyNameCmd( Calendar *cal, const QString& newvalue, const KUndo2MagicString& name ) : NamedCommand( name ), m_cal( cal ) { m_oldvalue = cal->name(); m_newvalue = newvalue; //debugPlan<name(); } void CalendarModifyNameCmd::execute() { m_cal->setName( m_newvalue ); //debugPlan<name(); } void CalendarModifyNameCmd::unexecute() { m_cal->setName( m_oldvalue ); //debugPlan<name(); } CalendarModifyParentCmd::CalendarModifyParentCmd( Project *project, Calendar *cal, Calendar *newvalue, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ), m_cal( cal ), m_cmd( new MacroCommand( KUndo2MagicString() ) ), m_oldindex( -1 ), m_newindex( -1 ) { m_oldvalue = cal->parentCal(); m_newvalue = newvalue; m_oldindex = m_oldvalue ? m_oldvalue->indexOf( cal ) : m_project->indexOf( cal ); if ( newvalue ) { m_cmd->addCommand( new CalendarModifyTimeZoneCmd( cal, newvalue->timeZone() ) ); } //debugPlan<name(); } CalendarModifyParentCmd::~CalendarModifyParentCmd() { delete m_cmd; } void CalendarModifyParentCmd::execute() { m_project->takeCalendar( m_cal ); m_project->addCalendar( m_cal, m_newvalue, m_newindex ); m_cmd->execute(); } void CalendarModifyParentCmd::unexecute() { m_cmd->unexecute(); m_project->takeCalendar( m_cal ); m_project->addCalendar( m_cal, m_oldvalue, m_oldindex ); } CalendarModifyTimeZoneCmd::CalendarModifyTimeZoneCmd( Calendar *cal, const QTimeZone &value, const KUndo2MagicString& name ) : NamedCommand( name ), m_cal( cal ), m_newvalue( value ), m_cmd( new MacroCommand( KUndo2MagicString() ) ) { m_oldvalue = cal->timeZone(); foreach ( Calendar *c, cal->calendars() ) { m_cmd->addCommand( new CalendarModifyTimeZoneCmd( c, value ) ); } //debugPlan<name(); } CalendarModifyTimeZoneCmd::~CalendarModifyTimeZoneCmd() { delete m_cmd; } void CalendarModifyTimeZoneCmd::execute() { m_cmd->execute(); m_cal->setTimeZone( m_newvalue ); } void CalendarModifyTimeZoneCmd::unexecute() { m_cal->setTimeZone( m_oldvalue ); m_cmd->unexecute(); } #ifdef HAVE_KHOLIDAYS CalendarModifyHolidayRegionCmd::CalendarModifyHolidayRegionCmd( Calendar *cal, const QString &value, const KUndo2MagicString& name ) : NamedCommand( name ), m_cal( cal ), m_newvalue( value ) { m_oldvalue = cal->holidayRegionCode(); } CalendarModifyHolidayRegionCmd::~CalendarModifyHolidayRegionCmd() { } void CalendarModifyHolidayRegionCmd::execute() { m_cal->setHolidayRegion( m_newvalue ); } void CalendarModifyHolidayRegionCmd::unexecute() { m_cal->setHolidayRegion( m_oldvalue ); } #endif CalendarAddDayCmd::CalendarAddDayCmd( Calendar *cal, CalendarDay *newvalue, const KUndo2MagicString& name ) : NamedCommand( name ), m_cal( cal ), m_mine( true ) { m_newvalue = newvalue; //debugPlan<name(); } CalendarAddDayCmd::~CalendarAddDayCmd() { //debugPlan; if ( m_mine ) delete m_newvalue; } void CalendarAddDayCmd::execute() { //debugPlan<name(); m_cal->addDay( m_newvalue ); m_mine = false; } void CalendarAddDayCmd::unexecute() { //debugPlan<name(); m_cal->takeDay( m_newvalue ); m_mine = true; } CalendarRemoveDayCmd::CalendarRemoveDayCmd( Calendar *cal,CalendarDay *day, const KUndo2MagicString& name ) : NamedCommand( name ), m_cal( cal ), m_value( day ), m_mine( false ) { //debugPlan<name(); // TODO check if any resources uses this calendar init(); } CalendarRemoveDayCmd::CalendarRemoveDayCmd( Calendar *cal, const QDate &day, const KUndo2MagicString& name ) : NamedCommand( name ), m_cal( cal ), m_mine( false ) { m_value = cal->findDay( day ); //debugPlan<name(); // TODO check if any resources uses this calendar init(); } void CalendarRemoveDayCmd::init() { } void CalendarRemoveDayCmd::execute() { //debugPlan<name(); m_cal->takeDay( m_value ); m_mine = true; } void CalendarRemoveDayCmd::unexecute() { //debugPlan<name(); m_cal->addDay( m_value ); m_mine = false; } CalendarModifyDayCmd::CalendarModifyDayCmd( Calendar *cal, CalendarDay *value, const KUndo2MagicString& name ) : NamedCommand( name ), m_cal( cal ), m_mine( true ) { m_newvalue = value; m_oldvalue = cal->findDay( value->date() ); //debugPlan<name()<<" old:("<takeDay( m_oldvalue ); } m_cal->addDay( m_newvalue ); m_mine = false; } void CalendarModifyDayCmd::unexecute() { //debugPlan; m_cal->takeDay( m_newvalue ); if ( m_oldvalue ) { m_cal->addDay( m_oldvalue ); } m_mine = true; } CalendarModifyStateCmd::CalendarModifyStateCmd( Calendar *calendar, CalendarDay *day, CalendarDay::State value, const KUndo2MagicString& name ) : NamedCommand( name ), m_calendar( calendar ), m_day( day ), m_cmd( new MacroCommand( KUndo2MagicString() ) ) { m_newvalue = value; m_oldvalue = (CalendarDay::State)day->state(); if ( value != CalendarDay::Working ) { foreach ( TimeInterval *ti, day->timeIntervals() ) { m_cmd->addCommand( new CalendarRemoveTimeIntervalCmd( calendar, day, ti ) ); } } } CalendarModifyStateCmd::~CalendarModifyStateCmd() { delete m_cmd; } void CalendarModifyStateCmd::execute() { //debugPlan; m_cmd->execute(); m_calendar->setState( m_day, m_newvalue ); } void CalendarModifyStateCmd::unexecute() { //debugPlan; m_calendar->setState( m_day, m_oldvalue ); m_cmd->unexecute(); } CalendarModifyTimeIntervalCmd::CalendarModifyTimeIntervalCmd( Calendar *calendar, TimeInterval &newvalue, TimeInterval *value, const KUndo2MagicString& name ) : NamedCommand( name ), m_calendar( calendar ) { m_value = value; // keep pointer m_oldvalue = *value; // save value m_newvalue = newvalue; } void CalendarModifyTimeIntervalCmd::execute() { //debugPlan; m_calendar->setWorkInterval( m_value, m_newvalue ); } void CalendarModifyTimeIntervalCmd::unexecute() { //debugPlan; m_calendar->setWorkInterval( m_value, m_oldvalue ); } CalendarAddTimeIntervalCmd::CalendarAddTimeIntervalCmd( Calendar *calendar, CalendarDay *day, TimeInterval *value, const KUndo2MagicString& name ) : NamedCommand( name ), m_calendar( calendar ), m_day( day ), m_value( value ), m_mine( true ) { } CalendarAddTimeIntervalCmd::~CalendarAddTimeIntervalCmd() { if ( m_mine ) delete m_value; } void CalendarAddTimeIntervalCmd::execute() { //debugPlan; m_calendar->addWorkInterval( m_day, m_value ); m_mine = false; } void CalendarAddTimeIntervalCmd::unexecute() { //debugPlan; m_calendar->takeWorkInterval( m_day, m_value ); m_mine = true; } CalendarRemoveTimeIntervalCmd::CalendarRemoveTimeIntervalCmd( Calendar *calendar, CalendarDay *day, TimeInterval *value, const KUndo2MagicString& name ) : CalendarAddTimeIntervalCmd( calendar, day, value, name ) { m_mine = false ; } void CalendarRemoveTimeIntervalCmd::execute() { CalendarAddTimeIntervalCmd::unexecute(); } void CalendarRemoveTimeIntervalCmd::unexecute() { CalendarAddTimeIntervalCmd::execute(); } CalendarModifyWeekdayCmd::CalendarModifyWeekdayCmd( Calendar *cal, int weekday, CalendarDay *value, const KUndo2MagicString& name ) : NamedCommand( name ), m_weekday( weekday ), m_cal( cal ), m_value( value ), m_orig( *( cal->weekday( weekday ) ) ) { //debugPlan << cal->name() <<" (" << value <<")"; } CalendarModifyWeekdayCmd::~CalendarModifyWeekdayCmd() { //debugPlan << m_weekday <<":" << m_value; delete m_value; } void CalendarModifyWeekdayCmd::execute() { m_cal->setWeekday( m_weekday, *m_value ); } void CalendarModifyWeekdayCmd::unexecute() { m_cal->setWeekday( m_weekday, m_orig ); } CalendarModifyDateCmd::CalendarModifyDateCmd( Calendar *cal, CalendarDay *day, const QDate &value, const KUndo2MagicString& name ) : NamedCommand( name ), m_cal( cal ), m_day( day ), m_newvalue( value ), m_oldvalue( day->date() ) { //debugPlan << cal->name() <<" (" << value <<")"; } void CalendarModifyDateCmd::execute() { m_cal->setDate( m_day, m_newvalue ); } void CalendarModifyDateCmd::unexecute() { m_cal->setDate( m_day, m_oldvalue ); } ProjectModifyDefaultCalendarCmd::ProjectModifyDefaultCalendarCmd( Project *project, Calendar *cal, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ), m_newvalue( cal ), m_oldvalue( project->defaultCalendar() ) { //debugPlan << cal->name() <<" (" << value <<")"; } void ProjectModifyDefaultCalendarCmd::execute() { m_project->setDefaultCalendar( m_newvalue ); } void ProjectModifyDefaultCalendarCmd::unexecute() { m_project->setDefaultCalendar( m_oldvalue ); } NodeDeleteCmd::NodeDeleteCmd( Node *node, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), m_index( -1 ), m_relCmd(0) { m_parent = node->parentNode(); m_mine = false; m_project = static_cast( node->projectNode() ); if ( m_project ) { foreach ( Schedule * s, m_project->schedules() ) { if ( s && s->isScheduled() ) { // Only invalidate schedules this node is part of Schedule *ns = node->findSchedule( s->id() ); if ( ns && ! ns->isDeleted() ) { addSchScheduled( s ); } } } } m_cmd = new MacroCommand( KUndo2MagicString() ); QList lst = node->childNodeIterator(); for ( int i = lst.count(); i > 0; --i ) { m_cmd->addCommand( new NodeDeleteCmd( lst[ i - 1 ] ) ); } if ( node->runningAccount() ) { m_cmd->addCommand( new NodeModifyRunningAccountCmd( *node, node->runningAccount(), 0 ) ); } if ( node->startupAccount() ) { m_cmd->addCommand( new NodeModifyRunningAccountCmd( *node, node->startupAccount(), 0 ) ); } if ( node->shutdownAccount() ) { m_cmd->addCommand( new NodeModifyRunningAccountCmd( *node, node->shutdownAccount(), 0 ) ); } } NodeDeleteCmd::~NodeDeleteCmd() { delete m_relCmd; // before node if ( m_mine ) { delete m_node; } delete m_cmd; while ( !m_appointments.isEmpty() ) delete m_appointments.takeFirst(); } void NodeDeleteCmd::execute() { if ( m_parent && m_project ) { m_index = m_parent->findChildNode( m_node ); //debugPlan<name()<<""<dependChildNodes() ) { m_relCmd->addCommand( new DeleteRelationCmd( *m_project, r ) ); } foreach ( Relation * r, m_node->dependParentNodes() ) { m_relCmd->addCommand( new DeleteRelationCmd( *m_project, r ) ); } } m_relCmd->execute(); if ( m_cmd ) { m_cmd->execute(); } m_project->takeTask( m_node ); m_mine = true; setSchScheduled( false ); } } void NodeDeleteCmd::unexecute() { if ( m_parent && m_project ) { //debugPlan<name()<<""<addSubTask( m_node, m_index, m_parent ); if ( m_cmd ) { m_cmd->unexecute(); } m_relCmd->unexecute(); m_mine = false; setSchScheduled(); } } TaskAddCmd::TaskAddCmd( Project *project, Node *node, Node *after, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ), m_node( node ), m_after( after ), m_added( false ) { // set some reasonable defaults for normally calculated values if ( after && after->parentNode() && after->parentNode() != project ) { node->setStartTime( after->parentNode() ->startTime() ); node->setEndTime( node->startTime() + node->duration() ); } else { if ( project->constraint() == Node::MustFinishOn ) { node->setEndTime( project->endTime() ); node->setStartTime( node->endTime() - node->duration() ); } else { node->setStartTime( project->startTime() ); node->setEndTime( node->startTime() + node->duration() ); } } node->setEarlyStart( node->startTime() ); node->setLateFinish( node->endTime() ); node->setWorkStartTime( node->startTime() ); node->setWorkEndTime( node->endTime() ); } TaskAddCmd::~TaskAddCmd() { if ( !m_added ) delete m_node; } void TaskAddCmd::execute() { //debugPlan<name(); m_project->addTask( m_node, m_after ); m_added = true; } void TaskAddCmd::unexecute() { m_project->takeTask( m_node ); m_added = false; } SubtaskAddCmd::SubtaskAddCmd( Project *project, Node *node, Node *parent, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ), m_node( node ), m_parent( parent ), m_added( false ), m_cmd( 0 ) { // set some reasonable defaults for normally calculated values node->setStartTime( parent->startTime() ); node->setEndTime( node->startTime() + node->duration() ); node->setEarlyStart( node->startTime() ); node->setLateFinish( node->endTime() ); node->setWorkStartTime( node->startTime() ); node->setWorkEndTime( node->endTime() ); // Summarytasks can't have resources, so remove resource requests from the new parent foreach ( ResourceGroupRequest *r, parent->requests().requests() ) { if ( m_cmd == 0 ) m_cmd = new MacroCommand( KUndo2MagicString() ); m_cmd->addCommand( new RemoveResourceGroupRequestCmd( r ) ); } // Also remove accounts if ( parent->runningAccount() ) { if ( m_cmd == 0 ) m_cmd = new MacroCommand( KUndo2MagicString() ); m_cmd->addCommand( new NodeModifyRunningAccountCmd( *parent, parent->runningAccount(), 0 ) ); } if ( parent->startupAccount() ) { if ( m_cmd == 0 ) m_cmd = new MacroCommand( KUndo2MagicString() ); m_cmd->addCommand( new NodeModifyStartupAccountCmd( *parent, parent->startupAccount(), 0 ) ); } if ( parent->shutdownAccount() ) { if ( m_cmd == 0 ) m_cmd = new MacroCommand( KUndo2MagicString() ); m_cmd->addCommand( new NodeModifyShutdownAccountCmd( *parent, parent->shutdownAccount(), 0 ) ); } } SubtaskAddCmd::~SubtaskAddCmd() { delete m_cmd; if ( !m_added ) delete m_node; } void SubtaskAddCmd::execute() { m_project->addSubTask( m_node, m_parent ); if ( m_cmd ) { m_cmd->execute(); } m_added = true; } void SubtaskAddCmd::unexecute() { m_project->takeTask( m_node ); if ( m_cmd ) { m_cmd->unexecute(); } m_added = false; } NodeModifyNameCmd::NodeModifyNameCmd( Node &node, const QString& nodename, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), newName( nodename ), oldName( node.name() ) { } void NodeModifyNameCmd::execute() { m_node.setName( newName ); } void NodeModifyNameCmd::unexecute() { m_node.setName( oldName ); } NodeModifyPriorityCmd::NodeModifyPriorityCmd(Node &node, int oldValue, int newValue, const KUndo2MagicString& name ) : NamedCommand( name ) , m_node( node ) , m_oldValue(oldValue) , m_newValue(newValue) { } void NodeModifyPriorityCmd::execute() { m_node.setPriority(m_newValue); } void NodeModifyPriorityCmd::unexecute() { m_node.setPriority(m_oldValue); } NodeModifyLeaderCmd::NodeModifyLeaderCmd( Node &node, const QString& leader, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), newLeader( leader ), oldLeader( node.leader() ) { } void NodeModifyLeaderCmd::execute() { m_node.setLeader( newLeader ); } void NodeModifyLeaderCmd::unexecute() { m_node.setLeader( oldLeader ); } NodeModifyDescriptionCmd::NodeModifyDescriptionCmd( Node &node, const QString& description, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), newDescription( description ), oldDescription( node.description() ) { } void NodeModifyDescriptionCmd::execute() { m_node.setDescription( newDescription ); } void NodeModifyDescriptionCmd::unexecute() { m_node.setDescription( oldDescription ); } NodeModifyConstraintCmd::NodeModifyConstraintCmd( Node &node, Node::ConstraintType c, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), newConstraint( c ), oldConstraint( static_cast( node.constraint() ) ) { } void NodeModifyConstraintCmd::execute() { m_node.setConstraint( newConstraint ); } void NodeModifyConstraintCmd::unexecute() { m_node.setConstraint( oldConstraint ); } NodeModifyConstraintStartTimeCmd::NodeModifyConstraintStartTimeCmd( Node &node, const QDateTime& dt, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), newTime( dt ), oldTime( node.constraintStartTime() ) { if ( node.projectNode() ) { m_timeZone = static_cast( node.projectNode() )->timeZone(); } } void NodeModifyConstraintStartTimeCmd::execute() { m_node.setConstraintStartTime( DateTime( newTime, m_timeZone ) ); } void NodeModifyConstraintStartTimeCmd::unexecute() { m_node.setConstraintStartTime( oldTime ); } NodeModifyConstraintEndTimeCmd::NodeModifyConstraintEndTimeCmd( Node &node, const QDateTime& dt, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), newTime( dt ), oldTime( node.constraintEndTime() ) { if ( node.projectNode() ) { m_timeZone = static_cast( node.projectNode() )->timeZone(); } } void NodeModifyConstraintEndTimeCmd::execute() { m_node.setConstraintEndTime( DateTime( newTime, m_timeZone ) ); } void NodeModifyConstraintEndTimeCmd::unexecute() { m_node.setConstraintEndTime( oldTime ); } NodeModifyStartTimeCmd::NodeModifyStartTimeCmd( Node &node, const QDateTime& dt, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), newTime( dt ), oldTime( node.startTime() ) { m_timeZone = static_cast( node.projectNode() )->timeZone(); } void NodeModifyStartTimeCmd::execute() { m_node.setStartTime( DateTime( newTime, m_timeZone ) ); } void NodeModifyStartTimeCmd::unexecute() { m_node.setStartTime( oldTime ); } NodeModifyEndTimeCmd::NodeModifyEndTimeCmd( Node &node, const QDateTime& dt, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), newTime( dt ), oldTime( node.endTime() ) { m_timeZone = static_cast( node.projectNode() )->timeZone(); } void NodeModifyEndTimeCmd::execute() { m_node.setEndTime( DateTime( newTime, m_timeZone ) ); } void NodeModifyEndTimeCmd::unexecute() { m_node.setEndTime( oldTime ); } NodeModifyIdCmd::NodeModifyIdCmd( Node &node, const QString& id, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), newId( id ), oldId( node.id() ) { } void NodeModifyIdCmd::execute() { m_node.setId( newId ); } void NodeModifyIdCmd::unexecute() { m_node.setId( oldId ); } NodeIndentCmd::NodeIndentCmd( Node &node, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), m_newparent( 0 ), m_newindex( -1 ), m_cmd( 0 ) { } NodeIndentCmd::~NodeIndentCmd() { delete m_cmd; } void NodeIndentCmd::execute() { m_oldparent = m_node.parentNode(); m_oldindex = m_oldparent->findChildNode( &m_node ); Project *p = dynamic_cast( m_node.projectNode() ); if ( p && p->indentTask( &m_node, m_newindex ) ) { m_newparent = m_node.parentNode(); m_newindex = m_newparent->findChildNode( &m_node ); // Summarytasks can't have resources, so remove resource requests from the new parent if ( m_cmd == 0 ) { foreach ( ResourceGroupRequest *r, m_newparent->requests().requests() ) { if ( m_cmd == 0 ) m_cmd = new MacroCommand( KUndo2MagicString() ); m_cmd->addCommand( new RemoveResourceGroupRequestCmd( r ) ); } // Also remove accounts if ( m_newparent->runningAccount() ) { if ( m_cmd == 0 ) m_cmd = new MacroCommand( KUndo2MagicString() ); m_cmd->addCommand( new NodeModifyRunningAccountCmd( *m_newparent, m_newparent->runningAccount(), 0 ) ); } if ( m_newparent->startupAccount() ) { if ( m_cmd == 0 ) m_cmd = new MacroCommand( KUndo2MagicString() ); m_cmd->addCommand( new NodeModifyStartupAccountCmd( *m_newparent, m_newparent->startupAccount(), 0 ) ); } if ( m_newparent->shutdownAccount() ) { if ( m_cmd == 0 ) m_cmd = new MacroCommand( KUndo2MagicString() ); m_cmd->addCommand( new NodeModifyShutdownAccountCmd( *m_newparent, m_newparent->shutdownAccount(), 0 ) ); } } if ( m_cmd ) { m_cmd->execute(); } } } void NodeIndentCmd::unexecute() { Project * p = dynamic_cast( m_node.projectNode() ); if ( m_newindex != -1 && p && p->unindentTask( &m_node ) ) { m_newindex = -1; if ( m_cmd ) { m_cmd->unexecute(); } } } NodeUnindentCmd::NodeUnindentCmd( Node &node, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), m_newparent( 0 ), m_newindex( -1 ) {} void NodeUnindentCmd::execute() { m_oldparent = m_node.parentNode(); m_oldindex = m_oldparent->findChildNode( &m_node ); Project *p = dynamic_cast( m_node.projectNode() ); if ( p && p->unindentTask( &m_node ) ) { m_newparent = m_node.parentNode(); m_newindex = m_newparent->findChildNode( &m_node ); } } void NodeUnindentCmd::unexecute() { Project * p = dynamic_cast( m_node.projectNode() ); if ( m_newindex != -1 && p && p->indentTask( &m_node, m_oldindex ) ) { m_newindex = -1; } } NodeMoveUpCmd::NodeMoveUpCmd( Node &node, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), m_moved( false ) { m_project = static_cast( m_node.projectNode() ); } void NodeMoveUpCmd::execute() { if ( m_project ) { m_moved = m_project->moveTaskUp( &m_node ); } } void NodeMoveUpCmd::unexecute() { if ( m_project && m_moved ) { m_project->moveTaskDown( &m_node ); } m_moved = false; } NodeMoveDownCmd::NodeMoveDownCmd( Node &node, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), m_moved( false ) { m_project = static_cast( m_node.projectNode() ); } void NodeMoveDownCmd::execute() { if ( m_project ) { m_moved = m_project->moveTaskDown( &m_node ); } } void NodeMoveDownCmd::unexecute() { if ( m_project && m_moved ) { m_project->moveTaskUp( &m_node ); } m_moved = false; } NodeMoveCmd::NodeMoveCmd( Project *project, Node *node, Node *newParent, int newPos, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ), m_node( node ), m_newparent( newParent ), m_newpos( newPos ), m_moved( false ) { m_oldparent = node->parentNode(); Q_ASSERT( m_oldparent ); } void NodeMoveCmd::execute() { if ( m_project ) { m_oldpos = m_oldparent->indexOf( m_node ); m_moved = m_project->moveTask( m_node, m_newparent, m_newpos ); if ( m_moved ) { if ( m_cmd.isEmpty() ) { // Summarytasks can't have resources, so remove resource requests from the new parent foreach ( ResourceGroupRequest *r, m_newparent->requests().requests() ) { m_cmd.addCommand( new RemoveResourceGroupRequestCmd( r ) ); } // TODO appointments ?? } m_cmd.execute(); } } } void NodeMoveCmd::unexecute() { if ( m_project && m_moved ) { m_moved = m_project->moveTask( m_node, m_oldparent, m_oldpos ); m_cmd.unexecute(); } m_moved = false; } AddRelationCmd::AddRelationCmd( Project &project, Relation *rel, const KUndo2MagicString& name ) : NamedCommand( name ), m_rel( rel ), m_project( project ) { m_taken = true; } AddRelationCmd::~AddRelationCmd() { if ( m_taken ) delete m_rel; } void AddRelationCmd::execute() { //debugPlan<parent()<<" to"<child(); m_taken = false; m_project.addRelation( m_rel, false ); } void AddRelationCmd::unexecute() { m_taken = true; m_project.takeRelation( m_rel ); } DeleteRelationCmd::DeleteRelationCmd( Project &project, Relation *rel, const KUndo2MagicString& name ) : NamedCommand( name ), m_rel( rel ), m_project( project ) { m_taken = false; } DeleteRelationCmd::~DeleteRelationCmd() { if ( m_taken ) { // do not access nodes, the may already be deleted m_rel->setParent(0); m_rel->setChild(0); delete m_rel; } } void DeleteRelationCmd::execute() { //debugPlan<parent()<<" to"<child(); m_taken = true; m_project.takeRelation( m_rel ); } void DeleteRelationCmd::unexecute() { m_taken = false; m_project.addRelation( m_rel, false ); } ModifyRelationTypeCmd::ModifyRelationTypeCmd( Relation *rel, Relation::Type type, const KUndo2MagicString& name ) : NamedCommand( name ), m_rel( rel ), m_newtype( type ) { m_oldtype = rel->type(); m_project = dynamic_cast( rel->parent() ->projectNode() ); } void ModifyRelationTypeCmd::execute() { if ( m_project ) { m_project->setRelationType( m_rel, m_newtype ); } } void ModifyRelationTypeCmd::unexecute() { if ( m_project ) { m_project->setRelationType( m_rel, m_oldtype ); } } ModifyRelationLagCmd::ModifyRelationLagCmd( Relation *rel, Duration lag, const KUndo2MagicString& name ) : NamedCommand( name ), m_rel( rel ), m_newlag( lag ) { m_oldlag = rel->lag(); m_project = dynamic_cast( rel->parent() ->projectNode() ); } void ModifyRelationLagCmd::execute() { if ( m_project ) { m_project->setRelationLag( m_rel, m_newlag ); } } void ModifyRelationLagCmd::unexecute() { if ( m_project ) { m_project->setRelationLag( m_rel, m_oldlag ); } } AddResourceRequestCmd::AddResourceRequestCmd( ResourceGroupRequest *group, ResourceRequest *request, const KUndo2MagicString& name ) : NamedCommand( name ), m_group( group ), m_request( request ) { m_mine = true; } AddResourceRequestCmd::~AddResourceRequestCmd() { if ( m_mine ) delete m_request; } void AddResourceRequestCmd::execute() { //debugPlan<<"group="<project() ); if ( m_group->project() ) { m_group->project()->addResource( m_group, m_resource, m_index ); m_mine = false; //debugPlan<<"added:"<project() ); if ( m_group->project() ) { m_group->project()->takeResource( m_group, m_resource ); //debugPlan<<"removed:"<project() ); } RemoveResourceCmd::RemoveResourceCmd( ResourceGroup *group, Resource *resource, const KUndo2MagicString& name ) : AddResourceCmd( group, resource, name ) { //debugPlan<requests(); if ( group->project() ) { foreach ( Schedule * s, group->project()->schedules() ) { Schedule *rs = resource->findSchedule( s->id() ); if ( rs && ! rs->isDeleted() ) { debugPlan<name(); addSchScheduled( s ); } } } if ( resource->account() ) { m_cmd.addCommand( new ResourceModifyAccountCmd( *resource, resource->account(), 0 ) ); } } RemoveResourceCmd::~RemoveResourceCmd() { while ( !m_appointments.isEmpty() ) delete m_appointments.takeFirst(); } void RemoveResourceCmd::execute() { foreach ( ResourceRequest * r, m_requests ) { r->parent() ->takeResourceRequest( r ); //debugPlan<<"Remove request for"<resource()->name(); } AddResourceCmd::unexecute(); m_cmd.execute(); setSchScheduled( false ); } void RemoveResourceCmd::unexecute() { foreach ( ResourceRequest * r, m_requests ) { r->parent() ->addResourceRequest( r ); //debugPlan<<"Add request for"<resource()->name(); } m_cmd.unexecute(); AddResourceCmd::execute(); setSchScheduled(); } MoveResourceCmd::MoveResourceCmd( ResourceGroup *group, Resource *resource, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( *(group->project()) ), m_resource( resource ), m_oldvalue( resource->parentGroup() ), m_newvalue( group ) { foreach ( ResourceRequest * r, resource->requests() ) { cmd.addCommand( new RemoveResourceRequestCmd( r->parent(), r ) ); } } void MoveResourceCmd::execute() { cmd.execute(); m_project.moveResource( m_newvalue, m_resource ); } void MoveResourceCmd::unexecute() { m_project.moveResource( m_oldvalue, m_resource ); cmd.unexecute(); } ModifyResourceNameCmd::ModifyResourceNameCmd( Resource *resource, const QString& value, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_newvalue( value ) { m_oldvalue = resource->name(); } void ModifyResourceNameCmd::execute() { m_resource->setName( m_newvalue ); } void ModifyResourceNameCmd::unexecute() { m_resource->setName( m_oldvalue ); } ModifyResourceInitialsCmd::ModifyResourceInitialsCmd( Resource *resource, const QString& value, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_newvalue( value ) { m_oldvalue = resource->initials(); } void ModifyResourceInitialsCmd::execute() { m_resource->setInitials( m_newvalue ); } void ModifyResourceInitialsCmd::unexecute() { m_resource->setInitials( m_oldvalue ); } ModifyResourceEmailCmd::ModifyResourceEmailCmd( Resource *resource, const QString& value, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_newvalue( value ) { m_oldvalue = resource->email(); } void ModifyResourceEmailCmd::execute() { m_resource->setEmail( m_newvalue ); } void ModifyResourceEmailCmd::unexecute() { m_resource->setEmail( m_oldvalue ); } ModifyResourceAutoAllocateCmd::ModifyResourceAutoAllocateCmd( Resource *resource,bool value, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_newvalue( value ) { m_oldvalue = resource->autoAllocate(); } void ModifyResourceAutoAllocateCmd::execute() { m_resource->setAutoAllocate( m_newvalue ); } void ModifyResourceAutoAllocateCmd::unexecute() { m_resource->setAutoAllocate( m_oldvalue ); } ModifyResourceTypeCmd::ModifyResourceTypeCmd( Resource *resource, int value, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_newvalue( value ) { m_oldvalue = resource->type(); } void ModifyResourceTypeCmd::execute() { m_resource->setType( ( Resource::Type ) m_newvalue ); } void ModifyResourceTypeCmd::unexecute() { m_resource->setType( ( Resource::Type ) m_oldvalue ); } ModifyResourceUnitsCmd::ModifyResourceUnitsCmd( Resource *resource, int value, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_newvalue( value ) { m_oldvalue = resource->units(); } void ModifyResourceUnitsCmd::execute() { m_resource->setUnits( m_newvalue ); } void ModifyResourceUnitsCmd::unexecute() { m_resource->setUnits( m_oldvalue ); } ModifyResourceAvailableFromCmd::ModifyResourceAvailableFromCmd( Resource *resource, const QDateTime& value, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_newvalue( value ) { m_oldvalue = resource->availableFrom(); m_timeZone = resource->timeZone(); } void ModifyResourceAvailableFromCmd::execute() { m_resource->setAvailableFrom( DateTime( m_newvalue, m_timeZone ) ); } void ModifyResourceAvailableFromCmd::unexecute() { m_resource->setAvailableFrom( m_oldvalue ); } ModifyResourceAvailableUntilCmd::ModifyResourceAvailableUntilCmd( Resource *resource, const QDateTime& value, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_newvalue( value ) { m_oldvalue = resource->availableUntil(); m_timeZone = resource->timeZone(); } void ModifyResourceAvailableUntilCmd::execute() { m_resource->setAvailableUntil( DateTime( m_newvalue, m_timeZone ) ); } void ModifyResourceAvailableUntilCmd::unexecute() { m_resource->setAvailableUntil( m_oldvalue ); } ModifyResourceNormalRateCmd::ModifyResourceNormalRateCmd( Resource *resource, double value, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_newvalue( value ) { m_oldvalue = resource->normalRate(); } void ModifyResourceNormalRateCmd::execute() { m_resource->setNormalRate( m_newvalue ); } void ModifyResourceNormalRateCmd::unexecute() { m_resource->setNormalRate( m_oldvalue ); } ModifyResourceOvertimeRateCmd::ModifyResourceOvertimeRateCmd( Resource *resource, double value, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_newvalue( value ) { m_oldvalue = resource->overtimeRate(); } void ModifyResourceOvertimeRateCmd::execute() { m_resource->setOvertimeRate( m_newvalue ); } void ModifyResourceOvertimeRateCmd::unexecute() { m_resource->setOvertimeRate( m_oldvalue ); } ModifyResourceCalendarCmd::ModifyResourceCalendarCmd( Resource *resource, Calendar *value, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_newvalue( value ) { m_oldvalue = resource->calendar( true ); } void ModifyResourceCalendarCmd::execute() { m_resource->setCalendar( m_newvalue ); } void ModifyResourceCalendarCmd::unexecute() { m_resource->setCalendar( m_oldvalue ); } ModifyRequiredResourcesCmd::ModifyRequiredResourcesCmd( Resource *resource, const QStringList &value, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_newvalue( value ) { m_oldvalue = resource->requiredIds(); } void ModifyRequiredResourcesCmd::execute() { m_resource->setRequiredIds( m_newvalue ); } void ModifyRequiredResourcesCmd::unexecute() { m_resource->setRequiredIds( m_oldvalue ); } AddResourceTeamCmd::AddResourceTeamCmd( Resource *team, const QString &member, const KUndo2MagicString& name ) : NamedCommand( name ), m_team( team ), m_member( member ) { } void AddResourceTeamCmd::execute() { m_team->addTeamMemberId( m_member ); } void AddResourceTeamCmd::unexecute() { m_team->removeTeamMemberId( m_member ); } RemoveResourceTeamCmd::RemoveResourceTeamCmd( Resource *team, const QString &member, const KUndo2MagicString& name ) : NamedCommand( name ), m_team( team ), m_member( member ) { } void RemoveResourceTeamCmd::execute() { m_team->removeTeamMemberId( m_member ); } void RemoveResourceTeamCmd::unexecute() { m_team->addTeamMemberId( m_member ); } RemoveResourceGroupCmd::RemoveResourceGroupCmd( Project *project, ResourceGroup *group, const KUndo2MagicString& name ) : NamedCommand( name ), m_group( group ), m_project( project ), m_cmd( 0 ) { m_index = project->indexOf( group ); m_mine = false; if ( !m_group->requests().isEmpty() ) { m_cmd = new MacroCommand(KUndo2MagicString()); foreach( ResourceGroupRequest * r, m_group->requests() ) { m_cmd->addCommand( new RemoveResourceGroupRequestCmd( r ) ); } } } RemoveResourceGroupCmd::~RemoveResourceGroupCmd() { delete m_cmd; if ( m_mine ) delete m_group; } void RemoveResourceGroupCmd::execute() { // remove all requests to this group if ( m_cmd ) { m_cmd->execute(); } if ( m_project ) m_project->takeResourceGroup( m_group ); m_mine = true; } void RemoveResourceGroupCmd::unexecute() { if ( m_project ) m_project->addResourceGroup( m_group, m_index ); m_mine = false; // add all requests if ( m_cmd ) { m_cmd->unexecute(); } } AddResourceGroupCmd::AddResourceGroupCmd( Project *project, ResourceGroup *group, const KUndo2MagicString& name ) : RemoveResourceGroupCmd( project, group, name ) { m_mine = true; } void AddResourceGroupCmd::execute() { RemoveResourceGroupCmd::unexecute(); } void AddResourceGroupCmd::unexecute() { RemoveResourceGroupCmd::execute(); } ModifyResourceGroupNameCmd::ModifyResourceGroupNameCmd( ResourceGroup *group, const QString& value, const KUndo2MagicString& name ) : NamedCommand( name ), m_group( group ), m_newvalue( value ) { m_oldvalue = group->name(); } void ModifyResourceGroupNameCmd::execute() { m_group->setName( m_newvalue ); } void ModifyResourceGroupNameCmd::unexecute() { m_group->setName( m_oldvalue ); } ModifyResourceGroupTypeCmd::ModifyResourceGroupTypeCmd( ResourceGroup *group, int value, const KUndo2MagicString& name ) : NamedCommand( name ), m_group( group ), m_newvalue( value ) { m_oldvalue = group->type(); } void ModifyResourceGroupTypeCmd::execute() { m_group->setType( static_cast( m_newvalue) ); } void ModifyResourceGroupTypeCmd::unexecute() { m_group->setType( static_cast( m_oldvalue ) ); } ModifyCompletionEntrymodeCmd::ModifyCompletionEntrymodeCmd( Completion &completion, Completion::Entrymode value, const KUndo2MagicString& name ) : NamedCommand( name ), m_completion( completion ), oldvalue( m_completion.entrymode() ), newvalue( value ) { } void ModifyCompletionEntrymodeCmd::execute() { m_completion.setEntrymode( newvalue ); } void ModifyCompletionEntrymodeCmd::unexecute() { m_completion.setEntrymode( oldvalue ); } ModifyCompletionPercentFinishedCmd::ModifyCompletionPercentFinishedCmd( Completion &completion, const QDate &date, int value, const KUndo2MagicString& name ) : NamedCommand( name ), m_completion( completion ), m_date( date ), m_newvalue( value ), m_oldvalue( completion.percentFinished( date ) ) { if ( ! completion.entries().contains( date ) ) { Completion::Entry *e = new Completion::Entry(); Completion::Entry *latest = completion.entry( completion.entryDate() ); if ( latest ) { *e = *latest; } cmd.addCommand( new AddCompletionEntryCmd( completion, date, e ) ); } } void ModifyCompletionPercentFinishedCmd::execute() { cmd.execute(); m_completion.setPercentFinished( m_date, m_newvalue ); } void ModifyCompletionPercentFinishedCmd::unexecute() { m_completion.setPercentFinished( m_date, m_oldvalue ); cmd.unexecute(); } ModifyCompletionRemainingEffortCmd::ModifyCompletionRemainingEffortCmd( Completion &completion, const QDate &date, const Duration &value, const KUndo2MagicString &name ) : NamedCommand( name ), m_completion( completion ), m_date( date ), m_newvalue( value ), m_oldvalue( completion.remainingEffort( date ) ) { if ( ! completion.entries().contains( date ) ) { Completion::Entry *e = new Completion::Entry(); Completion::Entry *latest = completion.entry( completion.entryDate() ); if ( latest ) { *e = *latest; } cmd.addCommand( new AddCompletionEntryCmd( completion, date, e ) ); } } void ModifyCompletionRemainingEffortCmd::execute() { cmd.execute(); m_completion.setRemainingEffort( m_date, m_newvalue ); } void ModifyCompletionRemainingEffortCmd::unexecute() { m_completion.setRemainingEffort( m_date, m_oldvalue ); cmd.unexecute(); } ModifyCompletionActualEffortCmd::ModifyCompletionActualEffortCmd( Completion &completion, const QDate &date, const Duration &value, const KUndo2MagicString &name ) : NamedCommand( name ), m_completion( completion ), m_date( date ), m_newvalue( value ), m_oldvalue( completion.actualEffort( date ) ) { if ( ! completion.entries().contains( date ) ) { Completion::Entry *e = new Completion::Entry(); Completion::Entry *latest = completion.entry( completion.entryDate() ); if ( latest ) { *e = *latest; } cmd.addCommand( new AddCompletionEntryCmd( completion, date, e ) ); } } void ModifyCompletionActualEffortCmd::execute() { cmd.execute(); m_completion.setActualEffort( m_date, m_newvalue ); } void ModifyCompletionActualEffortCmd::unexecute() { m_completion.setActualEffort( m_date, m_oldvalue ); cmd.unexecute(); } ModifyCompletionStartedCmd::ModifyCompletionStartedCmd( Completion &completion, bool value, const KUndo2MagicString& name ) : NamedCommand( name ), m_completion( completion ), oldvalue( m_completion.isStarted() ), newvalue( value ) { } void ModifyCompletionStartedCmd::execute() { m_completion.setStarted( newvalue ); } void ModifyCompletionStartedCmd::unexecute() { m_completion.setStarted( oldvalue ); } ModifyCompletionFinishedCmd::ModifyCompletionFinishedCmd( Completion &completion, bool value, const KUndo2MagicString& name ) : NamedCommand( name ), m_completion( completion ), oldvalue( m_completion.isFinished() ), newvalue( value ) { } void ModifyCompletionFinishedCmd::execute() { m_completion.setFinished( newvalue ); } void ModifyCompletionFinishedCmd::unexecute() { m_completion.setFinished( oldvalue ); } ModifyCompletionStartTimeCmd::ModifyCompletionStartTimeCmd( Completion &completion, const QDateTime &value, const KUndo2MagicString& name ) : NamedCommand( name ), m_completion( completion ), oldvalue( m_completion.startTime() ), newvalue( value ) { m_timeZone = static_cast( completion.node()->projectNode() )->timeZone(); } void ModifyCompletionStartTimeCmd::execute() { m_completion.setStartTime( DateTime( newvalue, m_timeZone ) ); } void ModifyCompletionStartTimeCmd::unexecute() { m_completion.setStartTime( oldvalue ); } ModifyCompletionFinishTimeCmd::ModifyCompletionFinishTimeCmd( Completion &completion, const QDateTime &value, const KUndo2MagicString& name ) : NamedCommand( name ), m_completion( completion ), oldvalue( m_completion.finishTime() ), newvalue( value ) { m_timeZone = static_cast( completion.node()->projectNode() )->timeZone(); } void ModifyCompletionFinishTimeCmd::execute() { m_completion.setFinishTime( DateTime( newvalue, m_timeZone ) ); } void ModifyCompletionFinishTimeCmd::unexecute() { m_completion.setFinishTime( oldvalue ); } AddCompletionEntryCmd::AddCompletionEntryCmd( Completion &completion, const QDate &date, Completion::Entry *value, const KUndo2MagicString& name ) : NamedCommand( name ), m_completion( completion ), m_date( date ), newvalue( value ), m_newmine( true ) { } AddCompletionEntryCmd::~AddCompletionEntryCmd() { if ( m_newmine ) delete newvalue; } void AddCompletionEntryCmd::execute() { Q_ASSERT( ! m_completion.entries().contains( m_date ) ); m_completion.addEntry( m_date, newvalue ); m_newmine = false; } void AddCompletionEntryCmd::unexecute() { m_completion.takeEntry( m_date ); m_newmine = true; } RemoveCompletionEntryCmd::RemoveCompletionEntryCmd( Completion &completion, const QDate &date, const KUndo2MagicString& name ) : NamedCommand( name ), m_completion( completion ), m_date( date ), m_mine( false ) { value = m_completion.entry( date ); } RemoveCompletionEntryCmd::~RemoveCompletionEntryCmd() { debugPlan<addCommand( new RemoveCompletionEntryCmd( completion, date ) ); cmd->addCommand( new AddCompletionEntryCmd( completion, date, value ) ); } ModifyCompletionEntryCmd::~ModifyCompletionEntryCmd() { delete cmd; } void ModifyCompletionEntryCmd::execute() { cmd->execute(); } void ModifyCompletionEntryCmd::unexecute() { cmd->unexecute(); } AddCompletionUsedEffortCmd::AddCompletionUsedEffortCmd( Completion &completion, const Resource *resource, Completion::UsedEffort *value, const KUndo2MagicString& name ) : NamedCommand( name ), m_completion( completion ), m_resource( resource ), newvalue( value ), m_newmine( true ), m_oldmine( false) { oldvalue = m_completion.usedEffort( resource ); } AddCompletionUsedEffortCmd::~AddCompletionUsedEffortCmd() { if ( m_oldmine ) delete oldvalue; if ( m_newmine ) delete newvalue; } void AddCompletionUsedEffortCmd::execute() { if ( oldvalue ) { m_completion.takeUsedEffort( m_resource ); m_oldmine = true; } m_completion.addUsedEffort( m_resource, newvalue ); m_newmine = false; } void AddCompletionUsedEffortCmd::unexecute() { m_completion.takeUsedEffort( m_resource ); if ( oldvalue ) { m_completion.addUsedEffort( m_resource, oldvalue ); } m_newmine = true; m_oldmine = false; } AddCompletionActualEffortCmd::AddCompletionActualEffortCmd( Completion::UsedEffort &ue, const QDate &date, const Completion::UsedEffort::ActualEffort &value, const KUndo2MagicString& name ) : NamedCommand( name ), m_usedEffort( ue ), m_date( date ), newvalue( value ) { oldvalue = ue.effort( date ); } AddCompletionActualEffortCmd::~AddCompletionActualEffortCmd() { } void AddCompletionActualEffortCmd::execute() { m_usedEffort.takeEffort( m_date ); if ( newvalue.effort() > 0 ) { m_usedEffort.setEffort( m_date, newvalue ); } } void AddCompletionActualEffortCmd::unexecute() { m_usedEffort.takeEffort( m_date ); if ( oldvalue.effort() > 0 ) { m_usedEffort.setEffort( m_date, oldvalue ); } } AddAccountCmd::AddAccountCmd( Project &project, Account *account, const QString& parent, int index, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ), m_account( account ), m_parent( 0 ), m_index( index ), m_parentName( parent ) { m_mine = true; } AddAccountCmd::AddAccountCmd( Project &project, Account *account, Account *parent, int index, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ), m_account( account ), m_parent( parent ), m_index( index ) { m_mine = true; } AddAccountCmd::~AddAccountCmd() { if ( m_mine ) delete m_account; } void AddAccountCmd::execute() { if ( m_parent == 0 && !m_parentName.isEmpty() ) { m_parent = m_project.accounts().findAccount( m_parentName ); } m_project.accounts().insert( m_account, m_parent, m_index ); m_mine = false; } void AddAccountCmd::unexecute() { m_project.accounts().take( m_account ); m_mine = true; } RemoveAccountCmd::RemoveAccountCmd( Project &project, Account *account, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ), m_account( account ), m_parent( account->parent() ) { if ( m_parent ) { m_index = m_parent->accountList().indexOf( account ); } else { m_index = project.accounts().accountList().indexOf( account ); } m_mine = false; m_isDefault = account == project.accounts().defaultAccount(); for (Account::CostPlace *cp : m_account->costPlaces()) { if (cp->node()) { if (cp->running()) { m_cmd.addCommand(new NodeModifyRunningAccountCmd(*cp->node(), cp->node()->runningAccount(), 0)); } if (cp->startup()) { m_cmd.addCommand(new NodeModifyStartupAccountCmd(*cp->node(), cp->node()->startupAccount(), 0)); } if (cp->shutdown()) { m_cmd.addCommand(new NodeModifyShutdownAccountCmd(*cp->node(), cp->node()->shutdownAccount(), 0)); } } else if (cp->resource()) { m_cmd.addCommand(new ResourceModifyAccountCmd(*cp->resource(), cp->resource()->account(), 0)); } } for (int i = account->accountList().count()-1; i >= 0; --i) { m_cmd.addCommand(new RemoveAccountCmd(project, account->accountList().at(i))); } } RemoveAccountCmd::~RemoveAccountCmd() { if ( m_mine ) delete m_account; } void RemoveAccountCmd::execute() { if ( m_isDefault ) { m_project.accounts().setDefaultAccount( 0 ); } m_cmd.execute(); // remove costplaces and children m_project.accounts().take( m_account ); m_mine = true; } void RemoveAccountCmd::unexecute() { m_project.accounts().insert( m_account, m_parent, m_index ); m_cmd.unexecute(); // add costplaces && children if ( m_isDefault ) { m_project.accounts().setDefaultAccount( m_account ); } m_mine = false; } RenameAccountCmd::RenameAccountCmd( Account *account, const QString& value, const KUndo2MagicString& name ) : NamedCommand( name ), m_account( account ) { m_oldvalue = account->name(); m_newvalue = value; } void RenameAccountCmd::execute() { m_account->setName( m_newvalue ); } void RenameAccountCmd::unexecute() { m_account->setName( m_oldvalue ); } ModifyAccountDescriptionCmd::ModifyAccountDescriptionCmd( Account *account, const QString& value, const KUndo2MagicString& name ) : NamedCommand( name ), m_account( account ) { m_oldvalue = account->description(); m_newvalue = value; } void ModifyAccountDescriptionCmd::execute() { m_account->setDescription( m_newvalue ); } void ModifyAccountDescriptionCmd::unexecute() { m_account->setDescription( m_oldvalue ); } NodeModifyStartupCostCmd::NodeModifyStartupCostCmd( Node &node, double value, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ) { m_oldvalue = node.startupCost(); m_newvalue = value; } void NodeModifyStartupCostCmd::execute() { m_node.setStartupCost( m_newvalue ); } void NodeModifyStartupCostCmd::unexecute() { m_node.setStartupCost( m_oldvalue ); } NodeModifyShutdownCostCmd::NodeModifyShutdownCostCmd( Node &node, double value, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ) { m_oldvalue = node.shutdownCost(); m_newvalue = value; } void NodeModifyShutdownCostCmd::execute() { m_node.setShutdownCost( m_newvalue ); } void NodeModifyShutdownCostCmd::unexecute() { m_node.setShutdownCost( m_oldvalue ); } NodeModifyRunningAccountCmd::NodeModifyRunningAccountCmd( Node &node, Account *oldvalue, Account *newvalue, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ) { m_oldvalue = oldvalue; m_newvalue = newvalue; //debugPlan; } void NodeModifyRunningAccountCmd::execute() { //debugPlan; if ( m_oldvalue ) { m_oldvalue->removeRunning( m_node ); } if ( m_newvalue ) { m_newvalue->addRunning( m_node ); } } void NodeModifyRunningAccountCmd::unexecute() { //debugPlan; if ( m_newvalue ) { m_newvalue->removeRunning( m_node ); } if ( m_oldvalue ) { m_oldvalue->addRunning( m_node ); } } NodeModifyStartupAccountCmd::NodeModifyStartupAccountCmd( Node &node, Account *oldvalue, Account *newvalue, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ) { m_oldvalue = oldvalue; m_newvalue = newvalue; //debugPlan; } void NodeModifyStartupAccountCmd::execute() { //debugPlan; if ( m_oldvalue ) { m_oldvalue->removeStartup( m_node ); } if ( m_newvalue ) { m_newvalue->addStartup( m_node ); } } void NodeModifyStartupAccountCmd::unexecute() { //debugPlan; if ( m_newvalue ) { m_newvalue->removeStartup( m_node ); } if ( m_oldvalue ) { m_oldvalue->addStartup( m_node ); } } NodeModifyShutdownAccountCmd::NodeModifyShutdownAccountCmd( Node &node, Account *oldvalue, Account *newvalue, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ) { m_oldvalue = oldvalue; m_newvalue = newvalue; //debugPlan; } void NodeModifyShutdownAccountCmd::execute() { //debugPlan; if ( m_oldvalue ) { m_oldvalue->removeShutdown( m_node ); } if ( m_newvalue ) { m_newvalue->addShutdown( m_node ); } } void NodeModifyShutdownAccountCmd::unexecute() { //debugPlan; if ( m_newvalue ) { m_newvalue->removeShutdown( m_node ); } if ( m_oldvalue ) { m_oldvalue->addShutdown( m_node ); } } ModifyDefaultAccountCmd::ModifyDefaultAccountCmd( Accounts &acc, Account *oldvalue, Account *newvalue, const KUndo2MagicString& name ) : NamedCommand( name ), m_accounts( acc ) { m_oldvalue = oldvalue; m_newvalue = newvalue; //debugPlan; } void ModifyDefaultAccountCmd::execute() { //debugPlan; m_accounts.setDefaultAccount( m_newvalue ); } void ModifyDefaultAccountCmd::unexecute() { //debugPlan; m_accounts.setDefaultAccount( m_oldvalue ); } ResourceModifyAccountCmd::ResourceModifyAccountCmd( Resource &resource, Account *oldvalue, Account *newvalue, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ) { m_oldvalue = oldvalue; m_newvalue = newvalue; } void ResourceModifyAccountCmd::execute() { //debugPlan; if ( m_oldvalue ) { m_oldvalue->removeRunning( m_resource ); } if ( m_newvalue ) { m_newvalue->addRunning( m_resource ); } } void ResourceModifyAccountCmd::unexecute() { //debugPlan; if ( m_newvalue ) { m_newvalue->removeRunning( m_resource ); } if ( m_oldvalue ) { m_oldvalue->addRunning( m_resource ); } } ProjectModifyConstraintCmd::ProjectModifyConstraintCmd( Project &node, Node::ConstraintType c, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), newConstraint( c ), oldConstraint( static_cast( node.constraint() ) ) { } void ProjectModifyConstraintCmd::execute() { m_node.setConstraint( newConstraint ); } void ProjectModifyConstraintCmd::unexecute() { m_node.setConstraint( oldConstraint ); } ProjectModifyStartTimeCmd::ProjectModifyStartTimeCmd( Project &node, const QDateTime& dt, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), newTime( dt ), oldTime( node.startTime() ) { m_timeZone = node.timeZone(); } void ProjectModifyStartTimeCmd::execute() { m_node.setConstraintStartTime( DateTime( newTime, m_timeZone ) ); } void ProjectModifyStartTimeCmd::unexecute() { m_node.setConstraintStartTime( oldTime ); } ProjectModifyEndTimeCmd::ProjectModifyEndTimeCmd( Project &node, const QDateTime& dt, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), newTime( dt ), oldTime( node.endTime() ) { m_timeZone = node.timeZone(); } void ProjectModifyEndTimeCmd::execute() { m_node.setEndTime( DateTime( newTime, m_timeZone ) ); m_node.setConstraintEndTime( DateTime( newTime, m_timeZone ) ); } void ProjectModifyEndTimeCmd::unexecute() { m_node.setConstraintEndTime( oldTime ); } //---------------------------- +SwapScheduleManagerCmd::SwapScheduleManagerCmd(Project &project, ScheduleManager *from, ScheduleManager *to, const KUndo2MagicString& name ) + : NamedCommand( name ), + m_node( project ), + m_from( from ), + m_to( to ) +{ +} + +SwapScheduleManagerCmd::~SwapScheduleManagerCmd() +{ +} + +void SwapScheduleManagerCmd::execute() +{ + m_node.swapScheduleManagers(m_from, m_to); +} + +void SwapScheduleManagerCmd::unexecute() +{ + m_node.swapScheduleManagers(m_to, m_from); +} + AddScheduleManagerCmd::AddScheduleManagerCmd( Project &node, ScheduleManager *sm, int index, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), m_parent( sm->parentManager() ), m_sm( sm ), m_index( index ), m_exp( sm->expected() ), m_mine( true) { } AddScheduleManagerCmd::AddScheduleManagerCmd( ScheduleManager *parent, ScheduleManager *sm, int index, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( parent->project() ), m_parent( parent ), m_sm( sm ), m_index( index ), m_exp( sm->expected() ), m_mine( true) { } AddScheduleManagerCmd::~AddScheduleManagerCmd() { if ( m_mine ) { m_sm->setParentManager( 0 ); delete m_sm; } } void AddScheduleManagerCmd::execute() { m_node.addScheduleManager( m_sm, m_parent, m_index ); m_sm->setExpected( m_exp ); m_mine = false; } void AddScheduleManagerCmd::unexecute() { m_node.takeScheduleManager( m_sm ); m_sm->setExpected( 0 ); m_mine = true; } DeleteScheduleManagerCmd::DeleteScheduleManagerCmd( Project &node, ScheduleManager *sm, const KUndo2MagicString& name ) : AddScheduleManagerCmd( node, sm, -1, name ) { m_mine = false; m_index = m_parent ? m_parent->indexOf( sm ) : node.indexOf( sm ); foreach ( ScheduleManager *s, sm->children() ) { cmd.addCommand( new DeleteScheduleManagerCmd( node, s ) ); } } void DeleteScheduleManagerCmd::execute() { cmd.execute(); AddScheduleManagerCmd::unexecute(); } void DeleteScheduleManagerCmd::unexecute() { AddScheduleManagerCmd::execute(); cmd.unexecute(); } MoveScheduleManagerCmd::MoveScheduleManagerCmd( ScheduleManager *sm, ScheduleManager *newparent, int newindex, const KUndo2MagicString& name ) : NamedCommand( name ), m_sm( sm ), m_oldparent( sm->parentManager() ), m_newparent( newparent ), m_newindex( newindex ) { m_oldindex = sm->parentManager() ? sm->parentManager()->indexOf( sm ) : sm->project().indexOf( sm ); } void MoveScheduleManagerCmd::execute() { m_sm->project().moveScheduleManager( m_sm, m_newparent, m_newindex ); } void MoveScheduleManagerCmd::unexecute() { m_sm->project().moveScheduleManager( m_sm, m_oldparent, m_oldindex ); } ModifyScheduleManagerNameCmd::ModifyScheduleManagerNameCmd( ScheduleManager &sm, const QString& value, const KUndo2MagicString& name ) : NamedCommand( name ), m_sm( sm ), oldvalue( sm.name() ), newvalue( value ) { } void ModifyScheduleManagerNameCmd::execute() { m_sm.setName( newvalue ); } void ModifyScheduleManagerNameCmd::unexecute() { m_sm.setName( oldvalue ); } ModifyScheduleManagerAllowOverbookingCmd::ModifyScheduleManagerAllowOverbookingCmd( ScheduleManager &sm, bool value, const KUndo2MagicString& name ) : NamedCommand( name ), m_sm( sm ), oldvalue( sm.allowOverbooking() ), newvalue( value ) { } void ModifyScheduleManagerAllowOverbookingCmd::execute() { m_sm.setAllowOverbooking( newvalue ); } void ModifyScheduleManagerAllowOverbookingCmd::unexecute() { m_sm.setAllowOverbooking( oldvalue ); } ModifyScheduleManagerDistributionCmd::ModifyScheduleManagerDistributionCmd( ScheduleManager &sm, bool value, const KUndo2MagicString& name ) : NamedCommand( name ), m_sm( sm ), oldvalue( sm.usePert() ), newvalue( value ) { } void ModifyScheduleManagerDistributionCmd::execute() { m_sm.setUsePert( newvalue ); } void ModifyScheduleManagerDistributionCmd::unexecute() { m_sm.setUsePert( oldvalue ); } ModifyScheduleManagerSchedulingDirectionCmd::ModifyScheduleManagerSchedulingDirectionCmd( ScheduleManager &sm, bool value, const KUndo2MagicString& name ) : NamedCommand( name ), m_sm( sm ), oldvalue( sm.schedulingDirection() ), newvalue( value ) { } void ModifyScheduleManagerSchedulingDirectionCmd::execute() { m_sm.setSchedulingDirection( newvalue ); } void ModifyScheduleManagerSchedulingDirectionCmd::unexecute() { m_sm.setSchedulingDirection( oldvalue ); } ModifyScheduleManagerSchedulerCmd::ModifyScheduleManagerSchedulerCmd( ScheduleManager &sm, int value, const KUndo2MagicString& name ) : NamedCommand( name ), m_sm( sm ), oldvalue( sm.schedulerPluginIndex() ), newvalue( value ) { } void ModifyScheduleManagerSchedulerCmd::execute() { m_sm.setSchedulerPlugin( newvalue ); } void ModifyScheduleManagerSchedulerCmd::unexecute() { m_sm.setSchedulerPlugin( oldvalue ); } ModifyScheduleManagerSchedulingGranularityCmd::ModifyScheduleManagerSchedulingGranularityCmd( ScheduleManager &sm, int value, const KUndo2MagicString& name ) : NamedCommand( name ), m_sm( sm ), oldvalue( sm.granularity() ), newvalue( value ) { } void ModifyScheduleManagerSchedulingGranularityCmd::execute() { m_sm.setGranularity( newvalue ); } void ModifyScheduleManagerSchedulingGranularityCmd::unexecute() { m_sm.setGranularity( oldvalue ); } CalculateScheduleCmd::CalculateScheduleCmd( Project &node, ScheduleManager *sm, const KUndo2MagicString& name ) : NamedCommand( name ), m_node( node ), m_sm( sm ), m_first( true ), - m_oldexpected( m_sm->expected() ), m_newexpected( 0 ) { + if (sm->recalculate() && sm->isScheduled()) { + m_sm = new ScheduleManager(node); + m_sm->setRecalculate(true); + m_sm->setGranularity(sm->granularity()); + m_sm->setUsePert(sm->usePert()); + m_sm->setSchedulerPluginId(sm->schedulerPluginId()); + m_sm->setAllowOverbooking(sm->allowOverbooking()); + m_sm->setName(sm->name()); + + preCmd.addCommand(new AddScheduleManagerCmd(sm, m_sm)); + + postCmd.addCommand(new SwapScheduleManagerCmd(node, sm, m_sm)); + postCmd.addCommand(new MoveScheduleManagerCmd(m_sm, sm->parentManager(), sm->parentManager() ? sm->parentManager()->indexOf(sm)+1 : node.indexOf(sm)+1)); + postCmd.addCommand(new DeleteScheduleManagerCmd(node, sm)); + } + m_oldexpected = m_sm->expected(); } void CalculateScheduleCmd::execute() { Q_ASSERT( m_sm ); + preCmd.redo(); if ( m_first ) { m_sm->calculateSchedule(); if ( m_sm->calculationResult() != ScheduleManager::CalculationCanceled ) { m_first = false; } m_newexpected = m_sm->expected(); } else { m_sm->setExpected( m_newexpected ); } + postCmd.redo(); } void CalculateScheduleCmd::unexecute() { if ( m_sm->scheduling() ) { // terminate scheduling QApplication::setOverrideCursor( Qt::WaitCursor ); m_sm->haltCalculation(); m_first = true; QApplication::restoreOverrideCursor(); } + postCmd.undo(); m_sm->setExpected( m_oldexpected ); + preCmd.undo(); } //------------------------ BaselineScheduleCmd::BaselineScheduleCmd( ScheduleManager &sm, const KUndo2MagicString& name ) : NamedCommand( name ), m_sm( sm ) { } void BaselineScheduleCmd::execute() { m_sm.setBaselined( true ); } void BaselineScheduleCmd::unexecute() { m_sm.setBaselined( false ); } ResetBaselineScheduleCmd::ResetBaselineScheduleCmd( ScheduleManager &sm, const KUndo2MagicString& name ) : NamedCommand( name ), m_sm( sm ) { } void ResetBaselineScheduleCmd::execute() { m_sm.setBaselined( false ); } void ResetBaselineScheduleCmd::unexecute() { m_sm.setBaselined( true ); } //------------------------ ModifyStandardWorktimeYearCmd::ModifyStandardWorktimeYearCmd( StandardWorktime *wt, double oldvalue, double newvalue, const KUndo2MagicString& name ) : NamedCommand( name ), swt( wt ), m_oldvalue( oldvalue ), m_newvalue( newvalue ) { } void ModifyStandardWorktimeYearCmd::execute() { swt->setYear( m_newvalue ); } void ModifyStandardWorktimeYearCmd::unexecute() { swt->setYear( m_oldvalue ); } ModifyStandardWorktimeMonthCmd::ModifyStandardWorktimeMonthCmd( StandardWorktime *wt, double oldvalue, double newvalue, const KUndo2MagicString& name ) : NamedCommand( name ), swt( wt ), m_oldvalue( oldvalue ), m_newvalue( newvalue ) { } void ModifyStandardWorktimeMonthCmd::execute() { swt->setMonth( m_newvalue ); } void ModifyStandardWorktimeMonthCmd::unexecute() { swt->setMonth( m_oldvalue ); } ModifyStandardWorktimeWeekCmd::ModifyStandardWorktimeWeekCmd( StandardWorktime *wt, double oldvalue, double newvalue, const KUndo2MagicString& name ) : NamedCommand( name ), swt( wt ), m_oldvalue( oldvalue ), m_newvalue( newvalue ) { } void ModifyStandardWorktimeWeekCmd::execute() { swt->setWeek( m_newvalue ); } void ModifyStandardWorktimeWeekCmd::unexecute() { swt->setWeek( m_oldvalue ); } ModifyStandardWorktimeDayCmd::ModifyStandardWorktimeDayCmd( StandardWorktime *wt, double oldvalue, double newvalue, const KUndo2MagicString& name ) : NamedCommand( name ), swt( wt ), m_oldvalue( oldvalue ), m_newvalue( newvalue ) { } void ModifyStandardWorktimeDayCmd::execute() { swt->setDay( m_newvalue ); } void ModifyStandardWorktimeDayCmd::unexecute() { swt->setDay( m_oldvalue ); } //---------------- DocumentAddCmd::DocumentAddCmd( Documents &docs, Document *value, const KUndo2MagicString& name ) : NamedCommand( name ), m_docs( docs ), m_mine( true ) { Q_ASSERT( value ); m_value = value; } DocumentAddCmd::~DocumentAddCmd() { //debugPlan; if ( m_mine ) delete m_value; } void DocumentAddCmd::execute() { m_docs.addDocument( m_value ); m_mine = false; } void DocumentAddCmd::unexecute() { m_docs.takeDocument( m_value ); m_mine = true; } //---------------- DocumentRemoveCmd::DocumentRemoveCmd( Documents &docs, Document *value, const KUndo2MagicString& name ) : NamedCommand( name ), m_docs( docs ), m_mine( false ) { Q_ASSERT( value ); m_value = value; } DocumentRemoveCmd::~DocumentRemoveCmd() { //debugPlan; if ( m_mine ) delete m_value; } void DocumentRemoveCmd::execute() { m_docs.takeDocument( m_value ); m_mine = true; } void DocumentRemoveCmd::unexecute() { m_docs.addDocument( m_value ); m_mine = false; } //---------------- DocumentModifyUrlCmd::DocumentModifyUrlCmd( Document *doc, const QUrl &value, const KUndo2MagicString& name ) : NamedCommand( name ), m_doc( doc ) { Q_ASSERT( doc ); m_value = value; m_oldvalue = doc->url(); } void DocumentModifyUrlCmd::execute() { m_doc->setUrl( m_value ); } void DocumentModifyUrlCmd::unexecute() { m_doc->setUrl( m_oldvalue ); } //---------------- DocumentModifyNameCmd::DocumentModifyNameCmd( Document *doc, const QString &value, const KUndo2MagicString& name ) : NamedCommand( name ), m_doc( doc ) { Q_ASSERT( doc ); m_value = value; m_oldvalue = doc->name(); } void DocumentModifyNameCmd::execute() { m_doc->setName( m_value ); } void DocumentModifyNameCmd::unexecute() { m_doc->setName( m_oldvalue ); } //---------------- DocumentModifyTypeCmd::DocumentModifyTypeCmd( Document *doc, Document::Type value, const KUndo2MagicString& name ) : NamedCommand( name ), m_doc( doc ) { Q_ASSERT( doc ); m_value = value; m_oldvalue = doc->type(); } void DocumentModifyTypeCmd::execute() { m_doc->setType( m_value ); } void DocumentModifyTypeCmd::unexecute() { m_doc->setType( m_oldvalue ); } //---------------- DocumentModifyStatusCmd::DocumentModifyStatusCmd( Document *doc, const QString &value, const KUndo2MagicString& name ) : NamedCommand( name ), m_doc( doc ) { Q_ASSERT( doc ); m_value = value; m_oldvalue = doc->type(); } void DocumentModifyStatusCmd::execute() { m_doc->setStatus( m_value ); } void DocumentModifyStatusCmd::unexecute() { m_doc->setStatus( m_oldvalue ); } //---------------- DocumentModifySendAsCmd::DocumentModifySendAsCmd( Document *doc, const Document::SendAs value, const KUndo2MagicString& name ) : NamedCommand( name ), m_doc( doc ) { Q_ASSERT( doc ); m_value = value; m_oldvalue = doc->sendAs(); } void DocumentModifySendAsCmd::execute() { m_doc->setSendAs( m_value ); } void DocumentModifySendAsCmd::unexecute() { m_doc->setSendAs( m_oldvalue ); } //---------------- WBSDefinitionModifyCmd::WBSDefinitionModifyCmd( Project &project, const WBSDefinition value, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ) { m_newvalue = value; m_oldvalue = m_project.wbsDefinition(); } void WBSDefinitionModifyCmd::execute() { m_project.setWbsDefinition( m_newvalue ); } void WBSDefinitionModifyCmd::unexecute() { m_project.setWbsDefinition( m_oldvalue ); } //---------------- InsertProjectCmd::InsertProjectCmd( Project &project, Node *parent, Node *after, const KUndo2MagicString& name ) : MacroCommand( name ), m_project( static_cast( parent->projectNode() ) ), m_parent( parent ) { Q_ASSERT( &project != m_project ); if ( m_project->defaultCalendar() ) { project.setDefaultCalendar( 0 ); // or else m_project default calendar may be overwitten } QString defaultAccount; if ( ! m_project->accounts().defaultAccount() && project.accounts().defaultAccount() ) { defaultAccount = project.accounts().defaultAccount()->name(); } QHash startupaccountmap; QHash shutdownaccountmap; QHash runningaccountmap; QHash nodecalendarmap; // remove unhandled info in tasks and get accounts and calendars foreach ( Node *n, project.allNodes() ) { if ( n->type() == Node::Type_Task ) { Task *t = static_cast( n ); t->workPackage().clear(); while ( ! t->workPackageLog().isEmpty() ) { WorkPackage *wp = t->workPackageLog().at( 0 ); t->removeWorkPackage( wp ); delete wp; } } if ( n->startupAccount() ) { startupaccountmap.insert( n, n->startupAccount()->name() ); n->setStartupAccount( 0 ); } if ( n->shutdownAccount() ) { shutdownaccountmap.insert( n, n->shutdownAccount()->name() ); n->setShutdownAccount( 0 ); } if ( n->runningAccount() ) { runningaccountmap.insert( n, n->runningAccount()->name() ); n->setRunningAccount( 0 ); } if ( n->estimate()->calendar() ) { nodecalendarmap.insert( n, n->estimate()->calendar()->id() ); n->estimate()->setCalendar( 0 ); } } // get resources pointing to calendars and accounts QHash resaccountmap; QHash rescalendarmap; foreach ( Resource *r, project.resourceList() ) { if ( r->account() ) { resaccountmap.insert( r, r->account()->name() ); r->setAccount( 0 ); } if ( r->calendar() ) { rescalendarmap.insert( r, r->calendar()->id() ); r->setCalendar( 0 ); } } // create add account commands and keep track of used and unused accounts QList unusedAccounts; QMap accountsmap; foreach ( Account *a, m_project->accounts().allAccounts() ) { accountsmap.insert( a->name(), a ); } foreach ( Account *a, project.accounts().accountList() ) { addAccounts( a, 0, unusedAccounts, accountsmap ); } // create add calendar commands and keep track of used and unused calendars QList unusedCalendars; QMap calendarsmap; foreach ( Calendar *c, m_project->allCalendars() ) { calendarsmap.insert( c->id(), c ); } foreach ( Calendar *c, project.calendars() ) { addCalendars( c, 0, unusedCalendars, calendarsmap ); } // get all requests before resources are merged QHash > greqs; QHash > rreqs; foreach ( Node *n, project.allNodes() ) { QList resReq; if ( n->type() != (int)Node::Type_Task || n->requests().isEmpty() ) { continue; } while ( ResourceGroupRequest *gr = n->requests().requests().value( 0 ) ) { while ( ResourceRequest *rr = gr->resourceRequests( false ).value( 0 ) ) { debugPlanInsertProject<<"Get resource request:"<( rr, rr->resource() ) ); // all resource requests shall be reinserted rr->unregisterRequest(); gr->takeResourceRequest( rr ); } // all group requests shall be reinserted greqs[ gr ] = QPair( n, gr->group() ); gr->group()->unregisterRequest( gr ); int i = n->requests().takeRequest( gr ); Q_ASSERT( i >= 0 ); #ifdef NDEBUG Q_UNUSED(i); #endif } } QList allGroups; QList allResources; QList newResources; QHash existingGroups; QHash existingResources; foreach ( ResourceGroup *g, project.resourceGroups() ) { ResourceGroup *gr = m_project->findResourceGroup( g->id() ); if ( gr == 0 ) { addCommand( new AddResourceGroupCmd( m_project, g, kundo2_noi18n("ResourceGroup") ) ); gr = g; debugPlanInsertProject<<"AddResourceGroupCmd:"<name(); } else { existingGroups[ gr ] = g; } allGroups << gr; foreach ( Resource *r, g->resources() ) { while ( Schedule *s = r->schedules().values().value( 0 ) ) { r->deleteSchedule( s ); // schedules not handled } Resource *res = m_project->findResource( r->id() ); if ( res == 0 ) { addCommand( new AddResourceCmd( gr, r, kundo2_noi18n("Resource") ) ); allResources << r; newResources << r; debugPlanInsertProject<<"AddResourceCmd:"<name()<name(); } else { existingResources[ res ] = r; allResources << res; } } } // Update resource account {QHash::const_iterator it = resaccountmap.constBegin(); QHash::const_iterator end = resaccountmap.constEnd(); for ( ; it != end; ++it ) { Resource *r = it.key(); if ( newResources.contains( r ) ) { Q_ASSERT( allResources.contains( r ) ); addCommand( new ResourceModifyAccountCmd( *r, 0, accountsmap.value( it.value() ) ) ); } }} // Update resource calendar {QHash::const_iterator it = rescalendarmap.constBegin(); QHash::const_iterator end = rescalendarmap.constEnd(); for ( ; it != end; ++it ) { Resource *r = it.key(); if ( newResources.contains( r ) ) { Q_ASSERT( allResources.contains( r ) ); addCommand( new ModifyResourceCalendarCmd( r, calendarsmap.value( it.value() ) ) ); } }} // Requests: clean up requests to resources already in m_project int gi = 0; int ri = 0; QHash >::const_iterator gregsIt; for (gregsIt = greqs.constBegin(); gregsIt != greqs.constEnd(); ++gregsIt) { ResourceGroupRequest *gr = gregsIt.key(); QPair pair = gregsIt.value(); Node *n = pair.first; ResourceGroup *newGroup = pair.second; if (ResourceGroup *ng = existingGroups.key(newGroup)) { newGroup = ng; } Q_ASSERT( allGroups.contains( newGroup ) ); gr->setGroup( newGroup ); addCommand( new AddResourceGroupRequestCmd( static_cast( *n ), gr, kundo2_noi18n("Group %1", ++gi) ) ); debugPlanInsertProject<<"Add resource group request:"<name()<<":"<name(); QHash >::const_iterator i = rreqs.constFind( gr ); for ( ; i != rreqs.constEnd() && i.key() == gr; ++i ) { ResourceRequest *rr = i.value().first; Resource *newRes = i.value().second; if (Resource *nr = existingResources.key(newRes)) { newRes = nr; } debugPlanInsertProject<<"Add resource request:"<name()<<":"<name()<<":"<name(); if ( ! rr->requiredResources().isEmpty() ) { // the resource request may have required resources that needs mapping QList required; foreach ( Resource *r, rr->requiredResources() ) { if ( newResources.contains( r ) ) { required << r; debugPlanInsertProject<<"Request: required (new)"<name(); continue; } Resource *r2 = existingResources.key( r ); Q_ASSERT( allResources.contains( r2 ) ); if ( r2 ) { debugPlanInsertProject<<"Request: required (existing)"<name(); required << r2; } } rr->setRequiredResources( required ); } Q_ASSERT( allResources.contains( newRes ) ); // all resource requests shall be reinserted rr->setResource( newRes ); addCommand( new AddResourceRequestCmd( gr, rr, kundo2_noi18n("Resource %1", ++ri) ) ); } } // Add nodes ( ids are unique, no need to check ) Node *node_after = after; for ( int i = 0; i < project.numChildren(); ++i ) { Node *n = project.childNode( i ); Q_ASSERT( n ); while ( Schedule *s = n->schedules().values().value( 0 ) ) { n->takeSchedule( s ); // schedules not handled delete s; } n->setParentNode( 0 ); if ( node_after ) { addCommand( new TaskAddCmd( m_project, n, node_after, kundo2_noi18n("Task") ) ); node_after = n; } else { addCommand( new SubtaskAddCmd( m_project, n, parent, kundo2_noi18n("Subtask") ) ); } addChildNodes( n ); } // Dependencies: foreach ( Node *n, project.allNodes() ) { while ( n->numDependChildNodes() > 0 ) { Relation *r = n->dependChildNodes().at( 0 ); n->takeDependChildNode( r ); r->child()->takeDependParentNode( r ); addCommand( new AddRelationCmd( *m_project, r ) ); } } // node calendar {QHash::const_iterator it = nodecalendarmap.constBegin(); QHash::const_iterator end = nodecalendarmap.constEnd(); for ( ; it != end; ++it ) { addCommand( new ModifyEstimateCalendarCmd( *(it.key()), 0, calendarsmap.value( it.value() ) ) ); }} // node startup account {QHash::const_iterator it = startupaccountmap.constBegin(); QHash::const_iterator end = startupaccountmap.constEnd(); for ( ; it != end; ++it ) { addCommand( new NodeModifyStartupAccountCmd( *(it.key()), 0, accountsmap.value( it.value() ) ) ); }} // node shutdown account {QHash::const_iterator it = shutdownaccountmap.constBegin(); QHash::const_iterator end = shutdownaccountmap.constEnd(); for ( ; it != end; ++it ) { addCommand( new NodeModifyShutdownAccountCmd( *(it.key()), 0, accountsmap.value( it.value() ) ) ); }} // node running account {QHash::const_iterator it = runningaccountmap.constBegin(); QHash::const_iterator end = runningaccountmap.constEnd(); for ( ; it != end; ++it ) { addCommand( new NodeModifyRunningAccountCmd( *(it.key()), 0, accountsmap.value( it.value() ) ) ); }} if ( ! defaultAccount.isEmpty() ) { Account *a = accountsmap.value( defaultAccount ); if ( a && a->list() ) { addCommand( new ModifyDefaultAccountCmd( m_project->accounts(), 0, a ) ); } } // Cleanup // Remove nodes from project so they are not deleted while ( Node *ch = project.childNode( 0 ) ) { project.takeChildNode( ch ); } foreach ( Node *n, project.allNodes() ) { project.removeId( n->id() ); } // Remove calendars from project while ( project.calendarCount() > 0 ) { project.takeCalendar( project.calendarAt( 0 ) ); } qDeleteAll( unusedCalendars ); // Remove accounts from project while ( project.accounts().accountCount() > 0 ) { project.accounts().take( project.accounts().accountAt( 0 ) ); } qDeleteAll( unusedAccounts ); while ( project.numResourceGroups() > 0 ) { ResourceGroup *g = project.resourceGroupAt( 0 ); while ( g->numResources() > 0 ) { g->takeResource( g->resourceAt( 0 ) ); } project.takeResourceGroup( g ); } qDeleteAll( existingResources ); // deletes unused resources qDeleteAll( existingGroups ); // deletes unused resource groups } void InsertProjectCmd::addCalendars( Calendar *calendar, Calendar *parent, QList &unused, QMap &calendarsmap ) { Calendar *par = 0; if ( parent ) { par = calendarsmap.value( parent->id() ); } if ( par == 0 ) { par = parent; } Calendar *cal = calendarsmap.value( calendar->id() ); if ( cal == 0 ) { calendarsmap.insert( calendar->id(), calendar ); addCommand( new CalendarAddCmd( m_project, calendar, -1, par ) ); } else { unused << calendar; } foreach ( Calendar *c, calendar->calendars() ) { addCalendars( c, calendar, unused, calendarsmap ); } } void InsertProjectCmd::addAccounts( Account *account, Account *parent, QList &unused, QMap &accountsmap ) { Account *par = 0; if ( parent ) { par = accountsmap.value( parent->name() ); } if ( par == 0 ) { par = parent; } Account *acc = accountsmap.value( account->name() ); if ( acc == 0 ) { debugPlanInsertProject<<"Move to new project:"<name(); accountsmap.insert( account->name(), account ); addCommand( new AddAccountCmd( *m_project, account, par, -1, kundo2_noi18n( "Add account %1", account->name() ) ) ); } else { debugPlanInsertProject<<"Already exists:"<name(); unused << account; } while ( ! account->accountList().isEmpty() ) { Account *a = account->accountList().first(); account->list()->take( a ); addAccounts( a, account, unused, accountsmap ); } } void InsertProjectCmd::addChildNodes( Node *node ) { // schedules not handled while ( Schedule *s = node->schedules().values().value( 0 ) ) { node->takeSchedule( s ); // schedules not handled delete s; } foreach ( Node *n, node->childNodeIterator() ) { n->setParentNode( 0 ); addCommand( new SubtaskAddCmd( m_project, n, node, kundo2_noi18n("Subtask") ) ); addChildNodes( n ); } // Remove child nodes so they are not added twice while ( Node *ch = node->childNode( 0 ) ) { node->takeChildNode( ch ); } } void InsertProjectCmd::execute() { QApplication::setOverrideCursor( Qt::WaitCursor ); MacroCommand::execute(); QApplication::restoreOverrideCursor(); } void InsertProjectCmd::unexecute() { QApplication::setOverrideCursor( Qt::WaitCursor ); MacroCommand::unexecute(); QApplication::restoreOverrideCursor(); } WorkPackageAddCmd::WorkPackageAddCmd( Project *project, Node *node, WorkPackage *value, const KUndo2MagicString& name ) : NamedCommand( name ), m_project( project ), m_node( node ), m_wp( value ), m_mine( true ) { } WorkPackageAddCmd::~WorkPackageAddCmd() { if ( m_mine ) { delete m_wp; } } void WorkPackageAddCmd::execute() { // FIXME use project //m_project->addWorkPackage( m_node, m_wp ); static_cast( m_node )->addWorkPackage( m_wp ); } void WorkPackageAddCmd::unexecute() { // FIXME use project //m_project->removeWorkPackage( m_node, m_wp ); static_cast( m_node )->removeWorkPackage( m_wp ); } ModifyProjectLocaleCmd::ModifyProjectLocaleCmd( Project &project, const KUndo2MagicString& name ) : MacroCommand( name ), m_project( project ) { }; void ModifyProjectLocaleCmd::execute() { MacroCommand::execute(); m_project.emitLocaleChanged(); } void ModifyProjectLocaleCmd::unexecute() { MacroCommand::unexecute(); m_project.emitLocaleChanged(); } ModifyCurrencySymolCmd::ModifyCurrencySymolCmd( Locale *locale, const QString &value, const KUndo2MagicString& name ) : NamedCommand( name ), m_locale( locale ), m_newvalue( value ), m_oldvalue( locale->currencySymbol() ) { }; void ModifyCurrencySymolCmd::execute() { m_locale->setCurrencySymbol( m_newvalue ); } void ModifyCurrencySymolCmd::unexecute() { m_locale->setCurrencySymbol( m_oldvalue ); } ModifyCurrencyFractionalDigitsCmd::ModifyCurrencyFractionalDigitsCmd( Locale *locale, int value, const KUndo2MagicString& name ) : NamedCommand( name ), m_locale( locale ), m_newvalue( value ), m_oldvalue(locale->monetaryDecimalPlaces()) { }; void ModifyCurrencyFractionalDigitsCmd::execute() { m_locale->setMonetaryDecimalPlaces(m_newvalue); } void ModifyCurrencyFractionalDigitsCmd::unexecute() { m_locale->setMonetaryDecimalPlaces(m_oldvalue); } AddExternalAppointmentCmd::AddExternalAppointmentCmd( Resource *resource, const QString &pid, const QString &pname, const QDateTime &start, const QDateTime &end, double load, const KUndo2MagicString& name ) : NamedCommand( name ), m_resource( resource ), m_pid( pid ), m_pname( pname ), m_start( start ), m_end( end ), m_load( load ) { } void AddExternalAppointmentCmd::execute() { m_resource->addExternalAppointment( m_pid, m_pname, m_start, m_end, m_load ); } void AddExternalAppointmentCmd::unexecute() { m_resource->subtractExternalAppointment( m_pid, m_start, m_end, m_load ); // FIXME do this smarter if ( ! m_resource->externalAppointments( m_pid ).isEmpty() ) { m_resource->takeExternalAppointment( m_pid ); } } ClearExternalAppointmentCmd::ClearExternalAppointmentCmd( Resource *resource, const QString &pid, const KUndo2MagicString &name ) : NamedCommand( name ), m_resource( resource ), m_pid( pid ), m_appointments( 0 ) { } ClearExternalAppointmentCmd::~ClearExternalAppointmentCmd() { delete m_appointments; } void ClearExternalAppointmentCmd::execute() { // debugPlan<name()<takeExternalAppointment( m_pid ); } void ClearExternalAppointmentCmd::unexecute() { // debugPlan<name()<addExternalAppointment( m_pid, m_appointments ); } m_appointments = 0; } ClearAllExternalAppointmentsCmd::ClearAllExternalAppointmentsCmd( Project *project, const KUndo2MagicString &name ) : NamedCommand( name ), m_project( project ) { foreach ( Resource *r, project->resourceList() ) { const QMap map = r->externalProjects(); QMap::const_iterator it; for (it = map.constBegin(); it != map.constEnd(); ++it) { m_cmd.addCommand(new ClearExternalAppointmentCmd(r, it.key())); } } } void ClearAllExternalAppointmentsCmd::execute() { m_cmd.redo(); } void ClearAllExternalAppointmentsCmd::unexecute() { m_cmd.undo(); } SharedResourcesFileCmd::SharedResourcesFileCmd(Project *project, const QString &newValue, const KUndo2MagicString& name) : NamedCommand(name) , m_project(project) , m_oldValue(project->sharedResourcesFile()) , m_newValue(newValue) { } void SharedResourcesFileCmd::execute() { m_project->setSharedResourcesFile(m_newValue); } void SharedResourcesFileCmd::unexecute() { m_project->setSharedResourcesFile(m_oldValue); } UseSharedResourcesCmd::UseSharedResourcesCmd(Project *project, bool newValue, const KUndo2MagicString& name) : NamedCommand(name) , m_project(project) , m_oldValue(project->useSharedResources()) , m_newValue(newValue) { } void UseSharedResourcesCmd::execute() { m_project->setUseSharedResources(m_newValue); } void UseSharedResourcesCmd::unexecute() { m_project->setUseSharedResources(m_oldValue); } SharedProjectsUrlCmd::SharedProjectsUrlCmd(Project *project, const QUrl &newValue, const KUndo2MagicString& name) : NamedCommand(name) , m_project(project) , m_oldValue(project->sharedProjectsUrl()) , m_newValue(newValue) { } void SharedProjectsUrlCmd::execute() { m_project->setSharedProjectsUrl(m_newValue); } void SharedProjectsUrlCmd::unexecute() { m_project->setSharedProjectsUrl(m_oldValue); } LoadProjectsAtStartupCmd::LoadProjectsAtStartupCmd(Project *project, bool newValue, const KUndo2MagicString& name) : NamedCommand(name) , m_project(project) , m_oldValue(project->loadProjectsAtStartup()) , m_newValue(newValue) { } void LoadProjectsAtStartupCmd::execute() { m_project->setLoadProjectsAtStartup(m_newValue); } void LoadProjectsAtStartupCmd::unexecute() { m_project->setLoadProjectsAtStartup(m_oldValue); } } //KPlato namespace diff --git a/src/libs/kernel/kptcommand.h b/src/libs/kernel/kptcommand.h index ec511d25..f8d944db 100644 --- a/src/libs/kernel/kptcommand.h +++ b/src/libs/kernel/kptcommand.h @@ -1,2002 +1,2017 @@ /* This file is part of the KDE project Copyright (C) 2004-2007 Dag Andersen Copyright (C) 2011 Dag Andersen Copyright (C) 2016 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 KPTCOMMAND_H #define KPTCOMMAND_H #include "plankernel_export.h" #include #include #include #include "kptappointment.h" #include "kptnode.h" #include "kptduration.h" #include "kpttask.h" #include "kptwbsdefinition.h" class QString; /** * @file * This file includes undo/redo commands for kernel data structures */ /// The main namespace namespace KPlato { class Locale; class Account; class Accounts; class Project; class Task; class Calendar; class CalendarDay; class Relation; class ResourceGroupRequest; class ResourceRequest; class ResourceGroup; class Resource; class Schedule; class StandardWorktime; class PLANKERNEL_EXPORT NamedCommand : public KUndo2Command { public: explicit NamedCommand( const KUndo2MagicString& name ) : KUndo2Command( name ) {} virtual void redo() { execute(); } virtual void undo() { unexecute(); } virtual void execute() = 0; virtual void unexecute() = 0; protected: /// Set all scheduled in the m_schedules map to their original scheduled state void setSchScheduled(); /// Set all schedules in the m_schedules map to scheduled state @p state void setSchScheduled( bool state ); /// Add a schedule to the m_schedules map along with its current scheduled state void addSchScheduled( Schedule *sch ); QHash m_schedules; }; class PLANKERNEL_EXPORT MacroCommand : public KUndo2Command { public: explicit MacroCommand( const KUndo2MagicString& name = KUndo2MagicString() ) : KUndo2Command( name ) {} ~MacroCommand(); void addCommand( KUndo2Command *cmd ); virtual void redo() { execute(); } virtual void undo() { unexecute(); } virtual void execute(); virtual void unexecute(); bool isEmpty() const { return cmds.isEmpty(); } protected: QList cmds; }; class PLANKERNEL_EXPORT CalendarAddCmd : public NamedCommand { public: CalendarAddCmd( Project *project, Calendar *cal, int pos, Calendar *parent, const KUndo2MagicString& name = KUndo2MagicString() ); ~CalendarAddCmd(); void execute(); void unexecute(); private: Project *m_project; Calendar *m_cal; int m_pos; Calendar *m_parent; bool m_mine; }; class PLANKERNEL_EXPORT CalendarRemoveCmd : public NamedCommand { public: CalendarRemoveCmd( Project *project, Calendar *cal, const KUndo2MagicString& name = KUndo2MagicString() ); ~CalendarRemoveCmd(); void execute(); void unexecute(); private: Project *m_project; Calendar *m_parent; Calendar *m_cal; int m_index; bool m_mine; MacroCommand *m_cmd; }; class PLANKERNEL_EXPORT CalendarMoveCmd : public NamedCommand { public: CalendarMoveCmd( Project *project, Calendar *cal, int position, Calendar *parent, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Project *m_project; Calendar *m_cal; int m_newpos; int m_oldpos; Calendar *m_newparent; Calendar *m_oldparent; }; class PLANKERNEL_EXPORT CalendarModifyNameCmd : public NamedCommand { public: CalendarModifyNameCmd( Calendar *cal, const QString& newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Calendar *m_cal; QString m_newvalue; QString m_oldvalue; }; class PLANKERNEL_EXPORT CalendarModifyParentCmd : public NamedCommand { public: CalendarModifyParentCmd( Project *project, Calendar *cal, Calendar *newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); ~CalendarModifyParentCmd(); void execute(); void unexecute(); private: Project *m_project; Calendar *m_cal; Calendar *m_newvalue; Calendar *m_oldvalue; MacroCommand *m_cmd; int m_oldindex; int m_newindex; }; class PLANKERNEL_EXPORT CalendarModifyTimeZoneCmd : public NamedCommand { public: CalendarModifyTimeZoneCmd( Calendar *cal, const QTimeZone &value, const KUndo2MagicString& name = KUndo2MagicString() ); ~CalendarModifyTimeZoneCmd(); void execute(); void unexecute(); private: Calendar *m_cal; QTimeZone m_newvalue; QTimeZone m_oldvalue; MacroCommand *m_cmd; }; #ifdef HAVE_KHOLIDAYS class PLANKERNEL_EXPORT CalendarModifyHolidayRegionCmd : public NamedCommand { public: CalendarModifyHolidayRegionCmd( Calendar *cal, const QString &value, const KUndo2MagicString& name = KUndo2MagicString() ); ~CalendarModifyHolidayRegionCmd(); void execute(); void unexecute(); private: Calendar *m_cal; QString m_newvalue; QString m_oldvalue; }; #endif class PLANKERNEL_EXPORT CalendarAddDayCmd : public NamedCommand { public: CalendarAddDayCmd( Calendar *cal, CalendarDay *newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); ~CalendarAddDayCmd(); void execute(); void unexecute(); protected: Calendar *m_cal; CalendarDay *m_newvalue; bool m_mine; }; class PLANKERNEL_EXPORT CalendarRemoveDayCmd : public NamedCommand { public: CalendarRemoveDayCmd( Calendar *cal, CalendarDay *day, const KUndo2MagicString& name = KUndo2MagicString() ); CalendarRemoveDayCmd( Calendar *cal, const QDate &day, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); protected: Calendar *m_cal; CalendarDay *m_value; bool m_mine; private: void init(); }; class PLANKERNEL_EXPORT CalendarModifyDayCmd : public NamedCommand { public: CalendarModifyDayCmd( Calendar *cal, CalendarDay *value, const KUndo2MagicString& name = KUndo2MagicString() ); ~CalendarModifyDayCmd(); void execute(); void unexecute(); private: Calendar *m_cal; CalendarDay *m_newvalue; CalendarDay *m_oldvalue; bool m_mine; }; class PLANKERNEL_EXPORT CalendarModifyStateCmd : public NamedCommand { public: CalendarModifyStateCmd( Calendar *calendar, CalendarDay *day, CalendarDay::State value, const KUndo2MagicString& name = KUndo2MagicString() ); ~CalendarModifyStateCmd(); void execute(); void unexecute(); private: Calendar *m_calendar; CalendarDay *m_day; CalendarDay::State m_newvalue; CalendarDay::State m_oldvalue; MacroCommand *m_cmd; }; class PLANKERNEL_EXPORT CalendarModifyTimeIntervalCmd : public NamedCommand { public: CalendarModifyTimeIntervalCmd( Calendar *calendar, TimeInterval &newvalue, TimeInterval *value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Calendar *m_calendar; TimeInterval *m_value; TimeInterval m_newvalue; TimeInterval m_oldvalue; }; class PLANKERNEL_EXPORT CalendarAddTimeIntervalCmd : public NamedCommand { public: CalendarAddTimeIntervalCmd( Calendar *calendar, CalendarDay *day, TimeInterval *value, const KUndo2MagicString& name = KUndo2MagicString() ); ~CalendarAddTimeIntervalCmd(); void execute(); void unexecute(); protected: Calendar *m_calendar; CalendarDay *m_day; TimeInterval *m_value; bool m_mine; }; class PLANKERNEL_EXPORT CalendarRemoveTimeIntervalCmd : public CalendarAddTimeIntervalCmd { public: CalendarRemoveTimeIntervalCmd( Calendar *calendar, CalendarDay *day, TimeInterval *value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); }; class PLANKERNEL_EXPORT CalendarModifyWeekdayCmd : public NamedCommand { public: CalendarModifyWeekdayCmd( Calendar *cal, int weekday, CalendarDay *value, const KUndo2MagicString& name = KUndo2MagicString() ); ~CalendarModifyWeekdayCmd(); void execute(); void unexecute(); private: int m_weekday; Calendar *m_cal; CalendarDay *m_value; CalendarDay m_orig; }; class PLANKERNEL_EXPORT CalendarModifyDateCmd : public NamedCommand { public: CalendarModifyDateCmd( Calendar *cal, CalendarDay *day, const QDate &value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Calendar *m_cal; CalendarDay *m_day; QDate m_newvalue, m_oldvalue; }; class PLANKERNEL_EXPORT ProjectModifyDefaultCalendarCmd : public NamedCommand { public: ProjectModifyDefaultCalendarCmd( Project *project, Calendar *cal, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Project *m_project; Calendar *m_newvalue, *m_oldvalue; }; class PLANKERNEL_EXPORT NodeDeleteCmd : public NamedCommand { public: explicit NodeDeleteCmd( Node *node, const KUndo2MagicString& name = KUndo2MagicString() ); ~NodeDeleteCmd(); void execute(); void unexecute(); private: Node *m_node; Node *m_parent; Project *m_project; int m_index; bool m_mine; QList m_appointments; MacroCommand *m_cmd; MacroCommand *m_relCmd; }; class PLANKERNEL_EXPORT TaskAddCmd : public NamedCommand { public: TaskAddCmd( Project *project, Node *node, Node *after, const KUndo2MagicString& name = KUndo2MagicString() ); ~TaskAddCmd(); void execute(); void unexecute(); private: Project *m_project; Node *m_node; Node *m_after; bool m_added; }; class PLANKERNEL_EXPORT SubtaskAddCmd : public NamedCommand { public: SubtaskAddCmd( Project *project, Node *node, Node *parent, const KUndo2MagicString& name = KUndo2MagicString() ); ~SubtaskAddCmd(); void execute(); void unexecute(); private: Project *m_project; Node *m_node; Node *m_parent; bool m_added; MacroCommand *m_cmd; }; class PLANKERNEL_EXPORT NodeModifyNameCmd : public NamedCommand { public: NodeModifyNameCmd( Node &node, const QString& nodename, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; QString newName; QString oldName; }; class PLANKERNEL_EXPORT NodeModifyPriorityCmd : public NamedCommand { public: NodeModifyPriorityCmd(Node &node, int oldValue, int newValue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; int m_oldValue; int m_newValue; }; class PLANKERNEL_EXPORT NodeModifyLeaderCmd : public NamedCommand { public: NodeModifyLeaderCmd( Node &node, const QString& leader, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; QString newLeader; QString oldLeader; }; class PLANKERNEL_EXPORT NodeModifyDescriptionCmd : public NamedCommand { public: NodeModifyDescriptionCmd( Node &node, const QString& description, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; QString newDescription; QString oldDescription; }; class PLANKERNEL_EXPORT NodeModifyConstraintCmd : public NamedCommand { public: NodeModifyConstraintCmd( Node &node, Node::ConstraintType c, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; Node::ConstraintType newConstraint; Node::ConstraintType oldConstraint; }; class PLANKERNEL_EXPORT NodeModifyConstraintStartTimeCmd : public NamedCommand { public: NodeModifyConstraintStartTimeCmd( Node &node, const QDateTime& dt, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; QDateTime newTime; DateTime oldTime; QTimeZone m_timeZone; }; class PLANKERNEL_EXPORT NodeModifyConstraintEndTimeCmd : public NamedCommand { public: NodeModifyConstraintEndTimeCmd( Node &node, const QDateTime& dt, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; QDateTime newTime; DateTime oldTime; QTimeZone m_timeZone; }; class PLANKERNEL_EXPORT NodeModifyStartTimeCmd : public NamedCommand { public: NodeModifyStartTimeCmd( Node &node, const QDateTime& dt, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; QDateTime newTime; DateTime oldTime; QTimeZone m_timeZone; }; class PLANKERNEL_EXPORT NodeModifyEndTimeCmd : public NamedCommand { public: NodeModifyEndTimeCmd( Node &node, const QDateTime& dt, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; QDateTime newTime; DateTime oldTime; QTimeZone m_timeZone; }; class PLANKERNEL_EXPORT NodeModifyIdCmd : public NamedCommand { public: NodeModifyIdCmd( Node &node, const QString& id, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; QString newId; QString oldId; }; class PLANKERNEL_EXPORT NodeIndentCmd : public NamedCommand { public: explicit NodeIndentCmd( Node &node, const KUndo2MagicString& name = KUndo2MagicString() ); ~NodeIndentCmd(); void execute(); void unexecute(); private: Node &m_node; Node *m_oldparent, *m_newparent; int m_oldindex, m_newindex; MacroCommand *m_cmd; }; class PLANKERNEL_EXPORT NodeUnindentCmd : public NamedCommand { public: explicit NodeUnindentCmd( Node &node, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; Node *m_oldparent, *m_newparent; int m_oldindex, m_newindex; }; class PLANKERNEL_EXPORT NodeMoveUpCmd : public NamedCommand { public: explicit NodeMoveUpCmd( Node &node, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; Project *m_project; bool m_moved; }; class PLANKERNEL_EXPORT NodeMoveDownCmd : public NamedCommand { public: explicit NodeMoveDownCmd( Node &node, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; Project *m_project; bool m_moved; }; class PLANKERNEL_EXPORT NodeMoveCmd : public NamedCommand { public: NodeMoveCmd( Project *project, Node *node, Node *newParent, int newPos, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Project *m_project; Node *m_node; Node *m_newparent; Node *m_oldparent; int m_newpos; int m_oldpos; bool m_moved; MacroCommand m_cmd; }; class PLANKERNEL_EXPORT AddRelationCmd : public NamedCommand { public: AddRelationCmd( Project &project, Relation *rel, const KUndo2MagicString& name = KUndo2MagicString() ); ~AddRelationCmd(); void execute(); void unexecute(); private: Relation *m_rel; Project &m_project; bool m_taken; }; class PLANKERNEL_EXPORT DeleteRelationCmd : public NamedCommand { public: DeleteRelationCmd( Project &project, Relation *rel, const KUndo2MagicString& name = KUndo2MagicString() ); ~DeleteRelationCmd(); void execute(); void unexecute(); private: Relation *m_rel; Project &m_project; bool m_taken; }; class PLANKERNEL_EXPORT ModifyRelationTypeCmd : public NamedCommand { public: ModifyRelationTypeCmd( Relation *rel, Relation::Type type, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Project *m_project; Relation *m_rel; Relation::Type m_newtype; Relation::Type m_oldtype; }; class PLANKERNEL_EXPORT ModifyRelationLagCmd : public NamedCommand { public: ModifyRelationLagCmd( Relation *rel, Duration lag, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Project *m_project; Relation *m_rel; Duration m_newlag; Duration m_oldlag; }; class PLANKERNEL_EXPORT AddResourceRequestCmd : public NamedCommand { public: AddResourceRequestCmd( ResourceGroupRequest *group, ResourceRequest *request, const KUndo2MagicString& name = KUndo2MagicString() ); ~AddResourceRequestCmd(); void execute(); void unexecute(); private: ResourceGroupRequest *m_group; ResourceRequest *m_request; bool m_mine; }; class PLANKERNEL_EXPORT RemoveResourceRequestCmd : public NamedCommand { public: RemoveResourceRequestCmd( ResourceGroupRequest *group, ResourceRequest *request, const KUndo2MagicString& name = KUndo2MagicString() ); ~RemoveResourceRequestCmd(); void execute(); void unexecute(); private: ResourceGroupRequest *m_group; ResourceRequest *m_request; bool m_mine; }; class PLANKERNEL_EXPORT ModifyResourceRequestUnitsCmd : public NamedCommand { public: ModifyResourceRequestUnitsCmd( ResourceRequest *request, int oldvalue, int newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ResourceRequest *m_request; int m_oldvalue, m_newvalue; }; class PLANKERNEL_EXPORT ModifyResourceRequestRequiredCmd : public NamedCommand { public: ModifyResourceRequestRequiredCmd( ResourceRequest *request, const QList &value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ResourceRequest *m_request; QList m_oldvalue, m_newvalue; }; class PLANKERNEL_EXPORT ModifyResourceGroupRequestUnitsCmd : public NamedCommand { public: ModifyResourceGroupRequestUnitsCmd( ResourceGroupRequest *request, int oldvalue, int newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ResourceGroupRequest *m_request; int m_oldvalue, m_newvalue; }; class PLANKERNEL_EXPORT ModifyEstimateCmd : public NamedCommand { public: ModifyEstimateCmd( Node &node, double oldvalue, double newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); ~ModifyEstimateCmd(); void execute(); void unexecute(); private: Estimate *m_estimate; double m_oldvalue, m_newvalue; int m_optimistic, m_pessimistic; MacroCommand *m_cmd; }; class PLANKERNEL_EXPORT EstimateModifyOptimisticRatioCmd : public NamedCommand { public: EstimateModifyOptimisticRatioCmd( Node &node, int oldvalue, int newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Estimate *m_estimate; int m_oldvalue, m_newvalue; }; class PLANKERNEL_EXPORT EstimateModifyPessimisticRatioCmd : public NamedCommand { public: EstimateModifyPessimisticRatioCmd( Node &node, int oldvalue, int newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Estimate *m_estimate; int m_oldvalue, m_newvalue; }; class PLANKERNEL_EXPORT ModifyEstimateTypeCmd : public NamedCommand { public: ModifyEstimateTypeCmd( Node &node, int oldvalue, int newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Estimate *m_estimate; int m_oldvalue, m_newvalue; }; class PLANKERNEL_EXPORT ModifyEstimateUnitCmd : public NamedCommand { public: ModifyEstimateUnitCmd( Node &node, Duration::Unit oldvalue, Duration::Unit newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Estimate *m_estimate; Duration::Unit m_oldvalue, m_newvalue; }; class PLANKERNEL_EXPORT EstimateModifyRiskCmd : public NamedCommand { public: EstimateModifyRiskCmd( Node &node, int oldvalue, int newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Estimate *m_estimate; int m_oldvalue, m_newvalue; }; class PLANKERNEL_EXPORT ModifyEstimateCalendarCmd : public NamedCommand { public: ModifyEstimateCalendarCmd( Node &node, Calendar *oldvalue, Calendar *newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Estimate *m_estimate; Calendar *m_oldvalue, *m_newvalue; }; class PLANKERNEL_EXPORT AddResourceGroupRequestCmd : public NamedCommand { public: AddResourceGroupRequestCmd( Task &task, ResourceGroupRequest *request, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Task &m_task; ResourceGroupRequest *m_request; bool m_mine; }; class PLANKERNEL_EXPORT RemoveResourceGroupRequestCmd : public NamedCommand { public: explicit RemoveResourceGroupRequestCmd( ResourceGroupRequest *request, const KUndo2MagicString& name = KUndo2MagicString() ); RemoveResourceGroupRequestCmd( Task &task, ResourceGroupRequest *request, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Task &m_task; ResourceGroupRequest *m_request; bool m_mine; }; class PLANKERNEL_EXPORT AddResourceCmd : public NamedCommand { public: AddResourceCmd( ResourceGroup *group, Resource *resource, const KUndo2MagicString& name = KUndo2MagicString() ); ~AddResourceCmd(); void execute(); void unexecute(); protected: ResourceGroup *m_group; Resource *m_resource; int m_index; bool m_mine; }; class PLANKERNEL_EXPORT RemoveResourceCmd : public AddResourceCmd { public: RemoveResourceCmd( ResourceGroup *group, Resource *resource, const KUndo2MagicString& name = KUndo2MagicString() ); ~RemoveResourceCmd(); void execute(); void unexecute(); private: QList m_requests; QList m_appointments; MacroCommand m_cmd; }; class PLANKERNEL_EXPORT MoveResourceCmd : public NamedCommand { public: MoveResourceCmd( ResourceGroup *group, Resource *resource, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Project &m_project; Resource *m_resource; ResourceGroup *m_oldvalue, *m_newvalue; MacroCommand cmd; }; class PLANKERNEL_EXPORT ModifyResourceNameCmd : public NamedCommand { public: ModifyResourceNameCmd( Resource *resource, const QString& value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; QString m_newvalue; QString m_oldvalue; }; class PLANKERNEL_EXPORT ModifyResourceInitialsCmd : public NamedCommand { public: ModifyResourceInitialsCmd( Resource *resource, const QString& value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; QString m_newvalue; QString m_oldvalue; }; class PLANKERNEL_EXPORT ModifyResourceEmailCmd : public NamedCommand { public: ModifyResourceEmailCmd( Resource *resource, const QString& value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; QString m_newvalue; QString m_oldvalue; }; class PLANKERNEL_EXPORT ModifyResourceAutoAllocateCmd : public NamedCommand { public: ModifyResourceAutoAllocateCmd( Resource *resource, bool value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; bool m_newvalue; bool m_oldvalue; }; class PLANKERNEL_EXPORT ModifyResourceTypeCmd : public NamedCommand { public: ModifyResourceTypeCmd( Resource *resource, int value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; int m_newvalue; int m_oldvalue; }; class PLANKERNEL_EXPORT ModifyResourceUnitsCmd : public NamedCommand { public: ModifyResourceUnitsCmd( Resource *resource, int value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; int m_newvalue; int m_oldvalue; }; class PLANKERNEL_EXPORT ModifyResourceAvailableFromCmd : public NamedCommand { public: ModifyResourceAvailableFromCmd( Resource *resource, const QDateTime& value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; QDateTime m_newvalue; DateTime m_oldvalue; QTimeZone m_timeZone; }; class PLANKERNEL_EXPORT ModifyResourceAvailableUntilCmd : public NamedCommand { public: ModifyResourceAvailableUntilCmd( Resource *resource, const QDateTime& value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; QDateTime m_newvalue; DateTime m_oldvalue; QTimeZone m_timeZone; }; class PLANKERNEL_EXPORT ModifyResourceNormalRateCmd : public NamedCommand { public: ModifyResourceNormalRateCmd( Resource *resource, double value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; double m_newvalue; double m_oldvalue; }; class PLANKERNEL_EXPORT ModifyResourceOvertimeRateCmd : public NamedCommand { public: ModifyResourceOvertimeRateCmd( Resource *resource, double value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; double m_newvalue; double m_oldvalue; }; class PLANKERNEL_EXPORT ModifyResourceCalendarCmd : public NamedCommand { public: ModifyResourceCalendarCmd( Resource *resource, Calendar *value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; Calendar *m_newvalue; Calendar *m_oldvalue; }; class PLANKERNEL_EXPORT ModifyRequiredResourcesCmd : public NamedCommand { public: ModifyRequiredResourcesCmd( Resource *resource, const QStringList &value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; QStringList m_newvalue; QStringList m_oldvalue; }; class PLANKERNEL_EXPORT ModifyResourceAccountCmd : public NamedCommand { public: ModifyResourceAccountCmd( Resource *resource, Account *account, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; Account *m_newvalue; Account *m_oldvalue; }; class PLANKERNEL_EXPORT AddResourceTeamCmd : public NamedCommand { public: AddResourceTeamCmd( Resource *team, const QString &member, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_team; QString m_member; }; class PLANKERNEL_EXPORT RemoveResourceTeamCmd : public NamedCommand { public: RemoveResourceTeamCmd( Resource *team, const QString &member, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_team; QString m_member; }; class PLANKERNEL_EXPORT RemoveResourceGroupCmd : public NamedCommand { public: RemoveResourceGroupCmd( Project *project, ResourceGroup *group, const KUndo2MagicString& name = KUndo2MagicString() ); ~RemoveResourceGroupCmd(); void execute(); void unexecute(); protected: ResourceGroup *m_group; Project *m_project; int m_index; bool m_mine; MacroCommand *m_cmd; }; class PLANKERNEL_EXPORT AddResourceGroupCmd : public RemoveResourceGroupCmd { public: AddResourceGroupCmd( Project *project, ResourceGroup *group, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); }; class PLANKERNEL_EXPORT ModifyResourceGroupNameCmd : public NamedCommand { public: ModifyResourceGroupNameCmd( ResourceGroup *group, const QString& value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ResourceGroup *m_group; QString m_newvalue; QString m_oldvalue; }; class PLANKERNEL_EXPORT ModifyResourceGroupTypeCmd : public NamedCommand { public: ModifyResourceGroupTypeCmd( ResourceGroup *group, int value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ResourceGroup *m_group; int m_newvalue; int m_oldvalue; }; class PLANKERNEL_EXPORT ModifyCompletionEntrymodeCmd : public NamedCommand { public: ModifyCompletionEntrymodeCmd( Completion &completion, Completion::Entrymode value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Completion &m_completion; Completion::Entrymode oldvalue; Completion::Entrymode newvalue; }; class PLANKERNEL_EXPORT ModifyCompletionStartedCmd : public NamedCommand { public: ModifyCompletionStartedCmd( Completion &completion, bool value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Completion &m_completion; bool oldvalue; bool newvalue; }; class PLANKERNEL_EXPORT ModifyCompletionFinishedCmd : public NamedCommand { public: ModifyCompletionFinishedCmd( Completion &completion, bool value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Completion &m_completion; bool oldvalue; bool newvalue; }; class PLANKERNEL_EXPORT ModifyCompletionStartTimeCmd : public NamedCommand { public: ModifyCompletionStartTimeCmd( Completion &completion, const QDateTime &value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Completion &m_completion; DateTime oldvalue; QDateTime newvalue; QTimeZone m_timeZone; }; class PLANKERNEL_EXPORT ModifyCompletionFinishTimeCmd : public NamedCommand { public: ModifyCompletionFinishTimeCmd( Completion &completion, const QDateTime &value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Completion &m_completion; DateTime oldvalue; QDateTime newvalue; QTimeZone m_timeZone; }; class PLANKERNEL_EXPORT AddCompletionEntryCmd : public NamedCommand { public: AddCompletionEntryCmd( Completion &completion, const QDate &date, Completion::Entry *value, const KUndo2MagicString& name = KUndo2MagicString() ); ~AddCompletionEntryCmd(); void execute(); void unexecute(); private: Completion &m_completion; QDate m_date; Completion::Entry *newvalue; bool m_newmine; }; class PLANKERNEL_EXPORT RemoveCompletionEntryCmd : public NamedCommand { public: RemoveCompletionEntryCmd( Completion &completion, const QDate& date, const KUndo2MagicString& name = KUndo2MagicString() ); ~RemoveCompletionEntryCmd(); void execute(); void unexecute(); private: Completion &m_completion; QDate m_date; Completion::Entry *value; bool m_mine; }; class PLANKERNEL_EXPORT ModifyCompletionEntryCmd : public NamedCommand { public: ModifyCompletionEntryCmd( Completion &completion, const QDate &date, Completion::Entry *value, const KUndo2MagicString& name = KUndo2MagicString() ); ~ModifyCompletionEntryCmd(); void execute(); void unexecute(); private: MacroCommand *cmd; }; class PLANKERNEL_EXPORT ModifyCompletionPercentFinishedCmd : public NamedCommand { public: ModifyCompletionPercentFinishedCmd( Completion &completion, const QDate &date, int value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Completion &m_completion; QDate m_date; int m_newvalue, m_oldvalue; MacroCommand cmd; }; class PLANKERNEL_EXPORT ModifyCompletionRemainingEffortCmd : public NamedCommand { public: ModifyCompletionRemainingEffortCmd( Completion &completion, const QDate &date, const Duration &value, const KUndo2MagicString &name = KUndo2MagicString() ); void execute(); void unexecute(); private: Completion &m_completion; QDate m_date; Duration m_newvalue, m_oldvalue; MacroCommand cmd; }; class PLANKERNEL_EXPORT ModifyCompletionActualEffortCmd : public NamedCommand { public: ModifyCompletionActualEffortCmd( Completion &completion, const QDate &date, const Duration &value, const KUndo2MagicString &name = KUndo2MagicString() ); void execute(); void unexecute(); private: Completion &m_completion; QDate m_date; Duration m_newvalue, m_oldvalue; MacroCommand cmd; }; /** * Add used effort for @p resource. * Note that the used effort definition in @p value must contain entries for *all* dates. * If used effort is already defined it will be replaced. */ class PLANKERNEL_EXPORT AddCompletionUsedEffortCmd : public NamedCommand { public: AddCompletionUsedEffortCmd( Completion &completion, const Resource *resource, Completion::UsedEffort *value, const KUndo2MagicString& name = KUndo2MagicString() ); ~AddCompletionUsedEffortCmd(); void execute(); void unexecute(); private: Completion &m_completion; const Resource *m_resource; Completion::UsedEffort *oldvalue; Completion::UsedEffort *newvalue; bool m_newmine, m_oldmine; }; class PLANKERNEL_EXPORT AddCompletionActualEffortCmd : public NamedCommand { public: AddCompletionActualEffortCmd( Completion::UsedEffort &ue, const QDate &date, const Completion::UsedEffort::ActualEffort &value, const KUndo2MagicString& name = KUndo2MagicString() ); ~AddCompletionActualEffortCmd(); void execute(); void unexecute(); private: Completion::UsedEffort &m_usedEffort; QDate m_date; Completion::UsedEffort::ActualEffort oldvalue; Completion::UsedEffort::ActualEffort newvalue; }; class PLANKERNEL_EXPORT AddAccountCmd : public NamedCommand { public: AddAccountCmd( Project &project, Account *account, Account *parent = 0, int index = -1, const KUndo2MagicString& name = KUndo2MagicString() ); AddAccountCmd( Project &project, Account *account, const QString& parent, int index = -1, const KUndo2MagicString& name = KUndo2MagicString() ); ~AddAccountCmd(); void execute(); void unexecute(); protected: bool m_mine; private: Project &m_project; Account *m_account; Account *m_parent; int m_index; QString m_parentName; }; class PLANKERNEL_EXPORT RemoveAccountCmd : public NamedCommand { public: RemoveAccountCmd( Project &project, Account *account, const KUndo2MagicString& name = KUndo2MagicString() ); ~RemoveAccountCmd(); void execute(); void unexecute(); private: Project &m_project; Account *m_account; Account *m_parent; int m_index; bool m_isDefault; bool m_mine; MacroCommand m_cmd; }; class PLANKERNEL_EXPORT RenameAccountCmd : public NamedCommand { public: RenameAccountCmd( Account *account, const QString& value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Account *m_account; QString m_oldvalue; QString m_newvalue; }; class PLANKERNEL_EXPORT ModifyAccountDescriptionCmd : public NamedCommand { public: ModifyAccountDescriptionCmd( Account *account, const QString& value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Account *m_account; QString m_oldvalue; QString m_newvalue; }; class PLANKERNEL_EXPORT NodeModifyStartupCostCmd : public NamedCommand { public: NodeModifyStartupCostCmd( Node &node, double value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; double m_oldvalue; double m_newvalue; }; class PLANKERNEL_EXPORT NodeModifyShutdownCostCmd : public NamedCommand { public: NodeModifyShutdownCostCmd( Node &node, double value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; double m_oldvalue; double m_newvalue; }; class PLANKERNEL_EXPORT NodeModifyRunningAccountCmd : public NamedCommand { public: NodeModifyRunningAccountCmd( Node &node, Account *oldvalue, Account *newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; Account *m_oldvalue; Account *m_newvalue; }; class PLANKERNEL_EXPORT NodeModifyStartupAccountCmd : public NamedCommand { public: NodeModifyStartupAccountCmd( Node &node, Account *oldvalue, Account *newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; Account *m_oldvalue; Account *m_newvalue; }; class PLANKERNEL_EXPORT NodeModifyShutdownAccountCmd : public NamedCommand { public: NodeModifyShutdownAccountCmd( Node &node, Account *oldvalue, Account *newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Node &m_node; Account *m_oldvalue; Account *m_newvalue; }; class PLANKERNEL_EXPORT ModifyDefaultAccountCmd : public NamedCommand { public: ModifyDefaultAccountCmd( Accounts &acc, Account *oldvalue, Account *newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Accounts &m_accounts; Account *m_oldvalue; Account *m_newvalue; }; class PLANKERNEL_EXPORT ResourceModifyAccountCmd : public NamedCommand { public: ResourceModifyAccountCmd( Resource &resource, Account *oldvalue, Account *newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource &m_resource; Account *m_oldvalue; Account *m_newvalue; }; class PLANKERNEL_EXPORT ProjectModifyConstraintCmd : public NamedCommand { public: ProjectModifyConstraintCmd( Project &node, Node::ConstraintType c, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Project &m_node; Node::ConstraintType newConstraint; Node::ConstraintType oldConstraint; }; class PLANKERNEL_EXPORT ProjectModifyStartTimeCmd : public NamedCommand { public: ProjectModifyStartTimeCmd( Project &node, const QDateTime& dt, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Project &m_node; QDateTime newTime; DateTime oldTime; QTimeZone m_timeZone; }; class PLANKERNEL_EXPORT ProjectModifyEndTimeCmd : public NamedCommand { public: ProjectModifyEndTimeCmd( Project &project, const QDateTime& dt, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Project &m_node; QDateTime newTime; DateTime oldTime; QTimeZone m_timeZone; }; +class PLANKERNEL_EXPORT SwapScheduleManagerCmd : public NamedCommand +{ +public: + SwapScheduleManagerCmd( Project &project, ScheduleManager *from, ScheduleManager *to, const KUndo2MagicString& name = KUndo2MagicString() ); + ~SwapScheduleManagerCmd(); + void execute(); + void unexecute(); + +protected: + Project &m_node; + ScheduleManager *m_from; + ScheduleManager *m_to; +}; class PLANKERNEL_EXPORT AddScheduleManagerCmd : public NamedCommand { public: AddScheduleManagerCmd( Project &project, ScheduleManager *sm, int index = -1, const KUndo2MagicString& name = KUndo2MagicString() ); AddScheduleManagerCmd( ScheduleManager *parent, ScheduleManager *sm, int index = -1, const KUndo2MagicString& name = KUndo2MagicString() ); ~AddScheduleManagerCmd(); void execute(); void unexecute(); protected: Project &m_node; ScheduleManager *m_parent; ScheduleManager *m_sm; int m_index; MainSchedule *m_exp; bool m_mine; }; class PLANKERNEL_EXPORT DeleteScheduleManagerCmd : public AddScheduleManagerCmd { public: DeleteScheduleManagerCmd( Project &project, ScheduleManager *sm, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: MacroCommand cmd; }; class PLANKERNEL_EXPORT MoveScheduleManagerCmd : public NamedCommand { public: MoveScheduleManagerCmd( ScheduleManager *sm, ScheduleManager *newparent, int newindex, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ScheduleManager *m_sm; ScheduleManager *m_oldparent; int m_oldindex; ScheduleManager *m_newparent; int m_newindex; MacroCommand m_cmd; }; class PLANKERNEL_EXPORT ModifyScheduleManagerNameCmd : public NamedCommand { public: ModifyScheduleManagerNameCmd( ScheduleManager &sm, const QString& value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ScheduleManager &m_sm; QString oldvalue, newvalue; }; class PLANKERNEL_EXPORT ModifyScheduleManagerAllowOverbookingCmd : public NamedCommand { public: ModifyScheduleManagerAllowOverbookingCmd( ScheduleManager &sm, bool value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ScheduleManager &m_sm; bool oldvalue, newvalue; }; class PLANKERNEL_EXPORT ModifyScheduleManagerDistributionCmd : public NamedCommand { public: ModifyScheduleManagerDistributionCmd( ScheduleManager &sm, bool value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ScheduleManager &m_sm; bool oldvalue, newvalue; }; class PLANKERNEL_EXPORT CalculateScheduleCmd : public NamedCommand { public: CalculateScheduleCmd( Project &project, ScheduleManager *sm, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Project &m_node; QPointer m_sm; bool m_first; MainSchedule *m_oldexpected; MainSchedule *m_newexpected; + MacroCommand preCmd; + MacroCommand postCmd; }; class PLANKERNEL_EXPORT BaselineScheduleCmd : public NamedCommand { public: explicit BaselineScheduleCmd( ScheduleManager &sm, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ScheduleManager &m_sm; }; class PLANKERNEL_EXPORT ResetBaselineScheduleCmd : public NamedCommand { public: explicit ResetBaselineScheduleCmd( ScheduleManager &sm, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ScheduleManager &m_sm; }; class PLANKERNEL_EXPORT ModifyScheduleManagerSchedulingDirectionCmd : public NamedCommand { public: ModifyScheduleManagerSchedulingDirectionCmd( ScheduleManager &sm, bool value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ScheduleManager &m_sm; bool oldvalue, newvalue; }; class PLANKERNEL_EXPORT ModifyScheduleManagerSchedulerCmd : public NamedCommand { public: ModifyScheduleManagerSchedulerCmd( ScheduleManager &sm, int value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ScheduleManager &m_sm; int oldvalue, newvalue; }; class PLANKERNEL_EXPORT ModifyScheduleManagerSchedulingGranularityCmd : public NamedCommand { public: ModifyScheduleManagerSchedulingGranularityCmd( ScheduleManager &sm, int value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: ScheduleManager &m_sm; int oldvalue, newvalue; }; class PLANKERNEL_EXPORT ModifyStandardWorktimeYearCmd : public NamedCommand { public: ModifyStandardWorktimeYearCmd( StandardWorktime *wt, double oldvalue, double newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: StandardWorktime *swt; double m_oldvalue; double m_newvalue; }; class PLANKERNEL_EXPORT ModifyStandardWorktimeMonthCmd : public NamedCommand { public: ModifyStandardWorktimeMonthCmd( StandardWorktime *wt, double oldvalue, double newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: StandardWorktime *swt; double m_oldvalue; double m_newvalue; }; class PLANKERNEL_EXPORT ModifyStandardWorktimeWeekCmd : public NamedCommand { public: ModifyStandardWorktimeWeekCmd( StandardWorktime *wt, double oldvalue, double newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: StandardWorktime *swt; double m_oldvalue; double m_newvalue; }; class PLANKERNEL_EXPORT ModifyStandardWorktimeDayCmd : public NamedCommand { public: ModifyStandardWorktimeDayCmd( StandardWorktime *wt, double oldvalue, double newvalue, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: StandardWorktime *swt; double m_oldvalue; double m_newvalue; }; class PLANKERNEL_EXPORT DocumentAddCmd : public NamedCommand { public: DocumentAddCmd( Documents& docs, Document *value, const KUndo2MagicString& name = KUndo2MagicString() ); ~DocumentAddCmd(); void execute(); void unexecute(); private: Documents& m_docs; Document *m_value; bool m_mine; }; class PLANKERNEL_EXPORT DocumentRemoveCmd : public NamedCommand { public: DocumentRemoveCmd( Documents& docs, Document *value, const KUndo2MagicString& name = KUndo2MagicString() ); ~DocumentRemoveCmd(); void execute(); void unexecute(); private: Documents& m_docs; Document *m_value; bool m_mine; }; class PLANKERNEL_EXPORT DocumentModifyUrlCmd : public NamedCommand { public: DocumentModifyUrlCmd( Document *doc, const QUrl &url, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Document *m_doc; QUrl m_value; QUrl m_oldvalue; }; class PLANKERNEL_EXPORT DocumentModifyNameCmd : public NamedCommand { public: DocumentModifyNameCmd( Document *doc, const QString &value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Document *m_doc; QString m_value; QString m_oldvalue; }; class PLANKERNEL_EXPORT DocumentModifyTypeCmd : public NamedCommand { public: DocumentModifyTypeCmd( Document *doc, Document::Type value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Document *m_doc; Document::Type m_value; Document::Type m_oldvalue; }; class PLANKERNEL_EXPORT DocumentModifyStatusCmd : public NamedCommand { public: DocumentModifyStatusCmd( Document *doc, const QString &value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Document *m_doc; QString m_value; QString m_oldvalue; }; class PLANKERNEL_EXPORT DocumentModifySendAsCmd : public NamedCommand { public: DocumentModifySendAsCmd( Document *doc, const Document::SendAs value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Document *m_doc; Document::SendAs m_value; Document::SendAs m_oldvalue; }; class PLANKERNEL_EXPORT WBSDefinitionModifyCmd : public NamedCommand { public: WBSDefinitionModifyCmd( Project &project, const WBSDefinition value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Project &m_project; WBSDefinition m_newvalue, m_oldvalue; }; class PLANKERNEL_EXPORT InsertProjectCmd : public MacroCommand { public: InsertProjectCmd( Project &project, Node *parent, Node *after, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); protected: void addAccounts( Account *account, Account *parent, QList &unused, QMap &all ); void addCalendars( Calendar *calendar, Calendar *parent, QList &unused, QMap &all ); void addChildNodes( Node *node ); private: Project *m_project; Node *m_parent; Node *m_after; }; class PLANKERNEL_EXPORT WorkPackageAddCmd : public NamedCommand { public: WorkPackageAddCmd( Project *project, Node *node, WorkPackage *wp, const KUndo2MagicString& name = KUndo2MagicString() ); ~WorkPackageAddCmd(); void execute(); void unexecute(); private: Project *m_project; Node *m_node; WorkPackage *m_wp; bool m_mine; }; class PLANKERNEL_EXPORT ModifyProjectLocaleCmd : public MacroCommand { public: ModifyProjectLocaleCmd( Project &project, const KUndo2MagicString &name ); void execute(); void unexecute(); private: Project &m_project; }; class PLANKERNEL_EXPORT ModifyCurrencySymolCmd : public NamedCommand { public: ModifyCurrencySymolCmd( Locale *locale, const QString &value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Locale *m_locale; QString m_newvalue; QString m_oldvalue; }; class PLANKERNEL_EXPORT ModifyCurrencyFractionalDigitsCmd : public NamedCommand { public: ModifyCurrencyFractionalDigitsCmd( Locale *locale, int value, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Locale *m_locale; int m_newvalue; int m_oldvalue; }; class PLANKERNEL_EXPORT AddExternalAppointmentCmd : public NamedCommand { public: AddExternalAppointmentCmd( Resource *resource, const QString &pid, const QString &pname, const QDateTime &start, const QDateTime &end, double load, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Resource *m_resource; QString m_pid; QString m_pname; QDateTime m_start; QDateTime m_end; double m_load; }; class PLANKERNEL_EXPORT ClearExternalAppointmentCmd : public NamedCommand { public: ClearExternalAppointmentCmd( Resource *resource, const QString &pid, const KUndo2MagicString& name = KUndo2MagicString() ); ~ClearExternalAppointmentCmd(); void execute(); void unexecute(); private: Resource *m_resource; QString m_pid; Appointment *m_appointments; }; class PLANKERNEL_EXPORT ClearAllExternalAppointmentsCmd : public NamedCommand { public: explicit ClearAllExternalAppointmentsCmd( Project *project, const KUndo2MagicString& name = KUndo2MagicString() ); void execute(); void unexecute(); private: Project *m_project; MacroCommand m_cmd; }; class PLANKERNEL_EXPORT SharedResourcesFileCmd : public NamedCommand { public: explicit SharedResourcesFileCmd(Project *project, const QString &newValue, const KUndo2MagicString& name = KUndo2MagicString()); void execute(); void unexecute(); private: Project *m_project; QString m_oldValue; QString m_newValue; }; class PLANKERNEL_EXPORT UseSharedResourcesCmd : public NamedCommand { public: explicit UseSharedResourcesCmd(Project *project, bool newValue, const KUndo2MagicString& name = KUndo2MagicString()); void execute(); void unexecute(); private: Project *m_project; bool m_oldValue; bool m_newValue; }; class PLANKERNEL_EXPORT SharedProjectsUrlCmd : public NamedCommand { public: explicit SharedProjectsUrlCmd(Project *project, const QUrl &newValue, const KUndo2MagicString& name = KUndo2MagicString()); void execute(); void unexecute(); private: Project *m_project; QUrl m_oldValue; QUrl m_newValue; }; class PLANKERNEL_EXPORT LoadProjectsAtStartupCmd : public NamedCommand { public: explicit LoadProjectsAtStartupCmd(Project *project, bool newValue, const KUndo2MagicString& name = KUndo2MagicString()); void execute(); void unexecute(); private: Project *m_project; bool m_oldValue; bool m_newValue; }; } //KPlato namespace #endif //COMMAND_H diff --git a/src/libs/kernel/kptproject.cpp b/src/libs/kernel/kptproject.cpp index b43b04bc..5b4ebe19 100644 --- a/src/libs/kernel/kptproject.cpp +++ b/src/libs/kernel/kptproject.cpp @@ -1,2964 +1,2969 @@ /* This file is part of the KDE project Copyright (C) 2001 Thomas zander Copyright (C) 2004 - 2010, 2012 Dag Andersen Copyright (C) 2007 Florian Piquemal Copyright (C) 2007 Alexis Ménard 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 "kptproject.h" #include "kptlocale.h" #include "kptappointment.h" #include "kpttask.h" #include "kptdatetime.h" #include "kpteffortcostmap.h" #include "kptschedule.h" #include "kptwbsdefinition.h" #include "kptxmlloaderobject.h" #include "XmlSaveContext.h" #include "kptschedulerplugin.h" #include "kptdebug.h" #include #include #include #include #include #include namespace KPlato { Project::Project( Node *parent ) : Node( parent ), m_accounts( *this ), m_defaultCalendar( 0 ), m_config( &emptyConfig ), m_schedulerPlugins(), m_useSharedResources(false), m_sharedResourcesLoaded(false), m_loadProjectsAtStartup(false) { //debugPlan<<"("<setDefaultValues(*this); } Project::Project( ConfigBase &config, bool useDefaultValues, Node *parent ) : Node( parent ), m_accounts( *this ), m_defaultCalendar( 0 ), m_config( &config ), m_schedulerPlugins(), m_useSharedResources(false), m_sharedResourcesLoaded(false), m_loadProjectsAtStartup(false) { debugPlan<<"("<setDefaultValues(*this); } } void Project::init() { m_refCount = 1; // always used by creator m_constraint = Node::MustStartOn; m_standardWorktime = new StandardWorktime(); m_timeZone = QTimeZone::systemTimeZone(); // local timezone as default //debugPlan<= 0 ); if ( m_refCount <= 0 ) { emit aboutToBeDeleted(); deleteLater(); } } Project::~Project() { debugPlan<<"("<blockChanged(); } for (Resource *r : qAsConst(resourceIdDict)) { r->blockChanged(); } for (ResourceGroup *g : qAsConst(resourceGroupIdDict)) { g->blockChanged(); } delete m_standardWorktime; while ( !m_resourceGroups.isEmpty() ) delete m_resourceGroups.takeFirst(); while ( !m_calendars.isEmpty() ) delete m_calendars.takeFirst(); while ( !m_managers.isEmpty() ) delete m_managers.takeFirst(); m_config = 0; //not mine, don't delete } int Project::type() const { return Node::Type_Project; } void Project::generateUniqueNodeIds() { foreach ( Node *n, nodeIdDict ) { debugPlan<name()<<"old"<id(); QString uid = uniqueNodeId(); nodeIdDict.remove( n->id() ); n->setId( uid ); nodeIdDict[ uid ] = n; debugPlan<name()<<"new"<id(); } } void Project::generateUniqueIds() { generateUniqueNodeIds(); foreach ( ResourceGroup *g, resourceGroupIdDict ) { if (g->isShared()) { continue; } resourceGroupIdDict.remove( g->id() ); g->setId( uniqueResourceGroupId() ); resourceGroupIdDict[ g->id() ] = g; } foreach ( Resource *r, resourceIdDict ) { if (r->isShared()) { continue; } resourceIdDict.remove( r->id() ); r->setId( uniqueResourceId() ); resourceIdDict[ r->id() ] = r; } foreach ( Calendar *c, calendarIdDict ) { if (c->isShared()) { continue; } calendarIdDict.remove( c->id() ); c->setId( uniqueCalendarId() ); calendarIdDict[ c->id() ] = c; } } void Project::calculate( Schedule *schedule, const DateTime &dt ) { if ( schedule == 0 ) { errorPlan << "Schedule == 0, cannot calculate"; return ; } m_currentSchedule = schedule; calculate( dt ); } void Project::calculate( const DateTime &dt ) { if ( m_currentSchedule == 0 ) { errorPlan << "No current schedule to calculate"; return ; } stopcalculation = false; QLocale locale; DateTime time = dt.isValid() ? dt : DateTime( QDateTime::currentDateTime() ); MainSchedule *cs = static_cast( m_currentSchedule ); Estimate::Use estType = ( Estimate::Use ) cs->type(); if ( type() == Type_Project ) { cs->setPhaseName( 0, i18n( "Init" ) ); cs->logInfo( i18n( "Schedule project from: %1", locale.toString(dt, QLocale::ShortFormat) ), 0 ); initiateCalculation( *cs ); initiateCalculationLists( *cs ); // must be after initiateCalculation() !! propagateEarliestStart( time ); // Calculate lateFinish from time. If a task has started, remainingEffort is used. cs->setPhaseName( 1, i18nc( "Schedule project forward", "Forward" ) ); cs->logInfo( i18n( "Calculate finish" ), 1 ); cs->lateFinish = calculateForward( estType ); cs->lateFinish = checkEndConstraints( cs->lateFinish ); propagateLatestFinish( cs->lateFinish ); // Calculate earlyFinish. If a task has started, remainingEffort is used. cs->setPhaseName( 2, i18nc( "Schedule project backward","Backward" ) ); cs->logInfo( i18n( "Calculate start" ), 2 ); calculateBackward( estType ); // Schedule. If a task has started, remainingEffort is used and appointments are copied from parent cs->setPhaseName( 3, i18n( "Schedule" ) ); cs->logInfo( i18n( "Schedule tasks forward" ), 3 ); cs->endTime = scheduleForward( cs->startTime, estType ); cs->logInfo( i18n( "Scheduled finish: %1", locale.toString(cs->endTime, QLocale::ShortFormat) ), 3 ); if ( cs->endTime > m_constraintEndTime ) { cs->logError( i18n( "Could not finish project in time: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 3 ); } else if ( cs->endTime == m_constraintEndTime ) { cs->logWarning( i18n( "Finished project exactly on time: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 3 ); } else { cs->logInfo( i18n( "Finished project before time: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 3 ); } calcCriticalPath( false ); calcResourceOverbooked(); cs->notScheduled = false; calcFreeFloat(); emit scheduleChanged( cs ); emit projectChanged(); } else if ( type() == Type_Subproject ) { warnPlan << "Subprojects not implemented"; } else { errorPlan << "Illegal project type: " << type(); } } void Project::calculate( ScheduleManager &sm ) { emit sigCalculationStarted( this, &sm ); sm.setScheduling( true ); m_progress = 0; int nodes = 0; foreach ( Node *n, nodeIdDict ) { if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) { nodes++; } } int maxprogress = nodes * 3; if ( sm.recalculate() ) { emit maxProgress( maxprogress ); sm.setMaxProgress( maxprogress ); incProgress(); if ( sm.parentManager() ) { sm.expected()->startTime = sm.parentManager()->expected()->startTime; sm.expected()->earlyStart = sm.parentManager()->expected()->earlyStart; } incProgress(); calculate( sm.expected(), sm.recalculateFrom() ); } else { emit maxProgress( maxprogress ); sm.setMaxProgress( maxprogress ); calculate( sm.expected() ); emit scheduleChanged( sm.expected() ); setCurrentSchedule( sm.expected()->id() ); } emit sigProgress( maxprogress ); emit sigCalculationFinished( this, &sm ); emit scheduleManagerChanged( &sm ); emit projectCalculated( &sm ); emit projectChanged(); sm.setScheduling( false ); } void Project::calculate( Schedule *schedule ) { if ( schedule == 0 ) { errorPlan << "Schedule == 0, cannot calculate"; return ; } m_currentSchedule = schedule; calculate(); } void Project::calculate() { if ( m_currentSchedule == 0 ) { errorPlan << "No current schedule to calculate"; return ; } stopcalculation = false; MainSchedule *cs = static_cast( m_currentSchedule ); bool backwards = false; if ( cs->manager() ) { backwards = cs->manager()->schedulingDirection(); } QLocale locale; Estimate::Use estType = ( Estimate::Use ) cs->type(); if ( type() == Type_Project ) { QTime timer; timer.start(); initiateCalculation( *cs ); initiateCalculationLists( *cs ); // must be after initiateCalculation() !! if ( ! backwards ) { cs->setPhaseName( 0, i18n( "Init" ) ); cs->logInfo( i18n( "Schedule project forward from: %1", locale.toString(m_constraintStartTime, QLocale::ShortFormat) ), 0 ); cs->startTime = m_constraintStartTime; cs->earlyStart = m_constraintStartTime; // Calculate from start time propagateEarliestStart( cs->earlyStart ); cs->setPhaseName( 1, i18nc( "Schedule project forward", "Forward" ) ); cs->logInfo( i18n( "Calculate late finish" ), 1 ); cs->lateFinish = calculateForward( estType ); // cs->lateFinish = checkEndConstraints( cs->lateFinish ); cs->logInfo( i18n( "Late finish calculated: %1", locale.toString(cs->lateFinish, QLocale::ShortFormat) ), 1 ); propagateLatestFinish( cs->lateFinish ); cs->setPhaseName( 2, i18nc( "Schedule project backward", "Backward" ) ); cs->logInfo( i18n( "Calculate early start" ), 2 ); calculateBackward( estType ); cs->setPhaseName( 3, i18n( "Schedule" ) ); cs->logInfo( i18n( "Schedule tasks forward" ), 3 ); cs->endTime = scheduleForward( cs->startTime, estType ); cs->duration = cs->endTime - cs->startTime; cs->logInfo( i18n( "Scheduled finish: %1", locale.toString(cs->endTime, QLocale::ShortFormat) ), 3 ); if ( cs->endTime > m_constraintEndTime ) { cs->constraintError = true; cs->logError( i18n( "Could not finish project in time: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 3 ); } else if ( cs->endTime == m_constraintEndTime ) { cs->logWarning( i18n( "Finished project exactly on time: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 3 ); } else { cs->logInfo( i18n( "Finished project before time: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 3 ); } calcCriticalPath( false ); } else { cs->setPhaseName( 0, i18n( "Init" ) ); cs->logInfo( i18n( "Schedule project backward from: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 0 ); // Calculate from end time propagateLatestFinish( m_constraintEndTime ); cs->setPhaseName( 1, i18nc( "Schedule project backward", "Backward" ) ); cs->logInfo( i18n( "Calculate early start" ), 1 ); cs->earlyStart = calculateBackward( estType ); // cs->earlyStart = checkStartConstraints( cs->earlyStart ); cs->logInfo( i18n( "Early start calculated: %1", locale.toString(cs->earlyStart, QLocale::ShortFormat) ), 1 ); propagateEarliestStart( cs->earlyStart ); cs->setPhaseName( 2, i18nc( "Schedule project forward", "Forward" ) ); cs->logInfo( i18n( "Calculate late finish" ), 2 ); cs->lateFinish = qMax( m_constraintEndTime, calculateForward( estType ) ); cs->logInfo( i18n( "Late finish calculated: %1", locale.toString(cs->lateFinish, QLocale::ShortFormat) ), 2 ); cs->setPhaseName( 3, i18n( "Schedule" ) ); cs->logInfo( i18n( "Schedule tasks backward" ), 3 ); cs->startTime = scheduleBackward( cs->lateFinish, estType ); cs->endTime = cs->startTime; foreach ( Node *n, allNodes() ) { if ( n->type() == Type_Task || n->type() == Type_Milestone ) { DateTime e = n->endTime( cs->id() ); if ( cs->endTime < e ) { cs->endTime = e; } } } if ( cs->endTime > m_constraintEndTime ) { cs->constraintError = true; cs->logError( i18n( "Failed to finish project within target time" ), 3 ); } cs->duration = cs->endTime - cs->startTime; cs->logInfo( i18n( "Scheduled start: %1, target time: %2", locale.toString(cs->startTime, QLocale::ShortFormat), locale.toString(m_constraintStartTime, QLocale::ShortFormat) ), 3 ); if ( cs->startTime < m_constraintStartTime ) { cs->constraintError = true; cs->logError( i18n( "Must start project early in order to finish in time: %1", locale.toString(m_constraintStartTime, QLocale::ShortFormat) ), 3 ); } else if ( cs->startTime == m_constraintStartTime ) { cs->logWarning( i18n( "Start project exactly on time: %1", locale.toString(m_constraintStartTime, QLocale::ShortFormat) ), 3 ); } else { cs->logInfo( i18n( "Can start project later than time: %1", locale.toString(m_constraintStartTime, QLocale::ShortFormat) ), 3 ); } calcCriticalPath( true ); } cs->logInfo( i18n( "Calculation took: %1", KFormat().formatDuration( timer.elapsed() ) ) ); // TODO: fix this uncertainty, manager should *always* be available if (cs->manager()) { finishCalculation(*(cs->manager())); } } else if ( type() == Type_Subproject ) { warnPlan << "Subprojects not implemented"; } else { errorPlan << "Illegal project type: " << type(); } } void Project::finishCalculation( ScheduleManager &sm ) { MainSchedule *cs = sm.expected(); if (nodeIdDict.count() > 1) { // calculate project duration cs->startTime = m_constraintEndTime; cs->endTime = m_constraintStartTime; for (const Node *n : qAsConst(nodeIdDict)) { cs->startTime = qMin(cs->startTime, n->startTime(cs->id())); cs->endTime = qMax(cs->endTime, n->endTime(cs->id())); } cs->duration = cs->endTime - cs->startTime; } calcCriticalPath( false ); calcResourceOverbooked(); cs->notScheduled = false; calcFreeFloat(); emit scheduleChanged( cs ); emit projectChanged(); debugPlan<startTime<endTime<<"-------------------------"; } void Project::setProgress( int progress, ScheduleManager *sm ) { m_progress = progress; if ( sm ) { sm->setProgress( progress ); } emit sigProgress( progress ); } void Project::setMaxProgress( int max, ScheduleManager *sm ) { if ( sm ) { sm->setMaxProgress( max ); } emitMaxProgress( max ); } void Project::incProgress() { m_progress += 1; emit sigProgress( m_progress ); } void Project::emitMaxProgress( int value ) { emit maxProgress( value ); } bool Project::calcCriticalPath( bool fromEnd ) { //debugPlan; MainSchedule *cs = static_cast( m_currentSchedule ); if ( cs == 0 ) { return false; } if ( fromEnd ) { QListIterator startnodes = cs->startNodes(); while ( startnodes.hasNext() ) { startnodes.next() ->calcCriticalPath( fromEnd ); } } else { QListIterator endnodes = cs->endNodes(); while ( endnodes.hasNext() ) { endnodes.next() ->calcCriticalPath( fromEnd ); } } calcCriticalPathList( cs ); return false; } void Project::calcCriticalPathList( MainSchedule *cs ) { //debugPlan<name(); cs->clearCriticalPathList(); foreach ( Node *n, allNodes() ) { if ( n->numDependParentNodes() == 0 && n->inCriticalPath( cs->id() ) ) { cs->addCriticalPath(); cs->addCriticalPathNode( n ); calcCriticalPathList( cs, n ); } } cs->criticalPathListCached = true; //debugPlan<<*(criticalPathList( cs->id() )); } void Project::calcCriticalPathList( MainSchedule *cs, Node *node ) { //debugPlan<name()<<", "<id(); bool newPath = false; QList lst = *( cs->currentCriticalPath() ); foreach ( Relation *r, node->dependChildNodes() ) { if ( r->child()->inCriticalPath( cs->id() ) ) { if ( newPath ) { cs->addCriticalPath( &lst ); //debugPlan<name()<<" new path"; } cs->addCriticalPathNode( r->child() ); calcCriticalPathList( cs, r->child() ); newPath = true; } } } const QList< QList > *Project::criticalPathList( long id ) { Schedule *s = schedule( id ); if ( s == 0 ) { //debugPlan<<"No schedule with id="<( s ); if ( ! ms->criticalPathListCached ) { initiateCalculationLists( *ms ); calcCriticalPathList( ms ); } return ms->criticalPathList(); } QList Project::criticalPath( long id, int index ) { Schedule *s = schedule( id ); if ( s == 0 ) { //debugPlan<<"No schedule with id="<(); } MainSchedule *ms = static_cast( s ); if ( ! ms->criticalPathListCached ) { initiateCalculationLists( *ms ); calcCriticalPathList( ms ); } return ms->criticalPath( index ); } DateTime Project::startTime( long id ) const { Schedule *s = schedule( id ); return s ? s->startTime : m_constraintStartTime; } DateTime Project::endTime( long id ) const { Schedule *s = schedule( id ); return s ? s->endTime : m_constraintEndTime; } Duration Project::duration( long id ) const { Schedule *s = schedule( id ); return s ? s->duration : Duration::zeroDuration; } Duration *Project::getRandomDuration() { return 0L; } DateTime Project::checkStartConstraints( const DateTime &dt ) const { DateTime t = dt; foreach ( Node *n, nodeIdDict ) { if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) { switch ( n->constraint() ) { case Node::FixedInterval: case Node::StartNotEarlier: case Node::MustStartOn: t = qMin( t, qMax( n->constraintStartTime(), m_constraintStartTime ) ); break; default: break; } } } return t; } DateTime Project::checkEndConstraints( const DateTime &dt ) const { DateTime t = dt; foreach ( Node *n, nodeIdDict ) { if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) { switch ( n->constraint() ) { case Node::FixedInterval: case Node::FinishNotLater: case Node::MustFinishOn: t = qMax( t, qMin( n->constraintEndTime(), m_constraintEndTime ) ); break; default: break; } } } return t; } #ifndef PLAN_NLOGDEBUG bool Project::checkParent( Node *n, const QList &list, QList &checked ) { if ( n->isStartNode() ) { debugPlan< lst = list; lst << n; foreach ( Relation *r, n->dependParentNodes() ) { if ( checked.contains( r ) ) { debugPlan<<"Depend:"<parent()<<": checked"; continue; } checked << r; if ( ! checkParent( r->parent(), lst, checked ) ) { return false; } } Task *t = static_cast( n ); foreach ( Relation *r, t->parentProxyRelations() ) { if ( checked.contains( r ) ) { debugPlan<<"Depend:"<parent()<<": checked"; continue; } checked << r; debugPlan<<"Proxy:"<parent()<<":"<parent(), lst, checked ) ) { return false; } } return true; } bool Project::checkChildren( Node *n, const QList &list, QList &checked ) { if ( n->isEndNode() ) { debugPlan< lst = list; lst << n; foreach ( Relation *r, n->dependChildNodes() ) { if ( checked.contains( r ) ) { debugPlan<<"Depend:"<parent()<<": checked"; continue; } checked << r; if ( ! checkChildren( r->child(), lst, checked ) ) { return false; } } Task *t = static_cast( n ); foreach ( Relation *r, t->childProxyRelations() ) { if ( checked.contains( r ) ) { debugPlan<<"Depend:"<parent()<<": checked"; continue; } debugPlan<<"Proxy:"<parent()<<":"<child(), lst, checked ) ) { return false; } } return true; } #endif void Project::tasksForward() { m_hardConstraints.clear(); m_softConstraints.clear(); m_terminalNodes.clear(); foreach ( Task *t, allTasks() ) { switch ( t->constraint() ) { case Node::MustStartOn: case Node::MustFinishOn: case Node::FixedInterval: m_hardConstraints.append( t ); break; case Node::StartNotEarlier: case Node::FinishNotLater: m_softConstraints.append( t ); break; default: if ( t->isEndNode() ) { m_terminalNodes.append( t ); } break; } } #ifndef PLAN_NLOGDEBUG debugPlan<<"End nodes:"< lst; QList rel; Q_ASSERT( checkParent( n, lst, rel ) ); Q_UNUSED( n ); } #endif } void Project::tasksBackward() { m_hardConstraints.clear(); m_softConstraints.clear(); m_terminalNodes.clear(); foreach ( Task *t, allTasks() ) { switch ( t->constraint() ) { case Node::MustStartOn: case Node::MustFinishOn: case Node::FixedInterval: m_hardConstraints.append( t ); break; case Node::StartNotEarlier: case Node::FinishNotLater: m_softConstraints.append( t ); break; default: if ( t->isStartNode() ) { m_terminalNodes.append( t ); } break; } } #ifndef PLAN_NLOGDEBUG debugPlan<<"Start nodes:"< lst; QList rel; Q_ASSERT( checkChildren( n, lst, rel ) ); Q_UNUSED( n ); } #endif } DateTime Project::calculateForward( int use ) { //debugPlan<( m_currentSchedule ); if ( cs == 0 ) { return finish; } if ( type() == Node::Type_Project ) { QTime timer; timer.start(); cs->logInfo( i18n( "Start calculating forward" ) ); m_visitedForward = true; if ( ! m_visitedBackward ) { // setup tasks tasksForward(); // Do all hard constrained first foreach ( Node *n, m_hardConstraints ) { cs->logDebug( "Calculate task with hard constraint:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateEarlyFinish( use ); // do not do predeccessors if ( time > finish ) { finish = time; } } // do the predeccessors foreach ( Node *n, m_hardConstraints ) { cs->logDebug( "Calculate predeccessors to hard constrained task:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateForward( use ); if ( time > finish ) { finish = time; } } // now try to schedule soft constrained *with* predeccessors foreach ( Node *n, m_softConstraints ) { cs->logDebug( "Calculate task with soft constraint:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateForward( use ); if ( time > finish ) { finish = time; } } // and then the rest using the end nodes to calculate everything (remaining) foreach ( Task *n, m_terminalNodes ) { cs->logDebug( "Calculate using end task:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateForward( use ); if ( time > finish ) { finish = time; } } } else { // tasks have been calculated backwards in this order foreach ( Node *n, cs->backwardNodes() ) { DateTime time = n->calculateForward( use ); if ( time > finish ) { finish = time; } } } cs->logInfo( i18n( "Finished calculating forward: %1 ms", timer.elapsed() ) ); } else { //TODO: subproject } return finish; } DateTime Project::calculateBackward( int use ) { //debugPlan<( m_currentSchedule ); if ( cs == 0 ) { return start; } if ( type() == Node::Type_Project ) { QTime timer; timer.start(); cs->logInfo( i18n( "Start calculating backward" ) ); m_visitedBackward = true; if ( ! m_visitedForward ) { // setup tasks tasksBackward(); // Do all hard constrained first foreach ( Task *n, m_hardConstraints ) { cs->logDebug( "Calculate task with hard constraint:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateLateStart( use ); // do not do predeccessors if ( ! start.isValid() || time < start ) { start = time; } } // then do the predeccessors foreach ( Task *n, m_hardConstraints ) { cs->logDebug( "Calculate predeccessors to hard constrained task:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateBackward( use ); if ( ! start.isValid() || time < start ) { start = time; } } // now try to schedule soft constrained *with* predeccessors foreach ( Task *n, m_softConstraints ) { cs->logDebug( "Calculate task with soft constraint:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateBackward( use ); if ( ! start.isValid() || time < start ) { start = time; } } // and then the rest using the start nodes to calculate everything (remaining) foreach ( Task *n, m_terminalNodes ) { cs->logDebug( "Calculate using start task:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateBackward( use ); if ( ! start.isValid() || time < start ) { start = time; } } } else { // tasks have been calculated forwards in this order foreach ( Node *n, cs->forwardNodes() ) { DateTime time = n->calculateBackward( use ); if ( ! start.isValid() || time < start ) { start = time; } } } cs->logInfo( i18n( "Finished calculating backward: %1 ms", timer.elapsed() ) ); } else { //TODO: subproject } return start; } DateTime Project::scheduleForward( const DateTime &earliest, int use ) { DateTime end; MainSchedule *cs = static_cast( m_currentSchedule ); if ( cs == 0 || stopcalculation ) { return DateTime(); } QTime timer; timer.start(); cs->logInfo( i18n( "Start scheduling forward" ) ); resetVisited(); // Schedule in the same order as calculated forward // Do all hard constrained first foreach ( Node *n, m_hardConstraints ) { cs->logDebug( "Schedule task with hard constraint:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->scheduleFromStartTime( use ); // do not do predeccessors if ( time > end ) { end = time; } } foreach ( Node *n, cs->forwardNodes() ) { cs->logDebug( "Schedule task:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->scheduleForward( earliest, use ); if ( time > end ) { end = time; } } // Fix summarytasks adjustSummarytask(); cs->logInfo( i18n( "Finished scheduling forward: %1 ms", timer.elapsed() ) ); foreach ( Node *n, allNodes() ) { if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) { Q_ASSERT( n->isScheduled() ); } } return end; } DateTime Project::scheduleBackward( const DateTime &latest, int use ) { DateTime start; MainSchedule *cs = static_cast( m_currentSchedule ); if ( cs == 0 || stopcalculation ) { return start; } QTime timer; timer.start(); cs->logInfo( i18n( "Start scheduling backward" ) ); resetVisited(); // Schedule in the same order as calculated backward // Do all hard constrained first foreach ( Node *n, m_hardConstraints ) { cs->logDebug( "Schedule task with hard constraint:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->scheduleFromEndTime( use ); // do not do predeccessors if ( ! start.isValid() || time < start ) { start = time; } } foreach ( Node *n, cs->backwardNodes() ) { cs->logDebug( "Schedule task:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->scheduleBackward( latest, use ); if ( ! start.isValid() || time < start ) { start = time; } } // Fix summarytasks adjustSummarytask(); cs->logInfo( i18n( "Finished scheduling backward: %1 ms", timer.elapsed() ) ); foreach ( Node *n, allNodes() ) { if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) { Q_ASSERT( n->isScheduled() ); } } return start; } void Project::adjustSummarytask() { MainSchedule *cs = static_cast( m_currentSchedule ); if ( cs == 0 || stopcalculation ) { return; } QListIterator it( cs->summaryTasks() ); while ( it.hasNext() ) { it.next() ->adjustSummarytask(); } } void Project::initiateCalculation( MainSchedule &sch ) { //debugPlan< git( m_resourceGroups ); while ( git.hasNext() ) { git.next() ->initiateCalculation( sch ); } Node::initiateCalculation( sch ); } void Project::initiateCalculationLists( MainSchedule &sch ) { //debugPlan< it = childNodeIterator(); while ( it.hasNext() ) { it.next() ->initiateCalculationLists( sch ); } } else { //TODO: subproject } } bool Project::load( KoXmlElement &element, XMLLoaderObject &status ) { //debugPlan<<"--->"; m_useSharedResources = false; // default should off in case old project // load locale first KoXmlNode n = element.firstChild(); for ( ; ! n.isNull(); n = n.nextSibling() ) { if ( ! n.isElement() ) { continue; } KoXmlElement e = n.toElement(); if ( e.tagName() == "locale" ) { Locale *l = locale(); l->setCurrencySymbol(e.attribute( "currency-symbol", "")); if ( e.hasAttribute( "currency-digits" ) ) { l->setMonetaryDecimalPlaces(e.attribute("currency-digits").toInt()); } QLocale::Language language = QLocale::AnyLanguage; QLocale::Country country = QLocale::AnyCountry; if (e.hasAttribute("language")) { language = static_cast(e.attribute("language").toInt()); } if (e.hasAttribute("country")) { country = static_cast(e.attribute("country").toInt()); } l->setCurrencyLocale(language, country); } else if (e.tagName() == "shared-resources") { m_useSharedResources = e.attribute("use", "0").toInt(); m_sharedResourcesFile = e.attribute("file"); m_sharedProjectsUrl = QUrl(e.attribute("projects-url")); m_loadProjectsAtStartup = (bool)e.attribute("projects-loadatstartup", "0").toInt(); } else if (e.tagName() == QLatin1String("documents")) { m_documents.load(e, status); } } QList cals; QString s; bool ok = false; setName( element.attribute( "name" ) ); removeId( m_id ); m_id = element.attribute( "id" ); registerNodeId( this ); m_priority = element.attribute(QStringLiteral("priority"), "0").toInt(); m_leader = element.attribute( "leader" ); m_description = element.attribute( "description" ); QTimeZone tz( element.attribute( "timezone" ).toLatin1() ); if ( tz.isValid() ) { m_timeZone = tz; } else warnPlan<<"No timezone specified, using default (local)"; status.setProjectTimeZone( m_timeZone ); // Allow for both numeric and text s = element.attribute( "scheduling", "0" ); m_constraint = ( Node::ConstraintType ) s.toInt( &ok ); if ( !ok ) setConstraint( s ); if ( m_constraint != Node::MustStartOn && m_constraint != Node::MustFinishOn ) { errorPlan << "Illegal constraint: " << constraintToString(); setConstraint( Node::MustStartOn ); } s = element.attribute( "start-time" ); if ( !s.isEmpty() ) m_constraintStartTime = DateTime::fromString( s, m_timeZone ); s = element.attribute( "end-time" ); if ( !s.isEmpty() ) m_constraintEndTime = DateTime::fromString( s, m_timeZone ); status.setProgress( 10 ); // Load the project children // Do calendars first, they only reference other calendars //debugPlan<<"Calendars--->"; n = element.firstChild(); for ( ; ! n.isNull(); n = n.nextSibling() ) { if ( ! n.isElement() ) { continue; } KoXmlElement e = n.toElement(); if ( e.tagName() == "calendar" ) { // Load the calendar. // Referenced by resources Calendar * child = new Calendar(); child->setProject( this ); if ( child->load( e, status ) ) { cals.append( child ); // temporary, reorder later } else { // TODO: Complain about this errorPlan << "Failed to load calendar"; delete child; } } else if ( e.tagName() == "standard-worktime" ) { // Load standard worktime StandardWorktime * child = new StandardWorktime(); if ( child->load( e, status ) ) { setStandardWorktime( child ); } else { errorPlan << "Failed to load standard worktime"; delete child; } } } // calendars references calendars in arbritary saved order bool added = false; do { added = false; QList lst; while ( !cals.isEmpty() ) { Calendar *c = cals.takeFirst(); c->m_blockversion = true; if ( c->parentId().isEmpty() ) { addCalendar( c, status.baseCalendar() ); // handle pre 0.6 version added = true; //debugPlan<<"added to project:"<name(); } else { Calendar *par = calendar( c->parentId() ); if ( par ) { par->m_blockversion = true; addCalendar( c, par ); added = true; //debugPlan<<"added:"<name()<<" to parent:"<name(); par->m_blockversion = false; } else { lst.append( c ); // treat later //debugPlan<<"treat later:"<name(); } } c->m_blockversion = false; } cals = lst; } while ( added ); if ( ! cals.isEmpty() ) { errorPlan<<"All calendars not saved!"; } //debugPlan<<"Calendars<---"; status.setProgress( 15 ); // Resource groups and resources, can reference calendars n = element.firstChild(); for ( ; ! n.isNull(); n = n.nextSibling() ) { if ( ! n.isElement() ) { continue; } KoXmlElement e = n.toElement(); if ( e.tagName() == "resource-group" ) { // Load the resources // References calendars ResourceGroup * child = new ResourceGroup(); if ( child->load( e, status ) ) { addResourceGroup( child ); } else { // TODO: Complain about this delete child; } } } status.setProgress( 20 ); // The main stuff n = element.firstChild(); for ( ; ! n.isNull(); n = n.nextSibling() ) { if ( ! n.isElement() ) { continue; } KoXmlElement e = n.toElement(); if ( e.tagName() == "project" ) { //debugPlan<<"Sub project--->"; /* // Load the subproject Project * child = new Project( this ); if ( child->load( e ) ) { if ( !addTask( child, this ) ) { delete child; // TODO: Complain about this } } else { // TODO: Complain about this delete child; }*/ } else if ( e.tagName() == "task" ) { //debugPlan<<"Task--->"; // Load the task (and resourcerequests). // Depends on resources already loaded Task * child = new Task( this ); if ( child->load( e, status ) ) { if ( !addTask( child, this ) ) { delete child; // TODO: Complain about this } } else { // TODO: Complain about this delete child; } } } status.setProgress( 70 ); // These go last n = element.firstChild(); for ( ; ! n.isNull(); n = n.nextSibling() ) { debugPlan<"; // Load accounts // References tasks if ( !m_accounts.load( e, *this ) ) { errorPlan << "Failed to load accounts"; } } else if ( e.tagName() == "relation" ) { //debugPlan<<"Relation--->"; // Load the relation // References tasks Relation * child = new Relation(); if ( !child->load( e, *this ) ) { // TODO: Complain about this errorPlan << "Failed to load relation"; delete child; } //debugPlan<<"Relation<---"; } else if ( e.tagName() == "schedules" ) { //debugPlan<<"Project schedules & task appointments--->"; // References tasks and resources KoXmlNode sn = e.firstChild(); for ( ; ! sn.isNull(); sn = sn.nextSibling() ) { if ( ! sn.isElement() ) { continue; } KoXmlElement el = sn.toElement(); //debugPlan<loadXML( el, status ) ) { if ( add ) addScheduleManager( sm ); } else { errorPlan << "Failed to load schedule manager"; delete sm; } } else { debugPlan<<"No schedule manager ?!"; } } //debugPlan<<"Node schedules<---"; } else if ( e.tagName() == "resource-teams" ) { //debugPlan<<"Resource teams--->"; // References other resources KoXmlNode tn = e.firstChild(); for ( ; ! tn.isNull(); tn = tn.nextSibling() ) { if ( ! tn.isElement() ) { continue; } KoXmlElement el = tn.toElement(); if ( el.tagName() == "team" ) { Resource *r = findResource( el.attribute( "team-id" ) ); Resource *tm = findResource( el.attribute( "member-id" ) ); if ( r == 0 || tm == 0 ) { errorPlan<<"resource-teams: cannot find resources"; continue; } if ( r == tm ) { errorPlan<<"resource-teams: a team cannot be a member of itself"; continue; } r->addTeamMemberId( tm->id() ); } else { errorPlan<<"resource-teams: unhandled tag"<currencySymbolExplicit().isEmpty()) { loc.setAttribute("currency-symbol", l->currencySymbolExplicit()); } loc.setAttribute("currency-digits", l->monetaryDecimalPlaces()); loc.setAttribute("language", l->currencyLanguage()); loc.setAttribute("country", l->currencyCountry()); QDomElement share = me.ownerDocument().createElement( "shared-resources" ); me.appendChild(share); share.setAttribute("use", m_useSharedResources); share.setAttribute("file", m_sharedResourcesFile); share.setAttribute("projects-url", QString(m_sharedProjectsUrl.toEncoded())); share.setAttribute("projects-loadatstartup", m_loadProjectsAtStartup); m_documents.save(me); if (context.saveAll(this)) { m_accounts.save( me ); // save calendars foreach ( Calendar *c, calendarIdDict ) { c->save( me ); } // save standard worktime if ( m_standardWorktime ) m_standardWorktime->save( me ); // save project resources, must be after calendars QListIterator git( m_resourceGroups ); while ( git.hasNext() ) { git.next() ->save( me ); } } // Only save parent relations QListIterator it( m_dependParentNodes ); while ( it.hasNext() ) { Relation *r = it.next(); if (context.saveNode(r->parent()) && context.saveNode(r->child())) { r->save(me, context); } } if (context.saveAll(this)) { for ( int i = 0; i < numChildren(); i++ ) // Save all children childNode(i)->save(me, context); } // Now we can save relations assuming no tasks have relations outside the project QListIterator nodes(m_nodes); while (nodes.hasNext()) { nodes.next()->saveRelations(me, context); } if (context.saveAll(this)) { if ( !m_managers.isEmpty() ) { QDomElement el = me.ownerDocument().createElement( "schedules" ); me.appendChild( el ); foreach ( ScheduleManager *sm, m_managers ) { sm->saveXML( el ); } } // save resource teams QDomElement el = me.ownerDocument().createElement( "resource-teams" ); me.appendChild( el ); foreach ( Resource *r, resourceIdDict ) { if ( r->type() != Resource::Type_Team ) { continue; } foreach ( const QString &id, r->teamMemberIds() ) { QDomElement e = el.ownerDocument().createElement( "team" ); el.appendChild( e ); e.setAttribute( "team-id", r->id() ); e.setAttribute( "member-id", id ); } } } } void Project::saveWorkPackageXML( QDomElement &element, const Node *node, long id ) const { QDomElement me = element.ownerDocument().createElement( "project" ); element.appendChild( me ); me.setAttribute( "name", m_name ); me.setAttribute( "leader", m_leader ); me.setAttribute( "id", m_id ); me.setAttribute( "description", m_description ); me.setAttribute( "timezone", m_timeZone.isValid() ? QString::fromLatin1(m_timeZone.id()) : QString() ); me.setAttribute( "scheduling", constraintToString() ); me.setAttribute( "start-time", m_constraintStartTime.toString( Qt::ISODate ) ); me.setAttribute( "end-time", m_constraintEndTime.toString( Qt::ISODate ) ); QListIterator git( m_resourceGroups ); while ( git.hasNext() ) { git.next() ->saveWorkPackageXML( me, node->assignedResources( id ) ); } if ( node == 0 ) { return; } node->saveWorkPackageXML( me, id ); foreach ( ScheduleManager *sm, m_managerIdMap ) { if ( sm->scheduleId() == id ) { QDomElement el = me.ownerDocument().createElement( "schedules" ); me.appendChild( el ); sm->saveWorkPackageXML( el, *node ); break; } } } void Project::setParentSchedule( Schedule *sch ) { QListIterator it = m_nodes; while ( it.hasNext() ) { it.next() ->setParentSchedule( sch ); } } void Project::addResourceGroup( ResourceGroup *group, int index ) { int i = index == -1 ? m_resourceGroups.count() : index; emit resourceGroupToBeAdded( group, i ); m_resourceGroups.insert( i, group ); setResourceGroupId( group ); group->setProject( this ); foreach ( Resource *r, group->resources() ) { setResourceId( r ); r->setProject( this ); } emit resourceGroupAdded( group ); emit projectChanged(); } ResourceGroup *Project::takeResourceGroup( ResourceGroup *group ) { int i = m_resourceGroups.indexOf( group ); Q_ASSERT( i != -1 ); if ( i == -1 ) { return 0; } emit resourceGroupToBeRemoved( group ); ResourceGroup *g = m_resourceGroups.takeAt( i ); Q_ASSERT( group == g ); g->setProject( 0 ); removeResourceGroupId( g->id() ); foreach ( Resource *r, g->resources() ) { r->setProject( 0 ); removeResourceId( r->id() ); } emit resourceGroupRemoved( g ); emit projectChanged(); return g; } QList &Project::resourceGroups() { return m_resourceGroups; } void Project::addResource( ResourceGroup *group, Resource *resource, int index ) { int i = index == -1 ? group->numResources() : index; emit resourceToBeAdded( group, i ); group->addResource( i, resource, 0 ); setResourceId( resource ); emit resourceAdded( resource ); emit projectChanged(); } Resource *Project::takeResource( ResourceGroup *group, Resource *resource ) { emit resourceToBeRemoved( resource ); bool result = removeResourceId( resource->id() ); Q_ASSERT( result == true ); if (!result) { warnPlan << "Could not remove resource with id" << resource->id(); } resource->removeRequests(); // not valid anymore Resource *r = group->takeResource( resource ); Q_ASSERT( resource == r ); if (resource != r) { warnPlan << "Could not take resource from group"; } emit resourceRemoved( resource ); emit projectChanged(); return r; } void Project::moveResource( ResourceGroup *group, Resource *resource ) { if ( group == resource->parentGroup() ) { return; } takeResource( resource->parentGroup(), resource ); addResource( group, resource ); return; } QMap< QString, QString > Project::externalProjects() const { QMap< QString, QString > map; foreach ( Resource *r, resourceList() ) { for( QMapIterator it( r->externalProjects() ); it.hasNext(); ) { it.next(); if ( ! map.contains( it.key() ) ) { map[ it.key() ] = it.value(); } } } return map; } bool Project::addTask( Node* task, Node* position ) { // we want to add a task at the given position. => the new node will // become next sibling right after position. if ( 0 == position ) { return addSubTask( task, this ); } //debugPlan<<"Add"<name()<<" after"<name(); // in case we want to add to the main project, we make it child element // of the root element. if ( Node::Type_Project == position->type() ) { return addSubTask( task, position ); } // find the position // we have to tell the parent that we want to delete one of its children Node* parentNode = position->parentNode(); if ( !parentNode ) { debugPlan <<"parent node not found???"; return false; } int index = parentNode->findChildNode( position ); if ( -1 == index ) { // ok, it does not exist debugPlan <<"Task not found???"; return false; } return addSubTask( task, index + 1, parentNode ); } bool Project::addSubTask( Node* task, Node* parent ) { // append task to parent return addSubTask( task, -1, parent ); } bool Project::addSubTask( Node* task, int index, Node* parent, bool emitSignal ) { // we want to add a subtask to the node "parent" at the given index. // If parent is 0, add to this Node *p = parent; if ( 0 == p ) { p = this; } if ( !registerNodeId( task ) ) { errorPlan << "Failed to register node id, can not add subtask: " << task->name(); return false; } int i = index == -1 ? p->numChildren() : index; if ( emitSignal ) emit nodeToBeAdded( p, i ); p->insertChildNode( i, task ); connect( this, &Project::standardWorktimeChanged, task, &Node::slotStandardWorktimeChanged ); if ( emitSignal ) { emit nodeAdded( task ); emit projectChanged(); if ( p != this && p->numChildren() == 1 ) { emit nodeChanged( p ); } } return true; } void Project::takeTask( Node *node, bool emitSignal ) { //debugPlan<name(); Node * parent = node->parentNode(); if ( parent == 0 ) { debugPlan <<"Node must have a parent!"; return; } removeId( node->id() ); if ( emitSignal ) emit nodeToBeRemoved( node ); disconnect( this, &Project::standardWorktimeChanged, node, &Node::slotStandardWorktimeChanged ); parent->takeChildNode( node ); if ( emitSignal ) { emit nodeRemoved( node ); emit projectChanged(); if ( parent != this && parent->type() != Node::Type_Summarytask ) { emit nodeChanged( parent ); } } } bool Project::canMoveTask( Node* node, Node *newParent ) { //debugPlan<name()<<" to"<name(); if ( node == this ) { return false; } Node *p = newParent; while ( p && p != this ) { if ( ! node->canMoveTo( p ) ) { return false; } p = p->parentNode(); } return true; } bool Project::moveTask( Node* node, Node *newParent, int newPos ) { //debugPlan<name()<<" to"<name()<<","<parentNode(); int oldPos = oldParent->indexOf( node ); int i = newPos < 0 ? newParent->numChildren() : newPos; if ( oldParent == newParent && i == oldPos ) { // no need to move to where it already is return false; } int newRow = i; if ( oldParent == newParent && newPos > oldPos ) { ++newRow; // itemmodels wants new row *before* node is removed from old position } debugPlan<name()<<"at"<indexOf( node )<<"to"<name()<numChildren() == 0 ) { emit nodeChanged( oldParent ); } if ( newParent != this && newParent->numChildren() == 1 ) { emit nodeChanged( newParent ); } return true; } bool Project::canIndentTask( Node* node ) { if ( 0 == node ) { // should always be != 0. At least we would get the Project, // but you never know who might change that, so better be careful return false; } if ( node->type() == Node::Type_Project ) { //debugPlan<<"The root node cannot be indented"; return false; } // we have to find the parent of task to manipulate its list of children Node* parentNode = node->parentNode(); if ( !parentNode ) { return false; } if ( parentNode->findChildNode( node ) == -1 ) { errorPlan << "Tasknot found???"; return false; } Node *sib = node->siblingBefore(); if ( !sib ) { //debugPlan<<"new parent node not found"; return false; } if ( node->findParentRelation( sib ) || node->findChildRelation( sib ) ) { //debugPlan<<"Cannot have relations to parent"; return false; } return true; } bool Project::indentTask( Node* node, int index ) { if ( canIndentTask( node ) ) { Node * newParent = node->siblingBefore(); int i = index == -1 ? newParent->numChildren() : index; moveTask( node, newParent, i ); //debugPlan; return true; } return false; } bool Project::canUnindentTask( Node* node ) { if ( 0 == node ) { // is always != 0. At least we would get the Project, but you // never know who might change that, so better be careful return false; } if ( Node::Type_Project == node->type() ) { //debugPlan<<"The root node cannot be unindented"; return false; } // we have to find the parent of task to manipulate its list of children // and we need the parent's parent too Node* parentNode = node->parentNode(); if ( !parentNode ) { return false; } Node* grandParentNode = parentNode->parentNode(); if ( !grandParentNode ) { //debugPlan<<"This node already is at the top level"; return false; } int index = parentNode->findChildNode( node ); if ( -1 == index ) { errorPlan << "Tasknot found???"; return false; } return true; } bool Project::unindentTask( Node* node ) { if ( canUnindentTask( node ) ) { Node * parentNode = node->parentNode(); Node *grandParentNode = parentNode->parentNode(); int i = grandParentNode->indexOf( parentNode ) + 1; if ( i == 0 ) { i = grandParentNode->numChildren(); } moveTask( node, grandParentNode, i ); //debugPlan; return true; } return false; } bool Project::canMoveTaskUp( Node* node ) { if ( node == 0 ) return false; // safety // we have to find the parent of task to manipulate its list of children Node* parentNode = node->parentNode(); if ( !parentNode ) { //debugPlan<<"No parent found"; return false; } if ( parentNode->findChildNode( node ) == -1 ) { errorPlan << "Tasknot found???"; return false; } if ( node->siblingBefore() ) { return true; } return false; } bool Project::moveTaskUp( Node* node ) { if ( canMoveTaskUp( node ) ) { moveTask( node, node->parentNode(), node->parentNode()->indexOf( node ) - 1 ); return true; } return false; } bool Project::canMoveTaskDown( Node* node ) { if ( node == 0 ) return false; // safety // we have to find the parent of task to manipulate its list of children Node* parentNode = node->parentNode(); if ( !parentNode ) { return false; } if ( parentNode->findChildNode( node ) == -1 ) { errorPlan << "Tasknot found???"; return false; } if ( node->siblingAfter() ) { return true; } return false; } bool Project::moveTaskDown( Node* node ) { if ( canMoveTaskDown( node ) ) { moveTask( node, node->parentNode(), node->parentNode()->indexOf( node ) + 1 ); return true; } return false; } Task *Project::createTask() { Task * node = new Task(); node->setId( uniqueNodeId() ); reserveId( node->id(), node ); return node; } Task *Project::createTask( const Task &def ) { Task * node = new Task( def ); node->setId( uniqueNodeId() ); reserveId( node->id(), node ); return node; } Node *Project::findNode( const QString &id ) const { if ( m_parent == 0 ) { if ( nodeIdDict.contains( id ) ) { return nodeIdDict[ id ]; } return 0; } return m_parent->findNode( id ); } bool Project::nodeIdentExists( const QString &id ) const { return nodeIdDict.contains( id ) || nodeIdReserved.contains( id ); } QString Project::uniqueNodeId( int seed ) const { Q_UNUSED(seed); QString s = QDateTime::currentDateTime().toString( Qt::ISODate ) + ' '; QString ident = s + KRandom::randomString( 10 ); // int i = seed; while ( nodeIdentExists( ident ) ) { ident = s + KRandom::randomString( 10 ); } return ident; } QString Project::uniqueNodeId( const QList &existingIds, int seed ) { QString id = uniqueNodeId( seed ); while ( existingIds.contains( id ) ) { id = uniqueNodeId( seed ); } return id; } bool Project::removeId( const QString &id ) { //debugPlan <<"id=" << id; if ( m_parent ) { return m_parent->removeId( id ); } //debugPlan << "id=" << id<< nodeIdDict.contains(id); return nodeIdDict.remove( id ); } void Project::reserveId( const QString &id, Node *node ) { //debugPlan <<"id=" << id << node->name(); nodeIdReserved.insert( id, node ); } bool Project::registerNodeId( Node *node ) { nodeIdReserved.remove( node->id() ); if ( node->id().isEmpty() ) { warnPlan << "Node id is empty, cannot register it"; return false; } Node *rn = findNode( node->id() ); if ( rn == 0 ) { //debugPlan <<"id=" << node->id() << node->name(); nodeIdDict.insert( node->id(), node ); return true; } if ( rn != node ) { errorPlan << "Id already exists for different task: " << node->id(); return false; } //debugPlan<<"Already exists" <<"id=" << node->id() << node->name(); return true; } QList Project::allNodes() const { QList lst = nodeIdDict.values(); int me = lst.indexOf( const_cast( this ) ); if ( me != -1 ) { lst.removeAt( me ); } return lst; } QList Project::allTasks( const Node *parent ) const { QList lst; const Node *p = parent ? parent : this; foreach ( Node *n, p->childNodeIterator() ) { if ( n->type() == Node::Type_Task || n->type() == Type_Milestone ) { lst << static_cast( n ); } lst += allTasks( n ); } return lst; } bool Project::isStarted() const { const QList tasks = allTasks(); for (const Task *t : tasks) { if (t->isStarted()) { return true; } } return false; } bool Project::setResourceGroupId( ResourceGroup *group ) { if ( group == 0 ) { return false; } if ( ! group->id().isEmpty() ) { ResourceGroup *g = findResourceGroup( group->id() ); if ( group == g ) { return true; } else if ( g == 0 ) { insertResourceGroupId( group->id(), group ); return true; } } QString id = uniqueResourceGroupId(); group->setId( id ); if ( id.isEmpty() ) { return false; } insertResourceGroupId( id, group ); return true; } QString Project::uniqueResourceGroupId() const { QString s = QDateTime::currentDateTime().toString( Qt::ISODate ) + ' '; QString id = s + KRandom::randomString( 10 ); while ( resourceGroupIdDict.contains( id ) ) { id = s + KRandom::randomString( 10 ); } return id; } ResourceGroup *Project::group( const QString& id ) { return findResourceGroup( id ); } ResourceGroup *Project::groupByName( const QString& name ) const { foreach ( ResourceGroup *g, resourceGroupIdDict ) { if ( g->name() == name ) { return g; } } return 0; } QList Project::autoAllocateResources() const { QList lst; foreach ( Resource *r, resourceIdDict ) { if ( r->autoAllocate() ) { lst << r; } } return lst; } void Project::insertResourceId( const QString &id, Resource *resource ) { resourceIdDict.insert( id, resource ); } bool Project::removeResourceId( const QString &id ) { return resourceIdDict.remove( id ); } bool Project::setResourceId( Resource *resource ) { if ( resource == 0 ) { return false; } if ( ! resource->id().isEmpty() ) { Resource *r = findResource( resource->id() ); if ( resource == r ) { return true; } else if ( r == 0 ) { insertResourceId( resource->id(), resource ); return true; } } QString id = uniqueResourceId(); resource->setId( id ); if ( id.isEmpty() ) { return false; } insertResourceId( id, resource ); return true; } QString Project::uniqueResourceId() const { QString s = QDateTime::currentDateTime().toString( Qt::ISODate ) + ' '; QString id = s + KRandom::randomString( 10 ); while ( resourceIdDict.contains( id ) ) { id = s + KRandom::randomString( 10 ); } return id; } Resource *Project::resource( const QString& id ) { return findResource( id ); } Resource *Project::resourceByName( const QString& name ) const { QHash::const_iterator it; for (it = resourceIdDict.constBegin(); it != resourceIdDict.constEnd(); ++it) { Resource *r = it.value(); if ( r->name() == name ) { Q_ASSERT( it.key() == r->id() ); return r; } } return 0; } QStringList Project::resourceNameList() const { QStringList lst; foreach ( Resource *r, resourceIdDict ) { lst << r->name(); } return lst; } EffortCostMap Project::plannedEffortCostPrDay( QDate start, QDate end, long id, EffortCostCalculationType typ ) const { //debugPlan< it( childNodeIterator() ); while ( it.hasNext() ) { ec += it.next() ->plannedEffortCostPrDay( start, end, id, typ ); } return ec; } EffortCostMap Project::plannedEffortCostPrDay( const Resource *resource, QDate start, QDate end, long id, EffortCostCalculationType typ ) const { //debugPlan< it( childNodeIterator() ); while ( it.hasNext() ) { ec += it.next() ->plannedEffortCostPrDay( resource, start, end, id, typ ); } return ec; } EffortCostMap Project::actualEffortCostPrDay( QDate start, QDate end, long id, EffortCostCalculationType typ ) const { //debugPlan< it( childNodeIterator() ); while ( it.hasNext() ) { ec += it.next() ->actualEffortCostPrDay( start, end, id, typ ); } return ec; } EffortCostMap Project::actualEffortCostPrDay( const Resource *resource, QDate start, QDate end, long id, EffortCostCalculationType typ ) const { //debugPlan< it( childNodeIterator() ); while ( it.hasNext() ) { ec += it.next() ->actualEffortCostPrDay( resource, start, end, id, typ ); } return ec; } // Returns the total planned effort for this project (or subproject) Duration Project::plannedEffort( long id, EffortCostCalculationType typ ) const { //debugPlan; Duration eff; QListIterator it( childNodeIterator() ); while ( it.hasNext() ) { eff += it.next() ->plannedEffort( id, typ ); } return eff; } // Returns the total planned effort for this project (or subproject) on date Duration Project::plannedEffort( QDate date, long id, EffortCostCalculationType typ ) const { //debugPlan; Duration eff; QListIterator it( childNodeIterator() ); while ( it.hasNext() ) { eff += it.next() ->plannedEffort( date, id, typ ); } return eff; } // Returns the total planned effort for this project (or subproject) upto and including date Duration Project::plannedEffortTo( QDate date, long id, EffortCostCalculationType typ ) const { //debugPlan; Duration eff; QListIterator it( childNodeIterator() ); while ( it.hasNext() ) { eff += it.next() ->plannedEffortTo( date, id, typ ); } return eff; } // Returns the total actual effort for this project (or subproject) upto and including date Duration Project::actualEffortTo( QDate date ) const { //debugPlan; Duration eff; QListIterator it( childNodeIterator() ); while ( it.hasNext() ) { eff += it.next() ->actualEffortTo( date ); } return eff; } // Returns the total planned effort for this project (or subproject) upto and including date double Project::plannedCostTo( QDate date, long id, EffortCostCalculationType typ ) const { //debugPlan; double c = 0; QListIterator it( childNodeIterator() ); while ( it.hasNext() ) { c += it.next() ->plannedCostTo( date, id, typ ); } return c; } // Returns the total actual cost for this project (or subproject) upto and including date EffortCost Project::actualCostTo( long int id, QDate date ) const { //debugPlan; EffortCost c; QListIterator it( childNodeIterator() ); while ( it.hasNext() ) { c += it.next() ->actualCostTo( id, date ); } return c; } Duration Project::budgetedWorkPerformed( QDate date, long id ) const { //debugPlan; Duration e; foreach (Node *n, childNodeIterator()) { e += n->budgetedWorkPerformed( date, id ); } return e; } double Project::budgetedCostPerformed( QDate date, long id ) const { //debugPlan; double c = 0.0; foreach (Node *n, childNodeIterator()) { c += n->budgetedCostPerformed( date, id ); } return c; } double Project::effortPerformanceIndex( QDate date, long id ) const { //debugPlan; debugPlan< 0.0 ) { r = p / s; } debugPlan< date ? end : date), id ); double budgetAtCompletion; double plannedCompleted; double budgetedCompleted; bool useEffort = false; //FIXME if ( useEffort ) { budgetAtCompletion = plan.totalEffort().toDouble( Duration::Unit_h ); plannedCompleted = plan.effortTo( date ).toDouble( Duration::Unit_h ); //actualCompleted = actual.effortTo( date ).toDouble( Duration::Unit_h ); budgetedCompleted = budgetedWorkPerformed( date, id ).toDouble( Duration::Unit_h ); } else { budgetAtCompletion = plan.totalCost(); plannedCompleted = plan.costTo( date ); budgetedCompleted = budgetedCostPerformed( date, id ); } double c = 0.0; if ( budgetAtCompletion > 0.0 ) { double percentageCompletion = budgetedCompleted / budgetAtCompletion; c = budgetAtCompletion * percentageCompletion; //?? debugPlan<name()<<","<<(parent?parent->name():"No parent"); int row = parent == 0 ? m_calendars.count() : parent->calendars().count(); if ( index >= 0 && index < row ) { row = index; } emit calendarToBeAdded( parent, row ); calendar->setProject( this ); if ( parent == 0 ) { calendar->setParentCal( 0 ); // in case m_calendars.insert( row, calendar ); } else { calendar->setParentCal( parent, row ); } if ( calendar->isDefault() ) { setDefaultCalendar( calendar ); } setCalendarId( calendar ); emit calendarAdded( calendar ); emit projectChanged(); } void Project::takeCalendar( Calendar *calendar ) { emit calendarToBeRemoved( calendar ); removeCalendarId( calendar->id() ); if ( calendar == m_defaultCalendar ) { m_defaultCalendar = 0; } if ( calendar->parentCal() == 0 ) { int i = indexOf( calendar ); if ( i != -1 ) { m_calendars.removeAt( i ); } } else { calendar->setParentCal( 0 ); } emit calendarRemoved( calendar ); calendar->setProject( 0 ); emit projectChanged(); } int Project::indexOf( const Calendar *calendar ) const { return m_calendars.indexOf( const_cast(calendar) ); } Calendar *Project::calendar( const QString& id ) const { return findCalendar( id ); } Calendar *Project::calendarByName( const QString& name ) const { foreach( Calendar *c, calendarIdDict ) { if ( c->name() == name ) { return c; } } return 0; } const QList &Project::calendars() const { return m_calendars; } QList Project::allCalendars() const { return calendarIdDict.values(); } QStringList Project::calendarNames() const { QStringList lst; foreach( Calendar *c, calendarIdDict ) { lst << c->name(); } return lst; } bool Project::setCalendarId( Calendar *calendar ) { if ( calendar == 0 ) { return false; } if ( ! calendar->id().isEmpty() ) { Calendar *c = findCalendar( calendar->id() ); if ( calendar == c ) { return true; } else if ( c == 0 ) { insertCalendarId( calendar->id(), calendar ); return true; } } QString id = uniqueCalendarId(); calendar->setId( id ); if ( id.isEmpty() ) { return false; } insertCalendarId( id, calendar ); return true; } QString Project::uniqueCalendarId() const { QString s = QDateTime::currentDateTime().toString( Qt::ISODate ) + ' '; QString id = s + KRandom::randomString( 10 ); while ( calendarIdDict.contains( id ) ) { id = s + KRandom::randomString( 10 ); } return id; } void Project::setDefaultCalendar( Calendar *cal ) { if ( m_defaultCalendar ) { m_defaultCalendar->setDefault( false ); } m_defaultCalendar = cal; if ( cal ) { cal->setDefault( true ); } emit defaultCalendarChanged( cal ); emit projectChanged(); } void Project::setStandardWorktime( StandardWorktime * worktime ) { if ( m_standardWorktime != worktime ) { delete m_standardWorktime; m_standardWorktime = worktime; m_standardWorktime->setProject( this ); emit standardWorktimeChanged( worktime ); } } void Project::emitDocumentAdded( Node *node , Document *doc , int index ) { emit documentAdded( node, doc, index ); } void Project::emitDocumentRemoved( Node *node , Document *doc , int index ) { emit documentRemoved( node, doc, index ); } void Project::emitDocumentChanged( Node *node , Document *doc , int index ) { emit documentChanged( node, doc, index ); } bool Project::linkExists( const Node *par, const Node *child ) const { if ( par == 0 || child == 0 || par == child || par->isDependChildOf( child ) ) { return false; } foreach ( Relation *r, par->dependChildNodes() ) { if ( r->child() == child ) { return true; } } return false; } bool Project::legalToLink( const Node *par, const Node *child ) const { //debugPlan<isDependChildOf( child ) ) { return false; } if ( linkExists( par, child ) ) { return false; } bool legal = true; // see if par/child is related if ( legal && ( par->isParentOf( child ) || child->isParentOf( par ) ) ) { legal = false; } if ( legal ) legal = legalChildren( par, child ); if ( legal ) legal = legalParents( par, child ); if ( legal ) { foreach ( Node *p, par->childNodeIterator() ) { if ( ! legalToLink( p, child ) ) { return false; } } } return legal; } bool Project::legalParents( const Node *par, const Node *child ) const { bool legal = true; //debugPlan<name()<<" ("<numDependParentNodes()<<" parents)"<name()<<" ("<numDependChildNodes()<<" children)"; for ( int i = 0; i < par->numDependParentNodes() && legal; ++i ) { Node *pNode = par->getDependParentNode( i ) ->parent(); if ( child->isParentOf( pNode ) || pNode->isParentOf( child ) ) { //debugPlan<<"Found:"<name()<<" is related to"<name(); legal = false; } else { legal = legalChildren( pNode, child ); } if ( legal ) legal = legalParents( pNode, child ); } return legal; } bool Project::legalChildren( const Node *par, const Node *child ) const { bool legal = true; //debugPlan<name()<<" ("<numDependParentNodes()<<" parents)"<name()<<" ("<numDependChildNodes()<<" children)"; for ( int j = 0; j < child->numDependChildNodes() && legal; ++j ) { Node *cNode = child->getDependChildNode( j ) ->child(); if ( par->isParentOf( cNode ) || cNode->isParentOf( par ) ) { //debugPlan<<"Found:"<name()<<" is related to"<name(); legal = false; } else { legal = legalChildren( par, cNode ); } } return legal; } WBSDefinition &Project::wbsDefinition() { return m_wbsDefinition; } void Project::setWbsDefinition( const WBSDefinition &def ) { //debugPlan; m_wbsDefinition = def; emit wbsDefinitionChanged(); emit projectChanged(); } QString Project::generateWBSCode( QList &indexes, bool sortable ) const { QString code = m_wbsDefinition.projectCode(); if (sortable) { int fw = (nodeIdDict.count() / 10) + 1; QLatin1Char fc('0'); foreach ( int index, indexes ) { code += ".%1"; code = code.arg(QString::number(index), fw, fc); } //debugPlan< hash = resourceIdDict; foreach ( Resource * r, hash ) { r->setCurrentSchedule( id ); } emit currentScheduleChanged(); emit projectChanged(); } ScheduleManager *Project::scheduleManager( long id ) const { foreach ( ScheduleManager *sm, m_managers ) { if ( sm->scheduleId() == id ) { return sm; } } return 0; } ScheduleManager *Project::scheduleManager( const QString &id ) const { return m_managerIdMap.value( id ); } ScheduleManager *Project::findScheduleManagerByName( const QString &name ) const { //debugPlan; ScheduleManager *m = 0; foreach( ScheduleManager *sm, m_managers ) { m = sm->findManager( name ); if ( m ) { break; } } return m; } QList Project::allScheduleManagers() const { QList lst; foreach ( ScheduleManager *sm, m_managers ) { lst << sm; lst << sm->allChildren(); } return lst; } QString Project::uniqueScheduleName() const { //debugPlan; QString n = i18n( "Plan" ); bool unique = findScheduleManagerByName( n ) == 0; if ( unique ) { return n; } n += " %1"; int i = 1; for ( ; true; ++i ) { unique = findScheduleManagerByName( n.arg( i ) ) == 0; if ( unique ) { break; } } return n.arg( i ); } void Project::addScheduleManager( ScheduleManager *sm, ScheduleManager *parent, int index ) { int row = parent == 0 ? m_managers.count() : parent->childCount(); if ( index >= 0 && index < row ) { row = index; } if ( parent == 0 ) { emit scheduleManagerToBeAdded( parent, row ); m_managers.insert( row, sm ); } else { emit scheduleManagerToBeAdded( parent, row ); sm->setParentManager( parent, row ); } if ( sm->managerId().isEmpty() ) { sm->setManagerId( uniqueScheduleManagerId() ); } Q_ASSERT( ! m_managerIdMap.contains( sm->managerId() ) ); m_managerIdMap.insert( sm->managerId(), sm ); emit scheduleManagerAdded( sm ); emit projectChanged(); //debugPlan<<"Added:"<name()<<", now"<children() ) { takeScheduleManager( s ); } if ( sm->scheduling() ) { sm->stopCalculation(); } int index = -1; if ( sm->parentManager() ) { int index = sm->parentManager()->indexOf( sm ); if ( index >= 0 ) { emit scheduleManagerToBeRemoved( sm ); sm->setParentManager( 0 ); m_managerIdMap.remove( sm->managerId() ); emit scheduleManagerRemoved( sm ); emit projectChanged(); } } else { index = indexOf( sm ); if ( index >= 0 ) { emit scheduleManagerToBeRemoved( sm ); m_managers.removeAt( indexOf( sm ) ); m_managerIdMap.remove( sm->managerId() ); emit scheduleManagerRemoved( sm ); emit projectChanged(); } } return index; } +void Project::swapScheduleManagers(ScheduleManager *from, ScheduleManager *to) +{ + emit scheduleManagersSwapped(from, to); +} + void Project::moveScheduleManager( ScheduleManager *sm, ScheduleManager *newparent, int newindex ) { //debugPlan<name()<parentManager() ) { m_managers.removeAt( indexOf( sm ) ); } sm->setParentManager( newparent, newindex ); if ( ! newparent ) { m_managers.insert( newindex, sm ); } emit scheduleManagerMoved( sm, newindex ); } bool Project::isScheduleManager( void *ptr ) const { const ScheduleManager *sm = static_cast( ptr ); if ( indexOf( sm ) >= 0 ) { return true; } foreach ( ScheduleManager *p, m_managers ) { if ( p->isParentOf( sm ) ) { return true; } } return false; } ScheduleManager *Project::createScheduleManager( const QString &name ) { //debugPlan<isBaselined() ) { return true; } } return false; } Schedule *s = schedule( id ); return s == 0 ? false : s->isBaselined(); } MainSchedule *Project::createSchedule( const QString& name, Schedule::Type type ) { //debugPlan<<"No of schedules:"<setName( name ); sch->setType( type ); addMainSchedule( sch ); return sch; } void Project::addMainSchedule( MainSchedule *sch ) { if ( sch == 0 ) { return; } //debugPlan<<"No of schedules:"<setId( i ); sch->setNode( this ); addSchedule( sch ); } bool Project::removeCalendarId( const QString &id ) { //debugPlan <<"id=" << id; return calendarIdDict.remove( id ); } void Project::insertCalendarId( const QString &id, Calendar *calendar ) { //debugPlan <<"id=" << id <<":" << calendar->name(); calendarIdDict.insert( id, calendar ); } void Project::changed( Node *node, int property ) { if ( m_parent == 0 ) { Node::changed( node, property ); // reset cache if ( property != Node::Type ) { // add/remove node is handled elsewhere emit nodeChanged( node ); emit projectChanged(); } return; } Node::changed( node, property ); } void Project::changed( ResourceGroup *group ) { //debugPlan; emit resourceGroupChanged( group ); emit projectChanged(); } void Project::changed( ScheduleManager *sm ) { emit scheduleManagerChanged( sm ); emit projectChanged(); } void Project::changed( MainSchedule *sch ) { //debugPlan<id(); emit scheduleChanged( sch ); emit projectChanged(); } void Project::sendScheduleToBeAdded( const ScheduleManager *sm, int row ) { emit scheduleToBeAdded( sm, row ); } void Project::sendScheduleAdded( const MainSchedule *sch ) { //debugPlan<id(); emit scheduleAdded( sch ); emit projectChanged(); } void Project::sendScheduleToBeRemoved( const MainSchedule *sch ) { //debugPlan<id(); emit scheduleToBeRemoved( sch ); } void Project::sendScheduleRemoved( const MainSchedule *sch ) { //debugPlan<id(); emit scheduleRemoved( sch ); emit projectChanged(); } void Project::changed( Resource *resource ) { emit resourceChanged( resource ); emit projectChanged(); } void Project::changed( Calendar *cal ) { emit calendarChanged( cal ); emit projectChanged(); } void Project::changed( StandardWorktime *w ) { emit standardWorktimeChanged( w ); emit projectChanged(); } bool Project::addRelation( Relation *rel, bool check ) { if ( rel->parent() == 0 || rel->child() == 0 ) { return false; } if ( check && !legalToLink( rel->parent(), rel->child() ) ) { return false; } emit relationToBeAdded( rel, rel->parent()->numDependChildNodes(), rel->child()->numDependParentNodes() ); rel->parent()->addDependChildNode( rel ); rel->child()->addDependParentNode( rel ); emit relationAdded( rel ); emit projectChanged(); return true; } void Project::takeRelation( Relation *rel ) { emit relationToBeRemoved( rel ); rel->parent() ->takeDependChildNode( rel ); rel->child() ->takeDependParentNode( rel ); emit relationRemoved( rel ); emit projectChanged(); } void Project::setRelationType( Relation *rel, Relation::Type type ) { emit relationToBeModified( rel ); rel->setType( type ); emit relationModified( rel ); emit projectChanged(); } void Project::setRelationLag( Relation *rel, const Duration &lag ) { emit relationToBeModified( rel ); rel->setLag( lag ); emit relationModified( rel ); emit projectChanged(); } QList Project::flatNodeList( Node *parent ) { QList lst; Node *p = parent == 0 ? this : parent; //debugPlan<name()<childNodeIterator() ) { lst.append( n ); if ( n->numChildren() > 0 ) { lst += flatNodeList( n ); } } return lst; } void Project::setSchedulerPlugins( const QMap &plugins ) { m_schedulerPlugins = plugins; debugPlan< Copyright (C) 2007 Florian Piquemal Copyright (C) 2007 Alexis Ménard 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 KPTPROJECT_H #define KPTPROJECT_H #include "plankernel_export.h" #include "kptnode.h" #include "kptglobal.h" #include "kptaccount.h" #include "kptcalendar.h" #include "kptdatetime.h" #include "kptduration.h" #include "kptresource.h" #include "kptwbsdefinition.h" #include "kptconfigbase.h" #include #include #include #include #include /// The main namespace. namespace KPlato { class Locale; class Schedule; class StandardWorktime; class ScheduleManager; class XMLLoaderObject; class Task; class SchedulerPlugin; class KPlatoXmlLoaderBase; class XmlSaveContext; /** * Project is the main node in a project, it contains child nodes and * possibly sub-projects. A sub-project is just another instantiation of this * node however. * * A note on timezones: * To be able to handle resources working in different timezones and * to facilitate data exchange with other applications like PIMs or * and groupware servers, the project has a timezone that is used for * all datetimes in nodes and schedules. * By default the local timezone is used. * * A resources timezone is defined by the associated calendar. * * Note that a projects datetimes are always displayed/modified in the timezone * it was originally created, not necessarily in your current local timezone. */ class PLANKERNEL_EXPORT Project : public Node { Q_OBJECT public: explicit Project( Node *parent = 0 ); explicit Project( ConfigBase &config, Node *parent = 0 ); explicit Project( ConfigBase &config, bool useDefaultValues, Node *parent = 0 ); ~Project(); /// Reference this project. void ref() { ++m_refCount; } /// De-reference this project. Deletes project of ref count <= 0 void deref(); /// Returns the node type. Can be Type_Project or Type_Subproject. virtual int type() const; /** * Calculate the schedules managed by the schedule manager * * @param sm Schedule manager */ void calculate( ScheduleManager &sm ); /** * Re-calculate the schedules managed by the schedule manager * * @param sm Schedule manager * @param dt The datetime from when the schedule shall be re-calculated */ void calculate( ScheduleManager &sm, const DateTime &dt ); virtual DateTime startTime( long id = -1 ) const; virtual DateTime endTime( long id = -1 ) const; /// Returns the calculated duration for schedule @p id Duration duration( long id = -1 ) const; using Node::duration; /** * Instead of using the expected duration, generate a random value using * the Distribution of each Task. This can be used for Monte-Carlo * estimation of Project duration. */ Duration *getRandomDuration(); virtual bool load( KoXmlElement &element, XMLLoaderObject &status ); virtual void save(QDomElement &element, const XmlSaveContext &context) const; using Node::saveWorkPackageXML; /// Save a workpackage document containing @p node with schedule identity @p id void saveWorkPackageXML( QDomElement &element, const Node *node, long id ) const; /** * Add the node @p task to the project, after node @p position * If @p position is zero or the project node, it will be added to this project. */ bool addTask( Node* task, Node* position ); /** * Add the node @p task to the @p parent */ bool addSubTask( Node* task, Node* parent ); /** * Add the node @p task to @p parent, in position @p index * If @p parent is zero, it will be added to this project. */ bool addSubTask( Node* task, int index, Node* parent, bool emitSignal = true ); /** * Remove the @p node. * The node is not deleted. */ void takeTask( Node *node, bool emitSignal = true ); bool canMoveTask( Node* node, Node *newParent ); bool moveTask( Node* node, Node *newParent, int newPos ); bool canIndentTask( Node* node ); bool indentTask( Node* node, int index = -1 ); bool canUnindentTask( Node* node ); bool unindentTask( Node* node ); bool canMoveTaskUp( Node* node ); bool moveTaskUp( Node* node ); bool canMoveTaskDown( Node* node ); bool moveTaskDown( Node* node ); /** * Create a task with a unique id. * The task is not added to the project. Do this with addSubTask(). */ Task *createTask(); /** * Create a copy of @p def with a unique id. * The task is not added to the project. Do this with addSubTask(). */ Task *createTask( const Task &def ); /// @return true if any of the tasks has been started bool isStarted() const; int resourceGroupCount() const { return m_resourceGroups.count(); } QList &resourceGroups(); /// Adds the resource group to the project. virtual void addResourceGroup( ResourceGroup *resource, int index = -1 ); /** * Removes the resource group @p resource from the project. * The resource group is not deleted. */ ResourceGroup *takeResourceGroup( ResourceGroup *resource ); int indexOf( ResourceGroup *resource ) const { return m_resourceGroups.indexOf( resource ); } ResourceGroup *resourceGroupAt( int pos ) const { return m_resourceGroups.value( pos ); } int numResourceGroups() const { return m_resourceGroups.count(); } /// Returns the resourcegroup with identity id. ResourceGroup *group( const QString& id ); /// Returns the resource group with the matching name, 0 if no match is found. ResourceGroup *groupByName( const QString& name ) const; /** * Adds the resource to the project and resource group. * Always use this to add resources. */ void addResource( ResourceGroup *group, Resource *resource, int index = -1 ); /** * Removes the resource from the project and resource group. * The resource is not deleted. * Always use this to remove resources. */ Resource *takeResource( ResourceGroup *group, Resource *resource ); /// Move @p resource to the new @p group. Requests are removed. void moveResource( ResourceGroup *group, Resource *resource ); /// Returns the resource with identity id. Resource *resource( const QString& id ); /// Returns the resource with matching name, 0 if no match is found. Resource *resourceByName( const QString& name ) const; QStringList resourceNameList() const; /// Returns a list of all resources QList resourceList() const { return resourceIdDict.values(); } virtual EffortCostMap plannedEffortCostPrDay( QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; virtual EffortCostMap plannedEffortCostPrDay(const Resource *resource, QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; using Node::plannedEffort; /// Returns the total planned effort for this project (or subproject) virtual Duration plannedEffort( long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the total planned effort for this project (or subproject) on date virtual Duration plannedEffort( QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; using Node::plannedEffortTo; /// Returns the planned effort up to and including date virtual Duration plannedEffortTo( QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the actual effort up to and including @p date virtual Duration actualEffortTo( QDate date ) const; /** * Planned cost up to and including date * @param date The cost is calculated from the start of the project upto including date. * @param id Identity of the schedule to be used. * @param typ the type of calculation. * @sa EffortCostCalculationType */ virtual double plannedCostTo( QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /** * Actual cost up to and including @p date * @param id Identity of the schedule to be used. * @param date The cost is calculated from the start of the project upto including date. */ virtual EffortCost actualCostTo( long int id, QDate date ) const; virtual EffortCostMap actualEffortCostPrDay( QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; virtual EffortCostMap actualEffortCostPrDay( const Resource *resource, QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; double effortPerformanceIndex( QDate date, long id ) const; double schedulePerformanceIndex( QDate date, long id ) const; /// Returns the effort planned to be used to reach the actual percent finished virtual Duration budgetedWorkPerformed( QDate date, long id = CURRENTSCHEDULE ) const; /// Returns the cost planned to be used to reach the actual percent finished virtual double budgetedCostPerformed( QDate date, long id = CURRENTSCHEDULE ) const; /// Budgeted Cost of Work Scheduled ( up to @p date ) virtual double bcws( QDate date, long id = BASELINESCHEDULE ) const; /// Budgeted Cost of Work Performed virtual double bcwp( long id = BASELINESCHEDULE ) const; /// Budgeted Cost of Work Performed ( up to @p date ) virtual double bcwp( QDate date, long id = BASELINESCHEDULE ) const; Calendar *defaultCalendar() const { return m_defaultCalendar; } void setDefaultCalendar( Calendar *cal ); const QList &calendars() const; void addCalendar( Calendar *calendar, Calendar *parent = 0, int index = -1 ); void takeCalendar( Calendar *calendar ); int indexOf( const Calendar *calendar ) const; /// Returns the calendar with identity id. Calendar *calendar( const QString& id ) const; /// Returns a list of all calendars QStringList calendarNames() const; /// Find calendar by name Calendar *calendarByName( const QString &name ) const; void changed( Calendar *cal ); QList allCalendars() const; /// Return number of calendars int calendarCount() const { return m_calendars.count(); } /// Return the calendar at @p index, 0 if index out of bounds Calendar *calendarAt( int index ) const { return m_calendars.value( index ); } /** * Defines the length of days, weeks, months and years * and the standard working week. * Used for estimation and calculation of effort, * and presentation in gantt chart. */ StandardWorktime *standardWorktime() { return m_standardWorktime; } void setStandardWorktime( StandardWorktime * worktime ); void changed( StandardWorktime* ); /// Check if a link exists between node @p par and @p child. bool linkExists( const Node *par, const Node *child ) const; /// Check if node @p par can be linked to node @p child. bool legalToLink( const Node *par, const Node *child ) const; using Node::legalToLink; virtual const QHash &nodeDict() { return nodeIdDict; } /// Return a list of all nodes in the project (excluding myself) QList allNodes() const; /// Return the number of all nodes in the project (excluding myself) int nodeCount() const { return nodeIdDict.count() - 1; } /// Return a list of all tasks and milestones int the wbs order QList allTasks( const Node *parent = 0 ) const; using Node::findNode; /// Find the node with identity id virtual Node *findNode( const QString &id ) const; using Node::removeId; /// Remove the node with identity id from the registers virtual bool removeId( const QString &id ); /// Reserve @p id for the @p node virtual void reserveId( const QString &id, Node *node ); /// Register @p node. The nodes id must be unique and non-empty. bool registerNodeId( Node *node ); /// Create a unique id. QString uniqueNodeId( int seed = 1 ) const; /// Check if node @p id is used bool nodeIdentExists( const QString &id ) const; /// Create a unique id. QString uniqueNodeId( const QList &existingIds, int seed = 1 ); ResourceGroup *findResourceGroup( const QString &id ) const { if ( resourceGroupIdDict.contains( id ) ) return resourceGroupIdDict[ id ]; return 0; } /// Remove the resourcegroup with identity id from the register bool removeResourceGroupId( const QString &id ) { if ( resourceGroupIdDict.contains( id ) ) return resourceGroupIdDict.remove( id ); return false; } /// Insert the resourcegroup with identity id void insertResourceGroupId( const QString &id, ResourceGroup* group ) { resourceGroupIdDict.insert( id, group ); } /// Generate, set and insert unique id bool setResourceGroupId( ResourceGroup *group); /// returns a unique resourcegroup id QString uniqueResourceGroupId() const; /// Return a list of resources that will be allocated to new tasks QList autoAllocateResources() const; Resource *findResource( const QString &id ) const { if ( resourceIdDict.contains( id ) ) return resourceIdDict[ id ]; return 0; } /// Remove the resource with identity id from the register bool removeResourceId( const QString &id ); /// Insert the resource with identity id void insertResourceId( const QString &id, Resource *resource ); /// Generate, set and insert unique id bool setResourceId( Resource *resource ); /// returns a unique resource id QString uniqueResourceId() const; /// Find the calendar with identity id virtual Calendar *findCalendar( const QString &id ) const { if ( id.isEmpty() || !calendarIdDict.contains( id ) ) return 0; return calendarIdDict[ id ]; } /// Remove the calendar with identity id from the register virtual bool removeCalendarId( const QString &id ); /// Insert the calendar with identity id virtual void insertCalendarId( const QString &id, Calendar *calendar ); /// Set and insert a unique id for calendar bool setCalendarId( Calendar *calendar ); /// returns a unique calendar id QString uniqueCalendarId() const; /// Return reference to WBS Definition WBSDefinition &wbsDefinition(); /// Set WBS Definition to @p def void setWbsDefinition( const WBSDefinition &def ); /// Generate WBS Code virtual QString generateWBSCode( QList &indexes, bool sortable = false ) const; Accounts &accounts() { return m_accounts; } const Accounts &accounts() const { return m_accounts; } /** * Set current schedule to the schedule with identity @p id, for me and my children * Note that this is used (and may be changed) when calculating schedules */ virtual void setCurrentSchedule( long id ); /// Create new schedule with unique name and id of type Expected. MainSchedule *createSchedule(); /// Create new schedule with unique id. MainSchedule *createSchedule( const QString& name, Schedule::Type type ); /// Add the schedule to the project. A fresh id will be generated for the schedule. void addMainSchedule( MainSchedule *schedule ); /// Set parent schedule for my children virtual void setParentSchedule( Schedule *sch ); /// Find the schedule manager that manages the Schedule with @p id ScheduleManager *scheduleManager( long id ) const; /// Find the schedule manager with @p id ScheduleManager *scheduleManager( const QString &id ) const; /// Create a unique schedule name (This may later be changed by the user) QString uniqueScheduleName() const; /// Create a unique schedule manager identity QString uniqueScheduleManagerId() const; ScheduleManager *createScheduleManager(); ScheduleManager *createScheduleManager( const QString &name ); /// Returns a list of all top level schedule managers QList scheduleManagers() const { return m_managers; } int numScheduleManagers() const { return m_managers.count(); } int indexOf( const ScheduleManager *sm ) const { return m_managers.indexOf( const_cast(sm) ); } bool isScheduleManager( void* ptr ) const; void addScheduleManager( ScheduleManager *sm, ScheduleManager *parent = 0, int index = -1 ); int takeScheduleManager( ScheduleManager *sm ); void moveScheduleManager( ScheduleManager *sm, ScheduleManager *newparent = 0, int newindex = -1 ); ScheduleManager *findScheduleManagerByName( const QString &name ) const; /// Returns a list of all schedule managers QList allScheduleManagers() const; /// Return true if schedule with identity @p id is baselined bool isBaselined( long id = ANYSCHEDULED ) const; void changed( ResourceGroup *group ); void changed( Resource *resource ); void changed( ScheduleManager *sm ); void changed( MainSchedule *sch ); void sendScheduleAdded( const MainSchedule *sch ); void sendScheduleToBeAdded( const ScheduleManager *manager, int row ); void sendScheduleRemoved( const MainSchedule *sch ); void sendScheduleToBeRemoved( const MainSchedule *sch ); /// Return the time zone used in this project QTimeZone timeZone() const { return m_timeZone; } /// Set the time zone to be used in this project void setTimeZone( const QTimeZone &tz ) { m_timeZone = tz; } /** * Add a relation between the nodes specified in the relation rel. * Emits signals relationToBeAdded() before the relation is added, * and relationAdded() after it has been added. * @param rel The relation to be added. * @param check If true, the relation is checked for validity * @return true if successful. */ bool addRelation( Relation *rel, bool check=true ); /** * Removes the relation @p rel without deleting it. * Emits signals relationToBeRemoved() before the relation is removed, * and relationRemoved() after it has been removed. */ void takeRelation( Relation *rel ); /** * Modify the @p type of the @p relation. */ void setRelationType( Relation *relation, Relation::Type type ); /** * Modify the @p lag of the @p relation. */ void setRelationLag( Relation *relation, const Duration &lag ); void calcCriticalPathList( MainSchedule *cs ); void calcCriticalPathList( MainSchedule *cs, Node *node ); /** * Returns the list of critical paths for schedule @p id */ const QList< QList > *criticalPathList( long id = CURRENTSCHEDULE ); QList criticalPath( long id = CURRENTSCHEDULE, int index = 0 ); /// Returns a flat list af all nodes QList flatNodeList( Node *parent = 0 ); void generateUniqueNodeIds(); void generateUniqueIds(); const ConfigBase &config() const { return m_config ? *m_config : emptyConfig; } /// Set configuration data void setConfig( ConfigBase *config ) { m_config = config; } const Task &taskDefaults() const { return config().taskDefaults(); } /// Return locale. (Used for currency, everything else is from KGlobal::locale) Locale *locale() { return const_cast(config()).locale(); } /// Return locale. (Used for currency, everything else is from KGlobal::locale) const Locale *locale() const { return config().locale(); } /// Signal that locale data has changed void emitLocaleChanged(); void setSchedulerPlugins( const QMap &plugins ); const QMap &schedulerPlugins() const { return m_schedulerPlugins; } void initiateCalculation( MainSchedule &sch ); void initiateCalculationLists( MainSchedule &sch ); void finishCalculation( ScheduleManager &sm ); void adjustSummarytask(); /// Increments progress and emits signal sigProgress() void incProgress(); /// Emits signal maxProgress() void emitMaxProgress( int value ); bool stopcalculation; /// return a map of all external projects QMap externalProjects() const; void emitDocumentAdded( Node*, Document*, int index ); void emitDocumentRemoved( Node*, Document*, int index ); void emitDocumentChanged( Node*, Document*, int index ); bool useSharedResources() const; void setUseSharedResources(bool on); bool isSharedResourcesLoaded() const; void setSharedResourcesLoaded(bool on); void setSharedResourcesFile(const QString &file); QString sharedResourcesFile() const; void setSharedProjectsUrl(const QUrl &url); QUrl sharedProjectsUrl() const; void setLoadProjectsAtStartup(bool value); bool loadProjectsAtStartup() const; public Q_SLOTS: /// Sets m_progress to @p progress and emits signal sigProgress() /// If @p sm is not 0, progress is also set for the schedule manager void setProgress(int progress, KPlato::ScheduleManager *sm = 0); /// Sets m_maxprogress to @p max and emits signal maxProgress() /// If @p sm is not 0, max progress is also set for the schedule manager void setMaxProgress(int max, KPlato::ScheduleManager *sm = 0 ); + void swapScheduleManagers(KPlato::ScheduleManager *from, KPlato::ScheduleManager *to); + Q_SIGNALS: + void scheduleManagersSwapped(KPlato::ScheduleManager *from, KPlato::ScheduleManager *to); /// Emitted when the project is about to be deleted (The destroyed signal is disabled) void aboutToBeDeleted(); /// Emitted when anything in the project is changed (use with care) void projectChanged(); /// Emitted when the WBS code definition has changed. This may change all nodes. void wbsDefinitionChanged(); /// Emitted when a schedule has been calculated void projectCalculated(KPlato::ScheduleManager *sm); /// Emitted when the pointer to the current schedule has been changed void currentScheduleChanged(); /// Use to show progress during calculation void sigProgress( int ); /// Use to set the maximum progress (minimum always 0) void maxProgress( int ); /// Emitted when calculation starts void sigCalculationStarted(KPlato::Project *project, KPlato::ScheduleManager *sm); /// Emitted when calculation is finished void sigCalculationFinished(KPlato::Project *project, KPlato::ScheduleManager *sm); /// This signal is emitted when one of the nodes members is changed. void nodeChanged(KPlato::Node*); /// This signal is emitted when the node is to be added to the project. void nodeToBeAdded(KPlato::Node*, int); /// This signal is emitted when the node has been added to the project. void nodeAdded(KPlato::Node*); /// This signal is emitted when the node is to be removed from the project. void nodeToBeRemoved(KPlato::Node*); /// This signal is emitted when the node has been removed from the project. void nodeRemoved(KPlato::Node*); /// This signal is emitted when the node is to be moved up, moved down, indented or unindented. void nodeToBeMoved(KPlato::Node* node, int pos, KPlato::Node* newParent, int newPos); /// This signal is emitted when the node has been moved up, moved down, indented or unindented. void nodeMoved(KPlato::Node*); /// This signal is emitted when a document is added void documentAdded(KPlato::Node*, KPlato::Document*, int index); /// This signal is emitted when a document is removed void documentRemoved(KPlato::Node*, KPlato::Document*, int index); /// This signal is emitted when a document is changed void documentChanged(KPlato::Node*, KPlato::Document*, int index); void resourceGroupChanged(KPlato::ResourceGroup *group); void resourceGroupAdded(const KPlato::ResourceGroup *group); void resourceGroupToBeAdded(const KPlato::ResourceGroup *group, int row); void resourceGroupRemoved(const KPlato::ResourceGroup *group); void resourceGroupToBeRemoved(const KPlato::ResourceGroup *group); void resourceChanged(KPlato::Resource *resource); void resourceAdded(const KPlato::Resource *resource); void resourceToBeAdded(const KPlato::ResourceGroup *group, int row); void resourceRemoved(const KPlato::Resource *resource); void resourceToBeRemoved(const KPlato::Resource *resource); void scheduleManagerChanged(KPlato::ScheduleManager *sch); void scheduleManagerAdded(const KPlato::ScheduleManager *sch); void scheduleManagerToBeAdded(const KPlato::ScheduleManager *sch, int row); void scheduleManagerRemoved(const KPlato::ScheduleManager *sch); void scheduleManagerToBeRemoved(const KPlato::ScheduleManager *sch); void scheduleManagerMoved(const KPlato::ScheduleManager *sch, int row); void scheduleManagerToBeMoved(const KPlato::ScheduleManager *sch); void scheduleChanged(KPlato::MainSchedule *sch); void scheduleToBeAdded(const KPlato::ScheduleManager *manager, int row); void scheduleAdded(const KPlato::MainSchedule *sch); void scheduleToBeRemoved(const KPlato::MainSchedule *sch); void scheduleRemoved(const KPlato::MainSchedule *sch); // void currentViewScheduleIdChanged( long id ); void calendarChanged(KPlato::Calendar *cal); void calendarToBeAdded(const KPlato::Calendar *cal, int row); void calendarAdded(const KPlato::Calendar *cal); void calendarToBeRemoved(const KPlato::Calendar *cal); void calendarRemoved(const KPlato::Calendar *cal); /** * Emitted when the default calendar pointer has changed * @param cal The new default calendar. May be 0. */ void defaultCalendarChanged(KPlato::Calendar *cal); /** * Emitted when the standard worktime has been changed. */ void standardWorktimeChanged(KPlato::StandardWorktime*); /// Emitted when the relation @p rel is about to be added. void relationToBeAdded(KPlato::Relation *rel, int parentIndex, int childIndex); /// Emitted when the relation @p rel has been added. void relationAdded(KPlato::Relation *rel); /// Emitted when the relation @p rel is about to be removed. void relationToBeRemoved(KPlato::Relation *rel); /// Emitted when the relation @p rel has been removed. void relationRemoved(KPlato::Relation *rel); /// Emitted when the relation @p rel shall be modified. void relationToBeModified(KPlato::Relation *rel); /// Emitted when the relation @p rel has been modified. void relationModified(KPlato::Relation *rel); /// Emitted when locale data has changed void localeChanged(); protected: /// Calculate the schedule. void calculate( Schedule *scedule ); /// Calculate current schedule void calculate(); /// Re-calculate the schedule from @p dt void calculate( Schedule *scedule, const DateTime &dt ); /// Calculate current schedule from @p dt (Always calculates forward) void calculate( const DateTime &dt ); /// Calculate critical path virtual bool calcCriticalPath( bool fromEnd ); /// Prepare task lists for scheduling void tasksForward(); /// Prepare task lists for scheduling void tasksBackward(); protected: friend class KPlatoXmlLoaderBase; using Node::changed; virtual void changed(Node *node, int property = -1); Accounts m_accounts; QList m_resourceGroups; QList m_calendars; Calendar * m_defaultCalendar; StandardWorktime *m_standardWorktime; DateTime calculateForward( int use ); DateTime calculateBackward( int use ); DateTime scheduleForward( const DateTime &earliest, int use ); DateTime scheduleBackward( const DateTime &latest, int use ); DateTime checkStartConstraints( const DateTime &dt ) const; DateTime checkEndConstraints( const DateTime &dt ) const; bool legalParents( const Node *par, const Node *child ) const; bool legalChildren( const Node *par, const Node *child ) const; #ifndef PLAN_NLOGDEBUG private: static bool checkParent( Node *n, const QList &list, QList &checked ); static bool checkChildren( Node *n, const QList &list, QList &checked ); #endif private: void init(); QHash resourceGroupIdDict; QHash resourceIdDict; QHash nodeIdDict; QMap nodeIdReserved; QMap calendarIdDict; QMap m_managerIdMap; QList m_managers; QTimeZone m_timeZone; WBSDefinition m_wbsDefinition; ConfigBase emptyConfig; QPointer m_config; // this one is not owned by me, don't delete int m_progress; QMap m_schedulerPlugins; int m_refCount; // make it possible to use the project by different threads QList m_hardConstraints; QList m_softConstraints; QList m_terminalNodes; bool m_useSharedResources; bool m_sharedResourcesLoaded; QString m_sharedResourcesFile; QUrl m_sharedProjectsUrl; bool m_loadProjectsAtStartup; }; } //KPlato namespace #endif