File indexing completed on 2024-04-28 16:24:39

0001 /* This file is part of the KDE project
0002   Copyright (C) 1998, 1999, 2000 Torben Weis <weis@kde.org>
0003   Copyright (C) 2002 - 2011 Dag Andersen <danders@get2net.dk>
0004   Copyright (C) 2012 Dag Andersen <danders@get2net.dk>
0005   Copyright (C) 2019 Dag Andersen <danders@get2net.dk>
0006   
0007   This library is free software; you can redistribute it and/or
0008   modify it under the terms of the GNU Library General Public
0009   License as published by the Free Software Foundation; either
0010   version 2 of the License, or (at your option) any later version.
0011 
0012   This library is distributed in the hope that it will be useful,
0013   but WITHOUT ANY WARRANTY; without even the implied warranty of
0014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015   Library General Public License for more details.
0016 
0017   You should have received a copy of the GNU Library General Public License
0018   along with this library; see the file COPYING.LIB.  If not, write to
0019   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020 * Boston, MA 02110-1301, USA.
0021 */
0022 
0023 // clazy:excludeall=qstring-arg
0024 #include "kptview.h"
0025 
0026 #include <kmessagebox.h>
0027 #include <KRecentFilesAction>
0028 
0029 #include "KoDocumentInfo.h"
0030 #include "KoMainWindow.h"
0031 #include <KoIcon.h>
0032 #include <KoResourcePaths.h>
0033 #include <KoFileDialog.h>
0034 
0035 #include <QAction>
0036 #include <QApplication>
0037 #include <QLabel>
0038 #include <QString>
0039 #include <QStringList>
0040 #include <QStackedWidget>
0041 #include <QVBoxLayout>
0042 #include <QPrintDialog>
0043 #include <QDomDocument>
0044 #include <QDomElement>
0045 #include <kundo2command.h>
0046 #include <QTimer>
0047 #include <QDockWidget>
0048 #include <QMenu>
0049 #include <QTemporaryFile>
0050 #include <QFileDialog>
0051 #include <QStatusBar>
0052 
0053 #include <kactioncollection.h>
0054 #include <kactionmenu.h>
0055 #include <kstandardaction.h>
0056 #include <ktoolbar.h>
0057 #include <kxmlguifactory.h>
0058 #include <ktoggleaction.h>
0059 #include <ktoolinvocation.h>
0060 #include <krun.h>
0061 #include <khelpclient.h>
0062 
0063 #include <KoPart.h>
0064 #include <KoComponentData.h>
0065 #include <KoPluginLoader.h>
0066 
0067 #include "kptlocale.h"
0068 #include "kptviewbase.h"
0069 #include "kptaccountsview.h"
0070 #include "kptaccountseditor.h"
0071 #include "kptcalendareditor.h"
0072 #include "kptfactory.h"
0073 #include "kptmilestoneprogressdialog.h"
0074 #include "kpttaskdescriptiondialog.h"
0075 #include "kptdocumentsdialog.h"
0076 #include "kptnode.h"
0077 #include "kptmaindocument.h"
0078 #include "kptproject.h"
0079 #include "kptmainprojectdialog.h"
0080 #include "kpttask.h"
0081 #include "kptsummarytaskdialog.h"
0082 #include "kpttaskdialog.h"
0083 #include "kpttaskprogressdialog.h"
0084 #include "kptganttview.h"
0085 #include "kpttaskeditor.h"
0086 #include "kptdependencyeditor.h"
0087 #include "kptperteditor.h"
0088 #include "kptdatetime.h"
0089 #include "kptcommand.h"
0090 #include "kptrelation.h"
0091 #include "kptrelationdialog.h"
0092 #include "kptresourceappointmentsview.h"
0093 #include "kptresourceeditor.h"
0094 #include "kptscheduleeditor.h"
0095 #include "kptresourcedialog.h"
0096 #include "kptresource.h"
0097 #include "kptstandardworktimedialog.h"
0098 #include "kptwbsdefinitiondialog.h"
0099 #include "kptresourceassignmentview.h"
0100 #include "kpttaskstatusview.h"
0101 #include "kptsplitterview.h"
0102 #include "kptpertresult.h"
0103 #include "kptinsertfiledlg.h"
0104 #include "kptloadsharedprojectsdialog.h"
0105 #include "kptlocaleconfigmoneydialog.h"
0106 #include "kptflatproxymodel.h"
0107 #include "kpttaskstatusmodel.h"
0108 #include "kptworkpackagemergedialog.h"
0109 #include "Help.h"
0110 
0111 #include "performance/PerformanceStatusView.h"
0112 #include "performance/ProjectStatusView.h"
0113 
0114 #include "reportsgenerator/ReportsGeneratorView.h"
0115 
0116 #ifdef PLAN_USE_KREPORT
0117 #include "reports/reportview.h"
0118 #include "reports/reportdata.h"
0119 #endif
0120 
0121 #include "kptviewlistdialog.h"
0122 #include "kptviewlistdocker.h"
0123 #include "kptviewlist.h"
0124 #include "kptschedulesdocker.h"
0125 #include "kptpart.h"
0126 #include "kptdebug.h"
0127 
0128 #include "calligraplansettings.h"
0129 #include "kptprintingcontrolprivate.h"
0130 
0131 // #include "KPtViewAdaptor.h"
0132 
0133 #include <assert.h>
0134 
0135 using namespace KPlato;
0136 
0137 View::View(KoPart *part, MainDocument *doc, QWidget *parent)
0138         : KoView(part, doc, parent),
0139         m_currentEstimateType(Estimate::Use_Expected),
0140         m_scheduleActionGroup(new QActionGroup(this)),
0141         m_readWrite(false),
0142         m_defaultView(1),
0143         m_partpart (part)
0144 {
0145     //debugPlan;
0146     new Help(KPlatoSettings::contextPath(), KPlatoSettings::contextLanguage());
0147 
0148     doc->registerView(this);
0149 
0150     setComponentName(Factory::global().componentName(), Factory::global().componentDisplayName());
0151     if (!doc->isReadWrite())
0152         setXMLFile("calligraplan_readonly.rc");
0153     else
0154         setXMLFile("calligraplan.rc");
0155 
0156 //     new ViewAdaptor(this);
0157 
0158     m_sp = new QSplitter(this);
0159     QVBoxLayout *layout = new QVBoxLayout(this);
0160     layout->setMargin(0);
0161     layout->addWidget(m_sp);
0162 
0163     ViewListDocker *docker = 0;
0164     if (mainWindow() == 0) {
0165         // Don't use docker if embedded
0166         m_viewlist = new ViewListWidget(doc, m_sp);
0167         m_viewlist->setProject(&(getProject()));
0168         connect(m_viewlist, &ViewListWidget::selectionChanged, this, &View::slotSelectionChanged);
0169         connect(this, &View::currentScheduleManagerChanged, m_viewlist, &ViewListWidget::setSelectedSchedule);
0170         connect(m_viewlist, &ViewListWidget::updateViewInfo, this, &View::slotUpdateViewInfo);
0171     } else {
0172         ViewListDockerFactory vl(this);
0173         docker = static_cast<ViewListDocker *>(mainWindow()->createDockWidget(&vl));
0174         if (docker->view() != this) {
0175             docker->setView(this);
0176         }
0177         m_viewlist = docker->viewList();
0178 #if 0        //SchedulesDocker
0179         SchedulesDockerFactory sdf;
0180         SchedulesDocker *sd = dynamic_cast<SchedulesDocker*>(createDockWidget(&sdf));
0181         Q_ASSERT(sd);
0182 
0183         sd->setProject(&getProject());
0184         connect(sd, SIGNAL(selectionChanged(KPlato::ScheduleManager*)), SLOT(slotSelectionChanged(KPlato::ScheduleManager*)));
0185         connect(this, &View::currentScheduleManagerChanged, sd, SLOT(setSelectedSchedule(KPlato::ScheduleManager*)));
0186 #endif
0187     }
0188 
0189     m_tab = new QStackedWidget(m_sp);
0190 
0191 ////////////////////////////////////////////////////////////////////////////////////////////////////
0192 
0193     // Add sub views
0194 
0195     // The menu items
0196     // ------ File
0197     actionCreateTemplate = new QAction(koIcon("document-save-as-template"), i18n("Create Project Template..."), this);
0198     actionCollection()->addAction("file_createtemplate", actionCreateTemplate);
0199     connect(actionCreateTemplate, SIGNAL(triggered(bool)), SLOT(slotCreateTemplate()));
0200 
0201     actionCreateNewProject = new QAction(i18n("Create New Project..."), this);
0202     actionCollection()->addAction("file_createnewproject", actionCreateNewProject);
0203     connect(actionCreateNewProject, &QAction::triggered, this, &View::slotCreateNewProject);
0204 
0205     // ------ Edit
0206     actionCut = actionCollection()->addAction(KStandardAction::Cut,  "edit_cut", this, SLOT(slotEditCut()));
0207     actionCopy = actionCollection()->addAction(KStandardAction::Copy,  "edit_copy", this, SLOT(slotEditCopy()));
0208     actionPaste = actionCollection()->addAction(KStandardAction::Paste,  "edit_paste", this, SLOT(slotEditPaste()));
0209 
0210     // ------ View
0211     actionCollection()->addAction(KStandardAction::Redisplay, "view_refresh" , this, SLOT(slotRefreshView()));
0212 
0213     actionViewSelector  = new KToggleAction(i18n("Show Selector"), this);
0214     actionCollection()->addAction("view_show_selector", actionViewSelector);
0215     connect(actionViewSelector, &QAction::triggered, this, &View::slotViewSelector);
0216 
0217     // ------ Insert
0218 
0219     // ------ Project
0220     actionEditMainProject  = new QAction(koIcon("view-time-schedule-edit"), i18n("Edit..."), this);
0221     actionCollection()->addAction("project_edit", actionEditMainProject);
0222     connect(actionEditMainProject, &QAction::triggered, this, &View::slotProjectEdit);
0223 
0224     actionEditStandardWorktime  = new QAction(koIcon("configure"), i18n("Define Estimate Conversions..."), this);
0225     actionCollection()->addAction("project_worktime", actionEditStandardWorktime);
0226     connect(actionEditStandardWorktime, &QAction::triggered, this, &View::slotProjectWorktime);
0227 
0228     actionDefineWBS  = new QAction(koIcon("configure"), i18n("Define WBS Pattern..."), this);
0229     actionCollection()->addAction("tools_define_wbs", actionDefineWBS);
0230     connect(actionDefineWBS, &QAction::triggered, this, &View::slotDefineWBS);
0231 
0232     actionCurrencyConfig  = new QAction(koIcon("configure"), i18n("Define Currency..."), this);
0233     actionCollection()->addAction("config_currency", actionCurrencyConfig);
0234     connect(actionCurrencyConfig, &QAction::triggered, this, &View::slotCurrencyConfig);
0235 
0236     QAction *actionProjectDescription = new QAction(koIcon("document-edit"), i18n("Edit Description..."), this);
0237     actionCollection()->addAction("edit_project_description", actionProjectDescription);
0238     connect(actionProjectDescription, &QAction::triggered, this, &View::slotOpenProjectDescription);
0239 
0240     // ------ Tools
0241     actionInsertFile  = new QAction(koIcon("document-import"), i18n("Insert Project File..."), this);
0242     actionCollection()->addAction("insert_file", actionInsertFile);
0243     connect(actionInsertFile, &QAction::triggered, this, &View::slotInsertFile);
0244 
0245     actionLoadSharedProjects  = new QAction(koIcon("document-import"), i18n("Load Shared Projects..."), this);
0246     actionCollection()->addAction("load_shared_projects", actionLoadSharedProjects);
0247     connect(actionLoadSharedProjects, &QAction::triggered, this, &View::slotLoadSharedProjects);
0248 
0249 #ifdef PLAN_USE_KREPORT
0250     actionOpenReportFile  = new QAction(koIcon("document-open"), i18n("Open Report Definition File..."), this);
0251     actionCollection()->addAction("reportdesigner_open_file", actionOpenReportFile);
0252     connect(actionOpenReportFile, QAction::triggered, this, &View::slotOpenReportFile);
0253 #endif
0254 
0255     // ------ Popup
0256     actionOpenNode  = new QAction(koIcon("document-edit"), i18n("Edit..."), this);
0257     actionCollection()->addAction("node_properties", actionOpenNode);
0258     connect(actionOpenNode, &QAction::triggered, this, &View::slotOpenCurrentNode);
0259     actionTaskProgress  = new QAction(koIcon("document-edit"), i18n("Progress..."), this);
0260     actionCollection()->addAction("task_progress", actionTaskProgress);
0261     connect(actionTaskProgress, &QAction::triggered, this, &View::slotTaskProgress);
0262     actionDeleteTask  = new QAction(koIcon("edit-delete"), i18n("Delete Task"), this);
0263     actionCollection()->addAction("delete_task", actionDeleteTask);
0264     connect(actionDeleteTask, &QAction::triggered, this, &View::slotDeleteCurrentTask);
0265     actionTaskDescription  = new QAction(koIcon("document-edit"), i18n("Description..."), this);
0266     actionCollection()->addAction("task_description", actionTaskDescription);
0267     connect(actionTaskDescription, &QAction::triggered, this, &View::slotTaskDescription);
0268     actionDocuments  = new QAction(koIcon("document-edit"), i18n("Documents..."), this);
0269     actionCollection()->addAction("task_documents", actionDocuments);
0270     connect(actionDocuments, &QAction::triggered, this, &View::slotDocuments);
0271     actionIndentTask = new QAction(koIcon("format-indent-more"), i18n("Indent Task"), this);
0272     actionCollection()->addAction("indent_task", actionIndentTask);
0273     connect(actionIndentTask, &QAction::triggered, this, &View::slotIndentTask);
0274     actionUnindentTask= new QAction(koIcon("format-indent-less"), i18n("Unindent Task"), this);
0275     actionCollection()->addAction("unindent_task", actionUnindentTask);
0276     connect(actionUnindentTask, &QAction::triggered, this, &View::slotUnindentTask);
0277     actionMoveTaskUp = new QAction(koIcon("arrow-up"), i18n("Move Task Up"), this);
0278     actionCollection()->addAction("move_task_up", actionMoveTaskUp);
0279     connect(actionMoveTaskUp, &QAction::triggered, this, &View::slotMoveTaskUp);
0280     actionMoveTaskDown = new QAction(koIcon("arrow-down"), i18n("Move Task Down"), this);
0281     actionCollection()->addAction("move_task_down", actionMoveTaskDown);
0282     connect(actionMoveTaskDown, &QAction::triggered, this, &View::slotMoveTaskDown);
0283 
0284     actionEditResource  = new QAction(koIcon("document-edit"), i18n("Edit Resource..."), this);
0285     actionCollection()->addAction("edit_resource", actionEditResource);
0286     connect(actionEditResource, &QAction::triggered, this, &View::slotEditCurrentResource);
0287 
0288     actionEditRelation  = new QAction(koIcon("document-edit"), i18n("Edit Dependency..."), this);
0289     actionCollection()->addAction("edit_dependency", actionEditRelation);
0290     connect(actionEditRelation, &QAction::triggered, this, &View::slotModifyCurrentRelation);
0291     actionDeleteRelation  = new QAction(koIcon("edit-delete"), i18n("Delete Dependency"), this);
0292     actionCollection()->addAction("delete_dependency", actionDeleteRelation);
0293     connect(actionDeleteRelation, &QAction::triggered, this, &View::slotDeleteRelation);
0294 
0295     // Viewlist popup
0296     connect(m_viewlist, &ViewListWidget::createView, this, &View::slotCreateView);
0297 
0298     m_workPackageButton = new QToolButton(this);
0299     m_workPackageButton->hide();
0300     m_workPackageButton->setIcon(koIcon("application-x-vnd.kde.plan.work"));
0301     m_workPackageButton->setText(i18n("Work Packages..."));
0302     m_workPackageButton->setToolTip(i18nc("@info:tooltip", "Work packages available"));
0303     m_workPackageButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
0304     connect(m_workPackageButton, &QToolButton::clicked, this, &View::openWorkPackageMergeDialog);
0305     m_estlabel = new QLabel("", 0);
0306     if (statusBar()) {
0307         addStatusBarItem(m_estlabel, 0, true);
0308     }
0309 
0310     connect(&getProject(), &Project::scheduleManagerAdded, this, &View::slotScheduleAdded);
0311     connect(&getProject(), &Project::scheduleManagerRemoved, this, &View::slotScheduleRemoved);
0312     connect(&getProject(), &Project::scheduleManagersSwapped, this, &View::slotScheduleSwapped);
0313     connect(&getProject(), &Project::sigCalculationFinished, this, &View::slotScheduleCalculated);
0314     slotPlugScheduleActions();
0315 
0316     connect(doc, &MainDocument::changed, this, &View::slotUpdate);
0317 
0318     connect(m_scheduleActionGroup, &QActionGroup::triggered, this, &View::slotViewSchedule);
0319 
0320 
0321     connect(getPart(), &MainDocument::workPackageLoaded, this, &View::slotWorkPackageLoaded);
0322 
0323     // views take time for large projects
0324     QTimer::singleShot(0, this, &View::initiateViews);
0325 
0326     const QList<KPluginFactory *> pluginFactories =
0327         KoPluginLoader::instantiatePluginFactories(QStringLiteral("calligraplan/extensions"));
0328 
0329     foreach (KPluginFactory* factory, pluginFactories) {
0330         QObject *object = factory->create<QObject>(this, QVariantList());
0331         KXMLGUIClient *clientPlugin = dynamic_cast<KXMLGUIClient*>(object);
0332         if (clientPlugin) {
0333             insertChildClient(clientPlugin);
0334         } else {
0335             // not our/valid plugin, so delete the created object
0336             object->deleteLater();
0337         }
0338     }
0339     //debugPlan<<" end";
0340 }
0341 
0342 View::~View()
0343 {
0344     // Disconnect and delete so we do not get called by destroyed() signal
0345     const QMap<QAction*, ScheduleManager*> map = m_scheduleActions; // clazy:exclude=qmap-with-pointer-key
0346     QMap<QAction*, ScheduleManager*>::const_iterator it;
0347     for (it = map.constBegin(); it != map.constEnd(); ++it) {
0348         disconnect(it.key(), &QObject::destroyed, this, &View::slotActionDestroyed);
0349         m_scheduleActionGroup->removeAction(it.key());
0350         delete it.key();
0351     }
0352     ViewBase *view = currentView();
0353     if (view) {
0354         // deactivate view to remove dockers etc
0355         slotGuiActivated(view, false);
0356     }
0357     /*    removeStatusBarItem(m_estlabel);
0358     delete m_estlabel;*/
0359 }
0360 
0361 void View::initiateViews()
0362 {
0363     QApplication::setOverrideCursor(Qt::WaitCursor);
0364     createViews();
0365 
0366     connect(m_viewlist, &ViewListWidget::activated, this, &View::slotViewActivated);
0367     // after createViews() !!
0368     connect(m_viewlist, &ViewListWidget::viewListItemRemoved, this, &View::slotViewListItemRemoved);
0369     // after createViews() !!
0370     connect(m_viewlist, &ViewListWidget::viewListItemInserted, this, &View::slotViewListItemInserted);
0371 
0372     ViewListDocker *docker = qobject_cast<ViewListDocker*>(m_viewlist->parent());
0373     if (docker) {
0374         // after createViews() !!
0375         connect(m_viewlist, &ViewListWidget::modified, docker, &ViewListDocker::slotModified);
0376         connect(m_viewlist, &ViewListWidget::modified, getPart(), &MainDocument::slotViewlistModified);
0377         connect(getPart(), &MainDocument::viewlistModified, docker, &ViewListDocker::updateWindowTitle);
0378     }
0379     connect(m_tab, &QStackedWidget::currentChanged, this, &View::slotCurrentChanged);
0380 
0381     slotSelectDefaultView();
0382 
0383     loadContext();
0384 
0385     QApplication::restoreOverrideCursor();
0386 }
0387 
0388 void View::slotCreateNewProject()
0389 {
0390     debugPlan;
0391     if (KMessageBox::Continue == KMessageBox::warningContinueCancel(this,
0392                       xi18nc("@info",
0393                              "<note>This action cannot be undone.</note><nl/><nl/>"
0394                              "Create a new Project from the current project "
0395                              "with new project- and task identities.<nl/>"
0396                              "Resource- and calendar identities are not changed.<nl/>"
0397                              "All scheduling information is removed.<nl/>"
0398                              "<nl/>Do you want to continue?")))
0399     {
0400         emit currentScheduleManagerChanged(0);
0401         getPart()->createNewProject();
0402         slotOpenNode(&getProject());
0403     }
0404 }
0405 
0406 void View::slotCreateTemplate()
0407 {
0408     debugPlan;
0409     KoFileDialog dlg(nullptr, KoFileDialog::SaveFile, "Create Template");
0410     dlg.setNameFilters(QStringList()<<"Plan Template (*.plant)");
0411     QString file = dlg.filename();
0412     if (!file.isEmpty()) {
0413         QTemporaryDir dir;
0414         dir.setAutoRemove(false);
0415         QString tmpfile = dir.path() + '/' + QUrl(file).fileName();
0416         tmpfile.replace(".plant", ".plan");
0417         Part *part = new Part(this);
0418         MainDocument *doc = new MainDocument(part);
0419         part->setDocument(doc);
0420         doc->disconnect(); // doc shall not handle feedback from openUrl()
0421         doc->setAutoSave(0); //disable
0422         bool ok = koDocument()->exportDocument(QUrl::fromUserInput("file:/" + tmpfile));
0423         ok &= doc->loadNativeFormat(tmpfile);
0424         if (ok) {
0425             // strip unused data
0426             Project *project = doc->project();
0427             for (ScheduleManager *sm : project->scheduleManagers()) {
0428                 DeleteScheduleManagerCmd c(*project, sm);
0429                 c.redo();
0430             }
0431         }
0432         ok &= doc->saveNativeFormat(file);
0433 
0434         part->deleteLater();
0435     }
0436 }
0437 
0438 void View::createViews()
0439 {
0440     Context *ctx = getPart()->context();
0441     if (ctx && ctx->isLoaded()) {
0442         debugPlan<<"isLoaded";
0443         KoXmlNode n = ctx->context().namedItem("categories");
0444         if (n.isNull()) {
0445             warnPlan<<"No categories";
0446         } else {
0447             n = n.firstChild();
0448             for (; ! n.isNull(); n = n.nextSibling()) {
0449                 if (! n.isElement()) {
0450                     continue;
0451                 }
0452                 KoXmlElement e = n.toElement();
0453                 if (e.tagName() != "category") {
0454                     continue;
0455                 }
0456                 debugPlan<<"category: "<<e.attribute("tag");
0457                 ViewListItem *cat;
0458                 QString cn = e.attribute("name");
0459                 QString ct = e.attribute("tag");
0460                 if (cn.isEmpty()) {
0461                     cn = defaultCategoryInfo(ct).name;
0462                 }
0463                 cat = m_viewlist->addCategory(ct, cn);
0464                 KoXmlNode n1 = e.firstChild();
0465                 for (; ! n1.isNull(); n1 = n1.nextSibling()) {
0466                     if (! n1.isElement()) {
0467                         continue;
0468                     }
0469                     KoXmlElement e1 = n1.toElement();
0470                     if (e1.tagName() != "view") {
0471                         continue;
0472                     }
0473                     ViewBase *v = 0;
0474                     QString type = e1.attribute("viewtype");
0475                     QString tag = e1.attribute("tag");
0476                     QString name = e1.attribute("name");
0477                     QString tip = e1.attribute("tooltip");
0478                     v = createView(cat, type, tag, name, tip);
0479                     //KoXmlNode settings = e1.namedItem("settings "); ????
0480                     KoXmlNode settings = e1.firstChild();
0481                     for (; ! settings.isNull(); settings = settings.nextSibling()) {
0482                         if (settings.nodeName() == "settings") {
0483                             break;
0484                         }
0485                     }
0486                     if (v && settings.isElement()) {
0487                         debugPlan<<" settings";
0488                         v->loadContext(settings.toElement());
0489                     }
0490                 }
0491             }
0492         }
0493     } else {
0494         debugPlan<<"Default";
0495         ViewBase *v = 0;
0496         ViewListItem *cat;
0497         QString ct = "Editors";
0498         cat = m_viewlist->addCategory(ct, defaultCategoryInfo(ct).name);
0499 
0500         createCalendarEditor(cat, "CalendarEditor", QString(), TIP_USE_DEFAULT_TEXT);
0501 
0502         createAccountsEditor(cat, "AccountsEditor", QString(), TIP_USE_DEFAULT_TEXT);
0503 
0504         v = createResourceEditor(cat, "ResourceEditor", QString(), TIP_USE_DEFAULT_TEXT);
0505 
0506         v = createTaskEditor(cat, "TaskEditor", QString(), TIP_USE_DEFAULT_TEXT);
0507         m_defaultView = m_tab->count() - 1;
0508         v->showColumns(QList<int>() << NodeModel::NodeName
0509                                     << NodeModel::NodeType
0510                                     << NodeModel::NodeAllocation
0511                                     << NodeModel::NodeEstimateCalendar
0512                                     << NodeModel::NodeEstimate
0513                                     << NodeModel::NodeOptimisticRatio
0514                                     << NodeModel::NodePessimisticRatio
0515                                     << NodeModel::NodeRisk
0516                                     << NodeModel::NodeResponsible
0517                                     << NodeModel::NodeDescription
0518                     );
0519 
0520         v = createTaskEditor(cat, "TaskConstraintEditor", i18n("Task Constraints"), i18n("Edit task scheduling constraints"));
0521         v->showColumns(QList<int>() << NodeModel::NodeName
0522                                     << NodeModel::NodeType
0523                                     << NodeModel::NodePriority
0524                                     << NodeModel::NodeConstraint
0525                                     << NodeModel::NodeConstraintStart
0526                                     << NodeModel::NodeConstraintEnd
0527                                     << NodeModel::NodeDescription
0528                       );
0529 
0530         v = createTaskEditor(cat, "TaskCostEditor", i18n("Task Cost"), i18n("Edit task cost"));
0531         v->showColumns(QList<int>() << NodeModel::NodeName
0532                                     << NodeModel::NodeType
0533                                     << NodeModel::NodeRunningAccount
0534                                     << NodeModel::NodeStartupAccount
0535                                     << NodeModel::NodeStartupCost
0536                                     << NodeModel::NodeShutdownAccount
0537                                     << NodeModel::NodeShutdownCost
0538                                     << NodeModel::NodeDescription
0539                       );
0540 
0541         createDependencyEditor(cat, "DependencyEditor", QString(), TIP_USE_DEFAULT_TEXT);
0542 
0543         // Do not show by default
0544         // createPertEditor(cat, "PertEditor", QString(), TIP_USE_DEFAULT_TEXT);
0545 
0546         createScheduleHandler(cat, "ScheduleHandlerView", QString(), TIP_USE_DEFAULT_TEXT);
0547 
0548         ct = "Views";
0549         cat = m_viewlist->addCategory(ct, defaultCategoryInfo(ct).name);
0550 
0551         createGanttView(cat, "GanttView", QString(), TIP_USE_DEFAULT_TEXT);
0552 
0553         createMilestoneGanttView(cat, "MilestoneGanttView", QString(), TIP_USE_DEFAULT_TEXT);
0554 
0555         createResourceAppointmentsView(cat, "ResourceAppointmentsView", QString(), TIP_USE_DEFAULT_TEXT);
0556 
0557         createResourceAppointmentsGanttView(cat, "ResourceAppointmentsGanttView", QString(), TIP_USE_DEFAULT_TEXT);
0558 
0559         createAccountsView(cat, "AccountsView", QString(), TIP_USE_DEFAULT_TEXT);
0560 
0561         ct = "Execution";
0562         cat = m_viewlist->addCategory(ct, defaultCategoryInfo(ct).name);
0563 
0564         createProjectStatusView(cat, "ProjectStatusView", QString(), TIP_USE_DEFAULT_TEXT);
0565 
0566         createPerformanceStatusView(cat, "PerformanceStatusView", QString(), TIP_USE_DEFAULT_TEXT);
0567 
0568         v = createTaskStatusView(cat, "TaskStatusView", QString(), TIP_USE_DEFAULT_TEXT);
0569 
0570         v = createTaskView(cat, "TaskView", QString(), TIP_USE_DEFAULT_TEXT);
0571 
0572         v = createTaskWorkPackageView(cat, "TaskWorkPackageView", QString(), TIP_USE_DEFAULT_TEXT);
0573 
0574         ct = "Reports";
0575         cat = m_viewlist->addCategory(ct, defaultCategoryInfo(ct).name);
0576 
0577         createReportsGeneratorView(cat, "ReportsGeneratorView", i18n("Generate reports"), TIP_USE_DEFAULT_TEXT);
0578 
0579 #ifdef PLAN_USE_KREPORT
0580         // Let user add reports explicitly, we prefer reportsgenerator now
0581         // A little hack to get the user started...
0582 #if 0
0583         ReportView *rv = qobject_cast<ReportView*>(createReportView(cat, "ReportView", i18n("Task Status Report"), TIP_USE_DEFAULT_TEXT));
0584         if (rv) {
0585             QDomDocument doc;
0586             doc.setContent(standardTaskStatusReport());
0587             rv->loadXML(doc);
0588         }
0589 #endif
0590 #endif
0591     }
0592 }
0593 
0594 ViewBase *View::createView(ViewListItem *cat, const QString &type, const QString &tag, const QString &name, const QString &tip, int index)
0595 {
0596     ViewBase *v = 0;
0597     //NOTE: type is the same as classname (so if it is changed...)
0598     if (type == "CalendarEditor") {
0599         v = createCalendarEditor(cat, tag, name, tip, index);
0600     } else if (type == "AccountsEditor") {
0601         v = createAccountsEditor(cat, tag, name, tip, index);
0602     } else if (type == "ResourceEditor") {
0603         v = createResourceEditor(cat, tag, name, tip, index);
0604     } else if (type == "TaskEditor") {
0605         v = createTaskEditor(cat, tag, name, tip, index);
0606     } else if (type == "DependencyEditor") {
0607         v = createDependencyEditor(cat, tag, name, tip, index);
0608     } else if (type == "PertEditor") {
0609         v = createPertEditor(cat, tag, name, tip, index);
0610     } else if (type == "ScheduleEditor") {
0611         v = createScheduleEditor(cat, tag, name, tip, index);
0612     } else if (type == "ScheduleHandlerView") {
0613         v = createScheduleHandler(cat, tag, name, tip, index);
0614     } else if (type == "ProjectStatusView") {
0615         v = createProjectStatusView(cat, tag, name, tip, index);
0616     } else if (type == "TaskStatusView") {
0617         v = createTaskStatusView(cat, tag, name, tip, index);
0618     } else if (type == "TaskView") {
0619         v = createTaskView(cat, tag, name, tip, index);
0620     } else if (type == "TaskWorkPackageView") {
0621         v = createTaskWorkPackageView(cat, tag, name, tip, index);
0622     } else if (type == "GanttView") {
0623         v = createGanttView(cat, tag, name, tip, index);
0624     } else if (type == "MilestoneGanttView") {
0625         v = createMilestoneGanttView(cat, tag, name, tip, index);
0626     } else if (type == "ResourceAppointmentsView") {
0627         v = createResourceAppointmentsView(cat, tag, name, tip, index);
0628     } else if (type == "ResourceAppointmentsGanttView") {
0629         v = createResourceAppointmentsGanttView(cat, tag, name, tip, index);
0630     } else if (type == "AccountsView") {
0631         v = createAccountsView(cat, tag, name, tip, index);
0632     } else if (type == "PerformanceStatusView") {
0633         v = createPerformanceStatusView(cat, tag, name, tip, index);
0634     } else if (type == "ReportsGeneratorView") {
0635         v = createReportsGeneratorView(cat, tag, name, tip, index);
0636     } else if (type == "ReportView") {
0637 #ifdef PLAN_USE_KREPORT
0638         v = createReportView(cat, tag, name, tip, index);
0639 #endif
0640     } else  {
0641         warnPlan<<"Unknown viewtype: "<<type;
0642     }
0643     return v;
0644 }
0645 
0646 void View::slotUpdateViewInfo(ViewListItem *itm)
0647 {
0648     if (itm->type() == ViewListItem::ItemType_SubView) {
0649         itm->setViewInfo(defaultViewInfo(itm->viewType()));
0650     } else if (itm->type() == ViewListItem::ItemType_Category) {
0651         ViewInfo vi = defaultCategoryInfo(itm->tag());
0652         itm->setViewInfo(vi);
0653     }
0654 }
0655 
0656 ViewInfo View::defaultViewInfo(const QString &type) const
0657 {
0658     ViewInfo vi;
0659     if (type == "CalendarEditor") {
0660         vi.name = i18n("Work & Vacation");
0661         vi.tip = xi18nc("@info:tooltip", "Edit working- and vacation days for resources");
0662     } else if (type == "AccountsEditor") {
0663         vi.name = i18n("Cost Breakdown Structure");
0664         vi.tip = xi18nc("@info:tooltip", "Edit cost breakdown structure.");
0665     } else if (type == "ResourceEditor") {
0666         vi.name = i18n("Resources");
0667         vi.tip = xi18nc("@info:tooltip", "Edit resource breakdown structure");
0668     } else if (type == "TaskEditor") {
0669         vi.name = i18n("Tasks");
0670         vi.tip = xi18nc("@info:tooltip", "Edit work breakdown structure");
0671     } else if (type == "DependencyEditor") {
0672         vi.name = i18n("Dependencies (Graphic)");
0673         vi.tip = xi18nc("@info:tooltip", "Edit task dependencies");
0674     } else if (type == "PertEditor") {
0675         vi.name = i18n("Dependencies (List)");
0676         vi.tip = xi18nc("@info:tooltip", "Edit task dependencies");
0677     } else if (type == "ScheduleEditor") {
0678         // This view is not used stand-alone atm
0679         vi.name = i18n("Schedules");
0680     } else if (type == "ScheduleHandlerView") {
0681         vi.name = i18n("Schedules");
0682         vi.tip = xi18nc("@info:tooltip", "Calculate and analyze project schedules");
0683     } else if (type == "ProjectStatusView") {
0684         vi.name = i18n("Project Performance Chart");
0685         vi.tip = xi18nc("@info:tooltip", "View project status information");
0686     } else if (type == "TaskStatusView") {
0687         vi.name = i18n("Task Status");
0688         vi.tip = xi18nc("@info:tooltip", "View task progress information");
0689     } else if (type == "TaskView") {
0690         vi.name = i18n("Task Execution");
0691         vi.tip = xi18nc("@info:tooltip", "View task execution information");
0692     } else if (type == "TaskWorkPackageView") {
0693         vi.name = i18n("Work Package View");
0694         vi.tip = xi18nc("@info:tooltip", "View task work package information");
0695     } else if (type == "GanttView") {
0696         vi.name = i18n("Gantt");
0697         vi.tip = xi18nc("@info:tooltip", "View Gantt chart");
0698     } else if (type == "MilestoneGanttView") {
0699         vi.name = i18n("Milestone Gantt");
0700         vi.tip = xi18nc("@info:tooltip", "View milestone Gantt chart");
0701     } else if (type == "ResourceAppointmentsView") {
0702         vi.name = i18n("Resource Assignments");
0703         vi.tip = xi18nc("@info:tooltip", "View resource assignments in a table");
0704     } else if (type == "ResourceAppointmentsGanttView") {
0705         vi.name = i18n("Resource Assignments (Gantt)");
0706         vi.tip = xi18nc("@info:tooltip", "View resource assignments in Gantt chart");
0707     } else if (type == "AccountsView") {
0708         vi.name = i18n("Cost Breakdown");
0709         vi.tip = xi18nc("@info:tooltip", "View planned and actual cost");
0710     } else if (type == "PerformanceStatusView") {
0711         vi.name = i18n("Tasks Performance Chart");
0712         vi.tip = xi18nc("@info:tooltip", "View tasks performance status information");
0713     } else if (type == "ReportsGeneratorView") {
0714         vi.name = i18n("Reports Generator");
0715         vi.tip = xi18nc("@info:tooltip", "Generate reports");
0716     } else if (type == "ReportView") {
0717         vi.name = i18n("Report");
0718         vi.tip = xi18nc("@info:tooltip", "View report");
0719     } else  {
0720         warnPlan<<"Unknown viewtype: "<<type;
0721     }
0722     return vi;
0723 }
0724 
0725 ViewInfo View::defaultCategoryInfo(const QString &type) const
0726 {
0727     ViewInfo vi;
0728     if (type == "Editors") {
0729         vi.name = i18n("Editors");
0730     } else if (type == "Views") {
0731         vi.name = i18n("Views");
0732     } else if (type == "Execution") {
0733         vi.name = i18nc("Project execution views", "Execution");
0734     } else if (type == "Reports") {
0735         vi.name = i18n("Reports");
0736     }
0737     return vi;
0738 }
0739 
0740 ViewBase *View::createResourceAppointmentsGanttView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
0741 {
0742     ResourceAppointmentsGanttView *v = new ResourceAppointmentsGanttView(getKoPart(), getPart(), m_tab);
0743     m_tab->addWidget(v);
0744 
0745     ViewListItem *i = m_viewlist->addView(cat, tag, name, v, getPart(), "", index);
0746     ViewInfo vi = defaultViewInfo("ResourceAppointmentsGanttView");
0747     if (name.isEmpty()) {
0748         i->setText(0, vi.name);
0749     }
0750     if (tip == TIP_USE_DEFAULT_TEXT) {
0751         i->setToolTip(0, vi.tip);
0752     } else {
0753         i->setToolTip(0, tip);
0754     }
0755 
0756 
0757     connect(v, &ViewBase::guiActivated, this, &View::slotGuiActivated);
0758 
0759     connect(this, &View::currentScheduleManagerChanged, v, &ResourceAppointmentsGanttView::setScheduleManager);
0760 
0761     connect(v, &ResourceAppointmentsGanttView::requestPopupMenu, this, &View::slotPopupMenuRequested);
0762 
0763     v->setProject(&(getProject()));
0764     v->setScheduleManager(currentScheduleManager());
0765     v->updateReadWrite(m_readWrite);
0766     return v;
0767 }
0768 
0769 
0770 ViewBase *View::createResourceAppointmentsView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
0771 {
0772     ResourceAppointmentsView *v = new ResourceAppointmentsView(getKoPart(), getPart(), m_tab);
0773     m_tab->addWidget(v);
0774 
0775     ViewListItem *i = m_viewlist->addView(cat, tag, name, v, getPart(), "", index);
0776     ViewInfo vi = defaultViewInfo("ResourceAppointmentsView");
0777     if (name.isEmpty()) {
0778         i->setText(0, vi.name);
0779     }
0780     if (tip == TIP_USE_DEFAULT_TEXT) {
0781         i->setToolTip(0, vi.tip);
0782     } else {
0783         i->setToolTip(0, tip);
0784     }
0785 
0786     connect(v, &ViewBase::guiActivated, this, &View::slotGuiActivated);
0787 
0788     connect(this, &View::currentScheduleManagerChanged, v, &ResourceAppointmentsView::setScheduleManager);
0789 
0790     connect(v, &ResourceAppointmentsView::requestPopupMenu, this, &View::slotPopupMenuRequested);
0791 
0792     v->setProject(&(getProject()));
0793     v->setScheduleManager(currentScheduleManager());
0794     v->updateReadWrite(m_readWrite);
0795     return v;
0796 }
0797 
0798 ViewBase *View::createResourceEditor(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
0799 {
0800     ResourceEditor *resourceeditor = new ResourceEditor(getKoPart(), getPart(), m_tab);
0801     resourceeditor->setViewSplitMode(false);
0802     m_tab->addWidget(resourceeditor);
0803     resourceeditor->setProject(&(getProject()));
0804 
0805     ViewListItem *i = m_viewlist->addView(cat, tag, name, resourceeditor, getPart(), "", index);
0806     ViewInfo vi = defaultViewInfo("ResourceEditor");
0807     if (name.isEmpty()) {
0808         i->setText(0, vi.name);
0809     }
0810     if (tip == TIP_USE_DEFAULT_TEXT) {
0811         i->setToolTip(0, vi.tip);
0812     } else {
0813         i->setToolTip(0, tip);
0814     }
0815 
0816     connect(resourceeditor, &ViewBase::guiActivated, this, &View::slotGuiActivated);
0817 
0818     connect(resourceeditor, &ResourceEditor::deleteObjectList, this, &View::slotDeleteResourceObjects);
0819 
0820     connect(resourceeditor, &ResourceEditor::requestPopupMenu, this, &View::slotPopupMenuRequested);
0821     resourceeditor->updateReadWrite(m_readWrite);
0822     return resourceeditor;
0823 }
0824 
0825 ViewBase *View::createTaskEditor(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
0826 {
0827     TaskEditor *taskeditor = new TaskEditor(getKoPart(), getPart(), m_tab);
0828     taskeditor->setViewSplitMode(false);
0829     m_tab->addWidget(taskeditor);
0830 
0831     ViewListItem *i = m_viewlist->addView(cat, tag, name, taskeditor, getPart(), "", index);
0832     ViewInfo vi = defaultViewInfo("TaskEditor");
0833     if (name.isEmpty()) {
0834         i->setText(0, vi.name);
0835     }
0836     if (tip == TIP_USE_DEFAULT_TEXT) {
0837         i->setToolTip(0, vi.tip);
0838     } else {
0839         i->setToolTip(0, tip);
0840     }
0841 
0842     taskeditor->setProject(&(getProject()));
0843     taskeditor->setScheduleManager(currentScheduleManager());
0844 
0845     connect(this, &View::currentScheduleManagerChanged, taskeditor, &TaskEditor::setScheduleManager);
0846 
0847     connect(taskeditor, &ViewBase::guiActivated, this, &View::slotGuiActivated);
0848 
0849     connect(taskeditor, &TaskEditor::addTask, this, &View::slotAddTask);
0850     connect(taskeditor, &TaskEditor::addMilestone, this, &View::slotAddMilestone);
0851     connect(taskeditor, &TaskEditor::addSubtask, this, &View::slotAddSubTask);
0852     connect(taskeditor, &TaskEditor::addSubMilestone, this, &View::slotAddSubMilestone);
0853     connect(taskeditor, &TaskEditor::deleteTaskList, this, &View::slotDeleteTaskList);
0854     connect(taskeditor, &TaskEditor::moveTaskUp, this, &View::slotMoveTaskUp);
0855     connect(taskeditor, &TaskEditor::moveTaskDown, this, &View::slotMoveTaskDown);
0856     connect(taskeditor, &TaskEditor::indentTask, this, &View::slotIndentTask);
0857     connect(taskeditor, &TaskEditor::unindentTask, this, &View::slotUnindentTask);
0858 
0859     connect(taskeditor, &TaskEditor::saveTaskModule, this, &View::saveTaskModule);
0860     connect(taskeditor, &TaskEditor::removeTaskModule, this, &View::removeTaskModule);
0861     connect(taskeditor, &ViewBase::openDocument, static_cast<KPlato::Part*>(m_partpart), &Part::openTaskModule);
0862 
0863     connect(taskeditor, &TaskEditor::requestPopupMenu, this, &View::slotPopupMenuRequested);
0864     connect(taskeditor, &TaskEditor::openTaskDescription, this, &View::slotOpenTaskDescription);
0865     taskeditor->updateReadWrite(m_readWrite);
0866 
0867     return taskeditor;
0868 }
0869 
0870 ViewBase *View::createAccountsEditor(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
0871 {
0872     AccountsEditor *ae = new AccountsEditor(getKoPart(), getPart(), m_tab);
0873     m_tab->addWidget(ae);
0874 
0875     ViewListItem *i = m_viewlist->addView(cat, tag, name, ae, getPart(), "", index);
0876     ViewInfo vi = defaultViewInfo("AccountsEditor");
0877     if (name.isEmpty()) {
0878         i->setText(0, vi.name);
0879     }
0880     if (tip == TIP_USE_DEFAULT_TEXT) {
0881         i->setToolTip(0, vi.tip);
0882     } else {
0883         i->setToolTip(0, tip);
0884     }
0885 
0886     ae->draw(getProject());
0887 
0888     connect(ae, &ViewBase::guiActivated, this, &View::slotGuiActivated);
0889     ae->updateReadWrite(m_readWrite);
0890     return ae;
0891 }
0892 
0893 ViewBase *View::createCalendarEditor(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
0894 {
0895     CalendarEditor *calendareditor = new CalendarEditor(getKoPart(), getPart(), m_tab);
0896     m_tab->addWidget(calendareditor);
0897 
0898     ViewListItem *i = m_viewlist->addView(cat, tag, name, calendareditor, getPart(), "", index);
0899     ViewInfo vi = defaultViewInfo("CalendarEditor");
0900     if (name.isEmpty()) {
0901         i->setText(0, vi.name);
0902     }
0903     if (tip == TIP_USE_DEFAULT_TEXT) {
0904         i->setToolTip(0, vi.tip);
0905     } else {
0906         i->setToolTip(0, tip);
0907     }
0908 
0909     calendareditor->draw(getProject());
0910 
0911     connect(calendareditor, &ViewBase::guiActivated, this, &View::slotGuiActivated);
0912 
0913     connect(calendareditor, &CalendarEditor::requestPopupMenu, this, &View::slotPopupMenuRequested);
0914     calendareditor->updateReadWrite(m_readWrite);
0915     return calendareditor;
0916 }
0917 
0918 ViewBase *View::createScheduleHandler(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
0919 {
0920     ScheduleHandlerView *handler = new ScheduleHandlerView(getKoPart(), getPart(), m_tab);
0921     m_tab->addWidget(handler);
0922 
0923     ViewListItem *i = m_viewlist->addView(cat, tag, name, handler, getPart(), "", index);
0924     ViewInfo vi = defaultViewInfo("ScheduleHandlerView");
0925     if (name.isEmpty()) {
0926         i->setText(0, vi.name);
0927     }
0928     if (tip == TIP_USE_DEFAULT_TEXT) {
0929         i->setToolTip(0, vi.tip);
0930     } else {
0931         i->setToolTip(0, tip);
0932     }
0933 
0934     connect(handler->scheduleEditor(), &ScheduleEditor::addScheduleManager, this, &View::slotAddScheduleManager);
0935     connect(handler->scheduleEditor(), &ScheduleEditor::deleteScheduleManager, this, &View::slotDeleteScheduleManager);
0936     connect(handler->scheduleEditor(), &ScheduleEditor::moveScheduleManager, this, &View::slotMoveScheduleManager);
0937 
0938     connect(handler->scheduleEditor(), &ScheduleEditor::calculateSchedule, this, &View::slotCalculateSchedule);
0939 
0940     connect(handler->scheduleEditor(), &ScheduleEditor::baselineSchedule, this, &View::slotBaselineSchedule);
0941 
0942 
0943     connect(handler, &ViewBase::guiActivated, this, &View::slotGuiActivated);
0944 
0945     connect(this, &View::currentScheduleManagerChanged, handler, &ScheduleHandlerView::currentScheduleManagerChanged);
0946 
0947     connect(handler, &ScheduleHandlerView::requestPopupMenu, this, &View::slotPopupMenuRequested);
0948 
0949     connect(handler, &ScheduleHandlerView::editNode, this, &View::slotOpenNode);
0950     connect(handler, &ScheduleHandlerView::editResource, this, &View::slotEditResource);
0951 
0952     handler->draw(getProject());
0953     handler->updateReadWrite(m_readWrite);
0954     return handler;
0955 }
0956 
0957 ScheduleEditor *View::createScheduleEditor(QWidget *parent)
0958 {
0959     ScheduleEditor *scheduleeditor = new ScheduleEditor(getKoPart(), getPart(), parent);
0960 
0961     connect(scheduleeditor, &ScheduleEditor::addScheduleManager, this, &View::slotAddScheduleManager);
0962     connect(scheduleeditor, &ScheduleEditor::deleteScheduleManager, this, &View::slotDeleteScheduleManager);
0963 
0964     connect(scheduleeditor, &ScheduleEditor::calculateSchedule, this, &View::slotCalculateSchedule);
0965 
0966     connect(scheduleeditor, &ScheduleEditor::baselineSchedule, this, &View::slotBaselineSchedule);
0967 
0968     scheduleeditor->updateReadWrite(m_readWrite);
0969     return scheduleeditor;
0970 }
0971 
0972 ViewBase *View::createScheduleEditor(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
0973 {
0974     ScheduleEditor *scheduleeditor = new ScheduleEditor(getKoPart(), getPart(), m_tab);
0975     m_tab->addWidget(scheduleeditor);
0976 
0977     ViewListItem *i = m_viewlist->addView(cat, tag, name, scheduleeditor, getPart(), "", index);
0978     ViewInfo vi = defaultViewInfo("ScheduleEditor");
0979     if (name.isEmpty()) {
0980         i->setText(0, vi.name);
0981     }
0982     if (tip == TIP_USE_DEFAULT_TEXT) {
0983         i->setToolTip(0, vi.tip);
0984     } else {
0985         i->setToolTip(0, tip);
0986     }
0987 
0988     scheduleeditor->setProject(&(getProject()));
0989 
0990     connect(scheduleeditor, &ViewBase::guiActivated, this, &View::slotGuiActivated);
0991 
0992     connect(scheduleeditor, &ScheduleEditor::addScheduleManager, this, &View::slotAddScheduleManager);
0993 
0994     connect(scheduleeditor, &ScheduleEditor::deleteScheduleManager, this, &View::slotDeleteScheduleManager);
0995 
0996     connect(scheduleeditor, &ScheduleEditor::calculateSchedule, this, &View::slotCalculateSchedule);
0997 
0998     connect(scheduleeditor, &ScheduleEditor::baselineSchedule, this, &View::slotBaselineSchedule);
0999 
1000     scheduleeditor->updateReadWrite(m_readWrite);
1001     return scheduleeditor;
1002 }
1003 
1004 
1005 ViewBase *View::createDependencyEditor(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1006 {
1007     DependencyEditor *editor = new DependencyEditor(getKoPart(), getPart(), m_tab);
1008     m_tab->addWidget(editor);
1009 
1010     ViewListItem *i = m_viewlist->addView(cat, tag, name, editor, getPart(), "", index);
1011     ViewInfo vi = defaultViewInfo("DependencyEditor");
1012     if (name.isEmpty()) {
1013         i->setText(0, vi.name);
1014     }
1015     if (tip == TIP_USE_DEFAULT_TEXT) {
1016         i->setToolTip(0, vi.tip);
1017     } else {
1018         i->setToolTip(0, tip);
1019     }
1020 
1021     editor->draw(getProject());
1022 
1023     connect(editor, &ViewBase::guiActivated, this, &View::slotGuiActivated);
1024 
1025     connect(editor, &DependencyEditor::addRelation, this, &View::slotAddRelation);
1026     connect(editor, &DependencyEditor::modifyRelation, this, &View::slotModifyRelation);
1027     connect(editor, &DependencyEditor::editRelation, this, &View::slotEditRelation);
1028 
1029     connect(editor, &DependencyEditor::editNode, this, &View::slotOpenNode);
1030     connect(editor, &DependencyEditor::addTask, this, &View::slotAddTask);
1031     connect(editor, &DependencyEditor::addMilestone, this, &View::slotAddMilestone);
1032     connect(editor, &DependencyEditor::addSubMilestone, this, &View::slotAddSubMilestone);
1033     connect(editor, &DependencyEditor::addSubtask, this, &View::slotAddSubTask);
1034     connect(editor, &DependencyEditor::deleteTaskList, this, &View::slotDeleteTaskList);
1035 
1036     connect(this, &View::currentScheduleManagerChanged, editor, &DependencyEditor::setScheduleManager);
1037 
1038     connect(editor, &DependencyEditor::requestPopupMenu, this, &View::slotPopupMenuRequested);
1039     editor->updateReadWrite(m_readWrite);
1040     editor->setScheduleManager(currentScheduleManager());
1041     return editor;
1042 }
1043 
1044 ViewBase *View::createPertEditor(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1045 {
1046     PertEditor *perteditor = new PertEditor(getKoPart(), getPart(), m_tab);
1047     m_tab->addWidget(perteditor);
1048 
1049     ViewListItem *i = m_viewlist->addView(cat, tag, name, perteditor, getPart(), "", index);
1050     ViewInfo vi = defaultViewInfo("PertEditor");
1051     if (name.isEmpty()) {
1052         i->setText(0, vi.name);
1053     }
1054     if (tip == TIP_USE_DEFAULT_TEXT) {
1055         i->setToolTip(0, vi.tip);
1056     } else {
1057         i->setToolTip(0, tip);
1058     }
1059 
1060     perteditor->draw(getProject());
1061 
1062     connect(perteditor, &ViewBase::guiActivated, this, &View::slotGuiActivated);
1063     m_updatePertEditor = true;
1064     perteditor->updateReadWrite(m_readWrite);
1065     return perteditor;
1066 }
1067 
1068 ViewBase *View::createProjectStatusView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1069 {
1070     ProjectStatusView *v = new ProjectStatusView(getKoPart(), getPart(), m_tab);
1071     m_tab->addWidget(v);
1072 
1073     ViewListItem *i = m_viewlist->addView(cat, tag, name, v, getPart(), "", index);
1074     ViewInfo vi = defaultViewInfo("ProjectStatusView");
1075     if (name.isEmpty()) {
1076         i->setText(0, vi.name);
1077     }
1078     if (tip == TIP_USE_DEFAULT_TEXT) {
1079         i->setToolTip(0, vi.tip);
1080     } else {
1081         i->setToolTip(0, tip);
1082     }
1083 
1084     connect(v, &ViewBase::guiActivated, this, &View::slotGuiActivated);
1085 
1086     connect(this, &View::currentScheduleManagerChanged, v, &ProjectStatusView::setScheduleManager);
1087 
1088     v->updateReadWrite(m_readWrite);
1089     v->setProject(&getProject());
1090     v->setScheduleManager(currentScheduleManager());
1091     return v;
1092 }
1093 
1094 ViewBase *View::createPerformanceStatusView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1095 {
1096     PerformanceStatusView *v = new PerformanceStatusView(getKoPart(), getPart(), m_tab);
1097     m_tab->addWidget(v);
1098 
1099     ViewListItem *i = m_viewlist->addView(cat, tag, name, v, getPart(), "", index);
1100     ViewInfo vi = defaultViewInfo("PerformanceStatusView");
1101     if (name.isEmpty()) {
1102         i->setText(0, vi.name);
1103     }
1104     if (tip == TIP_USE_DEFAULT_TEXT) {
1105         i->setToolTip(0, vi.tip);
1106     } else {
1107         i->setToolTip(0, tip);
1108     }
1109 
1110     connect(v, &ViewBase::guiActivated, this, &View::slotGuiActivated);
1111 
1112     connect(this, &View::currentScheduleManagerChanged, v, &PerformanceStatusView::setScheduleManager);
1113 
1114     connect(v, &PerformanceStatusView::requestPopupMenu, this, &View::slotPopupMenuRequested);
1115 
1116     v->updateReadWrite(m_readWrite);
1117     v->setProject(&getProject());
1118     v->setScheduleManager(currentScheduleManager());
1119     return v;
1120 }
1121 
1122 
1123 ViewBase *View::createTaskStatusView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1124 {
1125     TaskStatusView *taskstatusview = new TaskStatusView(getKoPart(), getPart(), m_tab);
1126     taskstatusview->setViewSplitMode(false);
1127     m_tab->addWidget(taskstatusview);
1128 
1129     ViewListItem *i = m_viewlist->addView(cat, tag, name, taskstatusview, getPart(), "", index);
1130     ViewInfo vi = defaultViewInfo("TaskStatusView");
1131     if (name.isEmpty()) {
1132         i->setText(0, vi.name);
1133     }
1134     if (tip == TIP_USE_DEFAULT_TEXT) {
1135         i->setToolTip(0, vi.tip);
1136     } else {
1137         i->setToolTip(0, tip);
1138     }
1139 
1140     connect(taskstatusview, &ViewBase::guiActivated, this, &View::slotGuiActivated);
1141 
1142     connect(this, &View::currentScheduleManagerChanged, taskstatusview, &TaskStatusView::setScheduleManager);
1143 
1144     connect(taskstatusview, &TaskStatusView::requestPopupMenu, this, &View::slotPopupMenuRequested);
1145     connect(taskstatusview, &TaskStatusView::openTaskDescription, this, &View::slotOpenTaskDescription);
1146 
1147     taskstatusview->updateReadWrite(m_readWrite);
1148     taskstatusview->draw(getProject());
1149     taskstatusview->setScheduleManager(currentScheduleManager());
1150     return taskstatusview;
1151 }
1152 
1153 ViewBase *View::createTaskView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1154 {
1155     TaskView *v = new TaskView(getKoPart(), getPart(), m_tab);
1156     v->setViewSplitMode(false);
1157     m_tab->addWidget(v);
1158 
1159     ViewListItem *i = m_viewlist->addView(cat, tag, name, v, getPart(), "", index);
1160     ViewInfo vi = defaultViewInfo("TaskView");
1161     if (name.isEmpty()) {
1162         i->setText(0, vi.name);
1163     }
1164     if (tip == TIP_USE_DEFAULT_TEXT) {
1165         i->setToolTip(0, vi.tip);
1166     } else {
1167         i->setToolTip(0, tip);
1168     }
1169 
1170     v->draw(getProject());
1171     v->setScheduleManager(currentScheduleManager());
1172 
1173     connect(this, &View::currentScheduleManagerChanged, v, &TaskView::setScheduleManager);
1174 
1175     connect(v, &ViewBase::guiActivated, this, &View::slotGuiActivated);
1176 
1177     connect(v, &TaskView::requestPopupMenu, this, &View::slotPopupMenuRequested);
1178     connect(v, &TaskView::openTaskDescription, this, &View::slotOpenTaskDescription);
1179     v->updateReadWrite(m_readWrite);
1180     return v;
1181 }
1182 
1183 ViewBase *View::createTaskWorkPackageView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1184 {
1185     TaskWorkPackageView *v = new TaskWorkPackageView(getKoPart(), getPart(), m_tab);
1186     v->setViewSplitMode(false);
1187     m_tab->addWidget(v);
1188 
1189     ViewListItem *i = m_viewlist->addView(cat, tag, name, v, getPart(), "", index);
1190     ViewInfo vi = defaultViewInfo("TaskWorkPackageView");
1191     if (name.isEmpty()) {
1192         i->setText(0, vi.name);
1193     }
1194     if (tip == TIP_USE_DEFAULT_TEXT) {
1195         i->setToolTip(0, vi.tip);
1196     } else {
1197         i->setToolTip(0, tip);
1198     }
1199 
1200     v->setProject(&getProject());
1201     v->setScheduleManager(currentScheduleManager());
1202 
1203     connect(this, &View::currentScheduleManagerChanged, v, &TaskWorkPackageView::setScheduleManager);
1204 
1205     connect(v, &ViewBase::guiActivated, this, &View::slotGuiActivated);
1206 
1207     connect(v, &TaskWorkPackageView::requestPopupMenu, this, &View::slotPopupMenuRequested);
1208 
1209     connect(v, &TaskWorkPackageView::mailWorkpackage, this, &View::slotMailWorkpackage);
1210     connect(v, &TaskWorkPackageView::publishWorkpackages, this, &View::slotPublishWorkpackages);
1211     connect(v, &TaskWorkPackageView::openWorkpackages, this, &View::openWorkPackageMergeDialog);
1212     connect(this, &View::workPackagesAvailable, v, &TaskWorkPackageView::slotWorkpackagesAvailable);
1213     connect(v, &TaskWorkPackageView::checkForWorkPackages, getPart(), &MainDocument::checkForWorkPackages);
1214     connect(v, &TaskWorkPackageView::loadWorkPackageUrl, this, &View::loadWorkPackage);
1215     connect(v, &TaskWorkPackageView::openTaskDescription, this, &View::slotOpenTaskDescription);
1216     v->updateReadWrite(m_readWrite);
1217 
1218     return v;
1219 }
1220 
1221 ViewBase *View::createGanttView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1222 {
1223     GanttView *ganttview = new GanttView(getKoPart(), getPart(), m_tab, koDocument()->isReadWrite());
1224     m_tab->addWidget(ganttview);
1225 
1226     ViewListItem *i = m_viewlist->addView(cat, tag, name, ganttview, getPart(), "", index);
1227     ViewInfo vi = defaultViewInfo("GanttView");
1228     if (name.isEmpty()) {
1229         i->setText(0, vi.name);
1230     }
1231     if (tip == TIP_USE_DEFAULT_TEXT) {
1232         i->setToolTip(0, vi.tip);
1233     } else {
1234         i->setToolTip(0, tip);
1235     }
1236 
1237     ganttview->setProject(&(getProject()));
1238     ganttview->setScheduleManager(currentScheduleManager());
1239 
1240     connect(ganttview, &ViewBase::guiActivated, this, &View::slotGuiActivated);
1241 /*  TODO: Review these
1242     connect(ganttview, SIGNAL(addRelation(KPlato::Node*,KPlato::Node*,int)), SLOT(slotAddRelation(KPlato::Node*,KPlato::Node*,int)));
1243     connect(ganttview, SIGNAL(modifyRelation(KPlato::Relation*,int)), SLOT(slotModifyRelation(KPlato::Relation*,int)));
1244     connect(ganttview, SIGNAL(modifyRelation(KPlato::Relation*)), SLOT(slotModifyRelation(KPlato::Relation*)));
1245     connect(ganttview, SIGNAL(itemDoubleClicked()), SLOT(slotOpenNode()));
1246     connect(ganttview, SIGNAL(itemRenamed(KPlato::Node*,QString)), this, SLOT(slotRenameNode(KPlato::Node*,QString)));*/
1247 
1248     connect(this, &View::currentScheduleManagerChanged, ganttview, &GanttView::setScheduleManager);
1249 
1250     connect(ganttview, &GanttView::requestPopupMenu, this, &View::slotPopupMenuRequested);
1251     connect(ganttview, &GanttView::openTaskDescription, this, &View::slotOpenTaskDescription);
1252     ganttview->updateReadWrite(m_readWrite);
1253 
1254     return ganttview;
1255 }
1256 
1257 ViewBase *View::createMilestoneGanttView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1258 {
1259     MilestoneGanttView *ganttview = new MilestoneGanttView(getKoPart(), getPart(), m_tab, koDocument()->isReadWrite());
1260     m_tab->addWidget(ganttview);
1261 
1262     ViewListItem *i = m_viewlist->addView(cat, tag, name, ganttview, getPart(), "", index);
1263     ViewInfo vi = defaultViewInfo("MilestoneGanttView");
1264     if (name.isEmpty()) {
1265         i->setText(0, vi.name);
1266     }
1267     if (tip == TIP_USE_DEFAULT_TEXT) {
1268         i->setToolTip(0, vi.tip);
1269     } else {
1270         i->setToolTip(0, tip);
1271     }
1272 
1273     ganttview->setProject(&(getProject()));
1274     ganttview->setScheduleManager(currentScheduleManager());
1275 
1276     connect(ganttview, &ViewBase::guiActivated, this, &View::slotGuiActivated);
1277 
1278     connect(this, &View::currentScheduleManagerChanged, ganttview, &MilestoneGanttView::setScheduleManager);
1279 
1280     connect(ganttview, &MilestoneGanttView::requestPopupMenu, this, &View::slotPopupMenuRequested);
1281     connect(ganttview, &MilestoneGanttView::openTaskDescription, this, &View::slotOpenTaskDescription);
1282     ganttview->updateReadWrite(m_readWrite);
1283 
1284     return ganttview;
1285 }
1286 
1287 
1288 ViewBase *View::createAccountsView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1289 {
1290     AccountsView *accountsview = new AccountsView(getKoPart(), &getProject(), getPart(), m_tab);
1291     m_tab->addWidget(accountsview);
1292 
1293     ViewListItem *i = m_viewlist->addView(cat, tag, name, accountsview, getPart(), "", index);
1294     ViewInfo vi = defaultViewInfo("AccountsView");
1295     if (name.isEmpty()) {
1296         i->setText(0, vi.name);
1297     }
1298     if (tip == TIP_USE_DEFAULT_TEXT) {
1299         i->setToolTip(0, vi.tip);
1300     } else {
1301         i->setToolTip(0, tip);
1302     }
1303 
1304     accountsview->setScheduleManager(currentScheduleManager());
1305 
1306     connect(this, &View::currentScheduleManagerChanged, accountsview, &AccountsView::setScheduleManager);
1307 
1308     connect(accountsview, &ViewBase::guiActivated, this, &View::slotGuiActivated);
1309     accountsview->updateReadWrite(m_readWrite);
1310     return accountsview;
1311 }
1312 
1313 ViewBase *View::createResourceAssignmentView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1314 {
1315     ResourceAssignmentView *resourceAssignmentView = new ResourceAssignmentView(getKoPart(), getPart(), m_tab);
1316     m_tab->addWidget(resourceAssignmentView);
1317     m_updateResourceAssignmentView = true;
1318 
1319     ViewListItem *i = m_viewlist->addView(cat, tag, name, resourceAssignmentView, getPart(), "", index);
1320     ViewInfo vi = defaultViewInfo("ResourceAssignmentView");
1321     if (name.isEmpty()) {
1322         i->setText(0, vi.name);
1323     }
1324     if (tip == TIP_USE_DEFAULT_TEXT) {
1325         i->setToolTip(0, vi.tip);
1326     } else {
1327         i->setToolTip(0, tip);
1328     }
1329 
1330     resourceAssignmentView->draw(getProject());
1331 
1332     connect(resourceAssignmentView, &ViewBase::guiActivated, this, &View::slotGuiActivated);
1333 
1334     connect(resourceAssignmentView, &ResourceAssignmentView::requestPopupMenu, this, &View::slotPopupMenuRequested);
1335     resourceAssignmentView->updateReadWrite(m_readWrite);
1336     return resourceAssignmentView;
1337 }
1338 
1339 ViewBase *View::createReportsGeneratorView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1340 {
1341     ReportsGeneratorView *v = new ReportsGeneratorView(getKoPart(), getPart(), m_tab);
1342     m_tab->addWidget(v);
1343 
1344     ViewListItem *i = m_viewlist->addView(cat, tag, name, v, getPart(), "", index);
1345     ViewInfo vi = defaultViewInfo("ReportsGeneratorView");
1346     if (name.isEmpty()) {
1347         i->setText(0, vi.name);
1348     }
1349     if (tip == TIP_USE_DEFAULT_TEXT) {
1350         i->setToolTip(0, vi.tip);
1351     } else {
1352         i->setToolTip(0, tip);
1353     }
1354 
1355     v->setProject(&getProject());
1356 
1357     connect(this, &View::currentScheduleManagerChanged, v, &ViewBase::setScheduleManager);
1358     connect(this, &View::currentScheduleManagerChanged, v, &ViewBase::slotRefreshView);
1359     v->setScheduleManager(currentScheduleManager());
1360 
1361     connect(v, &ViewBase::guiActivated, this, &View::slotGuiActivated);
1362     connect(v, &ReportsGeneratorView::requestPopupMenu, this, &View::slotPopupMenuRequested);
1363 
1364     v->updateReadWrite(m_readWrite);
1365     return v;
1366 }
1367 
1368 ViewBase *View::createReportView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
1369 {
1370 #ifdef PLAN_USE_KREPORT
1371     ReportView *v = new ReportView(getKoPart(), getPart(), m_tab);
1372     m_tab->addWidget(v);
1373 
1374     ViewListItem *i = m_viewlist->addView(cat, tag, name, v, getPart(), "", index);
1375     ViewInfo vi = defaultViewInfo("ReportView");
1376     if (name.isEmpty()) {
1377         i->setText(0, vi.name);
1378     }
1379     if (tip == TIP_USE_DEFAULT_TEXT) {
1380         i->setToolTip(0, vi.tip);
1381     } else {
1382         i->setToolTip(0, tip);
1383     }
1384 
1385     v->setProject(&getProject());
1386 
1387     connect(this, &View::currentScheduleManagerChanged, v, &ReportView::setScheduleManager);
1388     connect(this, &View::currentScheduleManagerChanged, v, SLOT(slotRefreshView()));
1389     v->setScheduleManager(currentScheduleManager());
1390 
1391     connect(v, &ReportView::guiActivated, this, &View::slotGuiActivated);
1392     v->updateReadWrite(m_readWrite);
1393     return v;
1394 #else
1395     Q_UNUSED(cat)
1396     Q_UNUSED(tag)
1397     Q_UNUSED(name)
1398     Q_UNUSED(tip)
1399     Q_UNUSED(index)
1400     return 0;
1401 #endif
1402 }
1403 
1404 Project& View::getProject() const
1405 {
1406     return getPart() ->getProject();
1407 }
1408 
1409 KoPrintJob * View::createPrintJob()
1410 {
1411     KoView *v = qobject_cast<KoView*>(canvas());
1412     if (v == 0) {
1413         return 0;
1414     }
1415     return v->createPrintJob();
1416 }
1417 
1418 ViewBase *View::currentView() const
1419 {
1420     return qobject_cast<ViewBase*>(m_tab->currentWidget());
1421 }
1422 
1423 void View::slotEditCut()
1424 {
1425     ViewBase *v = currentView();
1426     if (v) {
1427         v->slotEditCut();
1428     }
1429 }
1430 
1431 void View::slotEditCopy()
1432 {
1433     ViewBase *v = currentView();
1434     if (v) {
1435         v->slotEditCopy();
1436     }
1437 }
1438 
1439 void View::slotEditPaste()
1440 {
1441     ViewBase *v = currentView();
1442     if (v) {
1443         v->slotEditPaste();
1444     }
1445 }
1446 
1447 void View::slotRefreshView()
1448 {
1449     ViewBase *v = currentView();
1450     if (v) {
1451         debugPlan<<v;
1452         v->slotRefreshView();
1453     }
1454 }
1455 
1456 void View::slotViewSelector(bool show)
1457 {
1458     //debugPlan;
1459     m_viewlist->setVisible(show);
1460 }
1461 
1462 void View::slotInsertResourcesFile(const QString &file, const QUrl &projects)
1463 {
1464     getPart()->insertResourcesFile(QUrl(file), projects);
1465 }
1466 
1467 void View::slotInsertFile()
1468 {
1469     InsertFileDialog *dlg = new InsertFileDialog(getProject(), currentTask(), this);
1470     connect(dlg, &QDialog::finished, this, &View::slotInsertFileFinished);
1471     dlg->open();
1472 }
1473 
1474 void View::slotInsertFileFinished(int result)
1475 {
1476     InsertFileDialog *dlg = qobject_cast<InsertFileDialog*>(sender());
1477     if (dlg == 0) {
1478         return;
1479     }
1480     if (result == QDialog::Accepted) {
1481         getPart()->insertFile(dlg->url(), dlg->parentNode(), dlg->afterNode());
1482     }
1483     dlg->deleteLater();
1484 }
1485 
1486 void View::slotLoadSharedProjects()
1487 {
1488     LoadSharedProjectsDialog *dlg = new LoadSharedProjectsDialog(getProject(), getPart()->url(), this);
1489     connect(dlg, &QDialog::finished, this, &View::slotLoadSharedProjectsFinished);
1490     dlg->open();
1491 }
1492 
1493 void View::slotLoadSharedProjectsFinished(int result)
1494 {
1495     LoadSharedProjectsDialog *dlg = qobject_cast<LoadSharedProjectsDialog*>(sender());
1496     if (dlg == 0) {
1497         return;
1498     }
1499     if (result == QDialog::Accepted) {
1500         getPart()->insertSharedProjects(dlg->urls());
1501     }
1502     dlg->deleteLater();
1503 }
1504 
1505 void View::slotProjectEdit()
1506 {
1507     slotOpenNode(&getProject());
1508 }
1509 
1510 void View::slotProjectWorktime()
1511 {
1512     StandardWorktimeDialog *dia = new StandardWorktimeDialog(getProject(), this);
1513     connect(dia, &QDialog::finished, this, &View::slotProjectWorktimeFinished);
1514     dia->open();
1515 }
1516 
1517 void View::slotProjectWorktimeFinished(int result)
1518 {
1519     StandardWorktimeDialog *dia = qobject_cast<StandardWorktimeDialog*>(sender());
1520     if (dia == 0) {
1521         return;
1522     }
1523     if (result == QDialog::Accepted) {
1524         KUndo2Command * cmd = dia->buildCommand();
1525         if (cmd) {
1526             //debugPlan<<"Modifying calendar(s)";
1527             getPart() ->addCommand(cmd); //also executes
1528         }
1529     }
1530     dia->deleteLater();
1531 }
1532 
1533 void View::slotSelectionChanged(ScheduleManager *sm) {
1534     debugPlan<<sm;
1535     if (sm == 0) {
1536         return;
1537     }
1538     QAction *a = m_scheduleActions.key(sm);
1539     if (!a) {
1540         debugPlan<<sm<<"could not find action for schedule:"<<sm;
1541         return;
1542     }
1543     a->setChecked(true); // this doesn't trigger QActionGroup
1544     slotViewSchedule(a);
1545 }
1546 
1547 QList<QAction*> View::sortedActionList()
1548 {
1549     QMap<QString, QAction*> lst;
1550     const QMap<QAction*, ScheduleManager*> map = m_scheduleActions; // clazy:exclude=qmap-with-pointer-key
1551     QMap<QAction*, ScheduleManager*>::const_iterator it;
1552     for (it = map.constBegin(); it != map.constEnd(); ++it) {
1553         lst.insert(it.key()->objectName(), it.key());
1554     }
1555     return lst.values();
1556 }
1557 
1558 void View::slotScheduleSwapped(ScheduleManager *from,  ScheduleManager *to)
1559 {
1560     if (currentScheduleManager() == from) {
1561         QAction *a = m_scheduleActions.key(to);
1562         if (a) {
1563             a->setChecked(true);
1564         }
1565     }
1566 }
1567 
1568 void View::slotScheduleRemoved(const ScheduleManager *sch)
1569 {
1570     debugPlan<<sch<<sch->name();
1571     QAction *a = 0;
1572     QAction *checked = m_scheduleActionGroup->checkedAction();
1573     QMapIterator<QAction*, ScheduleManager*> i(m_scheduleActions);
1574     while (i.hasNext()) {
1575         i.next();
1576         if (i.value() == sch) {
1577             a = i.key();
1578             break;
1579         }
1580     }
1581     if (a) {
1582         unplugActionList("view_schedule_list");
1583         delete a;
1584         plugActionList("view_schedule_list", sortedActionList());
1585         if (checked && checked != a) {
1586             checked->setChecked(true);
1587         } else if (! m_scheduleActions.isEmpty()) {
1588             m_scheduleActions.firstKey()->setChecked(true);
1589         }
1590     }
1591     slotViewSchedule(m_scheduleActionGroup->checkedAction());
1592 }
1593 
1594 void View::slotScheduleAdded(const ScheduleManager *sch)
1595 {
1596     ScheduleManager *s = const_cast<ScheduleManager*>(sch);
1597     QAction *checked = m_scheduleActionGroup->checkedAction();
1598     unplugActionList("view_schedule_list");
1599     QAction *act = addScheduleAction(s);
1600     plugActionList("view_schedule_list", sortedActionList());
1601     if (!currentScheduleManager()) {
1602         if (act) {
1603             act->setChecked(true);
1604         } else if (! m_scheduleActions.isEmpty()) {
1605             m_scheduleActions.firstKey()->setChecked(true);
1606         }
1607         slotViewSchedule(m_scheduleActionGroup->checkedAction());
1608     }
1609 }
1610 
1611 void View::slotScheduleCalculated(Project *project, ScheduleManager *manager)
1612 {
1613     Q_UNUSED(project);
1614     if (manager == currentScheduleManager()) {
1615         slotViewScheduleManager(manager);
1616     }
1617 }
1618 
1619 QAction *View::addScheduleAction(ScheduleManager *sch)
1620 {
1621     QAction *act = 0;
1622     QString n = sch->name();
1623     act = new KToggleAction(n, this);
1624     actionCollection()->addAction(n, act);
1625     m_scheduleActions.insert(act, sch);
1626     m_scheduleActionGroup->addAction(act);
1627     //debugPlan<<"Add:"<<n;
1628     connect(act, &QObject::destroyed, this, &View::slotActionDestroyed);
1629     return act;
1630 }
1631 
1632 void View::slotViewScheduleManager(ScheduleManager *sm)
1633 {
1634     QApplication::setOverrideCursor(Qt::WaitCursor);
1635     setLabel(sm);
1636     emit currentScheduleManagerChanged(sm);
1637     QApplication::restoreOverrideCursor();
1638 }
1639 
1640 void View::slotViewSchedule(QAction *act)
1641 {
1642     //debugPlan<<act;
1643     ScheduleManager *sm = 0;
1644     if (act != 0) {
1645         ScheduleManager *sch = m_scheduleActions.value(act, 0);
1646         sm = m_scheduleActions.value(act, 0);
1647     }
1648     setLabel(0);
1649     slotViewScheduleManager(sm);
1650 }
1651 
1652 void View::slotActionDestroyed(QObject *o)
1653 {
1654     //debugPlan<<o->name();
1655     m_scheduleActions.remove(static_cast<QAction*>(o));
1656 }
1657 
1658 void View::slotPlugScheduleActions()
1659 {
1660     ScheduleManager *current = currentScheduleManager();
1661     unplugActionList("view_schedule_list");
1662     const QMap<QAction*, ScheduleManager*> map = m_scheduleActions; // clazy:exclude=qmap-with-pointer-key
1663     QMap<QAction*, ScheduleManager*>::const_iterator it;
1664     for (it = map.constBegin(); it != map.constEnd(); ++it) {
1665         m_scheduleActionGroup->removeAction(it.key());
1666         delete it.key();
1667     }
1668     m_scheduleActions.clear();
1669     QAction *ca = 0;
1670     foreach(ScheduleManager *sm, getProject().allScheduleManagers()) {
1671         QAction *act = addScheduleAction(sm);
1672         if (sm == current) {
1673             ca = act;
1674         }
1675     }
1676     plugActionList("view_schedule_list", sortedActionList());
1677     if (ca == 0 && m_scheduleActionGroup->actions().count() > 0) {
1678         ca = m_scheduleActionGroup->actions().constFirst();
1679     }
1680     if (ca) {
1681         ca->setChecked(true);
1682     }
1683     slotViewSchedule(ca);
1684 }
1685 
1686 void View::slotCalculateSchedule(Project *project, ScheduleManager *sm)
1687 {
1688     if (project == 0 || sm == 0) {
1689         return;
1690     }
1691     if (sm->parentManager() && ! sm->parentManager()->isScheduled()) {
1692         // the parent must be scheduled
1693         return;
1694     }
1695     CalculateScheduleCmd *cmd =  new CalculateScheduleCmd(*project, sm, kundo2_i18nc("@info:status 1=schedule name", "Calculate %1", sm->name()));
1696     getPart() ->addCommand(cmd);
1697     slotUpdate();
1698 }
1699 
1700 void View::slotRemoveCommands()
1701 {
1702     while (! m_undocommands.isEmpty()) {
1703         m_undocommands.last()->undo();
1704         delete m_undocommands.takeLast();
1705     }
1706 }
1707 
1708 void View::slotBaselineSchedule(Project *project, ScheduleManager *sm)
1709 {
1710     if (project == 0 || sm == 0) {
1711         return;
1712     }
1713     if (! sm->isBaselined() && project->isBaselined()) {
1714         KMessageBox::sorry(this, i18n("Cannot baseline. The project is already baselined."));
1715         return;
1716     }
1717     MacroCommand *cmd = nullptr;
1718     if (sm->isBaselined()) {
1719         KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel(this, i18n("This schedule is baselined. Do you want to remove the baseline?"));
1720         if (res == KMessageBox::Cancel) {
1721             return;
1722         }
1723         cmd = new MacroCommand(kundo2_i18n("Reset baseline %1", sm->name()));
1724         cmd->addCommand(new ResetBaselineScheduleCmd(*sm));
1725     } else {
1726         cmd = new MacroCommand(kundo2_i18n("Baseline %1", sm->name()));
1727         if (sm->schedulingMode() == ScheduleManager::AutoMode) {
1728             cmd->addCommand(new ModifyScheduleManagerSchedulingModeCmd(*sm, ScheduleManager::ManualMode));
1729         }
1730         cmd->addCommand(new BaselineScheduleCmd(*sm, kundo2_i18n("Baseline %1", sm->name())));
1731     }
1732     getPart() ->addCommand(cmd);
1733 }
1734 
1735 void View::slotAddScheduleManager(Project *project)
1736 {
1737     if (project == 0) {
1738         return;
1739     }
1740     ScheduleManager *sm = project->createScheduleManager();
1741     AddScheduleManagerCmd *cmd =  new AddScheduleManagerCmd(*project, sm, -1, kundo2_i18n("Add schedule %1", sm->name()));
1742     getPart() ->addCommand(cmd);
1743 }
1744 
1745 void View::slotDeleteScheduleManager(Project *project, ScheduleManager *sm)
1746 {
1747     if (project == 0 || sm == 0) {
1748         return;
1749     }
1750     DeleteScheduleManagerCmd *cmd =  new DeleteScheduleManagerCmd(*project, sm, kundo2_i18n("Delete schedule %1", sm->name()));
1751     getPart() ->addCommand(cmd);
1752 }
1753 
1754 void View::slotMoveScheduleManager(ScheduleManager *sm, ScheduleManager *parent, int index)
1755 {
1756     if (sm == 0) {
1757         return;
1758     }
1759     MoveScheduleManagerCmd *cmd =  new MoveScheduleManagerCmd(sm, parent, index, kundo2_i18n("Move schedule %1", sm->name()));
1760     getPart() ->addCommand(cmd);
1761 }
1762 
1763 void View::slotAddSubTask()
1764 {
1765     Task * node = getProject().createTask(getPart() ->config().taskDefaults());
1766     SubTaskAddDialog *dia = new SubTaskAddDialog(getProject(), *node, currentNode(), getProject().accounts(), this);
1767     connect(dia, &QDialog::finished, this, &View::slotAddSubTaskFinished);
1768     dia->open();
1769 }
1770 
1771 void View::slotAddSubTaskFinished(int result)
1772 {
1773     SubTaskAddDialog *dia = qobject_cast<SubTaskAddDialog*>(sender());
1774     if (dia == 0) {
1775         return;
1776     }
1777     if (result  == QDialog::Accepted) {
1778         KUndo2Command *m = dia->buildCommand();
1779         getPart() ->addCommand(m); // add task to project
1780     }
1781     dia->deleteLater();
1782 }
1783 
1784 void View::slotAddTask()
1785 {
1786     Task * node = getProject().createTask(getPart() ->config().taskDefaults());
1787     TaskAddDialog *dia = new TaskAddDialog(getProject(), *node, currentNode(), getProject().accounts(), this);
1788     connect(dia, &QDialog::finished, this, &View::slotAddTaskFinished);
1789     dia->open();
1790 }
1791 
1792 void View::slotAddTaskFinished(int result)
1793 {
1794     TaskAddDialog *dia = qobject_cast<TaskAddDialog*>(sender());
1795     if (dia == 0) {
1796         return;
1797     }
1798     if (result == QDialog::Accepted) {
1799         KUndo2Command *m = dia->buildCommand();
1800         getPart() ->addCommand(m); // add task to project
1801     }
1802     dia->deleteLater();
1803 }
1804 
1805 void View::slotAddMilestone()
1806 {
1807     Task * node = getProject().createTask();
1808     node->estimate() ->clear();
1809 
1810     TaskAddDialog *dia = new TaskAddDialog(getProject(), *node, currentNode(), getProject().accounts(), this);
1811     connect(dia, &QDialog::finished, this, &View::slotAddMilestoneFinished);
1812     dia->open();
1813 }
1814 
1815 void View::slotAddMilestoneFinished(int result)
1816 {
1817     TaskAddDialog *dia = qobject_cast<TaskAddDialog*>(sender());
1818     if (dia == 0) {
1819         return;
1820     }
1821     if (result == QDialog::Accepted) {
1822         MacroCommand *c = new MacroCommand(kundo2_i18n("Add milestone"));
1823         c->addCommand(dia->buildCommand());
1824         getPart() ->addCommand(c); // add task to project
1825     }
1826     dia->deleteLater();
1827 }
1828 
1829 void View::slotAddSubMilestone()
1830 {
1831     Task * node = getProject().createTask();
1832     node->estimate() ->clear();
1833 
1834     SubTaskAddDialog *dia = new SubTaskAddDialog(getProject(), *node, currentNode(), getProject().accounts(), this);
1835     connect(dia, &QDialog::finished, this, &View::slotAddSubMilestoneFinished);
1836     dia->open();
1837 }
1838 
1839 void View::slotAddSubMilestoneFinished(int result)
1840 {
1841     SubTaskAddDialog *dia = qobject_cast<SubTaskAddDialog*>(sender());
1842     if (dia == 0) {
1843         return;
1844     }
1845     if (result == QDialog::Accepted) {
1846         MacroCommand *c = new MacroCommand(kundo2_i18n("Add sub-milestone"));
1847         c->addCommand(dia->buildCommand());
1848         getPart() ->addCommand(c); // add task to project
1849     }
1850     dia->deleteLater();
1851 }
1852 
1853 void View::slotDefineWBS()
1854 {
1855     //debugPlan;
1856     Project &p = getProject();
1857     WBSDefinitionDialog *dia = new WBSDefinitionDialog(p, p.wbsDefinition(), this);
1858     connect(dia, &QDialog::finished, this, &View::slotDefineWBSFinished);
1859     dia->open();
1860 }
1861 
1862 void View::slotDefineWBSFinished(int result)
1863 {
1864     //debugPlan;
1865     WBSDefinitionDialog *dia = qobject_cast<WBSDefinitionDialog*>(sender());
1866     if (dia == 0) {
1867         return;
1868     }
1869     if (result == QDialog::Accepted) {
1870         KUndo2Command *cmd = dia->buildCommand();
1871         if (cmd) {
1872             getPart()->addCommand(cmd);
1873         }
1874     }
1875     dia->deleteLater();
1876 }
1877 
1878 Calendar *View::currentCalendar()
1879 {
1880     ViewBase *v = dynamic_cast<ViewBase*>(m_tab->currentWidget());
1881     if (v == 0) {
1882         return 0;
1883     }
1884     return v->currentCalendar();
1885 }
1886 
1887 Node *View::currentNode() const
1888 {
1889     ViewBase *v = dynamic_cast<ViewBase*>(m_tab->currentWidget());
1890     if (v == 0) {
1891         return 0;
1892     }
1893     Node * task = v->currentNode();
1894     if (0 != task) {
1895         return task;
1896     }
1897     return &(getProject());
1898 }
1899 
1900 Task *View::currentTask() const
1901 {
1902     ViewBase *v = dynamic_cast<ViewBase*>(m_tab->currentWidget());
1903     if (v == 0) {
1904         return 0;
1905     }
1906     Node * task = v->currentNode();
1907     if (task) {
1908         return dynamic_cast<Task*>(task);
1909     }
1910     return 0;
1911 }
1912 
1913 Resource *View::currentResource()
1914 {
1915     ViewBase *v = dynamic_cast<ViewBase*>(m_tab->currentWidget());
1916     if (v == 0) {
1917         return 0;
1918     }
1919     return v->currentResource();
1920 }
1921 
1922 ResourceGroup *View::currentResourceGroup()
1923 {
1924     ViewBase *v = dynamic_cast<ViewBase*>(m_tab->currentWidget());
1925     if (v == 0) {
1926         return 0;
1927     }
1928     return v->currentResourceGroup();
1929 }
1930 
1931 
1932 void View::slotOpenCurrentNode()
1933 {
1934     //debugPlan;
1935     Node * node = currentNode();
1936     slotOpenNode(node);
1937 }
1938 
1939 void View::slotOpenNode(Node *node)
1940 {
1941     //debugPlan;
1942     if (!node)
1943         return ;
1944 
1945     switch (node->type()) {
1946         case Node::Type_Project: {
1947                 Project * project = static_cast<Project *>(node);
1948                 MainProjectDialog *dia = new MainProjectDialog(*project, this);
1949                 connect(dia, &MainProjectDialog::dialogFinished, this, &View::slotProjectEditFinished);
1950                 connect(dia, &MainProjectDialog::sigLoadSharedResources, this, &View::slotInsertResourcesFile);
1951                 connect(dia, &MainProjectDialog::loadResourceAssignments, getPart(), &MainDocument::loadResourceAssignments);
1952                 connect(dia, &MainProjectDialog::clearResourceAssignments, getPart(), &MainDocument::clearResourceAssignments);
1953                 dia->open();
1954                 break;
1955             }
1956         case Node::Type_Subproject:
1957             //TODO
1958             break;
1959         case Node::Type_Task: {
1960                 Task *task = static_cast<Task *>(node);
1961                 TaskDialog *dia = new TaskDialog(getProject(), *task, getProject().accounts(), this);
1962                 connect(dia, &QDialog::finished, this, &View::slotTaskEditFinished);
1963                 dia->open();
1964                 break;
1965             }
1966         case Node::Type_Milestone: {
1967                 // Use the normal task dialog for now.
1968                 // Maybe milestone should have it's own dialog, but we need to be able to
1969                 // enter a duration in case we accidentally set a tasks duration to zero
1970                 // and hence, create a milestone
1971                 Task *task = static_cast<Task *>(node);
1972                 TaskDialog *dia = new TaskDialog(getProject(), *task, getProject().accounts(), this);
1973                 connect(dia, &QDialog::finished, this, &View::slotTaskEditFinished);
1974                 dia->open();
1975                 break;
1976             }
1977         case Node::Type_Summarytask: {
1978                 Task *task = dynamic_cast<Task *>(node);
1979                 Q_ASSERT(task);
1980                 SummaryTaskDialog *dia = new SummaryTaskDialog(*task, this);
1981                 connect(dia, &QDialog::finished, this, &View::slotSummaryTaskEditFinished);
1982                 dia->open();
1983                 break;
1984             }
1985         default:
1986             break; // avoid warnings
1987     }
1988 }
1989 
1990 void View::slotProjectEditFinished(int result)
1991 {
1992     MainProjectDialog *dia = qobject_cast<MainProjectDialog*>(sender());
1993     if (dia == 0) {
1994         return;
1995     }
1996     if (result == QDialog::Accepted) {
1997         KUndo2Command * cmd = dia->buildCommand();
1998         if (cmd) {
1999             getPart() ->addCommand(cmd);
2000         }
2001     }
2002     dia->deleteLater();
2003 }
2004 
2005 void View::slotTaskEditFinished(int result)
2006 {
2007     TaskDialog *dia = qobject_cast<TaskDialog*>(sender());
2008     if (dia == 0) {
2009         return;
2010     }
2011     if (result == QDialog::Accepted) {
2012         KUndo2Command * cmd = dia->buildCommand();
2013         if (cmd) {
2014             getPart() ->addCommand(cmd);
2015         }
2016     }
2017     dia->deleteLater();
2018 }
2019 
2020 void View::slotSummaryTaskEditFinished(int result)
2021 {
2022     SummaryTaskDialog *dia = qobject_cast<SummaryTaskDialog*>(sender());
2023     if (dia == 0) {
2024         return;
2025     }
2026     if (result == QDialog::Accepted) {
2027         KUndo2Command * cmd = dia->buildCommand();
2028         if (cmd) {
2029             getPart() ->addCommand(cmd);
2030         }
2031     }
2032     dia->deleteLater();
2033 }
2034 
2035 ScheduleManager *View::currentScheduleManager() const
2036 {
2037     return m_scheduleActions.value(m_scheduleActionGroup->checkedAction());
2038 }
2039 
2040 long View::activeScheduleId() const
2041 {
2042     ScheduleManager *s = m_scheduleActions.value(m_scheduleActionGroup->checkedAction());
2043     return s == nullptr || s->expected() == nullptr ? -1 : s->expected()->id();
2044 }
2045 
2046 void View::setActiveSchedule(long id)
2047 {
2048     if (id != -1) {
2049         QMap<QAction*, ScheduleManager*>::const_iterator it = m_scheduleActions.constBegin();
2050         for (; it != m_scheduleActions.constEnd(); ++it) {
2051             int mid = it.value()->expected() == nullptr ? -1 : it.value()->expected()->id();
2052             if (mid == id) {
2053                 it.key()->setChecked(true);
2054                 slotViewSchedule(it.key()); // signal not emitted from group, so trigger it here
2055                 break;
2056             }
2057         }
2058     }
2059 }
2060 
2061 void View::slotTaskProgress()
2062 {
2063     //debugPlan;
2064     Node * node = currentNode();
2065     if (!node)
2066         return ;
2067 
2068     switch (node->type()) {
2069         case Node::Type_Project: {
2070                 break;
2071             }
2072         case Node::Type_Subproject:
2073             //TODO
2074             break;
2075         case Node::Type_Task: {
2076                 Task *task = dynamic_cast<Task *>(node);
2077                 Q_ASSERT(task);
2078                 TaskProgressDialog *dia = new TaskProgressDialog(*task, currentScheduleManager(),  getProject().standardWorktime(), this);
2079                 connect(dia, &QDialog::finished, this, &View::slotTaskProgressFinished);
2080                 dia->open();
2081                 break;
2082             }
2083         case Node::Type_Milestone: {
2084                 Task *task = dynamic_cast<Task *>(node);
2085                 Q_ASSERT(task);
2086                 MilestoneProgressDialog *dia = new MilestoneProgressDialog(*task, this);
2087                 connect(dia, &QDialog::finished, this, &View::slotMilestoneProgressFinished);
2088                 dia->open();
2089                 break;
2090             }
2091         case Node::Type_Summarytask: {
2092                 // TODO
2093                 break;
2094             }
2095         default:
2096             break; // avoid warnings
2097     }
2098 }
2099 
2100 void View::slotTaskProgressFinished(int result)
2101 {
2102     TaskProgressDialog *dia = qobject_cast<TaskProgressDialog*>(sender());
2103     if (dia == 0) {
2104         return;
2105     }
2106     if (result == QDialog::Accepted) {
2107         KUndo2Command * m = dia->buildCommand();
2108         if (m) {
2109             getPart() ->addCommand(m);
2110         }
2111     }
2112     dia->deleteLater();
2113 }
2114 
2115 void View::slotMilestoneProgressFinished(int result)
2116 {
2117     MilestoneProgressDialog *dia = qobject_cast<MilestoneProgressDialog*>(sender());
2118     if (dia == 0) {
2119         return;
2120     }
2121     if (result == QDialog::Accepted) {
2122         KUndo2Command * m = dia->buildCommand();
2123         if (m) {
2124             getPart() ->addCommand(m);
2125         }
2126     }
2127     dia->deleteLater();
2128 }
2129 
2130 void View::slotOpenProjectDescription()
2131 {
2132     debugPlan<<koDocument()->isReadWrite();
2133     TaskDescriptionDialog *dia = new TaskDescriptionDialog(getProject(), this, !koDocument()->isReadWrite());
2134     connect(dia, &QDialog::finished, this, &View::slotTaskDescriptionFinished);
2135     dia->open();
2136 }
2137 
2138 void View::slotTaskDescription()
2139 {
2140     slotOpenTaskDescription(!koDocument()->isReadWrite());
2141 }
2142 
2143 void View::slotOpenTaskDescription(bool ro)
2144 {
2145     //debugPlan;
2146     Node * node = currentNode();
2147     if (!node)
2148         return ;
2149 
2150     switch (node->type()) {
2151         case Node::Type_Subproject:
2152             //TODO
2153             break;
2154         case Node::Type_Project:
2155         case Node::Type_Task:
2156         case Node::Type_Milestone:
2157         case Node::Type_Summarytask: {
2158                 TaskDescriptionDialog *dia = new TaskDescriptionDialog(*node, this, ro);
2159                 connect(dia, &QDialog::finished, this, &View::slotTaskDescriptionFinished);
2160                 dia->open();
2161                 break;
2162             }
2163         default:
2164             break; // avoid warnings
2165     }
2166 }
2167 
2168 void View::slotTaskDescriptionFinished(int result)
2169 {
2170     TaskDescriptionDialog *dia = qobject_cast<TaskDescriptionDialog*>(sender());
2171     if (dia == 0) {
2172         return;
2173     }
2174     if (result == QDialog::Accepted) {
2175         KUndo2Command * m = dia->buildCommand();
2176         if (m) {
2177             getPart() ->addCommand(m);
2178         }
2179     }
2180     dia->deleteLater();
2181 }
2182 
2183 void View::slotDocuments()
2184 {
2185     //debugPlan;
2186     Node * node = currentNode();
2187     if (!node) {
2188         return ;
2189     }
2190     switch (node->type()) {
2191         case Node::Type_Subproject:
2192             //TODO
2193             break;
2194         case Node::Type_Project:
2195         case Node::Type_Summarytask:
2196         case Node::Type_Task:
2197         case Node::Type_Milestone: {
2198             DocumentsDialog *dia = new DocumentsDialog(*node, this);
2199             connect(dia, &QDialog::finished, this, &View::slotDocumentsFinished);
2200             dia->open();
2201             break;
2202         }
2203         default:
2204             break; // avoid warnings
2205     }
2206 }
2207 
2208 void View::slotDocumentsFinished(int result)
2209 {
2210     DocumentsDialog *dia = qobject_cast<DocumentsDialog*>(sender());
2211     if (dia == 0) {
2212         return;
2213     }
2214     if (result == QDialog::Accepted) {
2215         KUndo2Command * m = dia->buildCommand();
2216         if (m) {
2217             getPart()->addCommand(m);
2218         }
2219     }
2220     dia->deleteLater();
2221 }
2222 
2223 void View::slotDeleteTaskList(QList<Node*> lst)
2224 {
2225     //debugPlan;
2226     foreach (Node *n, lst) {
2227         if (n->isScheduled()) {
2228             KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel(this, i18n("A task that has been scheduled will be deleted. This will invalidate the schedule."));
2229             if (res == KMessageBox::Cancel) {
2230                 return;
2231             }
2232             break;
2233         }
2234     }
2235     if (lst.count() == 1) {
2236         getPart()->addCommand(new NodeDeleteCmd(lst.takeFirst(), kundo2_i18n("Delete task")));
2237         return;
2238     }
2239     int num = 0;
2240     MacroCommand *cmd = new MacroCommand(kundo2_i18np("Delete task", "Delete tasks", lst.count()));
2241     while (!lst.isEmpty()) {
2242         Node *node = lst.takeFirst();
2243         if (node == 0 || node->parentNode() == 0) {
2244             debugPlan << (node ?"Task is main project" :"No current task");
2245             continue;
2246         }
2247         bool del = true;
2248         foreach (Node *n, lst) {
2249             if (node->isChildOf(n)) {
2250                 del = false; // node is going to be deleted when we delete n
2251                 break;
2252             }
2253         }
2254         if (del) {
2255             //debugPlan<<num<<": delete:"<<node->name();
2256             cmd->addCommand(new NodeDeleteCmd(node, kundo2_i18n("Delete task")));
2257             num++;
2258         }
2259     }
2260     if (num > 0) {
2261         getPart()->addCommand(cmd);
2262     } else {
2263         delete cmd;
2264     }
2265 }
2266 
2267 void View::slotDeleteTask(Node *node)
2268 {
2269     //debugPlan;
2270     if (node == 0 || node->parentNode() == 0) {
2271         debugPlan << (node ?"Task is main project" :"No current task");
2272         return ;
2273     }
2274     if (node->isScheduled()) {
2275         KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel(this, i18n("This task has been scheduled. This will invalidate the schedule."));
2276         if (res == KMessageBox::Cancel) {
2277             return;
2278         }
2279     }
2280     NodeDeleteCmd *cmd = new NodeDeleteCmd(node, kundo2_i18n("Delete task"));
2281     getPart() ->addCommand(cmd);
2282 }
2283 
2284 void View::slotDeleteCurrentTask()
2285 {
2286     //debugPlan;
2287     return slotDeleteTask(currentNode());
2288 }
2289 
2290 void View::slotIndentTask()
2291 {
2292     //debugPlan;
2293     Node * node = currentNode();
2294     if (node == 0 || node->parentNode() == 0) {
2295         debugPlan << (node ?"Task is main project" :"No current task");
2296         return ;
2297     }
2298     if (getProject().canIndentTask(node)) {
2299         NodeIndentCmd * cmd = new NodeIndentCmd(*node, kundo2_i18n("Indent task"));
2300         getPart() ->addCommand(cmd);
2301     }
2302 }
2303 
2304 void View::slotUnindentTask()
2305 {
2306     //debugPlan;
2307     Node * node = currentNode();
2308     if (node == 0 || node->parentNode() == 0) {
2309         debugPlan << (node ?"Task is main project" :"No current task");
2310         return ;
2311     }
2312     if (getProject().canUnindentTask(node)) {
2313         NodeUnindentCmd * cmd = new NodeUnindentCmd(*node, kundo2_i18n("Unindent task"));
2314         getPart() ->addCommand(cmd);
2315     }
2316 }
2317 
2318 void View::slotMoveTaskUp()
2319 {
2320     //debugPlan;
2321 
2322     Node * task = currentNode();
2323     if (0 == task) {
2324         // is always != 0. At least we would get the Project, but you never know who might change that
2325         // so better be careful
2326         errorPlan << "No current task" << endl;
2327         return ;
2328     }
2329 
2330     if (Node::Type_Project == task->type()) {
2331         debugPlan <<"The root node cannot be moved up";
2332         return ;
2333     }
2334     if (getProject().canMoveTaskUp(task)) {
2335         NodeMoveUpCmd * cmd = new NodeMoveUpCmd(*task, kundo2_i18n("Move task up"));
2336         getPart() ->addCommand(cmd);
2337     }
2338 }
2339 
2340 void View::slotMoveTaskDown()
2341 {
2342     //debugPlan;
2343 
2344     Node * task = currentNode();
2345     if (0 == task) {
2346         // is always != 0. At least we would get the Project, but you never know who might change that
2347         // so better be careful
2348         return ;
2349     }
2350 
2351     if (Node::Type_Project == task->type()) {
2352         debugPlan <<"The root node cannot be moved down";
2353         return ;
2354     }
2355     if (getProject().canMoveTaskDown(task)) {
2356         NodeMoveDownCmd * cmd = new NodeMoveDownCmd(*task, kundo2_i18n("Move task down"));
2357         getPart() ->addCommand(cmd);
2358     }
2359 }
2360 
2361 void View::openRelationDialog(Node *par, Node *child)
2362 {
2363     //debugPlan;
2364     Relation * rel = new Relation(par, child);
2365     AddRelationDialog *dia = new AddRelationDialog(getProject(), rel, this);
2366     connect(dia, &QDialog::finished, this, &View::slotAddRelationFinished);
2367     dia->open();
2368 }
2369 
2370 void View::slotAddRelationFinished(int result)
2371 {
2372     AddRelationDialog *dia = qobject_cast<AddRelationDialog*>(sender());
2373     if (dia == 0) {
2374         return;
2375     }
2376     if (result == QDialog::Accepted) {
2377         KUndo2Command * m = dia->buildCommand();
2378         if (m) {
2379             getPart() ->addCommand(m);
2380         }
2381     }
2382     dia->deleteLater();
2383 }
2384 
2385 void View::slotAddRelation(Node *par, Node *child, int linkType)
2386 {
2387     //debugPlan;
2388     if (linkType == Relation::FinishStart ||
2389             linkType == Relation::StartStart ||
2390             linkType == Relation::FinishFinish) {
2391         Relation * rel = new Relation(par, child, static_cast<Relation::Type>(linkType));
2392         getPart() ->addCommand(new AddRelationCmd(getProject(), rel, kundo2_i18n("Add task dependency")));
2393     } else {
2394         openRelationDialog(par, child);
2395     }
2396 }
2397 
2398 void View::slotEditRelation(Relation *rel)
2399 {
2400     //debugPlan;
2401     ModifyRelationDialog *dia = new ModifyRelationDialog(getProject(), rel, this);
2402     connect(dia, &QDialog::finished, this, &View::slotModifyRelationFinished);
2403     dia->open();
2404 }
2405 
2406 void View::slotModifyRelationFinished(int result)
2407 {
2408     ModifyRelationDialog *dia = qobject_cast<ModifyRelationDialog*>(sender());
2409     if (dia == 0) {
2410         return ;
2411     }
2412     if (result == QDialog::Accepted) {
2413         KUndo2Command *cmd = dia->buildCommand();
2414         if (cmd) {
2415             getPart() ->addCommand(cmd);
2416         }
2417     }
2418     dia->deleteLater();
2419 }
2420 
2421 void View::slotModifyRelation(Relation *rel, int linkType)
2422 {
2423     //debugPlan;
2424     if (linkType == Relation::FinishStart ||
2425             linkType == Relation::StartStart ||
2426             linkType == Relation::FinishFinish) {
2427         getPart() ->addCommand(new ModifyRelationTypeCmd(rel, static_cast<Relation::Type>(linkType)));
2428     } else {
2429         slotEditRelation(rel);
2430     }
2431 }
2432 
2433 void View::slotModifyCurrentRelation()
2434 {
2435     ViewBase *v = dynamic_cast<ViewBase*>(m_tab->currentWidget());
2436     if (v == 0) {
2437         return;
2438     }
2439     Relation *rel = v->currentRelation();
2440     if (rel) {
2441         slotEditRelation(rel);
2442     }
2443 }
2444 
2445 void View::slotDeleteRelation()
2446 {
2447     ViewBase *v = dynamic_cast<ViewBase*>(m_tab->currentWidget());
2448     if (v == 0) {
2449         return;
2450     }
2451     Relation *rel = v->currentRelation();
2452     if (rel) {
2453         getPart()->addCommand(new DeleteRelationCmd(getProject(), rel, kundo2_i18n("Delete task dependency")));
2454     }
2455 }
2456 
2457 void View::slotEditCurrentResource()
2458 {
2459     //debugPlan;
2460     slotEditResource(currentResource());
2461 }
2462 
2463 void View::slotEditResource(Resource *resource)
2464 {
2465     if (resource == 0) {
2466         return ;
2467     }
2468     ResourceDialog *dia = new ResourceDialog(getProject(), resource, this);
2469     connect(dia, &QDialog::finished, this, &View::slotEditResourceFinished);
2470     dia->open();
2471 }
2472 
2473 void View::slotEditResourceFinished(int result)
2474 {
2475     //debugPlan;
2476     ResourceDialog *dia = qobject_cast<ResourceDialog*>(sender());
2477     if (dia == 0) {
2478         return ;
2479     }
2480     if (result == QDialog::Accepted) {
2481         KUndo2Command * cmd = dia->buildCommand();
2482         if (cmd)
2483             getPart() ->addCommand(cmd);
2484     }
2485     dia->deleteLater();
2486 }
2487 
2488 void View::slotDeleteResource(Resource *resource)
2489 {
2490     getPart()->addCommand(new RemoveResourceCmd(resource->parentGroup(), resource, kundo2_i18n("Delete resource")));
2491 }
2492 
2493 void View::slotDeleteResourceGroup(ResourceGroup *group)
2494 {
2495     getPart()->addCommand(new RemoveResourceGroupCmd(group->project(), group, kundo2_i18n("Delete resourcegroup")));
2496 }
2497 
2498 void View::slotDeleteResourceObjects(QObjectList lst)
2499 {
2500     //debugPlan;
2501     foreach (QObject *o, lst) {
2502         Resource *r = qobject_cast<Resource*>(o);
2503         if (r && r->isScheduled()) {
2504             KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel(this, i18n("A resource that has been scheduled will be deleted. This will invalidate the schedule."));
2505             if (res == KMessageBox::Cancel) {
2506                 return;
2507             }
2508             break;
2509         }
2510         ResourceGroup *g = qobject_cast<ResourceGroup*>(o);
2511         if (g && g->isScheduled()) {
2512             KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel(this, i18n("A resource that has been scheduled will be deleted. This will invalidate the schedule."));
2513             if (res == KMessageBox::Cancel) {
2514                 return;
2515             }
2516             break;
2517         }
2518     }
2519     if (lst.count() == 1) {
2520         Resource *r = qobject_cast<Resource*>(lst.first());
2521         if (r) {
2522             slotDeleteResource(r);
2523         } else {
2524             ResourceGroup *g = qobject_cast<ResourceGroup*>(lst.first());
2525             if (g) {
2526                 slotDeleteResourceGroup(g);
2527             }
2528         }
2529         return;
2530     }
2531 //    int num = 0;
2532     MacroCommand *cmd = 0, *rc = 0, *gc = 0;
2533     foreach (QObject *o, lst) {
2534         Resource *r = qobject_cast<Resource*>(o);
2535         if (r) {
2536             if (rc == 0)  rc = new MacroCommand(KUndo2MagicString());
2537             rc->addCommand(new RemoveResourceCmd(r->parentGroup(), r));
2538             continue;
2539         }
2540         ResourceGroup *g = qobject_cast<ResourceGroup*>(o);
2541         if (g) {
2542             if (gc == 0)  gc = new MacroCommand(KUndo2MagicString());
2543             gc->addCommand(new RemoveResourceGroupCmd(g->project(), g));
2544         }
2545     }
2546     if (rc || gc) {
2547         KUndo2MagicString s;
2548         if (rc && gc) {
2549             s = kundo2_i18n("Delete resourcegroups and resources");
2550         } else if (rc) {
2551             s = kundo2_i18np("Delete resource", "Delete resources", lst.count());
2552         } else {
2553             s = kundo2_i18np("Delete resourcegroup", "Delete resourcegroups", lst.count());
2554         }
2555         cmd = new MacroCommand(s);
2556     }
2557     if (rc)
2558         cmd->addCommand(rc);
2559     if (gc)
2560         cmd->addCommand(gc);
2561     if (cmd)
2562         getPart()->addCommand(cmd);
2563 }
2564 
2565 
2566 void View::updateReadWrite(bool readwrite)
2567 {
2568     m_readWrite = readwrite;
2569     m_viewlist->setReadWrite(readwrite);
2570 }
2571 
2572 MainDocument *View::getPart() const
2573 {
2574     return (MainDocument *) koDocument();
2575 }
2576 
2577 KoPart *View::getKoPart() const
2578 {
2579     return m_partpart;
2580 }
2581 
2582 void View::slotConnectNode()
2583 {
2584     //debugPlan;
2585     /*    NodeItem *curr = ganttview->currentItem();
2586         if (curr) {
2587             debugPlan<<"node="<<curr->getNode().name();
2588         }*/
2589 }
2590 
2591 QMenu * View::popupMenu(const QString& name)
2592 {
2593     //debugPlan;
2594     if (factory()) {
2595         return ((QMenu*) factory() ->container(name, this));
2596     }
2597     debugPlan<<"No factory";
2598     return 0L;
2599 }
2600 
2601 void View::slotUpdate()
2602 {
2603     //debugPlan<<"calculate="<<calculate;
2604 
2605 //    m_updateResourceview = true;
2606     m_updateResourceAssignmentView = true;
2607     m_updatePertEditor = true;
2608     updateView(m_tab->currentWidget());
2609 }
2610 
2611 void View::slotGuiActivated(ViewBase *view, bool activate)
2612 {
2613     if (activate) {
2614         foreach (DockWidget *ds, view->dockers()) {
2615             m_dockers.append(ds);
2616             ds->activate(mainWindow());
2617         }
2618         if (!m_dockers.isEmpty()) {debugPlan<<"Added dockers:"<<view<<m_dockers;}
2619     } else {
2620         if (!m_dockers.isEmpty()) {debugPlan<<"Remove dockers:"<<view<<m_dockers;}
2621         while (! m_dockers.isEmpty()) {
2622             m_dockers.takeLast()->deactivate(mainWindow());
2623         }
2624     }
2625 }
2626 
2627 void View::guiActivateEvent(bool activated)
2628 {
2629     if (activated) {
2630         // plug my own actionlists, they may be gone
2631         slotPlugScheduleActions();
2632     }
2633     // propagate to sub-view
2634     ViewBase *v = dynamic_cast<ViewBase*>(m_tab->currentWidget());
2635     if (v) {
2636         v->setGuiActive(activated);
2637     }
2638 }
2639 
2640 void View::slotViewListItemRemoved(ViewListItem *item)
2641 {
2642     getPart()->removeViewListItem(this, item);
2643 }
2644 
2645 void View::removeViewListItem(const ViewListItem *item)
2646 {
2647     if (item == 0) {
2648         return;
2649     }
2650     ViewListItem *itm = m_viewlist->findItem(item->tag());
2651     if (itm == 0) {
2652         return;
2653     }
2654     m_viewlist->removeViewListItem(itm);
2655     return;
2656 }
2657 
2658 void View::slotViewListItemInserted(ViewListItem *item, ViewListItem *parent, int index)
2659 {
2660     getPart()->insertViewListItem(this, item, parent, index);
2661 }
2662 
2663 void View::addViewListItem(const ViewListItem *item, const ViewListItem *parent, int index)
2664 {
2665     if (item == 0) {
2666         return;
2667     }
2668     if (parent == 0) {
2669         if (item->type() != ViewListItem::ItemType_Category) {
2670             return;
2671         }
2672         m_viewlist->blockSignals(true);
2673         ViewListItem *cat = m_viewlist->addCategory(item->tag(), item->text(0));
2674         cat->setToolTip(0, item->toolTip(0));
2675         m_viewlist->blockSignals(false);
2676         return;
2677     }
2678     ViewListItem *cat = m_viewlist->findCategory(parent->tag());
2679     if (cat == 0) {
2680         return;
2681     }
2682     m_viewlist->blockSignals(true);
2683     createView(cat, item->viewType(), item->tag(), item->text(0), item->toolTip(0), index);
2684     m_viewlist->blockSignals(false);
2685 }
2686 
2687 void View::createReportView(const QDomDocument &doc)
2688 {
2689 #ifdef PLAN_USE_KREPORT
2690     QPointer<ViewListReportsDialog> vd = new ViewListReportsDialog(this, *m_viewlist, doc, this);
2691     vd->exec(); // FIXME  make non-crash
2692     delete vd;
2693 #else
2694     Q_UNUSED(doc)
2695 #endif
2696 }
2697 
2698 void View::slotOpenReportFile()
2699 {
2700 #ifdef PLAN_USE_KREPORT
2701     QFileDialog *dlg = new QFileDialog(this);
2702     connect(dlg, &QDialog::finished, &View::slotOpenReportFileFinished(int)));
2703     dlg->open();
2704 #endif
2705 }
2706 
2707 void View::slotOpenReportFileFinished(int result)
2708 {
2709 #ifdef PLAN_USE_KREPORT
2710     QFileDialog *fdlg = qobject_cast<QFileDialog*>(sender());
2711     if (fdlg == 0 || result != QDialog::Accepted) {
2712         return;
2713     }
2714     QString fn = fdlg->selectedFiles().value(0);
2715     if (fn.isEmpty()) {
2716         return;
2717     }
2718     QFile file(fn);
2719     if (! file.open(QIODevice::ReadOnly | QIODevice::Text)) {
2720         KMessageBox::sorry(this, xi18nc("@info", "Cannot open file:<br/><filename>%1</filename>", fn));
2721         return;
2722     }
2723     QDomDocument doc;
2724     doc.setContent(&file);
2725     createReportView(doc);
2726 #else
2727     Q_UNUSED(result)
2728 #endif
2729 }
2730 
2731 void View::slotReportDesignFinished(int /*result */)
2732 {
2733 #ifdef PLAN_USE_KREPORT
2734     if (sender()) {
2735         sender()->deleteLater();
2736     }
2737 #endif
2738 }
2739 
2740 void View::slotCreateView()
2741 {
2742     ViewListDialog *dlg = new ViewListDialog(this, *m_viewlist, this);
2743     connect(dlg, &QDialog::finished, this, &View::slotCreateViewFinished);
2744     dlg->open();
2745 }
2746 
2747 void View::slotCreateViewFinished(int)
2748 {
2749     if (sender()) {
2750         sender()->deleteLater();
2751     }
2752 }
2753 
2754 void View::slotViewActivated(ViewListItem *item, ViewListItem *prev)
2755 {
2756     QApplication::setOverrideCursor(Qt::WaitCursor);
2757     if (prev && prev->type() == ViewListItem::ItemType_Category && m_viewlist->previousViewItem()) {
2758         // A view is shown anyway...
2759         ViewBase *v = qobject_cast<ViewBase*>(m_viewlist->previousViewItem()->view());
2760         if (v) {
2761             factory()->removeClient(v);
2762             v->setGuiActive(false);
2763         }
2764     } else if (prev && prev->type() == ViewListItem::ItemType_SubView) {
2765         ViewBase *v = qobject_cast<ViewBase*>(prev->view());
2766         if (v) {
2767             factory()->removeClient(v);
2768             v->setGuiActive(false);
2769         }
2770     }
2771     if (item && item->type() == ViewListItem::ItemType_SubView) {
2772         //debugPlan<<"Activate:"<<item;
2773         m_tab->setCurrentWidget(item->view());
2774         // Add sub-view specific gui
2775         ViewBase *v = dynamic_cast<ViewBase*>(m_tab->currentWidget());
2776         if (v) {
2777             factory()->addClient(v);
2778             v->setGuiActive(true);
2779         }
2780     }
2781     QApplication::restoreOverrideCursor();
2782 }
2783 
2784 QWidget *View::canvas() const
2785 {
2786     return m_tab->currentWidget();//KoView::canvas();
2787 }
2788 
2789 KoPageLayout View::pageLayout() const
2790 {
2791     return currentView()->pageLayout();
2792 }
2793 
2794 void View::setPageLayout(const KoPageLayout &pageLayout)
2795 {
2796     currentView()->setPageLayout(pageLayout);
2797 }
2798 
2799 QPrintDialog *View::createPrintDialog(KoPrintJob *printJob, QWidget *parent)
2800 {
2801     debugPlan<<printJob;
2802     KoPrintingDialog *job = dynamic_cast<KoPrintingDialog*>(printJob);
2803     if (! job) {
2804         return 0;
2805     }
2806     QPrintDialog *dia = KoView::createPrintDialog(job, parent);
2807 
2808     PrintingDialog *j = dynamic_cast<PrintingDialog*>(job);
2809     if (j) {
2810         new PrintingControlPrivate(j, dia);
2811     }
2812     return dia;
2813 }
2814 
2815 void View::slotCurrentChanged(int view)
2816 {
2817     m_visitedViews << view;
2818     ViewListItem *item = m_viewlist->findItem(qobject_cast<ViewBase*>(m_tab->currentWidget()));
2819     m_viewlist->setCurrentItem(item);
2820 }
2821 
2822 void View::slotSelectDefaultView()
2823 {
2824     m_tab->setCurrentIndex(qMin(m_defaultView, m_tab->count()-1));
2825 }
2826 
2827 void View::updateView(QWidget *)
2828 {
2829     QApplication::setOverrideCursor(Qt::WaitCursor);
2830     //setScheduleActionsEnabled();
2831 
2832     QWidget *widget2;
2833 
2834     widget2 = m_viewlist->findView("ResourceAssignmentView");
2835     if (widget2 && m_updateResourceAssignmentView)
2836         static_cast<ViewBase*>(widget2) ->draw(getProject());
2837     m_updateResourceAssignmentView = false;
2838 
2839     QApplication::restoreOverrideCursor();
2840 }
2841 
2842 void View::slotRenameNode(Node *node, const QString& name)
2843 {
2844     //debugPlan<<name;
2845     if (node) {
2846         KUndo2MagicString s = kundo2_i18n("Modify name");
2847         switch(node->type()) {
2848             case Node::Type_Task: s = kundo2_i18n("Modify task name"); break;
2849             case Node::Type_Milestone: s = kundo2_i18n("Modify milestone name"); break;
2850             case Node::Type_Summarytask: s = kundo2_i18n("Modify summarytask name"); break;
2851             case Node::Type_Project: s = kundo2_i18n("Modify project name"); break;
2852         }
2853         NodeModifyNameCmd * cmd = new NodeModifyNameCmd(*node, name, s);
2854         getPart() ->addCommand(cmd);
2855     }
2856 }
2857 
2858 void View::slotPopupMenuRequested(const QString& menuname, const QPoint & pos)
2859 {
2860     QMenu * menu = this->popupMenu(menuname);
2861     if (menu) {
2862         //debugPlan<<menu<<":"<<menu->actions().count();
2863         ViewBase *v = qobject_cast<ViewBase*>(m_tab->currentWidget());
2864         //debugPlan<<v<<menuname;
2865         QList<QAction*> lst;
2866         if (v) {
2867             lst = v->contextActionList();
2868             debugPlan<<lst;
2869             if (! lst.isEmpty()) {
2870                 menu->addSeparator();
2871                 foreach (QAction *a, lst) {
2872                     menu->addAction(a);
2873                 }
2874             }
2875         }
2876         menu->exec(pos);
2877         foreach (QAction *a, lst) {
2878             menu->removeAction(a);
2879         }
2880     }
2881 }
2882 
2883 void View::slotPopupMenu(const QString& menuname, const QPoint &pos, ViewListItem *item)
2884 {
2885     //debugPlan<<menuname;
2886     m_viewlistItem = item;
2887     slotPopupMenuRequested(menuname, pos);
2888 }
2889 
2890 bool View::loadContext()
2891 {
2892     Context *ctx = getPart()->context();
2893     if (ctx == 0 || ! ctx->isLoaded()) {
2894         return false;
2895     }
2896     KoXmlElement n = ctx->context();
2897     QString cv = n.attribute("current-view");
2898     if (! cv.isEmpty()) {
2899         m_viewlist->setSelected(m_viewlist->findItem(cv));
2900     } else debugPlan<<"No current view";
2901 
2902     long id = n.attribute("current-schedule", "-1").toLong();
2903     if (id != -1) {
2904         setActiveSchedule(id);
2905     } else debugPlan<<"No current schedule";
2906 
2907     return true;
2908 }
2909 
2910 void View::saveContext(QDomElement &me) const
2911 {
2912     //debugPlan;
2913     long id = activeScheduleId();
2914     if (id != -1) {
2915         me.setAttribute("current-schedule", QString::number((qlonglong)id));
2916     }
2917     ViewListItem *item = m_viewlist->findItem(qobject_cast<ViewBase*>(m_tab->currentWidget()));
2918     if (item) {
2919         me.setAttribute("current-view", item->tag());
2920     }
2921     m_viewlist->save(me);
2922 }
2923 
2924 void View::loadWorkPackage(Project *project, const QList<QUrl> &urls)
2925 {
2926     bool loaded = false;
2927     for (const QUrl &url : urls) {
2928         loaded |= getPart()->loadWorkPackage(*project, url);
2929     }
2930     if (loaded) {
2931         slotWorkPackageLoaded();
2932     }
2933 }
2934 
2935 void View::setLabel(ScheduleManager *sm)
2936 {
2937     //debugPlan;
2938     Schedule *s = sm == 0 ? 0 : sm->expected();
2939     if (s && !s->isDeleted() && s->isScheduled()) {
2940         m_estlabel->setText(sm->name());
2941         return;
2942     }
2943     m_estlabel->setText(xi18nc("@info:status", "Not scheduled"));
2944 }
2945 
2946 void View::slotWorkPackageLoaded()
2947 {
2948     debugPlan<<getPart()->workPackages();
2949     addStatusBarItem(m_workPackageButton, 0, true);
2950     emit workPackagesAvailable(true);
2951 }
2952 
2953 void View::openWorkPackageMergeDialog()
2954 {
2955     WorkPackageMergeDialog *dlg = new WorkPackageMergeDialog(&getProject(), getPart()->workPackages(), this);
2956     connect(dlg, &QDialog::finished, this, &View::workPackageMergeDialogFinished);
2957     connect(dlg, SIGNAL(terminateWorkPackage(const KPlato::Package*)), getPart(), SLOT(terminateWorkPackage(const KPlato::Package*)));
2958     connect(dlg, &WorkPackageMergeDialog::executeCommand, koDocument(), &KoDocument::addCommand);
2959     dlg->open();
2960     removeStatusBarItem(m_workPackageButton);
2961     emit workPackagesAvailable(false);
2962 }
2963 
2964 void View::workPackageMergeDialogFinished(int result)
2965 {
2966     debugPlanWp<<"result:"<<result<<"sender:"<<sender();
2967     WorkPackageMergeDialog *dlg = qobject_cast<WorkPackageMergeDialog*>(sender());
2968     Q_ASSERT(dlg);
2969     if (!getPart()->workPackages().isEmpty()) {
2970         slotWorkPackageLoaded();
2971     }
2972     if (dlg) {
2973         dlg->deleteLater();
2974     }
2975 }
2976 
2977 
2978 void View::slotMailWorkpackage(Node *node, Resource *resource)
2979 {
2980     debugPlan;
2981     QTemporaryFile tmpfile(QDir::tempPath() + QLatin1String("/calligraplanwork_XXXXXX") + QLatin1String(".planwork"));
2982     tmpfile.setAutoRemove(false);
2983     if (! tmpfile.open()) {
2984         debugPlan<<"Failed to open file";
2985         KMessageBox::error(0, i18n("Failed to open temporary file"));
2986         return;
2987     }
2988     QUrl url = QUrl::fromLocalFile(tmpfile.fileName());
2989     if (! getPart()->saveWorkPackageUrl(url, node, activeScheduleId(), resource)) {
2990         debugPlan<<"Failed to save to file";
2991         KMessageBox::error(0, xi18nc("@info", "Failed to save to temporary file:<br/> <filename>%1</filename>", url.url()));
2992         return;
2993     }
2994     QStringList attachURLs;
2995     attachURLs << url.url();
2996     QString to = resource == 0 ? node->leader() : (resource->name() + " <" + resource->email() + '>');
2997     QString cc;
2998     QString bcc;
2999     QString subject = i18n("Work Package: %1", node->name());
3000     QString body = i18nc("1=project name, 2=task name", "%1\n%2", getProject().name(), node->name());
3001     QString messageFile;
3002 
3003     KToolInvocation::invokeMailer(to, cc, bcc, subject, body, messageFile, attachURLs);
3004 }
3005 
3006 void View::slotPublishWorkpackages(const QList<Node*> &nodes, Resource *resource, bool mailTo)
3007 {
3008     debugPlanWp<<resource<<nodes;
3009     if (resource == 0) {
3010         warnPlan<<"No resource, we don't handle node->leader() yet";
3011         return;
3012     }
3013     bool mail = mailTo;
3014     QString body;
3015     QStringList attachURLs;
3016 
3017     QString path;
3018     if (getProject().workPackageInfo().publishUrl.isValid()) {
3019         path = getProject().workPackageInfo().publishUrl.path();
3020         debugPlanWp<<"publish:"<<path;
3021     } else {
3022         path = QDir::tempPath();
3023         mail = true;
3024     }
3025     foreach (Node *n, nodes) {
3026         QTemporaryFile tmpfile(path + QLatin1String("/calligraplanwork_XXXXXX") + QLatin1String(".planwork"));
3027         tmpfile.setAutoRemove(false);
3028         if (! tmpfile.open()) {
3029             debugPlanWp<<"Failed to open file";
3030             KMessageBox::error(0, i18n("Failed to open work package file"));
3031             return;
3032         }
3033         QUrl url = QUrl::fromLocalFile(tmpfile.fileName());
3034         debugPlanWp<<url;
3035         if (! getPart()->saveWorkPackageUrl(url, n, activeScheduleId(), resource)) {
3036             debugPlan<<"Failed to save to file";
3037             KMessageBox::error(0, xi18nc("@info", "Failed to save to temporary file:<br/><filename>%1</filename>", url.url()));
3038             return;
3039         }
3040         attachURLs << url.url();
3041         body += n->name() + '\n';
3042     }
3043     if (mail) {
3044         debugPlanWp<<attachURLs;
3045         QString to = resource->name() + " <" + resource->email() + '>';
3046         QString subject = i18n("Work Package for project: %1", getProject().name());
3047         QString cc;
3048         QString bcc;
3049         QString messageFile;
3050 
3051         KToolInvocation::invokeMailer(to, cc, bcc, subject, body, messageFile, attachURLs);
3052     }
3053 }
3054 
3055 void View::slotCurrencyConfig()
3056 {
3057     LocaleConfigMoneyDialog *dlg = new LocaleConfigMoneyDialog(getProject().locale(), this);
3058     connect(dlg, &QDialog::finished, this, &View::slotCurrencyConfigFinished);
3059     dlg->open();
3060 }
3061 
3062 void View::slotCurrencyConfigFinished(int result)
3063 {
3064     LocaleConfigMoneyDialog *dlg = qobject_cast<LocaleConfigMoneyDialog*>(sender());
3065     if (dlg == 0) {
3066         return;
3067     }
3068     if (result == QDialog::Accepted) {
3069         KUndo2Command *c = dlg->buildCommand(getProject());
3070         if (c) {
3071             getPart()->addCommand(c);
3072         }
3073     }
3074     dlg->deleteLater();
3075 }
3076 
3077 void View::saveTaskModule(const QUrl &url, Project *project)
3078 {
3079     // NOTE: workaround: KoResourcePaths::saveLocation("calligraplan_taskmodules"); does not work
3080     const QString dir = KoResourcePaths::saveLocation("appdata", "taskmodules/");
3081     debugPlan<<"dir="<<dir;
3082     if (! dir.isEmpty()) {
3083         Part *part = new Part(this);
3084         MainDocument *doc = new MainDocument(part);
3085         part->setDocument(doc);
3086         doc->disconnect(); // doc shall not handle feedback from openUrl()
3087         doc->setAutoSave(0); //disable
3088         doc->insertProject(*project, 0, 0); // FIXME: destroys project, find better way
3089         doc->getProject().setName(project->name());
3090         doc->getProject().setLeader(project->leader());
3091         doc->getProject().setDescription(project->description());
3092         doc->saveNativeFormat(dir + url.fileName());
3093         part->deleteLater(); // also deletes document
3094         debugPlan<<dir + url.fileName();
3095     } else {
3096         debugPlan<<"Could not find a location";
3097     }
3098 }
3099 
3100 void View::removeTaskModule(const QUrl &url)
3101 {
3102     debugPlan<<url;
3103 }
3104 
3105 QString View::standardTaskStatusReport() const
3106 {
3107     QString s;
3108 #ifdef PLAN_USE_KREPORT
3109     s = QString::fromLatin1(
3110         "<planreportdefinition version=\"1.0\" mime=\"application/x-vnd.kde.plan.report.definition\" editor=\"Plan\" >"
3111         "<data-source select-from=\"taskstatus\" ></data-source>"
3112         "<report:content xmlns:report=\"http://kexi-project.org/report/2.0\" xmlns:fo=\"urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0\" xmlns:svg=\"urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0\" >"
3113         "<report:title>%1</report:title>"
3114         "<report:script report:script-interpreter=\"javascript\" ></report:script>"
3115         "<report:grid report:grid-divisions=\"4\" report:grid-snap=\"1\" report:page-unit=\"cm\" report:grid-visible=\"1\" />"
3116         "<report:page-style report:print-orientation=\"portrait\" fo:margin-bottom=\"1cm\" fo:margin-top=\"1cm\" fo:margin-left=\"1cm\" fo:margin-right=\"1cm\" report:page-size=\"A4\" >predefined</report:page-style>"
3117         "<report:body>"
3118         "<report:section svg:height=\"1.75cm\" fo:background-color=\"#ffffff\" report:section-type=\"header-page-any\" >"
3119         "<report:field report:name=\"field16\" report:horizontal-align=\"left\" report:item-data-source=\"#project.manager\" svg:x=\"13cm\" svg:width=\"5.9714cm\" svg:y=\"0.4cm\" report:vertical-align=\"bottom\" svg:height=\"0.6cm\" report:z-index=\"0\" >"
3120         "<report:text-style fo:font-weight=\"bold\" fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"10\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3121         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3122         "</report:field>"
3123         "<report:label report:name=\"label16\" report:horizontal-align=\"left\" svg:x=\"13cm\" svg:width=\"5.9714cm\" svg:y=\"0cm\" report:caption=\"%2\" report:vertical-align=\"center\" svg:height=\"0.4cm\" report:z-index=\"1\" >"
3124         "<report:text-style fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"8\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:font-style=\"italic\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3125         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3126         "</report:label>"
3127         "<report:field report:name=\"field17\" report:horizontal-align=\"left\" report:item-data-source=\"#project.name\" svg:x=\"0cm\" svg:width=\"13cm\" svg:y=\"0.4cm\" report:vertical-align=\"bottom\" svg:height=\"0.6cm\" report:z-index=\"1\" >"
3128         "<report:text-style fo:font-weight=\"bold\" fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"10\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:background-color=\"#ffffff\" fo:background-opacity=\"0%\" />"
3129         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3130         "</report:field>"
3131         "<report:label report:name=\"label18\" report:horizontal-align=\"left\" svg:x=\"0cm\" svg:width=\"13cm\" svg:y=\"0cm\" report:caption=\"%3\" report:vertical-align=\"center\" svg:height=\"0.4cm\" report:z-index=\"0\" >"
3132         "<report:text-style fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"8\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:font-style=\"italic\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3133         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3134         "</report:label>"
3135         "<report:line report:name=\"line15\" svg:y1=\"1.2229cm\" svg:x1=\"0cm\" svg:y2=\"1.2229cm\" svg:x2=\"18.9715cm\" report:z-index=\"0\" >"
3136         "<report:line-style report:line-style=\"solid\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3137         "</report:line>"
3138         "</report:section>"
3139         "<report:section svg:height=\"1.50cm\" fo:background-color=\"#ffffff\" report:section-type=\"header-report\" >"
3140         "<report:label report:name=\"label17\" report:horizontal-align=\"left\" svg:x=\"0cm\" svg:width=\"18.97cm\" svg:y=\"0cm\" report:caption=\"%4\" report:vertical-align=\"center\" svg:height=\"1.25cm\" report:z-index=\"0\" >"
3141         "<report:text-style fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"10\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3142         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3143         "</report:label>"
3144         "</report:section>"
3145         "<report:section svg:height=\"2.50cm\" fo:background-color=\"#ffffff\" report:section-type=\"footer-page-any\" >"
3146         "<report:field report:name=\"field10\" report:horizontal-align=\"right\" report:item-data-source=\"=constants.PageNumber()\" svg:x=\"6.75cm\" svg:width=\"0.75cm\" svg:y=\"0.25cm\" report:vertical-align=\"center\" svg:height=\"0.75cm\" report:z-index=\"0\" >"
3147         "<report:text-style fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"8\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3148         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3149         "</report:field>"
3150         "<report:field report:name=\"field11\" report:horizontal-align=\"left\" report:item-data-source=\"=constants.PageTotal()\" svg:x=\"8.25cm\" svg:width=\"3cm\" svg:y=\"0.25cm\" report:vertical-align=\"center\" svg:height=\"0.75cm\" report:z-index=\"0\" >"
3151         "<report:text-style fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"8\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3152         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3153         "</report:field>"
3154         "<report:label report:name=\"label12\" report:horizontal-align=\"center\" svg:x=\"7.5cm\" svg:width=\"0.75cm\" svg:y=\"0.25cm\" report:caption=\"%5\" report:vertical-align=\"center\" svg:height=\"0.75cm\" report:z-index=\"0\" >"
3155         "<report:text-style fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"8\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:font-style=\"italic\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3156         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3157         "</report:label>"
3158         "<report:label report:name=\"label13\" report:horizontal-align=\"right\" svg:x=\"5.75cm\" svg:width=\"1cm\" svg:y=\"0.25cm\" report:caption=\"%6\" report:vertical-align=\"center\" svg:height=\"0.75cm\" report:z-index=\"0\" >"
3159         "<report:text-style fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"8\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:font-style=\"italic\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3160         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3161         "</report:label>"
3162         "<report:line report:name=\"line14\" svg:y1=\"0.2195cm\" svg:x1=\"0cm\" svg:y2=\"0.2195cm\" svg:x2=\"18.9715cm\" report:z-index=\"0\" >"
3163         "<report:line-style report:line-style=\"solid\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3164         "</report:line>"
3165         "</report:section>"
3166         "<report:detail>"
3167         "<report:group report:group-sort=\"ascending\" report:group-column=\"Parent\" >"
3168         "<report:section svg:height=\"2.50cm\" fo:background-color=\"#ffffff\" report:section-type=\"group-header\" >"
3169         "<report:label report:name=\"label6\" report:horizontal-align=\"left\" svg:x=\"0.5cm\" svg:width=\"3.75cm\" svg:y=\"1.75cm\" report:caption=\"%7\" report:vertical-align=\"center\" svg:height=\"0.75cm\" report:z-index=\"0\" >"
3170         "<report:text-style fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"8\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3171         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3172         "</report:label>"
3173         "<report:field report:name=\"field8\" report:horizontal-align=\"left\" report:item-data-source=\"Parent\" svg:x=\"0.5cm\" svg:width=\"8cm\" svg:y=\"1cm\" report:vertical-align=\"center\" svg:height=\"0.689cm\" report:z-index=\"0\" >"
3174         "<report:text-style fo:font-weight=\"bold\" fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"8\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3175         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3176         "</report:field>"
3177         "<report:label report:name=\"label8\" report:horizontal-align=\"center\" svg:x=\"4.25cm\" svg:width=\"4.25cm\" svg:y=\"1.75cm\" report:caption=\"%8\" report:vertical-align=\"center\" svg:height=\"0.75cm\" report:z-index=\"0\" >"
3178         "<report:text-style fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"8\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3179         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3180         "</report:label>"
3181         "</report:section>"
3182         "</report:group>"
3183         "<report:section svg:height=\"0.50cm\" fo:background-color=\"#ffffff\" report:section-type=\"detail\" >"
3184         "<report:field report:name=\"field7\" report:horizontal-align=\"left\" report:item-data-source=\"NodeName\" svg:x=\"0.5cm\" svg:width=\"3.75cm\" svg:y=\"0cm\" report:vertical-align=\"center\" svg:height=\"0.5cm\" report:z-index=\"0\" >"
3185         "<report:text-style fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"8\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3186         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3187         "</report:field>"
3188         "<report:field report:name=\"field9\" report:horizontal-align=\"center\" report:item-data-source=\"NodeCompleted\" svg:x=\"4.25cm\" svg:width=\"4.25cm\" svg:y=\"0cm\" report:vertical-align=\"center\" svg:height=\"0.5cm\" report:z-index=\"0\" >"
3189         "<report:text-style fo:letter-spacing=\"0%\" style:letter-kerning=\"true\" fo:font-size=\"8\" fo:foreground-color=\"#000000\" fo:font-family=\"DejaVu Sans\" fo:background-color=\"#ffffff\" fo:background-opacity=\"100%\" />"
3190         "<report:line-style report:line-style=\"nopen\" report:line-weight=\"1\" report:line-color=\"#000000\" />"
3191         "</report:field>"
3192         "</report:section>"
3193         "</report:detail>"
3194         "</report:body>"
3195         "</report:content>"
3196         "</planreportdefinition>")
3197         .arg(
3198             i18n("Report"),
3199             i18nc("Project manager", "Manager:"),
3200             i18n("Project:"),
3201             i18n("Task Status Report"),
3202             i18nc("As in: Page 1 of 2", "of"),
3203             i18n("Page"),
3204             i18nc("Task name", "Name"),
3205             i18nc("Task completion", "Completion (%)")
3206         );
3207 #endif
3208     return s;
3209 }