diff --git a/src/calligraplansettings.kcfg b/src/calligraplansettings.kcfg
index fac1b0af..ff82c4db 100644
--- a/src/calligraplansettings.kcfg
+++ b/src/calligraplansettings.kcfg
@@ -1,355 +1,358 @@
1760
176
40
8
true
NoneExists
true
InWeekCalendar
Default
true
08:00
16:00
true
08:00
16:00
true
08:00
16:00
true
08:00
16:00
true
08:00
16:00
false
08:00
16:00
false
08:00
16:00
false
AsSoonAsPossible
CurrentdateTime
CurrentdateTime
Effort
Hour
8.0
-75
100
Linear
false
#0000ff
#0000ff
#0000ff
#0000ff
#0000ff
#00ff00
#ff0000
#A0A0A0
#ffff00
#0000ff
#ff0000
#A0A0A0
#ffff00
-
+
+
+
+
EnumUnit::Hour
EnumUnit::Month
diff --git a/src/kptconfig.cpp b/src/kptconfig.cpp
index a6264a72..a207110e 100644
--- a/src/kptconfig.cpp
+++ b/src/kptconfig.cpp
@@ -1,329 +1,328 @@
/* This file is part of the KDE project
Copyright (C) 2004, 2007 Dag Andersen
Copyright (C) 2011, 2012 Dag Andersen
-
+ Copyright (C) 2019 Dag Andersen
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
// clazy:excludeall=qstring-arg
#include "kptconfig.h"
#include "calligraplansettings.h"
#include "kptconfigskeleton.h"
#include "kptfactory.h"
#include "kptproject.h"
#include "kptdebug.h"
#include
namespace KPlato
{
Config::Config()
: ConfigBase()
{
debugPlan<<"Leader:"<save();
}
bool Config::isWorkingday(int day) const
{
switch (day) {
case Qt::Monday: return KPlatoSettings::monday(); break;
case Qt::Tuesday: return KPlatoSettings::tuesday(); break;
case Qt::Wednesday: return KPlatoSettings::wednesday(); break;
case Qt::Thursday: return KPlatoSettings::thursday(); break;
case Qt::Friday: return KPlatoSettings::friday(); break;
case Qt::Saturday: return KPlatoSettings::saturday(); break;
case Qt::Sunday: return KPlatoSettings::sunday(); break;
default: break;
};
return false;
}
QTime Config::dayStartTime(int day) const
{
switch (day) {
case Qt::Monday: return QTime::fromString(KPlatoSettings::mondayStart()); break;
case Qt::Tuesday: return QTime::fromString(KPlatoSettings::tuesdayStart()); break;
case Qt::Wednesday: return QTime::fromString(KPlatoSettings::wednesdayStart()); break;
case Qt::Thursday: return QTime::fromString(KPlatoSettings::thursdayStart()); break;
case Qt::Friday: return QTime::fromString(KPlatoSettings::fridayStart()); break;
case Qt::Saturday: return QTime::fromString(KPlatoSettings::saturdayStart()); break;
case Qt::Sunday: return QTime::fromString(KPlatoSettings::sundayStart()); break;
default: break;
};
return QTime();
}
int Config::dayLength(int day) const
{
QTime start = dayStartTime(day);
QTime end;
int value = 0;
switch (day) {
case Qt::Monday:
end = QTime::fromString(KPlatoSettings::mondayEnd());
break;
case Qt::Tuesday:
end = QTime::fromString(KPlatoSettings::tuesdayEnd());
break;
case Qt::Wednesday:
end = QTime::fromString(KPlatoSettings::wednesdayEnd());
break;
case Qt::Thursday:
end = QTime::fromString(KPlatoSettings::thursdayEnd());
break;
case Qt::Friday:
end = QTime::fromString(KPlatoSettings::fridayEnd());
break;
case Qt::Saturday:
end = QTime::fromString(KPlatoSettings::saturdayEnd());
break;
case Qt::Sunday:
end = QTime::fromString(KPlatoSettings::sundayEnd());
break;
default: break;
};
value = start.msecsTo(end);
if (value < 0) {
value = (24*60*60*1000) + value;
} else if (value == 0 && start == QTime(0, 0)) {
value = 24*60*60*1000;
}
return value;
}
void Config::setDefaultValues( Project &project )
{
project.setLeader( KPlatoSettings::manager() );
project.setUseSharedResources( KPlatoSettings::useSharedResources() );
project.setSharedResourcesFile( KPlatoSettings::sharedResourcesFile() );
project.setSharedProjectsUrl( QUrl(KPlatoSettings::sharedProjectsPlace()) );
project.setDescription( KPlatoSettings::projectDescription() );
StandardWorktime *v = project.standardWorktime();
Q_ASSERT(v);
if (v) {
v->setYear(KPlatoSettings::hoursPrYear());
v->setMonth(KPlatoSettings::hoursPrMonth());
v->setWeek(KPlatoSettings::hoursPrWeek());
v->setDay(KPlatoSettings::hoursPrDay());
}
+
+ Project::WorkPackageInfo wpi;
+ wpi.checkForWorkPackages = KPlatoSettings::checkForWorkPackages();
+ wpi.retrieveUrl = KPlatoSettings::retrieveUrl();
+ wpi.deleteAfterRetrieval = KPlatoSettings::deleteFile();
+ wpi.archiveAfterRetrieval = !KPlatoSettings::deleteFile();
+ wpi.archiveUrl = KPlatoSettings::saveUrl();
+ wpi.publishUrl = KPlatoSettings::publishUrl();
+ project.setWorkPackageInfo(wpi);
}
void Config::setDefaultValues( Task &task )
{
task.setLeader( KPlatoSettings::leader() );
task.setDescription( KPlatoSettings::description() );
task.setConstraint( (Node::ConstraintType) KPlatoSettings::constraintType() );
// avoid problems with start <= end & end >= start
task.setConstraintStartTime( DateTime() );
task.setConstraintEndTime( DateTime() );
switch ( KPlatoSettings::startTimeUsage() ) {
case KPlatoSettings::EnumStartTimeUsage::CurrentdateTime:
task.setConstraintStartTime( DateTime( QDateTime::currentDateTime() ) );
break;
case KPlatoSettings::EnumStartTimeUsage::CurrentDate:
task.setConstraintStartTime( DateTime( QDate::currentDate(), KPlatoSettings::constraintStartTime().time() ) );
break;
case KPlatoSettings::EnumStartTimeUsage::SpecifiedDateTime: //fall through
default:
task.setConstraintStartTime( DateTime( KPlatoSettings::constraintStartTime() ) );
break;
}
switch ( KPlatoSettings::endTimeUsage() ) {
case KPlatoSettings::EnumEndTimeUsage::CurrentdateTime:
task.setConstraintEndTime( DateTime( QDateTime::currentDateTime() ) );
break;
case KPlatoSettings::EnumEndTimeUsage::CurrentDate:
task.setConstraintEndTime( DateTime( QDate::currentDate(), KPlatoSettings::constraintEndTime().time() ) );
break;
case KPlatoSettings::EnumEndTimeUsage::SpecifiedDateTime: //fall through
default:
task.setConstraintEndTime( DateTime( KPlatoSettings::constraintEndTime() ) );
break;
}
task.estimate()->setType( (Estimate::Type) KPlatoSettings::estimateType() );
task.estimate()->setUnit( (Duration::Unit) KPlatoSettings::unit() );
task.estimate()->setExpectedEstimate( KPlatoSettings::expectedEstimate() );
task.estimate()->setPessimisticRatio( KPlatoSettings::pessimisticRatio() );
task.estimate()->setOptimisticRatio( KPlatoSettings::optimisticRatio() );
}
int Config::minimumDurationUnit() const
{
return KPlatoSettings::minimumDurationUnit();
}
int Config::maximumDurationUnit() const
{
return KPlatoSettings::maximumDurationUnit();
}
-bool Config::checkForWorkPackages() const
-{
- return KPlatoSettings::checkForWorkPackages();
-}
-
-QUrl Config::retrieveUrl() const
-{
- return KPlatoSettings::retrieveUrl();
-}
-
-
QBrush Config::summaryTaskDefaultColor() const
{
QColor c = KPlatoSettings::summaryTaskDefaultColor();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
bool Config::summaryTaskLevelColorsEnabled() const
{
return KPlatoSettings::summaryTaskLevelColorsEnabled();
}
QBrush Config::summaryTaskLevelColor_1() const
{
QColor c = KPlatoSettings::summaryTaskLevelColor_1();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
QBrush Config::summaryTaskLevelColor_2() const
{
QColor c = KPlatoSettings::summaryTaskLevelColor_2();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
QBrush Config::summaryTaskLevelColor_3() const
{
QColor c = KPlatoSettings::summaryTaskLevelColor_3();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
QBrush Config::summaryTaskLevelColor_4() const
{
QColor c = KPlatoSettings::summaryTaskLevelColor_4();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
QBrush Config::taskNormalColor() const
{
QColor c = KPlatoSettings::taskNormalColor();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
QBrush Config::taskErrorColor() const
{
QColor c = KPlatoSettings::taskErrorColor();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
QBrush Config::taskCriticalColor() const
{
QColor c = KPlatoSettings::taskCriticalColor();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
QBrush Config::taskFinishedColor() const
{
QColor c = KPlatoSettings::taskFinishedColor();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
QBrush Config::milestoneNormalColor() const
{
QColor c = KPlatoSettings::milestoneNormalColor();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
QBrush Config::milestoneErrorColor() const
{
QColor c = KPlatoSettings::milestoneErrorColor();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
QBrush Config::milestoneCriticalColor() const
{
QColor c = KPlatoSettings::milestoneCriticalColor();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
QBrush Config::milestoneFinishedColor() const
{
QColor c = KPlatoSettings::milestoneFinishedColor();
if ( KPlatoSettings::colorGradientType() == KPlatoSettings::EnumColorGradientType::Linear ) {
return gradientBrush( c );
}
return c;
}
} //KPlato namespace
diff --git a/src/kptconfig.h b/src/kptconfig.h
index 8cf838e9..8f9ca381 100644
--- a/src/kptconfig.h
+++ b/src/kptconfig.h
@@ -1,74 +1,72 @@
/* This file is part of the KDE project
Copyright (C) 2004, 2007 Dag Andersen
-
+ Copyright (C) 2019 Dag Andersen
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KPTCONFIG_H
#define KPTCONFIG_H
#include "kptconfigbase.h"
namespace KPlato
{
class Config : public ConfigBase
{
Q_OBJECT
public:
Config();
~Config();
void readConfig();
void saveSettings();
bool isWorkingday(int day) const;
QTime dayStartTime(int day) const;
int dayLength(int day) const;
virtual void setDefaultValues( Project &project );
virtual void setDefaultValues( Task &task );
- virtual bool checkForWorkPackages() const;
- virtual QUrl retrieveUrl() const;
-
virtual int minimumDurationUnit() const;
virtual int maximumDurationUnit() const;
virtual bool summaryTaskLevelColorsEnabled() const;
virtual QBrush summaryTaskDefaultColor() const;
virtual QBrush summaryTaskLevelColor_1() const;
virtual QBrush summaryTaskLevelColor_2() const;
virtual QBrush summaryTaskLevelColor_3() const;
virtual QBrush summaryTaskLevelColor_4() const;
virtual QBrush taskNormalColor() const;
virtual QBrush taskErrorColor() const;
virtual QBrush taskCriticalColor() const;
virtual QBrush taskFinishedColor() const;
virtual QBrush milestoneNormalColor() const;
virtual QBrush milestoneErrorColor() const;
virtual QBrush milestoneCriticalColor() const;
virtual QBrush milestoneFinishedColor() const;
};
} //KPlato namespace
#endif // CONFIG_H
diff --git a/src/kptmaindocument.cpp b/src/kptmaindocument.cpp
index ad010785..32589bba 100644
--- a/src/kptmaindocument.cpp
+++ b/src/kptmaindocument.cpp
@@ -1,1586 +1,1483 @@
/* This file is part of the KDE project
Copyright (C) 1998, 1999, 2000 Torben Weis
Copyright (C) 2004, 2010, 2012 Dag Andersen
Copyright (C) 2006 Raphael Langerhorst
Copyright (C) 2007 Thorsten Zachmann
-
+ Copyright (C) 2019 Dag Andersen
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
// clazy:excludeall=qstring-arg
#include "kptmaindocument.h"
#include "kptpart.h"
#include "kptview.h"
#include "kptfactory.h"
#include "kptproject.h"
#include "kptlocale.h"
#include "kptresource.h"
#include "kptcontext.h"
#include "kptschedulerpluginloader.h"
#include "kptschedulerplugin.h"
#include "kptbuiltinschedulerplugin.h"
#include "kptcommand.h"
#include "calligraplansettings.h"
#include "kpttask.h"
#include "KPlatoXmlLoader.h"
#include "XmlSaveContext.h"
#include "kptpackage.h"
-#include "kptworkpackagemergedialog.h"
#include "kptdebug.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef HAVE_KHOLIDAYS
#include
#endif
namespace KPlato
{
MainDocument::MainDocument(KoPart *part)
: KoDocument(part),
m_project( 0 ),
m_context( 0 ), m_xmlLoader(),
m_loadingTemplate( false ),
m_loadingSharedResourcesTemplate( false ),
m_viewlistModified( false ),
m_checkingForWorkPackages( false ),
m_loadingSharedProject(false),
m_skipSharedProjects(false),
m_isTaskModule(false)
{
Q_ASSERT(part);
setAlwaysAllowSaving(true);
m_config.setReadWrite( true );
loadSchedulerPlugins();
setProject( new Project( m_config ) ); // after config & plugins are loaded
m_project->setId( m_project->uniqueNodeId() );
m_project->registerNodeId( m_project ); // register myself
connect(this, &MainDocument::insertSharedProject, this, &MainDocument::slotInsertSharedProject);
}
MainDocument::~MainDocument()
{
qDeleteAll( m_schedulerPlugins );
if ( m_project ) {
m_project->deref(); // deletes if last user
}
qDeleteAll( m_mergedPackages );
delete m_context;
}
void MainDocument::setReadWrite( bool rw )
{
m_config.setReadWrite( rw );
KoDocument::setReadWrite( rw );
}
void MainDocument::loadSchedulerPlugins()
{
// Add built-in scheduler
addSchedulerPlugin( "Built-in", new BuiltinSchedulerPlugin( this ) );
// Add all real scheduler plugins
SchedulerPluginLoader *loader = new SchedulerPluginLoader(this);
connect(loader, &SchedulerPluginLoader::pluginLoaded, this, &MainDocument::addSchedulerPlugin);
loader->loadAllPlugins();
}
void MainDocument::addSchedulerPlugin( const QString &key, SchedulerPlugin *plugin)
{
debugPlan<setConfig( m_config );
}
void MainDocument::setProject( Project *project )
{
if ( m_project ) {
disconnect( m_project, &Project::projectChanged, this, &MainDocument::changed );
delete m_project;
}
m_project = project;
if ( m_project ) {
connect( m_project, &Project::projectChanged, this, &MainDocument::changed );
// m_project->setConfig( config() );
m_project->setSchedulerPlugins( m_schedulerPlugins );
}
m_aboutPage.setProject( project );
emit changed();
}
bool MainDocument::loadOdf( KoOdfReadStore &odfStore )
{
warnPlan<< "OpenDocument not supported, let's try native xml format";
return loadXML( odfStore.contentDoc(), 0 ); // We have only one format, so try to load that!
}
bool MainDocument::loadXML( const KoXmlDocument &document, KoStore* )
{
QPointer updater;
if (progressUpdater()) {
updater = progressUpdater()->startSubtask(1, "Plan::Part::loadXML");
updater->setProgress(0);
m_xmlLoader.setUpdater( updater );
}
QString value;
KoXmlElement plan = document.documentElement();
// Check if this is the right app
value = plan.attribute( "mime", QString() );
if ( value.isEmpty() ) {
errorPlan << "No mime type specified!";
setErrorMessage( i18n( "Invalid document. No mimetype specified." ) );
return false;
}
if ( value == "application/x-vnd.kde.kplato" ) {
if (updater) {
updater->setProgress(5);
}
m_xmlLoader.setMimetype( value );
QString message;
Project *newProject = new Project(m_config, false);
KPlatoXmlLoader loader( m_xmlLoader, newProject );
bool ok = loader.load( plan );
if ( ok ) {
setProject( newProject );
setModified( false );
debugPlan<schedules();
// Cleanup after possible bug:
// There should *not* be any deleted schedules (or with parent == 0)
foreach ( Node *n, newProject->nodeDict()) {
foreach ( Schedule *s, n->schedules()) {
if ( s->isDeleted() ) { // true also if parent == 0
errorPlan<name()<takeSchedule( s );
delete s;
}
}
}
} else {
setErrorMessage( loader.errorMessage() );
delete newProject;
}
if (updater) {
updater->setProgress(100); // the rest is only processing, not loading
}
emit changed();
return ok;
}
if ( value != "application/x-vnd.kde.plan" ) {
errorPlan << "Unknown mime type " << value;
setErrorMessage( i18n( "Invalid document. Expected mimetype application/x-vnd.kde.plan, got %1", value ) );
return false;
}
QString syntaxVersion = plan.attribute( "version", PLAN_FILE_SYNTAX_VERSION );
m_xmlLoader.setVersion( syntaxVersion );
if ( syntaxVersion > PLAN_FILE_SYNTAX_VERSION ) {
KMessageBox::ButtonCode ret = KMessageBox::warningContinueCancel(
0, i18n( "This document was created with a newer version of Plan (syntax version: %1)\n"
"Opening it in this version of Plan will lose some information.", syntaxVersion ),
i18n( "File-Format Mismatch" ), KGuiItem( i18n( "Continue" ) ) );
if ( ret == KMessageBox::Cancel ) {
setErrorMessage( "USER_CANCELED" );
return false;
}
}
if (updater) updater->setProgress(5);
/*
#ifdef KOXML_USE_QDOM
int numNodes = plan.childNodes().count();
#else
int numNodes = plan.childNodesCount();
#endif
*/
#if 0
This test does not work any longer. KoXml adds a couple of elements not present in the file!!
if ( numNodes > 2 ) {
//TODO: Make a proper bitching about this
debugPlan <<"*** Error ***";
debugPlan <<" Children count should be maximum 2, but is" << numNodes;
return false;
}
#endif
m_xmlLoader.startLoad();
KoXmlNode n = plan.firstChild();
for ( ; ! n.isNull(); n = n.nextSibling() ) {
if ( ! n.isElement() ) {
continue;
}
KoXmlElement e = n.toElement();
if ( e.tagName() == "project" ) {
- Project *newProject = new Project(m_config, false);
+ Project *newProject = new Project(m_config, true);
m_xmlLoader.setProject( newProject );
if ( newProject->load( e, m_xmlLoader ) ) {
if ( newProject->id().isEmpty() ) {
newProject->setId( newProject->uniqueNodeId() );
newProject->registerNodeId( newProject );
}
// The load went fine. Throw out the old project
setProject( newProject );
// Cleanup after possible bug:
// There should *not* be any deleted schedules (or with parent == 0)
foreach ( Node *n, newProject->nodeDict()) {
foreach ( Schedule *s, n->schedules()) {
if ( s->isDeleted() ) { // true also if parent == 0
errorPlan<name()<takeSchedule( s );
delete s;
}
}
}
} else {
delete newProject;
m_xmlLoader.addMsg( XMLLoaderObject::Errors, "Loading of project failed" );
//TODO add some ui here
}
}
}
m_xmlLoader.stopLoad();
if (updater) updater->setProgress(100); // the rest is only processing, not loading
setModified( false );
emit changed();
return true;
}
QDomDocument MainDocument::saveXML()
{
debugPlan;
// Save the project
XmlSaveContext context(m_project);
context.save();
return context.document;
}
QDomDocument MainDocument::saveWorkPackageXML( const Node *node, long id, Resource *resource )
{
- debugPlan;
+ debugPlanWp<name() );
wp.setAttribute( "owner-id", resource->id() );
}
wp.setAttribute( "time-tag", QDateTime::currentDateTime().toString( Qt::ISODate ) );
+ wp.setAttribute("save-url", m_project->workPackageInfo().retrieveUrl.toString(QUrl::None));
+ wp.setAttribute("load-url", m_project->workPackageInfo().publishUrl.toString(QUrl::None));
+ debugPlanWp<<"publish:"<workPackageInfo().publishUrl.toString(QUrl::None);
+ debugPlanWp<<"retrieve:"<workPackageInfo().retrieveUrl.toString(QUrl::None);
doc.appendChild( wp );
// Save the project
m_project->saveWorkPackageXML( doc, node, id );
return document;
}
bool MainDocument::saveWorkPackageToStream( QIODevice *dev, const Node *node, long id, Resource *resource )
{
QDomDocument doc = saveWorkPackageXML( node, id, resource );
// Save to buffer
QByteArray s = doc.toByteArray(); // utf8 already
dev->open( QIODevice::WriteOnly );
int nwritten = dev->write( s.data(), s.size() );
if ( nwritten != (int)s.size() ) {
- warnPlan<<"wrote:"<m_specialOutputFlag == SaveEncrypted ) {
backend = KoStore::Encrypted;
debugPlan <<"Saving using encrypted backend.";
}*/
#endif
QByteArray mimeType = "application/x-vnd.kde.plan.work";
- debugPlan <<"MimeType=" << mimeType;
+ debugPlanWp <<"MimeType=" << mimeType;
KoStore *store = KoStore::createStore( file, KoStore::Write, mimeType, backend );
/* if ( d->m_specialOutputFlag == SaveEncrypted && !d->m_password.isNull( ) ) {
store->setPassword( d->m_password );
}*/
if ( store->bad() ) {
setErrorMessage( i18n( "Could not create the workpackage file for saving: %1", file ) ); // more details needed?
delete store;
return false;
}
// Tell KoStore not to touch the file names
if ( ! store->open( "root" ) ) {
setErrorMessage( i18n( "Not able to write '%1'. Partition full?", QString( "maindoc.xml") ) );
delete store;
return false;
}
KoStoreDevice dev( store );
if ( !saveWorkPackageToStream( &dev, node, id, resource ) || !store->close() ) {
- debugPlan <<"saveToStream failed";
+ errorPlanWp <<"saveToStream failed";
delete store;
return false;
}
node->documents().saveToStore( store );
- debugPlan <<"Saving done of url:" << file;
+ debugPlanWp <<"Saving done of url:" << file;
if ( !store->finalize() ) {
delete store;
return false;
}
// Success
delete store;
return true;
}
bool MainDocument::saveWorkPackageUrl( const QUrl &_url, const Node *node, long id, Resource *resource )
{
- //debugPlan<<_url;
+ debugPlanWp<<_url;
QApplication::setOverrideCursor( Qt::WaitCursor );
emit statusBarMessage( i18n("Saving...") );
bool ret = false;
ret = saveWorkPackageFormat( _url.path(), node, id, resource ); // kzip don't handle file://
QApplication::restoreOverrideCursor();
emit clearStatusBarMessage();
return ret;
}
bool MainDocument::loadWorkPackage( Project &project, const QUrl &url )
{
- debugPlan<bad() ) {
// d->lastErrorMessage = i18n( "Not a valid Calligra file: %1", file );
- debugPlan<<"bad store"<open( "root" ) ) { // "old" file format (maindoc.xml)
// i18n( "File does not have a maindoc.xml: %1", file );
- debugPlan<<"No root"<device(), &errorMsg, &errorLine, &errorColumn );
if ( ! ok ) {
- errorPlan << "Parsing error in " << url.url() << "! Aborting!" << endl
+ errorPlanWp << "Parsing error in " << url.url() << "! Aborting!" << endl
<< " In line: " << errorLine << ", column: " << errorColumn << endl
<< " Error message: " << errorMsg;
//d->lastErrorMessage = i18n( "Parsing error in %1 at line %2, column %3\nError message: %4",filename ,errorLine, errorColumn , QCoreApplication::translate("QXml", errorMsg.toUtf8(), 0, QCoreApplication::UnicodeUTF8));
} else {
package = loadWorkPackageXML( project, store->device(), doc, url );
if ( package ) {
package->url = url;
m_workpackages.insert( package->timeTag, package );
} else {
ok = false;
}
}
store->close();
//###
if ( ok && package && package->settings.documents ) {
ok = extractFiles( store, package );
}
delete store;
if ( ! ok ) {
// QApplication::restoreOverrideCursor();
return false;
}
return true;
}
-Package *MainDocument::loadWorkPackageXML( Project &project, QIODevice *, const KoXmlDocument &document, const QUrl &/*url*/ )
+Package *MainDocument::loadWorkPackageXML( Project &project, QIODevice *, const KoXmlDocument &document, const QUrl &url )
{
QString value;
bool ok = true;
Project *proj = 0;
Package *package = 0;
KoXmlElement plan = document.documentElement();
// Check if this is the right app
value = plan.attribute( "mime", QString() );
if ( value.isEmpty() ) {
- debugPlan << "No mime type specified!";
+ errorPlanWp<timeTag = QDateTime::fromString( loader.timeTag(), Qt::ISODate );
} else if ( value != "application/x-vnd.kde.plan.work" ) {
- debugPlan << "Unknown mime type " << value;
+ errorPlanWp << "Unknown mime type " << value;
setErrorMessage( i18n( "Invalid document. Expected mimetype application/x-vnd.kde.plan.work, got %1", value ) );
return 0;
} else {
+ if (plan.attribute("editor") != QStringLiteral("PlanWork")) {
+ warnPlanWp<<"Skipped work package file not generated with PlanWork:"< PLANWORK_FILE_SYNTAX_VERSION ) {
KMessageBox::ButtonCode ret = KMessageBox::warningContinueCancel(
0, i18n( "This document was created with a newer version of PlanWork (syntax version: %1)\n"
"Opening it in this version of PlanWork will lose some information.", syntaxVersion ),
i18n( "File-Format Mismatch" ), KGuiItem( i18n( "Continue" ) ) );
if ( ret == KMessageBox::Cancel ) {
setErrorMessage( "USER_CANCELED" );
return 0;
}
}
m_xmlLoader.setVersion( plan.attribute( "plan-version", PLAN_FILE_SYNTAX_VERSION ) );
m_xmlLoader.startLoad();
proj = new Project();
package = new Package();
package->project = proj;
KoXmlNode n = plan.firstChild();
for ( ; ! n.isNull(); n = n.nextSibling() ) {
if ( ! n.isElement() ) {
continue;
}
KoXmlElement e = n.toElement();
if ( e.tagName() == "project" ) {
m_xmlLoader.setProject( proj );
ok = proj->load( e, m_xmlLoader );
if ( ! ok ) {
m_xmlLoader.addMsg( XMLLoaderObject::Errors, "Loading of work package failed" );
+ warnPlanWp<<"Skip workpackage:"<<"Loading project failed";
//TODO add some ui here
}
} else if ( e.tagName() == "workpackage" ) {
package->timeTag = QDateTime::fromString( e.attribute( "time-tag" ), Qt::ISODate );
package->ownerId = e.attribute( "owner-id" );
package->ownerName = e.attribute( "owner" );
debugPlan<<"workpackage:"<timeTag<ownerId<ownerName;
KoXmlElement elem;
forEachElement( elem, e ) {
if ( elem.tagName() != "settings" ) {
continue;
}
package->settings.usedEffort = (bool)elem.attribute( "used-effort" ).toInt();
package->settings.progress = (bool)elem.attribute( "progress" ).toInt();
package->settings.documents = (bool)elem.attribute( "documents" ).toInt();
}
}
}
if ( proj->numChildren() > 0 ) {
package->task = static_cast( proj->childNode( 0 ) );
package->toTask = qobject_cast( m_project->findNode( package->task->id() ) );
WorkPackage &wp = package->task->workPackage();
if ( wp.ownerId().isEmpty() ) {
wp.setOwnerId( package->ownerId );
wp.setOwnerName( package->ownerName );
}
- debugPlan<<"Task set:"<task->name();
+ if (wp.ownerId() != package->ownerId) {
+ warnPlanWp<<"Current owner:"<ownerName;
+ }
+ debugPlanWp<<"Task set:"<task->name();
}
m_xmlLoader.stopLoad();
}
- if ( ok && proj->id() == project.id() && proj->childNode( 0 ) ) {
- ok = project.nodeDict().contains( proj->childNode( 0 )->id() );
- if ( ok && m_mergedPackages.contains( package->timeTag ) ) {
- ok = false; // already merged
- }
- if ( ok && package->timeTag.isValid() && ! m_mergedPackages.contains( package->timeTag ) ) {
- m_mergedPackages[ package->timeTag ] = proj; // register this for next time
- }
- if ( ok && ! package->timeTag.isValid() ) {
- warnPlan<<"Work package is not time tagged:"<childNode( 0 )->name()<url;
- ok = false;
- }
+ if (ok && proj->id() != project.id()) {
+ debugPlanWp<<"Skip workpackage:"<<"Not the correct project";
+ ok = false;
}
- if ( ! ok ) {
+ if (ok && (package->task == nullptr)) {
+ warnPlanWp<<"Skip workpackage:"<<"No task in workpackage file";
+ ok = false;
+ }
+ if (ok && (package->toTask == nullptr)) {
+ warnPlanWp<<"Skip workpackage:"<<"Cannot find task:"<task->id()<task->name();
+ ok = false;
+ }
+ if (ok && !package->timeTag.isValid()) {
+ warnPlanWp<<"Work package is not time tagged:"<task->name()<url;
+ ok = false;
+ }
+ if (ok && m_mergedPackages.contains(package->timeTag)) {
+ ok = false; // already merged
+ }
+ if (!ok) {
delete proj;
delete package;
- return 0;
+ return nullptr;
+ }
+ if (package->timeTag.isValid() && !m_mergedPackages.contains( package->timeTag)) {
+ m_mergedPackages[package->timeTag] = proj; // register this for next time
}
- Q_ASSERT( package );
return package;
}
bool MainDocument::extractFiles( KoStore *store, Package *package )
{
if ( package->task == 0 ) {
errorPlan<<"No task!";
return false;
}
foreach ( Document *doc, package->task->documents().documents() ) {
if ( ! doc->isValid() || doc->type() != Document::Type_Product || doc->sendAs() != Document::SendAs_Copy ) {
continue;
}
if ( ! extractFile( store, package, doc ) ) {
return false;
}
}
return true;
}
bool MainDocument::extractFile( KoStore *store, Package *package, const Document *doc )
{
QTemporaryFile tmpfile;
if ( ! tmpfile.open() ) {
errorPlan<<"Failed to open temporary file";
return false;
}
if ( ! store->extractFile( doc->url().fileName(), tmpfile.fileName() ) ) {
errorPlan<<"Failed to extract file:"<url().fileName()<<"to:"<documents.insert( tmpfile.fileName(), doc->url() );
tmpfile.setAutoRemove( false );
debugPlan<<"extracted:"<url().fileName()<<"->"<(sender());
- if ( m_config.checkForWorkPackages() ) {
+ if (m_project && m_project->workPackageInfo().checkForWorkPackages) {
checkForWorkPackages( true );
}
if (timer && timer->interval() != 10000) {
timer->stop();
timer->setInterval(10000);
timer->start();
}
}
void MainDocument::checkForWorkPackages( bool keep )
{
- if ( m_checkingForWorkPackages || m_config.retrieveUrl().isEmpty() || m_project == 0 || m_project->numChildren() == 0 ) {
+ if (m_checkingForWorkPackages || m_project == nullptr || m_project->numChildren() == 0 || m_project->workPackageInfo().retrieveUrl.isEmpty()) {
return;
}
if ( ! keep ) {
qDeleteAll( m_mergedPackages );
m_mergedPackages.clear();
}
- QDir dir( m_config.retrieveUrl().path(), "*.planwork" );
+ QDir dir( m_project->workPackageInfo().retrieveUrl.path(), "*.planwork" );
m_infoList = dir.entryInfoList( QDir::Files | QDir::Readable, QDir::Time );
checkForWorkPackage();
return;
}
void MainDocument::checkForWorkPackage()
{
if ( ! m_infoList.isEmpty() ) {
m_checkingForWorkPackages = true;
- loadWorkPackage( *m_project, QUrl::fromLocalFile( m_infoList.takeLast().absoluteFilePath() ) );
+ QUrl url = QUrl::fromLocalFile( m_infoList.takeLast().absoluteFilePath() );
+ if (m_skipUrls.contains(url)) {
+ return;
+ }
+ if (!loadWorkPackage( *m_project, url )) {
+ m_skipUrls << url;
+ }
if ( ! m_infoList.isEmpty() ) {
QTimer::singleShot ( 0, this, &MainDocument::checkForWorkPackage );
return;
}
// all files read
// remove other projects
QMutableMapIterator it( m_workpackages );
while ( it.hasNext() ) {
it.next();
Package *package = it.value();
if ( package->project->id() != m_project->id() ) {
delete package->project;
delete package;
it.remove();
}
}
// Merge our workpackages
if ( ! m_workpackages.isEmpty() ) {
- WorkPackageMergeDialog *dlg = new WorkPackageMergeDialog( i18n( "New work packages detected. Merge data with existing tasks?" ), m_workpackages );
- connect(dlg, &QDialog::finished, this, &MainDocument::workPackageMergeDialogFinished);
- dlg->show();
- dlg->raise();
- dlg->activateWindow();
+ emit workPackageLoaded();
} else {
m_checkingForWorkPackages = false;
}
}
}
-void MainDocument::workPackageMergeDialogFinished( int result )
-{
- WorkPackageMergeDialog *dlg = qobject_cast( sender() );
- Q_ASSERT(dlg);
- if ( dlg == 0 ) {
- return;
- }
- if ( result == KoDialog::Yes ) {
- // merge the oldest first
- foreach( int i, dlg->checkedList() ) {
- const QList &packages = m_workpackages.values();
- mergeWorkPackage(packages.at(i));
- }
- // 'Yes' was hit so terminate all packages
- foreach(const Package *p, m_workpackages) {
- terminateWorkPackage( p );
- }
- }
- qDeleteAll( m_workpackages );
- m_workpackages.clear();
- m_checkingForWorkPackages = false;
- dlg->deleteLater();
-}
-
-void MainDocument::mergeWorkPackages()
-{
- foreach (const Package *package, m_workpackages) {
- mergeWorkPackage( package );
- }
-}
-
void MainDocument::terminateWorkPackage( const Package *package )
{
+ if (m_workpackages.value(package->timeTag) == package) {
+ m_workpackages.remove(package->timeTag);
+ }
QFile file( package->url.path() );
if ( ! file.exists() ) {
return;
}
- if ( KPlatoSettings::deleteFile() || KPlatoSettings::saveUrl().isEmpty() ) {
- file.remove();
- } else if ( KPlatoSettings::saveFile() && ! KPlatoSettings::saveUrl().isEmpty() ) {
- QDir dir( KPlatoSettings::saveUrl().path() );
+ Project::WorkPackageInfo wpi = m_project->workPackageInfo();
+ if (wpi.archiveAfterRetrieval && wpi.archiveUrl.isValid()) {
+ QDir dir(wpi.archiveUrl.path());
if ( ! dir.exists() ) {
if ( ! dir.mkpath( dir.path() ) ) {
//TODO message
- debugPlan<<"Could not create directory:"<project);
- if ( proj.id() == m_project->id() && proj.childNode( 0 ) ) {
- const Task *from = package->task;
- Task *to = package->toTask;
- if ( to && from ) {
- mergeWorkPackage( to, from, package );
- }
- }
-}
-
-void MainDocument::mergeWorkPackage( Task *to, const Task *from, const Package *package )
-{
- Resource *resource = m_project->findResource( package->ownerId );
- if ( resource == 0 ) {
- KMessageBox::error( 0, i18n( "The package owner '%1' is not a resource in this project. You must handle this manually.", package->ownerName ) );
- return;
- }
-
- MacroCommand *cmd = new MacroCommand( kundo2_noi18n("Merge workpackage") );
- Completion &org = to->completion();
- const Completion &curr = from->completion();
-
- if ( package->settings.progress ) {
- if ( org.isStarted() != curr.isStarted() ) {
- cmd->addCommand( new ModifyCompletionStartedCmd(org, curr.isStarted() ) );
- }
- if ( org.isFinished() != curr.isFinished() ) {
- cmd->addCommand( new ModifyCompletionFinishedCmd( org, curr.isFinished() ) );
- }
- if ( org.startTime() != curr.startTime() ) {
- cmd->addCommand( new ModifyCompletionStartTimeCmd( org, curr.startTime() ) );
- }
- if ( org.finishTime() != curr.finishTime() ) {
- cmd->addCommand( new ModifyCompletionFinishTimeCmd( org, curr.finishTime() ) );
- }
- // TODO: review how/if to merge data from different resources
- // remove entries
- const QList &dates = org.entries().keys();
- for (const QDate &d : dates) {
- if ( ! curr.entries().contains( d ) ) {
- debugPlan<<"remove entry "<addCommand( new RemoveCompletionEntryCmd( org, d ) );
+ QString name = dir.absolutePath() + '/' + from.fileName();
+ if (!file.rename(name)) {
+ // try to create a unique name in case name already existed
+ name = dir.absolutePath() + '/';
+ name += from.completeBaseName() + "-%1";
+ if ( ! from.suffix().isEmpty() ) {
+ name += '.' + from.suffix();
}
- }
- // add new entries / modify existing
- const QList &cdates = curr.entries().keys();
- for (const QDate &d : cdates) {
- if ( org.entries().contains( d ) && curr.entry( d ) == org.entry( d ) ) {
- continue;
+ int i = 0;
+ bool ok = false;
+ while ( ! ok && i < 1000 ) {
+ ++i;
+ ok = QFile::rename( file.fileName(), name.arg( i ) );
}
- Completion::Entry *e = new Completion::Entry( *( curr.entry( d ) ) );
- cmd->addCommand( new ModifyCompletionEntryCmd( org, d, e ) );
- }
- }
- if ( package->settings.usedEffort ) {
- Completion::UsedEffort *ue = new Completion::UsedEffort();
- Completion::Entry prev;
- Completion::EntryList::ConstIterator entriesIt = curr.entries().constBegin();
- const Completion::EntryList::ConstIterator entriesEnd = curr.entries().constEnd();
- for (; entriesIt != entriesEnd; ++entriesIt) {
- const QDate &d = entriesIt.key();
- const Completion::Entry &e = *entriesIt.value();
- // set used effort from date entry and remove used effort from date entry
- Completion::UsedEffort::ActualEffort effort( e.totalPerformed - prev.totalPerformed );
- ue->setEffort( d, effort );
- prev = e;
- }
- cmd->addCommand( new AddCompletionUsedEffortCmd( org, resource, ue ) );
- }
- bool docsaved = false;
- if ( package->settings.documents ) {
- //TODO: handle remote files
- QMap::const_iterator it = package->documents.constBegin();
- QMap::const_iterator end = package->documents.constEnd();
- for ( ; it != end; ++it ) {
- const QUrl src = QUrl::fromLocalFile(it.key());
- KIO::CopyJob *job = KIO::move( src, it.value(), KIO::Overwrite );
- if ( job->exec() ) {
- docsaved = true;
- //TODO: async
- debugPlan<<"Moved file:"<isEmpty() ) {
- KMessageBox::information( 0, i18n( "Nothing to save from this package" ) );
- }
- // add a copy to our tasks list of transmitted packages
- WorkPackage *wp = new WorkPackage( from->workPackage() );
- wp->setParentTask( to );
- if ( ! wp->transmitionTime().isValid() ) {
- wp->setTransmitionTime( package->timeTag );
- }
- wp->setTransmitionStatus( WorkPackage::TS_Receive );
- cmd->addCommand( new WorkPackageAddCmd( m_project, to, wp ) );
- addCommand( cmd );
}
void MainDocument::paintContent( QPainter &, const QRect &)
{
// Don't embed this app!!!
}
void MainDocument::slotViewDestroyed()
{
}
void MainDocument::setLoadingTemplate(bool loading)
{
m_loadingTemplate = loading;
}
void MainDocument::setLoadingSharedResourcesTemplate(bool loading)
{
m_loadingSharedResourcesTemplate = loading;
}
bool MainDocument::completeLoading( KoStore *store )
{
// If we get here the new project is loaded and set
if (m_loadingSharedProject) {
// this file is loaded by another project
// to read resource appointments,
// so we must not load any extra stuff
return true;
}
if ( m_loadingTemplate ) {
//debugPlan<<"Loading template, generate unique ids";
m_project->generateUniqueIds();
m_project->setConstraintStartTime( QDateTime(QDate::currentDate(), QTime(0, 0, 0), Qt::LocalTime) );
m_project->setConstraintEndTime( m_project->constraintStartTime().addYears( 2 ) );
m_project->locale()->setCurrencyLocale(QLocale::AnyLanguage, QLocale::AnyCountry);
m_project->locale()->setCurrencySymbol(QString());
} else if ( isImporting() ) {
// NOTE: I don't think this is a good idea.
// Let the filter generate ids for non-plan files.
// If the user wants to create a new project from an old one,
// he should use Tools -> Insert Project File
//m_project->generateUniqueNodeIds();
}
if (m_loadingSharedResourcesTemplate && m_project->calendarCount() > 0) {
Calendar *c = m_project->calendarAt(0);
c->setTimeZone(QTimeZone::systemTimeZone());
}
if (m_project->useSharedResources() && !m_project->sharedResourcesFile().isEmpty() && !m_skipSharedProjects) {
QUrl url = QUrl::fromLocalFile(m_project->sharedResourcesFile());
if (url.isValid()) {
insertResourcesFile(url, m_project->loadProjectsAtStartup() ? m_project->sharedProjectsUrl() : QUrl());
}
}
if ( store == 0 ) {
// can happen if loading a template
debugPlan<<"No store";
return true; // continue anyway
}
delete m_context;
m_context = new Context();
KoXmlDocument doc;
if ( loadAndParse( store, "context.xml", doc ) ) {
store->close();
m_context->load( doc );
} else warnPlan<<"No context";
return true;
}
// TODO:
// Due to splitting of KoDocument into a document and a part,
// we simulate the old behaviour by registering all views in the document.
// Find a better solution!
void MainDocument::registerView( View* view )
{
if ( view && ! m_views.contains( view ) ) {
m_views << QPointer( view );
}
}
bool MainDocument::completeSaving( KoStore *store )
{
foreach ( View *view, m_views ) {
if ( view ) {
if ( store->open( "context.xml" ) ) {
if ( m_context == 0 ) m_context = new Context();
QDomDocument doc = m_context->save( view );
KoStoreDevice dev( store );
QByteArray s = doc.toByteArray(); // this is already Utf8!
(void)dev.write( s.data(), s.size() );
(void)store->close();
m_viewlistModified = false;
emit viewlistModified( false );
}
break;
}
}
return true;
}
bool MainDocument::loadAndParse(KoStore *store, const QString &filename, KoXmlDocument &doc)
{
//debugPlan << "oldLoadAndParse: Trying to open " << filename;
if (!store->open(filename))
{
warnPlan << "Entry " << filename << " not found!";
// d->lastErrorMessage = i18n( "Could not find %1",filename );
return false;
}
// Error variables for QDomDocument::setContent
QString errorMsg;
int errorLine, errorColumn;
bool ok = doc.setContent( store->device(), &errorMsg, &errorLine, &errorColumn );
if ( !ok )
{
errorPlan << "Parsing error in " << filename << "! Aborting!" << endl
<< " In line: " << errorLine << ", column: " << errorColumn << endl
<< " Error message: " << errorMsg;
/* d->lastErrorMessage = i18n( "Parsing error in %1 at line %2, column %3\nError message: %4"
,filename ,errorLine, errorColumn ,
QCoreApplication::translate("QXml", errorMsg.toUtf8(), 0,
QCoreApplication::UnicodeUTF8));*/
store->close();
return false;
}
debugPlan << "File " << filename << " loaded and parsed";
return true;
}
void MainDocument::insertFile( const QUrl &url, Node *parent, Node *after )
{
Part *part = new Part( this );
MainDocument *doc = new MainDocument( part );
part->setDocument( doc );
doc->disconnect(); // doc shall not handle feedback from openUrl()
doc->setAutoSave( 0 ); //disable
doc->m_insertFileInfo.url = url;
doc->m_insertFileInfo.parent = parent;
doc->m_insertFileInfo.after = after;
connect(doc, &KoDocument::completed, this, &MainDocument::insertFileCompleted);
connect(doc, &KoDocument::canceled, this, &MainDocument::insertFileCancelled);
doc->openUrl( url );
}
void MainDocument::insertFileCompleted()
{
debugPlan<( sender() );
if ( doc ) {
Project &p = doc->getProject();
insertProject( p, doc->m_insertFileInfo.parent, doc->m_insertFileInfo.after );
doc->documentPart()->deleteLater(); // also deletes document
} else {
KMessageBox::error( 0, i18n("Internal error, failed to insert file.") );
}
}
void MainDocument::insertResourcesFile(const QUrl &url, const QUrl &projects)
{
insertSharedProjects(projects); // prepare for insertion after shared resources
m_sharedProjectsFiles.removeAll(url); // resource file is not a project
Part *part = new Part( this );
MainDocument *doc = new MainDocument( part );
doc->m_skipSharedProjects = true; // should not have shared projects, but...
part->setDocument( doc );
doc->disconnect(); // doc shall not handle feedback from openUrl()
doc->setAutoSave( 0 ); //disable
doc->setCheckAutoSaveFile(false);
connect(doc, &KoDocument::completed, this, &MainDocument::insertResourcesFileCompleted);
connect(doc, &KoDocument::canceled, this, &MainDocument::insertFileCancelled);
doc->openUrl( url );
}
void MainDocument::insertResourcesFileCompleted()
{
debugPlanShared<( sender() );
if (doc) {
Project &p = doc->getProject();
mergeResources(p);
m_project->setSharedResourcesLoaded(true);
doc->documentPart()->deleteLater(); // also deletes document
slotInsertSharedProject(); // insert shared bookings
} else {
KMessageBox::error( 0, i18n("Internal error, failed to insert file.") );
}
}
void MainDocument::insertFileCancelled( const QString &error )
{
debugPlan<( sender() );
if ( doc ) {
doc->documentPart()->deleteLater(); // also deletes document
}
}
void MainDocument::clearResourceAssignments()
{
foreach (Resource *r, m_project->resourceList()) {
r->clearExternalAppointments();
}
}
void MainDocument::loadResourceAssignments(QUrl url)
{
insertSharedProjects(url);
slotInsertSharedProject();
}
void MainDocument::insertSharedProjects(const QList &urls)
{
clearResourceAssignments();
m_sharedProjectsFiles = urls;
slotInsertSharedProject();
}
void MainDocument::insertSharedProjects(const QUrl &url)
{
m_sharedProjectsFiles.clear();
QFileInfo fi(url.path());
if (!fi.exists()) {
return;
}
if (fi.isFile()) {
m_sharedProjectsFiles = QList() << url;
debugPlan<<"Get all projects in file:"<m_skipSharedProjects = true; // never load recursively
part->setDocument( doc );
doc->disconnect(); // doc shall not handle feedback from openUrl()
doc->setAutoSave( 0 ); //disable
doc->setCheckAutoSaveFile(false);
doc->m_loadingSharedProject = true;
connect(doc, &KoDocument::completed, this, &MainDocument::insertSharedProjectCompleted);
connect(doc, &KoDocument::canceled, this, &MainDocument::insertSharedProjectCancelled);
doc->openUrl(m_sharedProjectsFiles.takeFirst());
}
void MainDocument::insertSharedProjectCompleted()
{
debugPlanShared<( sender() );
if (doc) {
Project &p = doc->getProject();
debugPlanShared<id()<<"Loaded project:"<id() && p.isScheduled(ANYSCHEDULED)) {
// FIXME: improve!
// find a suitable schedule
ScheduleManager *sm = 0;
foreach(ScheduleManager *m, p.allScheduleManagers()) {
if (m->isBaselined()) {
sm = m;
break;
}
if (m->isScheduled()) {
sm = m; // take the last one, more likely to be subschedule
}
}
if (sm) {
foreach(Resource *r, p.resourceList()) {
Resource *res = m_project->resource(r->id());
if (res && res->isShared()) {
Appointment *app = new Appointment();
app->setAuxcilliaryInfo(p.name());
foreach(const Appointment *a, r->appointments(sm->scheduleId())) {
*app += *a;
}
if (app->isEmpty()) {
delete app;
} else {
res->addExternalAppointment(p.id(), app);
debugPlanShared<name()<<"added:"<auxcilliaryInfo()<documentPart()->deleteLater(); // also deletes document
emit insertSharedProject(); // do next file
} else {
KMessageBox::error( 0, i18n("Internal error, failed to insert file.") );
}
}
void MainDocument::insertSharedProjectCancelled( const QString &error )
{
debugPlanShared<( sender() );
if ( doc ) {
doc->documentPart()->deleteLater(); // also deletes document
}
}
bool MainDocument::insertProject( Project &project, Node *parent, Node *after )
{
debugPlan<<&project;
// make sure node ids in new project is unique also in old project
QList existingIds = m_project->nodeDict().keys();
foreach ( Node *n, project.allNodes() ) {
QString oldid = n->id();
n->setId( project.uniqueNodeId( existingIds ) );
project.removeId( oldid ); // remove old id
project.registerNodeId( n ); // register new id
}
MacroCommand *m = new InsertProjectCmd( project, parent==0?m_project:parent, after, kundo2_i18n( "Insert project" ) );
if ( m->isEmpty() ) {
delete m;
} else {
addCommand( m );
}
return true;
}
// check if calendar 'c' has children that will not be removed (normally 'Local' calendars)
bool canRemoveCalendar(const Calendar *c, const QList &lst)
{
for (Calendar *cc : c->calendars()) {
if (!lst.contains(cc)) {
return false;
}
if (!canRemoveCalendar(cc, lst)) {
return false;
}
}
return true;
}
// sort parent calendars before children
QList sortedRemoveCalendars(Project &shared, const QList &lst) {
QList result;
for (Calendar *c : lst) {
if (c->isShared() && !shared.calendar(c->id())) {
result << c;
}
result += sortedRemoveCalendars(shared, c->calendars());
}
return result;
}
bool MainDocument::mergeResources(Project &project)
{
debugPlanShared<<&project;
// Just in case, remove stuff not related to resources
foreach(Node *n, project.childNodeIterator()) {
debugPlanShared<<"Project not empty, delete node:"<name();
NodeDeleteCmd cmd(n);
cmd.execute();
}
foreach(ScheduleManager *m, project.scheduleManagers()) {
debugPlanShared<<"Project not empty, delete schedule:"<name();
DeleteScheduleManagerCmd cmd(project, m);
cmd.execute();
}
foreach(Account *a, project.accounts().accountList()) {
debugPlanShared<<"Project not empty, delete account:"<name();
RemoveAccountCmd cmd(project, a);
cmd.execute();
}
// Mark all resources / groups as shared
foreach(ResourceGroup *g, project.resourceGroups()) {
g->setShared(true);
}
foreach(Resource *r, project.resourceList()) {
r->setShared(true);
}
// Mark all calendars shared
foreach(Calendar *c, project.allCalendars()) {
c->setShared(true);
}
// check if any shared stuff has been removed
QList removedGroups;
QList removedResources;
QList removedCalendars;
QStringList removed;
foreach(ResourceGroup *g, m_project->resourceGroups()) {
if (g->isShared() && !project.findResourceGroup(g->id())) {
removedGroups << g;
removed << i18n("Group: %1", g->name());
}
}
foreach(Resource *r, m_project->resourceList()) {
if (r->isShared() && !project.findResource(r->id())) {
removedResources << r;
removed << i18n("Resource: %1", r->name());
}
}
removedCalendars = sortedRemoveCalendars(project, m_project->calendars());
for (Calendar *c : qAsConst(removedCalendars)) {
removed << i18n("Calendar: %1", c->name());
}
if (!removed.isEmpty()) {
KMessageBox::ButtonCode result = KMessageBox::warningYesNoCancelList(
0,
i18n("Shared resources has been removed from the shared resources file."
"\nSelect how they shall be treated in this project."),
removed,
xi18nc("@title:window", "Shared resources"),
KStandardGuiItem::remove(),
KGuiItem(i18n("Convert")),
KGuiItem(i18n("Keep"))
);
switch (result) {
case KMessageBox::Yes: // Remove
for (Resource *r : qAsConst(removedResources)) {
RemoveResourceCmd cmd(r->parentGroup(), r);
cmd.redo();
}
for (ResourceGroup *g : qAsConst(removedGroups)) {
if (g->resources().isEmpty()) {
RemoveResourceGroupCmd cmd(m_project, g);
cmd.redo();
} else {
// we may have put local resource(s) in this group
// so we need to keep it
g->setShared(false);
m_project->removeResourceGroupId(g->id());
g->setId(m_project->uniqueResourceGroupId());
m_project->insertResourceGroupId(g->id(), g);
}
}
for (Calendar *c : qAsConst(removedCalendars)) {
CalendarRemoveCmd cmd(m_project, c);
cmd.redo();
}
break;
case KMessageBox::No: // Convert
for (Resource *r : qAsConst(removedResources)) {
r->setShared(false);
m_project->removeResourceId(r->id());
r->setId(m_project->uniqueResourceId());
m_project->insertResourceId(r->id(), r);
}
for (ResourceGroup *g : qAsConst(removedGroups)) {
g->setShared(false);
m_project->removeResourceGroupId(g->id());
g->setId(m_project->uniqueResourceGroupId());
m_project->insertResourceGroupId(g->id(), g);
}
for (Calendar *c : qAsConst(removedCalendars)) {
c->setShared(false);
m_project->removeCalendarId(c->id());
c->setId(m_project->uniqueCalendarId());
m_project->insertCalendarId(c->id(), c);
}
break;
case KMessageBox::Cancel: // Keep
break;
default:
break;
}
}
// update values of already existing objects
QStringList l1;
foreach(ResourceGroup *g, project.resourceGroups()) {
l1 << g->id();
}
QStringList l2;
foreach(ResourceGroup *g, m_project->resourceGroups()) {
l2 << g->id();
}
debugPlanShared< removegroups;
foreach(ResourceGroup *g, project.resourceGroups()) {
ResourceGroup *group = m_project->findResourceGroup(g->id());
if (group) {
if (!group->isShared()) {
// User has probably created shared resources from this project,
// so the resources exists but are local ones.
// Convert to shared and do not load the group from shared.
removegroups << g;
group->setShared(true);
debugPlanShared<<"Set group to shared:"<id();
}
group->setName(g->name());
group->setType(g->type());
debugPlanShared<<"Updated group:"<id();
}
}
QList removeresources;
foreach(Resource *r, project.resourceList()) {
Resource *resource = m_project->findResource(r->id());
if (resource) {
if (!resource->isShared()) {
// User has probably created shared resources from this project,
// so the resources exists but are local ones.
// Convert to shared and do not load the resource from shared.
removeresources << r;
resource->setShared(true);
debugPlanShared<<"Set resource to shared:"<id();
}
resource->setName(r->name());
resource->setInitials(r->initials());
resource->setEmail(r->email());
resource->setType(r->type());
resource->setAutoAllocate(r->autoAllocate());
resource->setAvailableFrom(r->availableFrom());
resource->setAvailableUntil(r->availableUntil());
resource->setUnits(r->units());
resource->setNormalRate(r->normalRate());
resource->setOvertimeRate(r->overtimeRate());
QString id = r->calendar(true) ? r->calendar(true)->id() : QString();
resource->setCalendar(m_project->findCalendar(id));
id = r->account() ? r->account()->name() : QString();
resource->setAccount(m_project->accounts().findAccount(id));
resource->setRequiredIds(r->requiredIds());
resource->setTeamMemberIds(r->teamMemberIds());
debugPlanShared<<"Updated resource:"<id();
}
}
QList removecalendars;
foreach(Calendar *c, project.allCalendars()) {
Calendar *calendar = m_project->findCalendar(c->id());
if (calendar) {
if (!calendar->isShared()) {
// User has probably created shared resources from this project,
// so the calendar exists but are local ones.
// Convert to shared and do not load the resource from shared.
removecalendars << c;
calendar->setShared(true);
debugPlanShared<<"Set calendar to shared:"<id();
}
*calendar = *c;
debugPlanShared<<"Updated calendar:"<id();
}
}
debugPlanShared<<"Remove:"<childCount() == 0) {
removecalendars.removeAt(i);
debugPlanShared<<"Delete calendar:"<id();
CalendarRemoveCmd cmd(&project, c);
cmd.execute();
}
}
}
for (Resource *r : qAsConst(removeresources)) {
debugPlanShared<<"Delete resource:"<id();
RemoveResourceCmd cmd(r->parentGroup(), r);
cmd.execute();
}
for (ResourceGroup *g : qAsConst(removegroups)) {
debugPlanShared<<"Delete group:"<id();
RemoveResourceGroupCmd cmd(&project, g);
cmd.execute();
}
// insert new objects
Q_ASSERT(project.childNodeIterator().isEmpty());
InsertProjectCmd cmd(project, m_project, 0);
cmd.execute();
return true;
}
void MainDocument::insertViewListItem( View */*view*/, const ViewListItem *item, const ViewListItem *parent, int index )
{
// FIXME callers should take care that they now get a signal even if originating from themselves
emit viewListItemAdded(item, parent, index);
setModified( true );
m_viewlistModified = true;
}
void MainDocument::removeViewListItem( View */*view*/, const ViewListItem *item )
{
// FIXME callers should take care that they now get a signal even if originating from themselves
emit viewListItemRemoved(item);
setModified( true );
m_viewlistModified = true;
}
void MainDocument::setModified( bool mod )
{
debugPlan<name().isEmpty()) {
setUrl(QUrl(m_project->name() + ".plan"));
}
Calendar *week = 0;
if (KPlatoSettings::generateWeek()) {
bool always = KPlatoSettings::generateWeekChoice() == KPlatoSettings::EnumGenerateWeekChoice::Always;
bool ifnone = KPlatoSettings::generateWeekChoice() == KPlatoSettings::EnumGenerateWeekChoice::NoneExists;
if (always || (ifnone && m_project->calendarCount() == 0)) {
// create a calendar
week = new Calendar(i18nc("Base calendar name", "Base"));
m_project->addCalendar(week);
CalendarDay vd(CalendarDay::NonWorking);
for (int i = Qt::Monday; i <= Qt::Sunday; ++i) {
if (m_config.isWorkingday(i)) {
CalendarDay wd(CalendarDay::Working);
TimeInterval ti(m_config.dayStartTime(i), m_config.dayLength(i));
wd.addInterval(ti);
week->setWeekday(i, wd);
} else {
week->setWeekday(i, vd);
}
}
}
}
#ifdef HAVE_KHOLIDAYS
if (KPlatoSettings::generateHolidays()) {
bool inweek = week != 0 && KPlatoSettings::generateHolidaysChoice() == KPlatoSettings::EnumGenerateHolidaysChoice::InWeekCalendar;
bool subcalendar = week != 0 && KPlatoSettings::generateHolidaysChoice() == KPlatoSettings::EnumGenerateHolidaysChoice::AsSubCalendar;
bool separate = week == 0 || KPlatoSettings::generateHolidaysChoice() == KPlatoSettings::EnumGenerateHolidaysChoice::AsSeparateCalendar;
Calendar *c = 0;
if (inweek) {
c = week;
qDebug()<addCalendar(c, week);
qDebug()<addCalendar(c);
qDebug()<setHolidayRegion(KPlatoSettings::region());
}
#endif
}
// creates a "new" project from current project (new ids etc)
void MainDocument::createNewProject()
{
setEmpty();
clearUndoHistory();
setModified( false );
resetURL();
KoDocumentInfo *info = documentInfo();
info->resetMetaData();
info->setProperty( "title", "" );
setTitleModified();
m_project->generateUniqueNodeIds();
Duration dur = m_project->constraintEndTime() - m_project->constraintStartTime();
m_project->setConstraintStartTime( QDateTime(QDate::currentDate(), QTime(0, 0, 0), Qt::LocalTime) );
m_project->setConstraintEndTime( m_project->constraintStartTime() + dur );
while ( m_project->numScheduleManagers() > 0 ) {
foreach ( ScheduleManager *sm, m_project->allScheduleManagers() ) {
if ( sm->childCount() > 0 ) {
continue;
}
if ( sm->expected() ) {
sm->expected()->setDeleted( true );
sm->setExpected( 0 );
}
m_project->takeScheduleManager( sm );
delete sm;
}
}
foreach ( Schedule *s, m_project->schedules() ) {
m_project->takeSchedule( s );
delete s;
}
foreach ( Node *n, m_project->allNodes() ) {
foreach ( Schedule *s, n->schedules() ) {
n->takeSchedule( s );
delete s;
}
}
foreach ( Resource *r, m_project->resourceList() ) {
foreach ( Schedule *s, r->schedules() ) {
r->takeSchedule( s );
delete s;
}
}
}
void MainDocument::setIsTaskModule(bool value)
{
m_isTaskModule = value;
}
bool MainDocument::isTaskModule() const
{
return m_isTaskModule;
}
} //KPlato namespace
diff --git a/src/kptmaindocument.h b/src/kptmaindocument.h
index 72cc3ad1..6fd36931 100644
--- a/src/kptmaindocument.h
+++ b/src/kptmaindocument.h
@@ -1,254 +1,257 @@
/* This file is part of the KDE project
Copyright (C) 1998, 1999, 2000 Torben Weis
Copyright (C) 2004 - 2010 Dag Andersen
Copyright (C) 2006 Raphael Langerhorst
Copyright (C) 2007 Thorsten Zachmann
-
+ Copyright (C) 2019 Dag Andersen
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KPTMAINDOCUMENT_H
#define KPTMAINDOCUMENT_H
#include "plan_export.h"
+#include "kptpackage.h"
#include "kpttask.h"
#include "kptconfig.h"
#include "kptwbsdefinition.h"
#include "kptxmlloaderobject.h"
#include "about/aboutpage.h"
#include "KoDocument.h"
#include
#include
#define PLAN_MIME_TYPE "application/x-vnd.kde.plan"
/// The main namespace.
namespace KPlato
{
class DocumentChild;
class Project;
class Context;
class SchedulerPlugin;
class ViewListItem;
class View;
class Package;
class PLAN_EXPORT MainDocument : public KoDocument
{
Q_OBJECT
public:
explicit MainDocument(KoPart *part);
~MainDocument();
/// reimplemented from KoDocument
virtual QByteArray nativeFormatMimeType() const { return PLAN_MIME_TYPE; }
/// reimplemented from KoDocument
virtual QByteArray nativeOasisMimeType() const { return ""; }
/// reimplemented from KoDocument
virtual QStringList extraNativeMimeTypes() const
{
return QStringList() << PLAN_MIME_TYPE;
}
void setReadWrite( bool rw );
void configChanged();
virtual void paintContent( QPainter& painter, const QRect& rect);
void setProject( Project *project );
Project &getProject() { return *m_project; }
const Project &getProject() const { return * m_project; }
/**
* Return the set of SupportedSpecialFormats that the kplato wants to
* offer in the "Save" file dialog.
* Note: SaveEncrypted is not supported.
*/
virtual int supportedSpecialFormats() const { return SaveAsDirectoryStore; }
// The load and save functions. Look in the file kplato.dtd for info
virtual bool loadXML( const KoXmlDocument &document, KoStore *store );
virtual QDomDocument saveXML();
/// Save a workpackage file containing @p node with schedule identity @p id, owned by @p resource
QDomDocument saveWorkPackageXML( const Node *node, long id, Resource *resource = 0 );
bool saveOdf( SavingContext &/*documentContext */) { return false; }
bool loadOdf( KoOdfReadStore & odfStore );
Config &config() { return m_config; }
Context *context() const { return m_context; }
WBSDefinition &wbsDefinition() { return m_project->wbsDefinition(); }
const XMLLoaderObject &xmlLoader() const { return m_xmlLoader; }
DocumentChild *createChild( KoDocument *doc, const QRect &geometry = QRect() );
bool saveWorkPackageToStream( QIODevice * dev, const Node *node, long id, Resource *resource = 0 );
bool saveWorkPackageFormat( const QString &file, const Node *node, long id, Resource *resource = 0 );
bool saveWorkPackageUrl( const QUrl & _url, const Node *node, long id, Resource *resource = 0 );
- void mergeWorkPackages();
- void mergeWorkPackage( const Package *package );
- void terminateWorkPackage( const Package *package );
/// Load the workpackage from @p url into @p project. Return true if successful, else false.
bool loadWorkPackage( Project &project, const QUrl &url );
Package *loadWorkPackageXML( Project& project, QIODevice*, const KoXmlDocument& document, const QUrl& url );
QMap workPackages() const { return m_workpackages; }
+ void clearWorkPackages() {
+ qDeleteAll(m_workpackages);
+ m_workpackages.clear();
+ m_checkingForWorkPackages = false;
+ }
void insertFile( const QUrl &url, Node *parent, Node *after = 0 );
bool insertProject( Project &project, Node *parent, Node *after );
bool mergeResources(Project &project);
KPlatoAboutPage &aboutPage() { return m_aboutPage; }
bool extractFiles( KoStore *store, Package *package );
bool extractFile( KoStore *store, Package *package, const Document *doc );
void registerView( View *view );
/// Create a new project from this project
/// Generates new project id and task ids
/// Keeps resource- and calendar ids
void createNewProject();
bool isTaskModule() const;
using KoDocument::setModified;
public Q_SLOTS:
void setModified( bool mod );
/// Inserts an item into all other views than @p view
void insertViewListItem(KPlato::View *view, const KPlato::ViewListItem *item, const KPlato::ViewListItem *parent, int index);
/// Removes the view list item from all other views than @p view
void removeViewListItem(KPlato::View *view, const KPlato::ViewListItem *item);
/// View selector has been modified
void slotViewlistModified();
/// Check for workpackages
/// If @p keep is true, packages that has been refused will not be checked for again
void checkForWorkPackages(bool keep);
+ /// Remove @p package
+ void terminateWorkPackage( const KPlato::Package *package );
void setLoadingTemplate( bool );
void setLoadingSharedResourcesTemplate( bool );
void insertResourcesFile(const QUrl &url, const QUrl &projects = QUrl());
void slotProjectCreated();
/// Prepare for insertion of resource assignments of shared resources from the project(s) in @p urls
void insertSharedProjects(const QList &urls);
/// Prepare for insertion of resource assignments of shared resources from the project(s) in @p url
void insertSharedProjects(const QUrl &url);
/// Clear resource assignments of shared resources
void clearResourceAssignments();
/// Load resource assignments of shared resources from the project(s) in @p url
void loadResourceAssignments(QUrl url);
void setIsTaskModule(bool value);
void autoCheckForWorkPackages();
Q_SIGNALS:
void changed();
void workPackageLoaded();
void viewlistModified( bool );
void viewListItemAdded(const KPlato::ViewListItem *item, const KPlato::ViewListItem *parent, int index);
void viewListItemRemoved(const KPlato::ViewListItem *item);
void insertSharedProject();
protected:
/// Load kplato specific files
virtual bool completeLoading( KoStore* store );
/// Save kplato specific files
virtual bool completeSaving( KoStore* store );
- void mergeWorkPackage( Task *to, const Task *from, const Package *package );
-
// used by insert file
struct InsertFileInfo {
QUrl url;
Node *parent;
Node *after;
} m_insertFileInfo;
protected Q_SLOTS:
void slotViewDestroyed();
void addSchedulerPlugin(const QString&, KPlato::SchedulerPlugin *plugin);
void checkForWorkPackage();
void insertFileCompleted();
void insertResourcesFileCompleted();
void insertFileCancelled( const QString& );
void slotInsertSharedProject();
void insertSharedProjectCompleted();
void insertSharedProjectCancelled( const QString& );
- void workPackageMergeDialogFinished( int result );
-
private:
bool loadAndParse(KoStore* store, const QString& filename, KoXmlDocument& doc);
void loadSchedulerPlugins();
private:
Project *m_project;
QWidget* m_parentWidget;
Config m_config;
Context *m_context;
XMLLoaderObject m_xmlLoader;
bool m_loadingTemplate;
bool m_loadingSharedResourcesTemplate;
QMap m_schedulerPlugins;
QMap m_workpackages;
QFileInfoList m_infoList;
+ QList m_skipUrls;
QMap m_mergedPackages;
KPlatoAboutPage m_aboutPage;
QDomDocument m_reports;
bool m_viewlistModified;
bool m_checkingForWorkPackages;
QList > m_views;
bool m_loadingSharedProject;
QList m_sharedProjectsFiles;
bool m_skipSharedProjects;
bool m_isTaskModule;
};
} //KPlato namespace
#endif
diff --git a/src/kptview.cpp b/src/kptview.cpp
index f9b10917..062e88be 100644
--- a/src/kptview.cpp
+++ b/src/kptview.cpp
@@ -1,3325 +1,3382 @@
/* This file is part of the KDE project
Copyright (C) 1998, 1999, 2000 Torben Weis
Copyright (C) 2002 - 2011 Dag Andersen
Copyright (C) 2012 Dag Andersen
-
+ Copyright (C) 2019 Dag Andersen
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
// clazy:excludeall=qstring-arg
#include "kptview.h"
#include
#include
#include "KoDocumentInfo.h"
#include "KoMainWindow.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
+#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kptlocale.h"
#include "kptviewbase.h"
#include "kptaccountsview.h"
#include "kptaccountseditor.h"
#include "kptcalendareditor.h"
#include "kptfactory.h"
#include "kptmilestoneprogressdialog.h"
#include "kpttaskdescriptiondialog.h"
#include "kptdocumentsdialog.h"
#include "kptnode.h"
#include "kptmaindocument.h"
#include "kptproject.h"
#include "kptmainprojectdialog.h"
#include "kpttask.h"
#include "kptsummarytaskdialog.h"
#include "kpttaskdialog.h"
#include "kpttaskprogressdialog.h"
#include "kptganttview.h"
#include "kpttaskeditor.h"
#include "kptdependencyeditor.h"
#include "kptperteditor.h"
#include "kptdatetime.h"
#include "kptcommand.h"
#include "kptrelation.h"
#include "kptrelationdialog.h"
#include "kptresourceappointmentsview.h"
#include "kptresourceeditor.h"
#include "kptscheduleeditor.h"
#include "kptresourcedialog.h"
#include "kptresource.h"
#include "kptstandardworktimedialog.h"
#include "kptwbsdefinitiondialog.h"
#include "kptresourceassignmentview.h"
#include "kpttaskstatusview.h"
#include "kptsplitterview.h"
#include "kptpertresult.h"
#include "ConfigProjectPanel.h"
#include "ConfigWorkVacationPanel.h"
#include "kpttaskdefaultpanel.h"
#include "kptworkpackageconfigpanel.h"
#include "kptcolorsconfigpanel.h"
#include "kptinsertfiledlg.h"
#include "kptloadsharedprojectsdialog.h"
#include "kpthtmlview.h"
#include "about/aboutpage.h"
#include "kptlocaleconfigmoneydialog.h"
#include "kptflatproxymodel.h"
#include "kpttaskstatusmodel.h"
+#include "kptworkpackagemergedialog.h"
#include "performance/PerformanceStatusView.h"
#include "performance/ProjectStatusView.h"
#include "reportsgenerator/ReportsGeneratorView.h"
#ifdef PLAN_USE_KREPORT
#include "reports/reportview.h"
#include "reports/reportdata.h"
#endif
#include "kptviewlistdialog.h"
#include "kptviewlistdocker.h"
#include "kptviewlist.h"
#include "kptschedulesdocker.h"
#include "kptpart.h"
#include "kptdebug.h"
#include "calligraplansettings.h"
#include "kptprintingcontrolprivate.h"
// #include "KPtViewAdaptor.h"
#include
namespace KPlato
{
//-------------------------------
ConfigDialog::ConfigDialog(QWidget *parent, const QString& name, KConfigSkeleton *config )
: KConfigDialog( parent, name, config ),
m_config( config )
{
KConfigDialogManager::changedMap()->insert("KRichTextWidget", SIGNAL(textChanged()) );
}
bool ConfigDialog::hasChanged()
{
QRegExp kcfg( "kcfg_*" );
foreach ( KRichTextWidget *w, findChildren( kcfg ) ) {
KConfigSkeletonItem *item = m_config->findItem( w->objectName().mid(5) );
if ( ! item->isEqual( w->toHtml() ) ) {
return true;
}
}
return false;
}
void ConfigDialog::updateSettings()
{
bool changed = false;
QRegExp kcfg( "kcfg_*" );
foreach ( KRichTextWidget *w, findChildren( kcfg ) ) {
KConfigSkeletonItem *item = m_config->findItem( w->objectName().mid(5) );
if ( ! item ) {
warnPlan << "The setting '" << w->objectName().mid(5) << "' has disappeared!";
continue;
}
if ( ! item->isEqual( QVariant( w->toHtml() ) ) ) {
item->setProperty( QVariant( w->toHtml() ) );
changed = true;
}
}
if ( changed ) {
m_config->save();
}
}
void ConfigDialog::updateWidgets()
{
QRegExp kcfg( "kcfg_*" );
foreach ( KRichTextWidget *w, findChildren( kcfg ) ) {
KConfigSkeletonItem *item = m_config->findItem( w->objectName().mid(5) );
if ( ! item ) {
warnPlan << "The setting '" << w->objectName().mid(5) << "' has disappeared!";
continue;
}
if ( ! item->isEqual( QVariant( w->toHtml() ) ) ) {
w->setHtml( item->property().toString() );
}
}
}
void ConfigDialog::updateWidgetsDefault()
{
bool usedefault = m_config->useDefaults( true );
updateWidgets();
m_config->useDefaults( usedefault );
}
bool ConfigDialog::isDefault()
{
bool bUseDefaults = m_config->useDefaults(true);
bool result = !hasChanged();
m_config->useDefaults(bUseDefaults);
return result;
}
//------------------------------------
View::View(KoPart *part, MainDocument *doc, QWidget *parent)
: KoView(part, doc, parent),
m_currentEstimateType( Estimate::Use_Expected ),
m_scheduleActionGroup( new QActionGroup( this ) ),
m_readWrite( false ),
m_defaultView(1),
m_partpart (part)
{
//debugPlan;
doc->registerView( this );
setComponentName(Factory::global().componentName(), Factory::global().componentDisplayName());
if ( !doc->isReadWrite() )
setXMLFile( "calligraplan_readonly.rc" );
else
setXMLFile( "calligraplan.rc" );
// new ViewAdaptor( this );
m_sp = new QSplitter( this );
QVBoxLayout *layout = new QVBoxLayout( this );
layout->setMargin(0);
layout->addWidget( m_sp );
ViewListDocker *docker = 0;
if ( mainWindow() == 0 ) {
// Don't use docker if embedded
m_viewlist = new ViewListWidget(doc, m_sp);
m_viewlist->setProject( &( getProject() ) );
connect( m_viewlist, &ViewListWidget::selectionChanged, this, &View::slotSelectionChanged);
connect( this, &View::currentScheduleManagerChanged, m_viewlist, &ViewListWidget::setSelectedSchedule);
connect( m_viewlist, &ViewListWidget::updateViewInfo, this, &View::slotUpdateViewInfo);
} else {
ViewListDockerFactory vl(this);
docker = static_cast(mainWindow()->createDockWidget(&vl));
if (docker->view() != this) {
docker->setView(this);
}
m_viewlist = docker->viewList();
#if 0 //SchedulesDocker
SchedulesDockerFactory sdf;
SchedulesDocker *sd = dynamic_cast( createDockWidget( &sdf ) );
Q_ASSERT( sd );
sd->setProject( &getProject() );
connect(sd, SIGNAL(selectionChanged(KPlato::ScheduleManager*)), SLOT(slotSelectionChanged(KPlato::ScheduleManager*)));
connect(this, &View::currentScheduleManagerChanged, sd, SLOT(setSelectedSchedule(KPlato::ScheduleManager*)));
#endif
}
m_tab = new QStackedWidget( m_sp );
////////////////////////////////////////////////////////////////////////////////////////////////////
// Add sub views
createIntroductionView();
// The menu items
// ------ File
/* actionCreateTemplate = new QAction( i18n( "&Create Template From Document..." ), this );
actionCollection()->addAction("file_createtemplate", actionCreateTemplate );
connect( actionCreateTemplate, SIGNAL(triggered(bool)), SLOT(slotCreateTemplate()) );
*/
actionCreateNewProject = new QAction( i18n( "&Create New Project..." ), this );
actionCollection()->addAction("file_createnewproject", actionCreateNewProject );
connect( actionCreateNewProject, &QAction::triggered, this, &View::slotCreateNewProject );
// ------ Edit
actionCut = actionCollection()->addAction(KStandardAction::Cut, "edit_cut", this, SLOT(slotEditCut()));
actionCopy = actionCollection()->addAction(KStandardAction::Copy, "edit_copy", this, SLOT(slotEditCopy()));
actionPaste = actionCollection()->addAction(KStandardAction::Paste, "edit_paste", this, SLOT(slotEditPaste()));
// ------ View
actionCollection()->addAction( KStandardAction::Redisplay, "view_refresh" , this, SLOT(slotRefreshView()) );
actionViewSelector = new KToggleAction(i18n("Show Selector"), this);
actionCollection()->addAction("view_show_selector", actionViewSelector );
connect( actionViewSelector, &QAction::triggered, this, &View::slotViewSelector );
// ------ Insert
// ------ Project
actionEditMainProject = new QAction(koIcon("view-time-schedule-edit"), i18n("Edit Main Project..."), this);
actionCollection()->addAction("project_edit", actionEditMainProject );
connect( actionEditMainProject, &QAction::triggered, this, &View::slotProjectEdit );
actionEditStandardWorktime = new QAction(koIcon("configure"), i18n("Define Estimate Conversions..."), this);
actionCollection()->addAction("project_worktime", actionEditStandardWorktime );
connect( actionEditStandardWorktime, &QAction::triggered, this, &View::slotProjectWorktime );
// ------ Tools
actionDefineWBS = new QAction(koIcon("configure"), i18n("Define WBS Pattern..."), this);
actionCollection()->addAction("tools_define_wbs", actionDefineWBS );
connect( actionDefineWBS, &QAction::triggered, this, &View::slotDefineWBS );
actionInsertFile = new QAction(koIcon("document-import"), i18n("Insert Project File..."), this);
actionCollection()->addAction("insert_file", actionInsertFile );
connect( actionInsertFile, &QAction::triggered, this, &View::slotInsertFile );
actionLoadSharedProjects = new QAction(koIcon("document-import"), i18n("Load Shared Projects..."), this);
actionCollection()->addAction("load_shared_projects", actionLoadSharedProjects );
connect( actionLoadSharedProjects, &QAction::triggered, this, &View::slotLoadSharedProjects );
// ------ Settings
actionConfigure = new QAction(koIcon("configure"), i18n("Configure Plan..."), this);
actionCollection()->addAction("configure", actionConfigure );
connect( actionConfigure, &QAction::triggered, this, &View::slotConfigure );
actionCurrencyConfig = new QAction(koIcon("configure"), i18n("Define Currency..."), this);
actionCollection()->addAction( "config_currency", actionCurrencyConfig );
connect( actionCurrencyConfig, &QAction::triggered, this, &View::slotCurrencyConfig );
#ifdef PLAN_USE_KREPORT
actionOpenReportFile = new QAction(koIcon("document-open"), i18n("Open Report Definition File..."), this);
actionCollection()->addAction( "reportdesigner_open_file", actionOpenReportFile );
connect( actionOpenReportFile, QAction::triggered, this, &View::slotOpenReportFile);
#endif
// ------ Help
actionIntroduction = new QAction(koIcon("dialog-information"), i18n("Introduction to Plan"), this);
actionCollection()->addAction("plan_introduction", actionIntroduction );
connect( actionIntroduction, &QAction::triggered, this, &View::slotIntroduction );
// ------ Popup
actionOpenNode = new QAction(koIcon("document-edit"), i18n("Edit..."), this);
actionCollection()->addAction("node_properties", actionOpenNode );
connect( actionOpenNode, &QAction::triggered, this, &View::slotOpenCurrentNode );
actionTaskProgress = new QAction(koIcon("document-edit"), i18n("Progress..."), this);
actionCollection()->addAction("task_progress", actionTaskProgress );
connect( actionTaskProgress, &QAction::triggered, this, &View::slotTaskProgress );
actionDeleteTask = new QAction(koIcon("edit-delete"), i18n("Delete Task"), this);
actionCollection()->addAction("delete_task", actionDeleteTask );
connect( actionDeleteTask, &QAction::triggered, this, &View::slotDeleteCurrentTask );
actionTaskDescription = new QAction(koIcon("document-edit"), i18n("Description..."), this);
actionCollection()->addAction("task_description", actionTaskDescription );
connect( actionTaskDescription, &QAction::triggered, this, &View::slotTaskDescription );
actionDocuments = new QAction(koIcon("document-edit"), i18n("Documents..."), this);
actionCollection()->addAction("task_documents", actionDocuments );
connect( actionDocuments, &QAction::triggered, this, &View::slotDocuments );
actionIndentTask = new QAction(koIcon("format-indent-more"), i18n("Indent Task"), this);
actionCollection()->addAction("indent_task", actionIndentTask );
connect( actionIndentTask, &QAction::triggered, this, &View::slotIndentTask );
actionUnindentTask= new QAction(koIcon("format-indent-less"), i18n("Unindent Task"), this);
actionCollection()->addAction("unindent_task", actionUnindentTask );
connect( actionUnindentTask, &QAction::triggered, this, &View::slotUnindentTask );
actionMoveTaskUp = new QAction(koIcon("arrow-up"), i18n("Move Task Up"), this);
actionCollection()->addAction("move_task_up", actionMoveTaskUp );
connect( actionMoveTaskUp, &QAction::triggered, this, &View::slotMoveTaskUp );
actionMoveTaskDown = new QAction(koIcon("arrow-down"), i18n("Move Task Down"), this);
actionCollection()->addAction("move_task_down", actionMoveTaskDown );
connect( actionMoveTaskDown, &QAction::triggered, this, &View::slotMoveTaskDown );
actionEditResource = new QAction(koIcon("document-edit"), i18n("Edit Resource..."), this);
actionCollection()->addAction("edit_resource", actionEditResource );
connect( actionEditResource, &QAction::triggered, this, &View::slotEditCurrentResource );
actionEditRelation = new QAction(koIcon("document-edit"), i18n("Edit Dependency..."), this);
actionCollection()->addAction("edit_dependency", actionEditRelation );
connect( actionEditRelation, &QAction::triggered, this, &View::slotModifyCurrentRelation );
actionDeleteRelation = new QAction(koIcon("edit-delete"), i18n("Delete Dependency"), this);
actionCollection()->addAction("delete_dependency", actionDeleteRelation );
connect( actionDeleteRelation, &QAction::triggered, this, &View::slotDeleteRelation );
// Viewlist popup
connect( m_viewlist, &ViewListWidget::createView, this, &View::slotCreateView );
+ m_workPackageButton = new QToolButton(this);
+ m_workPackageButton->hide();
+ m_workPackageButton->setIcon(koIcon("application-x-vnd.kde.plan.work"));
+ m_workPackageButton->setText(i18n("Work Packages..."));
+ m_workPackageButton->setToolTip(i18nc("@info:tooltip", "Work packages available"));
+ m_workPackageButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ connect(m_workPackageButton, &QToolButton::clicked, this, &View::openWorkPackageMergeDialog);
m_estlabel = new QLabel( "", 0 );
if ( statusBar() ) {
addStatusBarItem( m_estlabel, 0, true );
}
connect( &getProject(), &Project::scheduleManagerAdded, this, &View::slotScheduleAdded );
connect( &getProject(), &Project::scheduleManagerRemoved, this, &View::slotScheduleRemoved );
connect( &getProject(), &Project::scheduleManagersSwapped, this, &View::slotScheduleSwapped );
connect( &getProject(), &Project::sigCalculationFinished, this, &View::slotScheduleCalculated );
slotPlugScheduleActions();
connect( doc, &MainDocument::changed, this, &View::slotUpdate );
connect( m_scheduleActionGroup, &QActionGroup::triggered, this, &View::slotViewSchedule );
connect( getPart(), &MainDocument::workPackageLoaded, this, &View::slotWorkPackageLoaded );
// views take time for large projects
QTimer::singleShot(0, this, &View::initiateViews);
const QList pluginFactories =
KoPluginLoader::instantiatePluginFactories(QStringLiteral("calligraplan/extensions"));
foreach (KPluginFactory* factory, pluginFactories) {
QObject *object = factory->create(this, QVariantList());
KXMLGUIClient *clientPlugin = dynamic_cast(object);
if (clientPlugin) {
insertChildClient(clientPlugin);
} else {
// not our/valid plugin, so delete the created object
object->deleteLater();
}
}
// do not watch task module changes if we are editing one
if (!doc->isTaskModule()) {
QString dir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
if (!dir.isEmpty()) {
dir += "/taskmodules";
m_dirwatch.addDir(dir, KDirWatch::WatchFiles);
QStringList modules = KoResourcePaths::findAllResources( "calligraplan_taskmodules", "*.plan", KoResourcePaths::NoDuplicates|KoResourcePaths::Recursive );
for (const QString &f : modules) {
m_dirwatch.addFile(f);
}
connect(&m_dirwatch, &KDirWatch::created, this, &View::taskModuleFileChanged);
connect(&m_dirwatch, &KDirWatch::deleted, this, &View::taskModuleFileChanged);
}
}
//debugPlan<<" end";
}
View::~View()
{
// Disconnect and delete so we do not get called by destroyd() signal
const QMap map = m_scheduleActions; // clazy:exclude=qmap-with-pointer-key
QMap::const_iterator it;
for (it = map.constBegin(); it != map.constEnd(); ++it) {
disconnect(it.key(), &QObject::destroyed, this, &View::slotActionDestroyed);
m_scheduleActionGroup->removeAction(it.key());
delete it.key();
}
ViewBase *view = currentView();
if (view) {
// deactivate view to remove dockers etc
slotGuiActivated(view, false);
}
/* removeStatusBarItem( m_estlabel );
delete m_estlabel;*/
}
void View::initiateViews()
{
QApplication::setOverrideCursor( Qt::WaitCursor );
createViews();
connect( m_viewlist, &ViewListWidget::activated, this, &View::slotViewActivated );
// after createViews() !!
connect( m_viewlist, &ViewListWidget::viewListItemRemoved, this, &View::slotViewListItemRemoved );
// after createViews() !!
connect( m_viewlist, &ViewListWidget::viewListItemInserted, this, &View::slotViewListItemInserted );
ViewListDocker *docker = qobject_cast( m_viewlist->parent() );
if ( docker ) {
// after createViews() !!
connect( m_viewlist, &ViewListWidget::modified, docker, &ViewListDocker::slotModified);
connect( m_viewlist, &ViewListWidget::modified, getPart(), &MainDocument::slotViewlistModified);
connect(getPart(), &MainDocument::viewlistModified, docker, &ViewListDocker::updateWindowTitle);
}
connect( m_tab, &QStackedWidget::currentChanged, this, &View::slotCurrentChanged );
slotSelectDefaultView();
loadContext();
QApplication::restoreOverrideCursor();
}
void View::slotCreateNewProject()
{
debugPlan;
if ( KMessageBox::Continue == KMessageBox::warningContinueCancel( this,
xi18nc( "@info",
"This action cannot be undone."
"Create a new Project from the current project "
"with new project- and task identities."
"Resource- and calendar identities are not changed."
"All scheduling information is removed."
"Do you want to continue?" ) ) )
{
emit currentScheduleManagerChanged(0);
getPart()->createNewProject();
slotOpenNode( &getProject() );
}
}
void View::createViews()
{
Context *ctx = getPart()->context();
if ( ctx && ctx->isLoaded() ) {
debugPlan<<"isLoaded";
KoXmlNode n = ctx->context().namedItem( "categories" );
if ( n.isNull() ) {
warnPlan<<"No categories";
} else {
n = n.firstChild();
for ( ; ! n.isNull(); n = n.nextSibling() ) {
if ( ! n.isElement() ) {
continue;
}
KoXmlElement e = n.toElement();
if (e.tagName() != "category") {
continue;
}
debugPlan<<"category: "<addCategory( ct, cn );
KoXmlNode n1 = e.firstChild();
for ( ; ! n1.isNull(); n1 = n1.nextSibling() ) {
if ( ! n1.isElement() ) {
continue;
}
KoXmlElement e1 = n1.toElement();
if (e1.tagName() != "view") {
continue;
}
ViewBase *v = 0;
QString type = e1.attribute( "viewtype" );
QString tag = e1.attribute( "tag" );
QString name = e1.attribute( "name" );
QString tip = e1.attribute( "tooltip" );
v = createView( cat, type, tag, name, tip );
//KoXmlNode settings = e1.namedItem( "settings " ); ????
KoXmlNode settings = e1.firstChild();
for ( ; ! settings.isNull(); settings = settings.nextSibling() ) {
if ( settings.nodeName() == "settings" ) {
break;
}
}
if ( v && settings.isElement() ) {
debugPlan<<" settings";
v->loadContext( settings.toElement() );
}
}
}
}
} else {
debugPlan<<"Default";
ViewBase *v = 0;
ViewListItem *cat;
QString ct = "Editors";
cat = m_viewlist->addCategory( ct, defaultCategoryInfo( ct ).name );
createCalendarEditor( cat, "CalendarEditor", QString(), TIP_USE_DEFAULT_TEXT );
createAccountsEditor( cat, "AccountsEditor", QString(), TIP_USE_DEFAULT_TEXT );
v = createResourceEditor( cat, "ResourceEditor", QString(), TIP_USE_DEFAULT_TEXT );
v = createTaskEditor( cat, "TaskEditor", QString(), TIP_USE_DEFAULT_TEXT );
m_defaultView = m_tab->count() - 1;
v->showColumns(QList() << NodeModel::NodeName
<< NodeModel::NodeType
<< NodeModel::NodePriority
<< NodeModel::NodeAllocation
<< NodeModel::NodeEstimateCalendar
<< NodeModel::NodeEstimate
<< NodeModel::NodeOptimisticRatio
<< NodeModel::NodePessimisticRatio
<< NodeModel::NodeRisk
<< NodeModel::NodeResponsible
<< NodeModel::NodeDescription
);
v = createTaskEditor( cat, "TaskConstraintEditor", i18n("Task Constraints"), i18n("Edit task scheduling constraints") );
v->showColumns(QList() << NodeModel::NodeName
<< NodeModel::NodeType
<< NodeModel::NodeConstraint
<< NodeModel::NodeConstraintStart
<< NodeModel::NodeConstraintEnd
<< NodeModel::NodeDescription
);
v = createTaskEditor( cat, "TaskCostEditor", i18n("Task Cost"), i18n("Edit task cost") );
v->showColumns(QList() << NodeModel::NodeName
<< NodeModel::NodeType
<< NodeModel::NodeRunningAccount
<< NodeModel::NodeStartupAccount
<< NodeModel::NodeStartupCost
<< NodeModel::NodeShutdownAccount
<< NodeModel::NodeShutdownCost
<< NodeModel::NodeDescription
);
createDependencyEditor( cat, "DependencyEditor", QString(), TIP_USE_DEFAULT_TEXT );
// Do not show by default
// createPertEditor( cat, "PertEditor", QString(), TIP_USE_DEFAULT_TEXT );
createScheduleHandler( cat, "ScheduleHandlerView", QString(), TIP_USE_DEFAULT_TEXT );
ct = "Views";
cat = m_viewlist->addCategory( ct, defaultCategoryInfo( ct ).name );
createGanttView( cat, "GanttView", QString(), TIP_USE_DEFAULT_TEXT );
createMilestoneGanttView( cat, "MilestoneGanttView", QString(), TIP_USE_DEFAULT_TEXT );
createResourceAppointmentsView( cat, "ResourceAppointmentsView", QString(), TIP_USE_DEFAULT_TEXT );
createResourceAppointmentsGanttView( cat, "ResourceAppointmentsGanttView", QString(), TIP_USE_DEFAULT_TEXT );
createAccountsView( cat, "AccountsView", QString(), TIP_USE_DEFAULT_TEXT );
ct = "Execution";
cat = m_viewlist->addCategory( ct, defaultCategoryInfo( ct ).name );
createProjectStatusView( cat, "ProjectStatusView", QString(), TIP_USE_DEFAULT_TEXT );
createPerformanceStatusView( cat, "PerformanceStatusView", QString(), TIP_USE_DEFAULT_TEXT );
v = createTaskStatusView( cat, "TaskStatusView", QString(), TIP_USE_DEFAULT_TEXT );
v = createTaskView( cat, "TaskView", QString(), TIP_USE_DEFAULT_TEXT );
v = createTaskWorkPackageView( cat, "TaskWorkPackageView", QString(), TIP_USE_DEFAULT_TEXT );
ct = "Reports";
cat = m_viewlist->addCategory(ct, defaultCategoryInfo(ct).name);
createReportsGeneratorView(cat, "ReportsGeneratorView", i18n("Generate reports"), TIP_USE_DEFAULT_TEXT);
#ifdef PLAN_USE_KREPORT
// Let user add reports explicitly, we prefer reportsgenerator now
// A little hack to get the user started...
#if 0
ReportView *rv = qobject_cast( createReportView( cat, "ReportView", i18n( "Task Status Report" ), TIP_USE_DEFAULT_TEXT ) );
if ( rv ) {
QDomDocument doc;
doc.setContent( standardTaskStatusReport() );
rv->loadXML( doc );
}
#endif
#endif
}
}
ViewBase *View::createView( ViewListItem *cat, const QString &type, const QString &tag, const QString &name, const QString &tip, int index )
{
ViewBase *v = 0;
//NOTE: type is the same as classname (so if it is changed...)
if ( type == "CalendarEditor" ) {
v = createCalendarEditor( cat, tag, name, tip, index );
} else if ( type == "AccountsEditor" ) {
v = createAccountsEditor( cat, tag, name, tip, index );
} else if ( type == "ResourceEditor" ) {
v = createResourceEditor( cat, tag, name, tip, index );
} else if ( type == "TaskEditor" ) {
v = createTaskEditor( cat, tag, name, tip, index );
} else if ( type == "DependencyEditor" ) {
v = createDependencyEditor( cat, tag, name, tip, index );
} else if ( type == "PertEditor" ) {
v = createPertEditor( cat, tag, name, tip, index );
} else if ( type == "ScheduleEditor" ) {
v = createScheduleEditor( cat, tag, name, tip, index );
} else if ( type == "ScheduleHandlerView" ) {
v = createScheduleHandler( cat, tag, name, tip, index );
} else if ( type == "ProjectStatusView" ) {
v = createProjectStatusView( cat, tag, name, tip, index );
} else if ( type == "TaskStatusView" ) {
v = createTaskStatusView( cat, tag, name, tip, index );
} else if ( type == "TaskView" ) {
v = createTaskView( cat, tag, name, tip, index );
} else if ( type == "TaskWorkPackageView" ) {
v = createTaskWorkPackageView( cat, tag, name, tip, index );
} else if ( type == "GanttView" ) {
v = createGanttView( cat, tag, name, tip, index );
} else if ( type == "MilestoneGanttView" ) {
v = createMilestoneGanttView( cat, tag, name, tip, index );
} else if ( type == "ResourceAppointmentsView" ) {
v = createResourceAppointmentsView( cat, tag, name, tip, index );
} else if ( type == "ResourceAppointmentsGanttView" ) {
v = createResourceAppointmentsGanttView( cat, tag, name, tip, index );
} else if ( type == "AccountsView" ) {
v = createAccountsView( cat, tag, name, tip, index );
} else if ( type == "PerformanceStatusView" ) {
v = createPerformanceStatusView( cat, tag, name, tip, index );
} else if ( type == "ReportsGeneratorView" ) {
v = createReportsGeneratorView(cat, tag, name, tip, index);
} else if ( type == "ReportView" ) {
#ifdef PLAN_USE_KREPORT
v = createReportView( cat, tag, name, tip, index );
#endif
} else {
warnPlan<<"Unknown viewtype: "<type() == ViewListItem::ItemType_SubView ) {
itm->setViewInfo( defaultViewInfo( itm->viewType() ) );
} else if ( itm->type() == ViewListItem::ItemType_Category ) {
ViewInfo vi = defaultCategoryInfo( itm->tag() );
itm->setViewInfo( vi );
}
}
ViewInfo View::defaultViewInfo( const QString &type ) const
{
ViewInfo vi;
if ( type == "CalendarEditor" ) {
vi.name = i18n( "Work & Vacation" );
vi.tip = xi18nc( "@info:tooltip", "Edit working- and vacation days for resources" );
} else if ( type == "AccountsEditor" ) {
vi.name = i18n( "Cost Breakdown Structure" );
vi.tip = xi18nc( "@info:tooltip", "Edit cost breakdown structure." );
} else if ( type == "ResourceEditor" ) {
vi.name = i18n( "Resources" );
vi.tip = xi18nc( "@info:tooltip", "Edit resource breakdown structure" );
} else if ( type == "TaskEditor" ) {
vi.name = i18n( "Tasks" );
vi.tip = xi18nc( "@info:tooltip", "Edit work breakdown structure" );
} else if ( type == "DependencyEditor" ) {
vi.name = i18n( "Dependencies (Graphic)" );
vi.tip = xi18nc( "@info:tooltip", "Edit task dependencies" );
} else if ( type == "PertEditor" ) {
vi.name = i18n( "Dependencies (List)" );
vi.tip = xi18nc( "@info:tooltip", "Edit task dependencies" );
} else if ( type == "ScheduleEditor" ) {
// This view is not used stand-alone atm
vi.name = i18n( "Schedules" );
} else if ( type == "ScheduleHandlerView" ) {
vi.name = i18n( "Schedules" );
vi.tip = xi18nc( "@info:tooltip", "Calculate and analyze project schedules" );
} else if ( type == "ProjectStatusView" ) {
vi.name = i18n( "Project Performance Chart" );
vi.tip = xi18nc( "@info:tooltip", "View project status information" );
} else if ( type == "TaskStatusView" ) {
vi.name = i18n( "Task Status" );
vi.tip = xi18nc( "@info:tooltip", "View task progress information" );
} else if ( type == "TaskView" ) {
vi.name = i18n( "Task Execution" );
vi.tip = xi18nc( "@info:tooltip", "View task execution information" );
} else if ( type == "TaskWorkPackageView" ) {
vi.name = i18n( "Work Package View" );
vi.tip = xi18nc( "@info:tooltip", "View task work package information" );
} else if ( type == "GanttView" ) {
vi.name = i18n( "Gantt" );
vi.tip = xi18nc( "@info:tooltip", "View Gantt chart" );
} else if ( type == "MilestoneGanttView" ) {
vi.name = i18n( "Milestone Gantt" );
vi.tip = xi18nc( "@info:tooltip", "View milestone Gantt chart" );
} else if ( type == "ResourceAppointmentsView" ) {
vi.name = i18n( "Resource Assignments" );
vi.tip = xi18nc( "@info:tooltip", "View resource assignments in a table" );
} else if ( type == "ResourceAppointmentsGanttView" ) {
vi.name = i18n( "Resource Assignments (Gantt)" );
vi.tip = xi18nc( "@info:tooltip", "View resource assignments in Gantt chart" );
} else if ( type == "AccountsView" ) {
vi.name = i18n( "Cost Breakdown" );
vi.tip = xi18nc( "@info:tooltip", "View planned and actual cost" );
} else if ( type == "PerformanceStatusView" ) {
vi.name = i18n( "Tasks Performance Chart" );
vi.tip = xi18nc( "@info:tooltip", "View tasks performance status information" );
} else if ( type == "ReportsGeneratorView" ) {
vi.name = i18n( "Reports Generator" );
vi.tip = xi18nc( "@info:tooltip", "Generate reports" );
} else if ( type == "ReportView" ) {
vi.name = i18n( "Report" );
vi.tip = xi18nc( "@info:tooltip", "View report" );
} else {
warnPlan<<"Unknown viewtype: "<count()-1) : m_visitedViews.at(m_visitedViews.count() - 2);
debugPlan<<"Prev:"<setCurrentIndex(view);
return;
}
if ( url.url().startsWith( QLatin1String( "about:plan" ) ) ) {
getPart()->aboutPage().generatePage( v->htmlPart(), url );
return;
}
}
if ( url.scheme() == QLatin1String("help") ) {
KHelpClient::invokeHelp( "", url.fileName() );
return;
}
// try to open the url
debugPlan<htmlPart().setJScriptEnabled(false);
v->htmlPart().setJavaEnabled(false);
v->htmlPart().setMetaRefreshEnabled(false);
v->htmlPart().setPluginsEnabled(false);
slotOpenUrlRequest( v, QUrl( "about:plan/main" ) );
connect( v, &HtmlView::openUrlRequest, this, &View::slotOpenUrlRequest );
m_tab->addWidget( v );
return v;
}
ViewBase *View::createResourceAppointmentsGanttView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
ResourceAppointmentsGanttView *v = new ResourceAppointmentsGanttView(getKoPart(), getPart(), m_tab );
m_tab->addWidget( v );
ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "ResourceAppointmentsGanttView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( this, &View::currentScheduleManagerChanged, v, &ResourceAppointmentsGanttView::setScheduleManager);
connect( v, &ResourceAppointmentsGanttView::requestPopupMenu, this, &View::slotPopupMenuRequested);
v->setProject( &( getProject() ) );
v->setScheduleManager( currentScheduleManager() );
v->updateReadWrite( m_readWrite );
return v;
}
ViewBase *View::createResourceAppointmentsView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
ResourceAppointmentsView *v = new ResourceAppointmentsView(getKoPart(), getPart(), m_tab );
m_tab->addWidget( v );
ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "ResourceAppointmentsView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( this, &View::currentScheduleManagerChanged, v, &ResourceAppointmentsView::setScheduleManager);
connect( v, &ResourceAppointmentsView::requestPopupMenu, this, &View::slotPopupMenuRequested);
v->setProject( &( getProject() ) );
v->setScheduleManager( currentScheduleManager() );
v->updateReadWrite( m_readWrite );
return v;
}
ViewBase *View::createResourceEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
ResourceEditor *resourceeditor = new ResourceEditor(getKoPart(), getPart(), m_tab );
resourceeditor->setViewSplitMode(false);
m_tab->addWidget( resourceeditor );
resourceeditor->setProject( &(getProject()) );
ViewListItem *i = m_viewlist->addView( cat, tag, name, resourceeditor, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "ResourceEditor" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
connect( resourceeditor, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( resourceeditor, &ResourceEditor::deleteObjectList, this, &View::slotDeleteResourceObjects );
connect( resourceeditor, &ResourceEditor::requestPopupMenu, this, &View::slotPopupMenuRequested);
resourceeditor->updateReadWrite( m_readWrite );
return resourceeditor;
}
ViewBase *View::createTaskEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
TaskEditor *taskeditor = new TaskEditor(getKoPart(), getPart(), m_tab );
taskeditor->setViewSplitMode(false);
m_tab->addWidget( taskeditor );
ViewListItem *i = m_viewlist->addView( cat, tag, name, taskeditor, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "TaskEditor" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
taskeditor->setProject( &(getProject()) );
taskeditor->setScheduleManager( currentScheduleManager() );
connect( this, &View::currentScheduleManagerChanged, taskeditor, &TaskEditor::setScheduleManager);
connect( taskeditor, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( taskeditor, &TaskEditor::addTask, this, &View::slotAddTask );
connect( taskeditor, &TaskEditor::addMilestone, this, &View::slotAddMilestone );
connect( taskeditor, &TaskEditor::addSubtask, this, &View::slotAddSubTask );
connect( taskeditor, &TaskEditor::addSubMilestone, this, &View::slotAddSubMilestone );
connect(taskeditor, &TaskEditor::deleteTaskList, this, &View::slotDeleteTaskList);
connect( taskeditor, &TaskEditor::moveTaskUp, this, &View::slotMoveTaskUp );
connect( taskeditor, &TaskEditor::moveTaskDown, this, &View::slotMoveTaskDown );
connect( taskeditor, &TaskEditor::indentTask, this, &View::slotIndentTask );
connect( taskeditor, &TaskEditor::unindentTask, this, &View::slotUnindentTask );
connect(taskeditor, &TaskEditor::saveTaskModule, this, &View::saveTaskModule);
connect(taskeditor, &TaskEditor::removeTaskModule, this, &View::removeTaskModule);
connect(taskeditor, &ViewBase::openDocument, static_cast(m_partpart), &Part::openTaskModule);
connect(this, &View::taskModulesChanged, taskeditor, &TaskEditor::setTaskModules);
connect( taskeditor, &TaskEditor::requestPopupMenu, this, &View::slotPopupMenuRequested);
taskeditor->updateReadWrite( m_readWrite );
// last:
QStringList modules = KoResourcePaths::findAllResources( "calligraplan_taskmodules", "*.plan", KoResourcePaths::NoDuplicates|KoResourcePaths::Recursive );
debugPlan<setTaskModules( modules );
return taskeditor;
}
ViewBase *View::createAccountsEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
AccountsEditor *ae = new AccountsEditor(getKoPart(), getPart(), m_tab );
m_tab->addWidget( ae );
ViewListItem *i = m_viewlist->addView( cat, tag, name, ae, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "AccountsEditor" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
ae->draw( getProject() );
connect( ae, &ViewBase::guiActivated, this, &View::slotGuiActivated );
ae->updateReadWrite( m_readWrite );
return ae;
}
ViewBase *View::createCalendarEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
CalendarEditor *calendareditor = new CalendarEditor(getKoPart(), getPart(), m_tab );
m_tab->addWidget( calendareditor );
ViewListItem *i = m_viewlist->addView( cat, tag, name, calendareditor, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "CalendarEditor" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
calendareditor->draw( getProject() );
connect( calendareditor, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( calendareditor, &CalendarEditor::requestPopupMenu, this, &View::slotPopupMenuRequested);
calendareditor->updateReadWrite( m_readWrite );
return calendareditor;
}
ViewBase *View::createScheduleHandler( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
ScheduleHandlerView *handler = new ScheduleHandlerView(getKoPart(), getPart(), m_tab );
m_tab->addWidget( handler );
ViewListItem *i = m_viewlist->addView( cat, tag, name, handler, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "ScheduleHandlerView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
connect( handler->scheduleEditor(), &ScheduleEditor::addScheduleManager, this, &View::slotAddScheduleManager );
connect( handler->scheduleEditor(), &ScheduleEditor::deleteScheduleManager, this, &View::slotDeleteScheduleManager );
connect( handler->scheduleEditor(), &ScheduleEditor::moveScheduleManager, this, &View::slotMoveScheduleManager);
connect( handler->scheduleEditor(), &ScheduleEditor::calculateSchedule, this, &View::slotCalculateSchedule );
connect( handler->scheduleEditor(), &ScheduleEditor::baselineSchedule, this, &View::slotBaselineSchedule );
connect( handler, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( this, &View::currentScheduleManagerChanged, handler, &ScheduleHandlerView::currentScheduleManagerChanged );
connect( handler, &ScheduleHandlerView::requestPopupMenu, this, &View::slotPopupMenuRequested);
connect(handler, &ScheduleHandlerView::editNode, this, &View::slotOpenNode);
connect(handler, &ScheduleHandlerView::editResource, this, &View::slotEditResource);
handler->draw( getProject() );
handler->updateReadWrite( m_readWrite );
return handler;
}
ScheduleEditor *View::createScheduleEditor( QWidget *parent )
{
ScheduleEditor *scheduleeditor = new ScheduleEditor(getKoPart(), getPart(), parent );
connect( scheduleeditor, &ScheduleEditor::addScheduleManager, this, &View::slotAddScheduleManager );
connect( scheduleeditor, &ScheduleEditor::deleteScheduleManager, this, &View::slotDeleteScheduleManager );
connect( scheduleeditor, &ScheduleEditor::calculateSchedule, this, &View::slotCalculateSchedule );
connect( scheduleeditor, &ScheduleEditor::baselineSchedule, this, &View::slotBaselineSchedule );
scheduleeditor->updateReadWrite( m_readWrite );
return scheduleeditor;
}
ViewBase *View::createScheduleEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
ScheduleEditor *scheduleeditor = new ScheduleEditor(getKoPart(), getPart(), m_tab );
m_tab->addWidget( scheduleeditor );
ViewListItem *i = m_viewlist->addView( cat, tag, name, scheduleeditor, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "ScheduleEditor" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
scheduleeditor->setProject( &( getProject() ) );
connect( scheduleeditor, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( scheduleeditor, &ScheduleEditor::addScheduleManager, this, &View::slotAddScheduleManager );
connect( scheduleeditor, &ScheduleEditor::deleteScheduleManager, this, &View::slotDeleteScheduleManager );
connect( scheduleeditor, &ScheduleEditor::calculateSchedule, this, &View::slotCalculateSchedule );
connect( scheduleeditor, &ScheduleEditor::baselineSchedule, this, &View::slotBaselineSchedule );
scheduleeditor->updateReadWrite( m_readWrite );
return scheduleeditor;
}
ViewBase *View::createDependencyEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
DependencyEditor *editor = new DependencyEditor(getKoPart(), getPart(), m_tab );
m_tab->addWidget( editor );
ViewListItem *i = m_viewlist->addView( cat, tag, name, editor, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "DependencyEditor" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
editor->draw( getProject() );
connect( editor, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( editor, &DependencyEditor::addRelation, this, &View::slotAddRelation);
connect( editor, &DependencyEditor::modifyRelation, this, &View::slotModifyRelation);
connect( editor, &DependencyEditor::editRelation, this, &View::slotEditRelation);
connect( editor, &DependencyEditor::editNode, this, &View::slotOpenNode);
connect( editor, &DependencyEditor::addTask, this, &View::slotAddTask );
connect( editor, &DependencyEditor::addMilestone, this, &View::slotAddMilestone );
connect( editor, &DependencyEditor::addSubMilestone, this, &View::slotAddSubMilestone );
connect( editor, &DependencyEditor::addSubtask, this, &View::slotAddSubTask );
connect( editor, &DependencyEditor::deleteTaskList, this, &View::slotDeleteTaskList);
connect( this, &View::currentScheduleManagerChanged, editor, &DependencyEditor::setScheduleManager);
connect( editor, &DependencyEditor::requestPopupMenu, this, &View::slotPopupMenuRequested);
editor->updateReadWrite( m_readWrite );
editor->setScheduleManager( currentScheduleManager() );
return editor;
}
ViewBase *View::createPertEditor( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
PertEditor *perteditor = new PertEditor(getKoPart(), getPart(), m_tab );
m_tab->addWidget( perteditor );
ViewListItem *i = m_viewlist->addView( cat, tag, name, perteditor, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "PertEditor" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
perteditor->draw( getProject() );
connect( perteditor, &ViewBase::guiActivated, this, &View::slotGuiActivated );
m_updatePertEditor = true;
perteditor->updateReadWrite( m_readWrite );
return perteditor;
}
ViewBase *View::createProjectStatusView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
ProjectStatusView *v = new ProjectStatusView(getKoPart(), getPart(), m_tab );
m_tab->addWidget( v );
ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "ProjectStatusView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( this, &View::currentScheduleManagerChanged, v, &ProjectStatusView::setScheduleManager);
v->updateReadWrite( m_readWrite );
v->setProject( &getProject() );
v->setScheduleManager( currentScheduleManager() );
return v;
}
ViewBase *View::createPerformanceStatusView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
PerformanceStatusView *v = new PerformanceStatusView(getKoPart(), getPart(), m_tab );
m_tab->addWidget( v );
ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "PerformanceStatusView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( this, &View::currentScheduleManagerChanged, v, &PerformanceStatusView::setScheduleManager);
connect( v, &PerformanceStatusView::requestPopupMenu, this, &View::slotPopupMenuRequested);
v->updateReadWrite( m_readWrite );
v->setProject( &getProject() );
v->setScheduleManager( currentScheduleManager() );
return v;
}
ViewBase *View::createTaskStatusView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
TaskStatusView *taskstatusview = new TaskStatusView(getKoPart(), getPart(), m_tab );
taskstatusview->setViewSplitMode(false);
m_tab->addWidget( taskstatusview );
ViewListItem *i = m_viewlist->addView( cat, tag, name, taskstatusview, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "TaskStatusView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
connect( taskstatusview, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( this, &View::currentScheduleManagerChanged, taskstatusview, &TaskStatusView::setScheduleManager);
connect( taskstatusview, &TaskStatusView::requestPopupMenu, this, &View::slotPopupMenuRequested);
taskstatusview->updateReadWrite( m_readWrite );
taskstatusview->draw( getProject() );
taskstatusview->setScheduleManager( currentScheduleManager() );
return taskstatusview;
}
ViewBase *View::createTaskView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
TaskView *v = new TaskView(getKoPart(), getPart(), m_tab );
v->setViewSplitMode(false);
m_tab->addWidget( v );
ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "TaskView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
v->draw( getProject() );
v->setScheduleManager( currentScheduleManager() );
connect( this, &View::currentScheduleManagerChanged, v, &TaskView::setScheduleManager);
connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( v, &TaskView::requestPopupMenu, this, &View::slotPopupMenuRequested);
v->updateReadWrite( m_readWrite );
return v;
}
ViewBase *View::createTaskWorkPackageView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
TaskWorkPackageView *v = new TaskWorkPackageView(getKoPart(), getPart(), m_tab );
v->setViewSplitMode(false);
m_tab->addWidget( v );
ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "TaskWorkPackageView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
v->setProject( &getProject() );
v->setScheduleManager( currentScheduleManager() );
connect( this, &View::currentScheduleManagerChanged, v, &TaskWorkPackageView::setScheduleManager);
connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( v, &TaskWorkPackageView::requestPopupMenu, this, &View::slotPopupMenuRequested);
connect( v, &TaskWorkPackageView::mailWorkpackage, this, &View::slotMailWorkpackage );
- connect( v, &TaskWorkPackageView::mailWorkpackages, this, &View::slotMailWorkpackages );
-
+ connect( v, &TaskWorkPackageView::publishWorkpackages, this, &View::slotPublishWorkpackages );
+ connect(v, &TaskWorkPackageView::openWorkpackages, this, &View::openWorkPackageMergeDialog);
+ connect(this, &View::workPackagesAvailable, v, &TaskWorkPackageView::slotWorkpackagesAvailable);
connect(v, &TaskWorkPackageView::checkForWorkPackages, getPart(), &MainDocument::checkForWorkPackages);
+ connect(v, &TaskWorkPackageView::loadWorkPackageUrl, this, &View::loadWorkPackage);
v->updateReadWrite( m_readWrite );
return v;
}
ViewBase *View::createGanttView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
GanttView *ganttview = new GanttView(getKoPart(), getPart(), m_tab, koDocument()->isReadWrite() );
m_tab->addWidget( ganttview );
ViewListItem *i = m_viewlist->addView( cat, tag, name, ganttview, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "GanttView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
ganttview->setProject( &( getProject() ) );
ganttview->setScheduleManager( currentScheduleManager() );
connect( ganttview, &ViewBase::guiActivated, this, &View::slotGuiActivated );
/* TODO: Review these
connect( ganttview, SIGNAL(addRelation(KPlato::Node*,KPlato::Node*,int)), SLOT(slotAddRelation(KPlato::Node*,KPlato::Node*,int)) );
connect( ganttview, SIGNAL(modifyRelation(KPlato::Relation*,int)), SLOT(slotModifyRelation(KPlato::Relation*,int)) );
connect( ganttview, SIGNAL(modifyRelation(KPlato::Relation*)), SLOT(slotModifyRelation(KPlato::Relation*)) );
connect( ganttview, SIGNAL(itemDoubleClicked()), SLOT(slotOpenNode()) );
connect( ganttview, SIGNAL(itemRenamed(KPlato::Node*,QString)), this, SLOT(slotRenameNode(KPlato::Node*,QString)) );*/
connect( this, &View::currentScheduleManagerChanged, ganttview, &GanttView::setScheduleManager);
connect( ganttview, &GanttView::requestPopupMenu, this, &View::slotPopupMenuRequested);
ganttview->updateReadWrite( m_readWrite );
return ganttview;
}
ViewBase *View::createMilestoneGanttView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
MilestoneGanttView *ganttview = new MilestoneGanttView(getKoPart(), getPart(), m_tab, koDocument()->isReadWrite() );
m_tab->addWidget( ganttview );
ViewListItem *i = m_viewlist->addView( cat, tag, name, ganttview, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "MilestoneGanttView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
ganttview->setProject( &( getProject() ) );
ganttview->setScheduleManager( currentScheduleManager() );
connect( ganttview, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( this, &View::currentScheduleManagerChanged, ganttview, &MilestoneGanttView::setScheduleManager);
connect( ganttview, &MilestoneGanttView::requestPopupMenu, this, &View::slotPopupMenuRequested);
ganttview->updateReadWrite( m_readWrite );
return ganttview;
}
ViewBase *View::createAccountsView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
AccountsView *accountsview = new AccountsView(getKoPart(), &getProject(), getPart(), m_tab );
m_tab->addWidget( accountsview );
ViewListItem *i = m_viewlist->addView( cat, tag, name, accountsview, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "AccountsView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
accountsview->setScheduleManager( currentScheduleManager() );
connect( this, &View::currentScheduleManagerChanged, accountsview, &AccountsView::setScheduleManager);
connect( accountsview, &ViewBase::guiActivated, this, &View::slotGuiActivated );
accountsview->updateReadWrite( m_readWrite );
return accountsview;
}
ViewBase *View::createResourceAssignmentView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
ResourceAssignmentView *resourceAssignmentView = new ResourceAssignmentView(getKoPart(), getPart(), m_tab );
m_tab->addWidget( resourceAssignmentView );
m_updateResourceAssignmentView = true;
ViewListItem *i = m_viewlist->addView( cat, tag, name, resourceAssignmentView, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "ResourceAssignmentView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
resourceAssignmentView->draw( getProject() );
connect( resourceAssignmentView, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( resourceAssignmentView, &ResourceAssignmentView::requestPopupMenu, this, &View::slotPopupMenuRequested);
resourceAssignmentView->updateReadWrite( m_readWrite );
return resourceAssignmentView;
}
ViewBase *View::createReportsGeneratorView(ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index)
{
ReportsGeneratorView *v = new ReportsGeneratorView(getKoPart(), getPart(), m_tab );
m_tab->addWidget( v );
ViewListItem *i = m_viewlist->addView(cat, tag, name, v, getPart(), "", index);
ViewInfo vi = defaultViewInfo( "ReportsGeneratorView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
v->setProject( &getProject() );
connect( this, &View::currentScheduleManagerChanged, v, &ViewBase::setScheduleManager );
connect( this, &View::currentScheduleManagerChanged, v, &ViewBase::slotRefreshView);
v->setScheduleManager( currentScheduleManager() );
connect( v, &ViewBase::guiActivated, this, &View::slotGuiActivated );
connect( v, &ReportsGeneratorView::requestPopupMenu, this, &View::slotPopupMenuRequested);
v->updateReadWrite( m_readWrite );
return v;
}
ViewBase *View::createReportView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index )
{
#ifdef PLAN_USE_KREPORT
ReportView *v = new ReportView(getKoPart(), getPart(), m_tab );
m_tab->addWidget( v );
ViewListItem *i = m_viewlist->addView( cat, tag, name, v, getPart(), "", index );
ViewInfo vi = defaultViewInfo( "ReportView" );
if ( name.isEmpty() ) {
i->setText( 0, vi.name );
}
if ( tip == TIP_USE_DEFAULT_TEXT ) {
i->setToolTip( 0, vi.tip );
} else {
i->setToolTip( 0, tip );
}
v->setProject( &getProject() );
connect( this, &View::currentScheduleManagerChanged, v, &ReportView::setScheduleManager);
connect( this, &View::currentScheduleManagerChanged, v, SLOT(slotRefreshView()));
v->setScheduleManager( currentScheduleManager() );
connect( v, &ReportView::guiActivated, this, &View::slotGuiActivated);
v->updateReadWrite( m_readWrite );
return v;
#else
Q_UNUSED(cat)
Q_UNUSED(tag)
Q_UNUSED(name)
Q_UNUSED(tip)
Q_UNUSED(index)
return 0;
#endif
}
Project& View::getProject() const
{
return getPart() ->getProject();
}
KoPrintJob * View::createPrintJob()
{
KoView *v = qobject_cast( canvas() );
if ( v == 0 ) {
return 0;
}
return v->createPrintJob();
}
ViewBase *View::currentView() const
{
return qobject_cast( m_tab->currentWidget() );
}
void View::slotEditCut()
{
ViewBase *v = currentView();
if ( v ) {
v->slotEditCut();
}
}
void View::slotEditCopy()
{
ViewBase *v = currentView();
if ( v ) {
v->slotEditCopy();
}
}
void View::slotEditPaste()
{
ViewBase *v = currentView();
if ( v ) {
v->slotEditPaste();
}
}
void View::slotRefreshView()
{
ViewBase *v = currentView();
if ( v ) {
debugPlan<slotRefreshView();
}
}
void View::slotViewSelector( bool show )
{
//debugPlan;
m_viewlist->setVisible( show );
}
void View::slotInsertResourcesFile(const QString &file, const QUrl &projects)
{
getPart()->insertResourcesFile(QUrl(file), projects);
}
void View::slotInsertFile()
{
InsertFileDialog *dlg = new InsertFileDialog( getProject(), currentTask(), this );
connect(dlg, &QDialog::finished, this, &View::slotInsertFileFinished);
dlg->show();
dlg->raise();
dlg->activateWindow();
}
void View::slotInsertFileFinished( int result )
{
InsertFileDialog *dlg = qobject_cast( sender() );
if ( dlg == 0 ) {
return;
}
if ( result == QDialog::Accepted ) {
getPart()->insertFile( dlg->url(), dlg->parentNode(), dlg->afterNode() );
}
dlg->deleteLater();
}
void View::slotLoadSharedProjects()
{
LoadSharedProjectsDialog *dlg = new LoadSharedProjectsDialog( getProject(), getPart()->url(), this );
connect(dlg, &QDialog::finished, this, &View::slotLoadSharedProjectsFinished);
dlg->show();
dlg->raise();
dlg->activateWindow();
}
void View::slotLoadSharedProjectsFinished( int result )
{
LoadSharedProjectsDialog *dlg = qobject_cast( sender() );
if ( dlg == 0 ) {
return;
}
if ( result == QDialog::Accepted ) {
getPart()->insertSharedProjects(dlg->urls());
}
dlg->deleteLater();
}
void View::slotProjectEdit()
{
slotOpenNode( &getProject() );
}
void View::slotProjectWorktime()
{
StandardWorktimeDialog *dia = new StandardWorktimeDialog( getProject(), this );
connect(dia, &QDialog::finished, this, &View::slotProjectWorktimeFinished);
dia->show();
dia->raise();
dia->activateWindow();
}
void View::slotProjectWorktimeFinished( int result )
{
StandardWorktimeDialog *dia = qobject_cast( sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
KUndo2Command * cmd = dia->buildCommand();
if ( cmd ) {
//debugPlan<<"Modifying calendar(s)";
getPart() ->addCommand( cmd ); //also executes
}
}
dia->deleteLater();
}
void View::slotSelectionChanged( ScheduleManager *sm ) {
debugPlan<setChecked( true ); // this doesn't trigger QActionGroup
slotViewSchedule( a );
}
QList View::sortedActionList()
{
QMap lst;
const QMap map = m_scheduleActions; // clazy:exclude=qmap-with-pointer-key
QMap::const_iterator it;
for (it = map.constBegin(); it != map.constEnd(); ++it) {
lst.insert(it.key()->objectName(), it.key());
}
return lst.values();
}
void View::slotScheduleSwapped(ScheduleManager *from, ScheduleManager *to)
{
if (currentScheduleManager() == from) {
QAction *a = m_scheduleActions.key(to);
if (a) {
a->setChecked(true);
}
}
}
void View::slotScheduleRemoved( const ScheduleManager *sch )
{
debugPlan<name();
QAction *a = 0;
QAction *checked = m_scheduleActionGroup->checkedAction();
QMapIterator i( m_scheduleActions );
while (i.hasNext()) {
i.next();
if ( i.value() == sch ) {
a = i.key();
break;
}
}
if ( a ) {
unplugActionList( "view_schedule_list" );
delete a;
plugActionList( "view_schedule_list", sortedActionList() );
if ( checked && checked != a ) {
checked->setChecked( true );
} else if ( ! m_scheduleActions.isEmpty() ) {
m_scheduleActions.firstKey()->setChecked( true );
}
}
slotViewSchedule( m_scheduleActionGroup->checkedAction() );
}
void View::slotScheduleAdded( const ScheduleManager *sch )
{
ScheduleManager *s = const_cast( sch );
QAction *checked = m_scheduleActionGroup->checkedAction();
unplugActionList( "view_schedule_list" );
QAction *act = addScheduleAction( s );
plugActionList( "view_schedule_list", sortedActionList() );
if (!currentScheduleManager()) {
if ( act ) {
act->setChecked( true );
} else if ( ! m_scheduleActions.isEmpty() ) {
m_scheduleActions.firstKey()->setChecked( true );
}
slotViewSchedule( m_scheduleActionGroup->checkedAction() );
}
}
void View::slotScheduleCalculated(Project *project, ScheduleManager *manager)
{
Q_UNUSED(project);
if (manager == currentScheduleManager()) {
slotViewScheduleManager(manager);
}
}
QAction *View::addScheduleAction( ScheduleManager *sch )
{
QAction *act = 0;
QString n = sch->name();
act = new KToggleAction( n, this);
actionCollection()->addAction(n, act );
m_scheduleActions.insert( act, sch );
m_scheduleActionGroup->addAction( act );
//debugPlan<<"Add:"<name();
m_scheduleActions.remove( static_cast( o ) );
}
void View::slotPlugScheduleActions()
{
ScheduleManager *current = currentScheduleManager();
unplugActionList( "view_schedule_list" );
const QMap map = m_scheduleActions; // clazy:exclude=qmap-with-pointer-key
QMap::const_iterator it;
for (it = map.constBegin(); it != map.constEnd(); ++it) {
m_scheduleActionGroup->removeAction(it.key());
delete it.key();
}
m_scheduleActions.clear();
QAction *ca = 0;
foreach( ScheduleManager *sm, getProject().allScheduleManagers() ) {
QAction *act = addScheduleAction(sm);
if (sm == current) {
ca = act;
}
}
plugActionList( "view_schedule_list", sortedActionList() );
if ( ca == 0 && m_scheduleActionGroup->actions().count() > 0 ) {
ca = m_scheduleActionGroup->actions().constFirst();
}
if ( ca ) {
ca->setChecked( true );
}
slotViewSchedule( ca );
}
void View::slotCalculateSchedule( Project *project, ScheduleManager *sm )
{
if ( project == 0 || sm == 0 ) {
return;
}
if ( sm->parentManager() && ! sm->parentManager()->isScheduled() ) {
// the parent must be scheduled
return;
}
CalculateScheduleCmd *cmd = new CalculateScheduleCmd( *project, sm, kundo2_i18nc("@info:status 1=schedule name", "Calculate %1", sm->name() ) );
getPart() ->addCommand( cmd );
slotUpdate();
}
void View::slotRemoveCommands()
{
while ( ! m_undocommands.isEmpty() ) {
m_undocommands.last()->undo();
delete m_undocommands.takeLast();
}
}
void View::slotBaselineSchedule( Project *project, ScheduleManager *sm )
{
if ( project == 0 || sm == 0 ) {
return;
}
if ( ! sm->isBaselined() && project->isBaselined() ) {
KMessageBox::sorry( this, i18n( "Cannot baseline. The project is already baselined." ) );
return;
}
KUndo2Command *cmd;
if ( sm->isBaselined() ) {
KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel( this, i18n( "This schedule is baselined. Do you want to remove the baseline?" ) );
if ( res == KMessageBox::Cancel ) {
return;
}
cmd = new ResetBaselineScheduleCmd( *sm, kundo2_i18n( "Reset baseline %1", sm->name() ) );
} else {
cmd = new BaselineScheduleCmd( *sm, kundo2_i18n( "Baseline %1", sm->name() ) );
}
getPart() ->addCommand( cmd );
}
void View::slotAddScheduleManager( Project *project )
{
if ( project == 0 ) {
return;
}
ScheduleManager *sm = project->createScheduleManager();
AddScheduleManagerCmd *cmd = new AddScheduleManagerCmd( *project, sm, -1, kundo2_i18n( "Add schedule %1", sm->name() ) );
getPart() ->addCommand( cmd );
}
void View::slotDeleteScheduleManager( Project *project, ScheduleManager *sm )
{
if ( project == 0 || sm == 0) {
return;
}
DeleteScheduleManagerCmd *cmd = new DeleteScheduleManagerCmd( *project, sm, kundo2_i18n( "Delete schedule %1", sm->name() ) );
getPart() ->addCommand( cmd );
}
void View::slotMoveScheduleManager( ScheduleManager *sm, ScheduleManager *parent, int index )
{
if ( sm == 0 ) {
return;
}
MoveScheduleManagerCmd *cmd = new MoveScheduleManagerCmd( sm, parent, index, kundo2_i18n( "Move schedule %1", sm->name() ) );
getPart() ->addCommand( cmd );
}
void View::slotAddSubTask()
{
Task * node = getProject().createTask( getPart() ->config().taskDefaults() );
SubTaskAddDialog *dia = new SubTaskAddDialog( getProject(), *node, currentNode(), getProject().accounts(), this );
connect(dia, &QDialog::finished, this, &View::slotAddSubTaskFinished);
dia->show();
dia->raise();
dia->activateWindow();
}
void View::slotAddSubTaskFinished( int result )
{
SubTaskAddDialog *dia = qobject_cast( sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
KUndo2Command *m = dia->buildCommand();
getPart() ->addCommand( m ); // add task to project
}
dia->deleteLater();
}
void View::slotAddTask()
{
Task * node = getProject().createTask( getPart() ->config().taskDefaults() );
TaskAddDialog *dia = new TaskAddDialog( getProject(), *node, currentNode(), getProject().accounts(), this );
connect(dia, &QDialog::finished, this, &View::slotAddTaskFinished);
dia->show();
dia->raise();
dia->activateWindow();
}
void View::slotAddTaskFinished( int result )
{
TaskAddDialog *dia = qobject_cast( sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
KUndo2Command *m = dia->buildCommand();
getPart() ->addCommand( m ); // add task to project
}
dia->deleteLater();
}
void View::slotAddMilestone()
{
Task * node = getProject().createTask();
node->estimate() ->clear();
TaskAddDialog *dia = new TaskAddDialog( getProject(), *node, currentNode(), getProject().accounts(), this );
connect(dia, &QDialog::finished, this, &View::slotAddMilestoneFinished);
dia->show();
dia->raise();
dia->activateWindow();
}
void View::slotAddMilestoneFinished( int result )
{
TaskAddDialog *dia = qobject_cast( sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
MacroCommand *c = new MacroCommand( kundo2_i18n( "Add milestone" ) );
c->addCommand( dia->buildCommand() );
getPart() ->addCommand( c ); // add task to project
}
dia->deleteLater();
}
void View::slotAddSubMilestone()
{
Task * node = getProject().createTask();
node->estimate() ->clear();
SubTaskAddDialog *dia = new SubTaskAddDialog( getProject(), *node, currentNode(), getProject().accounts(), this );
connect(dia, &QDialog::finished, this, &View::slotAddSubMilestoneFinished);
dia->show();
dia->raise();
dia->activateWindow();
}
void View::slotAddSubMilestoneFinished( int result )
{
SubTaskAddDialog *dia = qobject_cast( sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
MacroCommand *c = new MacroCommand( kundo2_i18n( "Add sub-milestone" ) );
c->addCommand( dia->buildCommand() );
getPart() ->addCommand( c ); // add task to project
}
dia->deleteLater();
}
void View::slotDefineWBS()
{
//debugPlan;
Project &p = getProject();
WBSDefinitionDialog *dia = new WBSDefinitionDialog( p, p.wbsDefinition(), this );
connect(dia, &QDialog::finished, this, &View::slotDefineWBSFinished);
dia->show();
dia->raise();
dia->activateWindow();
}
void View::slotDefineWBSFinished( int result )
{
//debugPlan;
WBSDefinitionDialog *dia = qobject_cast( sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted ) {
KUndo2Command *cmd = dia->buildCommand();
if ( cmd ) {
getPart()->addCommand( cmd );
}
}
dia->deleteLater();
}
void View::slotConfigure()
{
//debugPlan;
if( KConfigDialog::showDialog("Plan Settings") ) {
return;
}
ConfigDialog *dialog = new ConfigDialog( this, "Plan Settings", KPlatoSettings::self() );
dialog->addPage(new ConfigProjectPanel(), i18n("Project Defaults"), koIconName("calligraplan") );
dialog->addPage(new ConfigWorkVacationPanel(), i18n("Work & Vacation"), koIconName("view-calendar") );
dialog->addPage(new TaskDefaultPanel(), i18n("Task Defaults"), koIconName("view-task") );
dialog->addPage(new ColorsConfigPanel(), i18n("Task Colors"), koIconName("fill-color") );
dialog->addPage(new WorkPackageConfigPanel(), i18n("Work Package"), koIconName("calligraplanwork") );
dialog->show();
}
void View::slotIntroduction()
{
m_tab->setCurrentIndex(0);
}
Calendar *View::currentCalendar()
{
ViewBase *v = dynamic_cast( m_tab->currentWidget() );
if ( v == 0 ) {
return 0;
}
return v->currentCalendar();
}
Node *View::currentNode() const
{
ViewBase *v = dynamic_cast( m_tab->currentWidget() );
if ( v == 0 ) {
return 0;
}
Node * task = v->currentNode();
if ( 0 != task ) {
return task;
}
return &( getProject() );
}
Task *View::currentTask() const
{
ViewBase *v = dynamic_cast( m_tab->currentWidget() );
if ( v == 0 ) {
return 0;
}
Node * task = v->currentNode();
if ( task ) {
return dynamic_cast( task );
}
return 0;
}
Resource *View::currentResource()
{
ViewBase *v = dynamic_cast( m_tab->currentWidget() );
if ( v == 0 ) {
return 0;
}
return v->currentResource();
}
ResourceGroup *View::currentResourceGroup()
{
ViewBase *v = dynamic_cast( m_tab->currentWidget() );
if ( v == 0 ) {
return 0;
}
return v->currentResourceGroup();
}
void View::slotOpenCurrentNode()
{
//debugPlan;
Node * node = currentNode();
slotOpenNode( node );
}
void View::slotOpenNode( Node *node )
{
//debugPlan;
if ( !node )
return ;
switch ( node->type() ) {
case Node::Type_Project: {
Project * project = static_cast( node );
MainProjectDialog *dia = new MainProjectDialog( *project, this );
connect(dia, &MainProjectDialog::dialogFinished, this, &View::slotProjectEditFinished);
connect(dia, &MainProjectDialog::sigLoadSharedResources, this, &View::slotInsertResourcesFile);
connect(dia, &MainProjectDialog::loadResourceAssignments, getPart(), &MainDocument::loadResourceAssignments);
connect(dia, &MainProjectDialog::clearResourceAssignments, getPart(), &MainDocument::clearResourceAssignments);
dia->show();
dia->raise();
dia->activateWindow();
break;
}
case Node::Type_Subproject:
//TODO
break;
case Node::Type_Task: {
Task *task = static_cast( node );
TaskDialog *dia = new TaskDialog( getProject(), *task, getProject().accounts(), this );
connect(dia, &QDialog::finished, this, &View::slotTaskEditFinished);
dia->show();
dia->raise();
dia->activateWindow();
break;
}
case Node::Type_Milestone: {
// Use the normal task dialog for now.
// Maybe milestone should have it's own dialog, but we need to be able to
// enter a duration in case we accidentally set a tasks duration to zero
// and hence, create a milestone
Task *task = static_cast( node );
TaskDialog *dia = new TaskDialog( getProject(), *task, getProject().accounts(), this );
connect(dia, &QDialog::finished, this, &View::slotTaskEditFinished);
dia->show();
dia->raise();
dia->activateWindow();
break;
}
case Node::Type_Summarytask: {
Task *task = dynamic_cast( node );
Q_ASSERT( task );
SummaryTaskDialog *dia = new SummaryTaskDialog( *task, this );
connect(dia, &QDialog::finished, this, &View::slotSummaryTaskEditFinished);
dia->show();
dia->raise();
dia->activateWindow();
break;
}
default:
break; // avoid warnings
}
}
void View::slotProjectEditFinished( int result )
{
MainProjectDialog *dia = qobject_cast( sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
KUndo2Command * cmd = dia->buildCommand();
if ( cmd ) {
getPart() ->addCommand( cmd );
}
}
dia->deleteLater();
}
void View::slotTaskEditFinished( int result )
{
TaskDialog *dia = qobject_cast( sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
KUndo2Command * cmd = dia->buildCommand();
if ( cmd ) {
getPart() ->addCommand( cmd );
}
}
dia->deleteLater();
}
void View::slotSummaryTaskEditFinished( int result )
{
SummaryTaskDialog *dia = qobject_cast( sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
KUndo2Command * cmd = dia->buildCommand();
if ( cmd ) {
getPart() ->addCommand( cmd );
}
}
dia->deleteLater();
}
ScheduleManager *View::currentScheduleManager() const
{
return m_scheduleActions.value( m_scheduleActionGroup->checkedAction() );
}
long View::activeScheduleId() const
{
ScheduleManager *s = m_scheduleActions.value( m_scheduleActionGroup->checkedAction() );
return s == nullptr || s->expected() == nullptr ? -1 : s->expected()->id();
}
void View::setActiveSchedule( long id )
{
if ( id != -1 ) {
QMap::const_iterator it = m_scheduleActions.constBegin();
for (; it != m_scheduleActions.constEnd(); ++it ) {
int mid = it.value()->expected() == nullptr ? -1 : it.value()->expected()->id();
if (mid == id) {
it.key()->setChecked( true );
slotViewSchedule( it.key() ); // signal not emitted from group, so trigger it here
break;
}
}
}
}
void View::slotTaskProgress()
{
//debugPlan;
Node * node = currentNode();
if ( !node )
return ;
switch ( node->type() ) {
case Node::Type_Project: {
break;
}
case Node::Type_Subproject:
//TODO
break;
case Node::Type_Task: {
Task *task = dynamic_cast( node );
Q_ASSERT( task );
TaskProgressDialog *dia = new TaskProgressDialog( *task, currentScheduleManager(), getProject().standardWorktime(), this );
connect(dia, &QDialog::finished, this, &View::slotTaskProgressFinished);
dia->show();
dia->raise();
dia->activateWindow();
break;
}
case Node::Type_Milestone: {
Task *task = dynamic_cast( node );
Q_ASSERT( task );
MilestoneProgressDialog *dia = new MilestoneProgressDialog( *task, this );
connect(dia, &QDialog::finished, this, &View::slotMilestoneProgressFinished);
dia->show();
dia->raise();
dia->activateWindow();
break;
}
case Node::Type_Summarytask: {
// TODO
break;
}
default:
break; // avoid warnings
}
}
void View::slotTaskProgressFinished( int result )
{
TaskProgressDialog *dia = qobject_cast(sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
KUndo2Command * m = dia->buildCommand();
if ( m ) {
getPart() ->addCommand( m );
}
}
dia->deleteLater();
}
void View::slotMilestoneProgressFinished( int result )
{
MilestoneProgressDialog *dia = qobject_cast(sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
KUndo2Command * m = dia->buildCommand();
if ( m ) {
getPart() ->addCommand( m );
}
}
dia->deleteLater();
}
void View::slotTaskDescription()
{
//debugPlan;
Node * node = currentNode();
if ( !node )
return ;
switch ( node->type() ) {
case Node::Type_Subproject:
//TODO
break;
case Node::Type_Project:
case Node::Type_Task:
case Node::Type_Milestone:
case Node::Type_Summarytask: {
TaskDescriptionDialog *dia = new TaskDescriptionDialog( *node, this );
connect(dia, &QDialog::finished, this, &View::slotTaskDescriptionFinished);
dia->show();
dia->raise();
dia->activateWindow();
break;
}
default:
break; // avoid warnings
}
}
void View::slotTaskDescriptionFinished( int result )
{
TaskDescriptionDialog *dia = qobject_cast(sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
KUndo2Command * m = dia->buildCommand();
if ( m ) {
getPart() ->addCommand( m );
}
}
dia->deleteLater();
}
void View::slotDocuments()
{
//debugPlan;
Node * node = currentNode();
if ( !node ) {
return ;
}
switch ( node->type() ) {
case Node::Type_Subproject:
//TODO
break;
case Node::Type_Project:
case Node::Type_Summarytask:
case Node::Type_Task:
case Node::Type_Milestone: {
DocumentsDialog *dia = new DocumentsDialog(*node, this);
connect(dia, &QDialog::finished, this, &View::slotDocumentsFinished);
dia->show();
dia->raise();
dia->activateWindow();
break;
}
default:
break; // avoid warnings
}
}
void View::slotDocumentsFinished( int result )
{
DocumentsDialog *dia = qobject_cast(sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
KUndo2Command * m = dia->buildCommand();
if ( m ) {
getPart()->addCommand( m );
}
}
dia->deleteLater();
}
void View::slotDeleteTaskList( QList lst )
{
//debugPlan;
foreach ( Node *n, lst ) {
if ( n->isScheduled() ) {
KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel( this, i18n( "A task that has been scheduled will be deleted. This will invalidate the schedule." ) );
if ( res == KMessageBox::Cancel ) {
return;
}
break;
}
}
if ( lst.count() == 1 ) {
getPart()->addCommand( new NodeDeleteCmd( lst.takeFirst(), kundo2_i18n( "Delete task" ) ) );
return;
}
int num = 0;
MacroCommand *cmd = new MacroCommand( kundo2_i18np( "Delete task", "Delete tasks", lst.count() ) );
while ( !lst.isEmpty() ) {
Node *node = lst.takeFirst();
if ( node == 0 || node->parentNode() == 0 ) {
debugPlan << ( node ?"Task is main project" :"No current task" );
continue;
}
bool del = true;
foreach ( Node *n, lst ) {
if ( node->isChildOf( n ) ) {
del = false; // node is going to be deleted when we delete n
break;
}
}
if ( del ) {
//debugPlan<name();
cmd->addCommand( new NodeDeleteCmd( node, kundo2_i18n( "Delete task" ) ) );
num++;
}
}
if ( num > 0 ) {
getPart()->addCommand( cmd );
} else {
delete cmd;
}
}
void View::slotDeleteTask( Node *node )
{
//debugPlan;
if ( node == 0 || node->parentNode() == 0 ) {
debugPlan << ( node ?"Task is main project" :"No current task" );
return ;
}
if ( node->isScheduled() ) {
KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel( this, i18n( "This task has been scheduled. This will invalidate the schedule." ) );
if ( res == KMessageBox::Cancel ) {
return;
}
}
NodeDeleteCmd *cmd = new NodeDeleteCmd( node, kundo2_i18n( "Delete task" ) );
getPart() ->addCommand( cmd );
}
void View::slotDeleteCurrentTask()
{
//debugPlan;
return slotDeleteTask( currentNode() );
}
void View::slotIndentTask()
{
//debugPlan;
Node * node = currentNode();
if ( node == 0 || node->parentNode() == 0 ) {
debugPlan << ( node ?"Task is main project" :"No current task" );
return ;
}
if ( getProject().canIndentTask( node ) ) {
NodeIndentCmd * cmd = new NodeIndentCmd( *node, kundo2_i18n( "Indent task" ) );
getPart() ->addCommand( cmd );
}
}
void View::slotUnindentTask()
{
//debugPlan;
Node * node = currentNode();
if ( node == 0 || node->parentNode() == 0 ) {
debugPlan << ( node ?"Task is main project" :"No current task" );
return ;
}
if ( getProject().canUnindentTask( node ) ) {
NodeUnindentCmd * cmd = new NodeUnindentCmd( *node, kundo2_i18n( "Unindent task" ) );
getPart() ->addCommand( cmd );
}
}
void View::slotMoveTaskUp()
{
//debugPlan;
Node * task = currentNode();
if ( 0 == task ) {
// is always != 0. At least we would get the Project, but you never know who might change that
// so better be careful
errorPlan << "No current task" << endl;
return ;
}
if ( Node::Type_Project == task->type() ) {
debugPlan <<"The root node cannot be moved up";
return ;
}
if ( getProject().canMoveTaskUp( task ) ) {
NodeMoveUpCmd * cmd = new NodeMoveUpCmd( *task, kundo2_i18n( "Move task up" ) );
getPart() ->addCommand( cmd );
}
}
void View::slotMoveTaskDown()
{
//debugPlan;
Node * task = currentNode();
if ( 0 == task ) {
// is always != 0. At least we would get the Project, but you never know who might change that
// so better be careful
return ;
}
if ( Node::Type_Project == task->type() ) {
debugPlan <<"The root node cannot be moved down";
return ;
}
if ( getProject().canMoveTaskDown( task ) ) {
NodeMoveDownCmd * cmd = new NodeMoveDownCmd( *task, kundo2_i18n( "Move task down" ) );
getPart() ->addCommand( cmd );
}
}
void View::openRelationDialog( Node *par, Node *child )
{
//debugPlan;
Relation * rel = new Relation( par, child );
AddRelationDialog *dia = new AddRelationDialog( getProject(), rel, this );
connect(dia, &QDialog::finished, this, &View::slotAddRelationFinished);
dia->show();
dia->raise();
dia->activateWindow();
}
void View::slotAddRelationFinished( int result )
{
AddRelationDialog *dia = qobject_cast(sender() );
if ( dia == 0 ) {
return;
}
if ( result == QDialog::Accepted) {
KUndo2Command * m = dia->buildCommand();
if ( m ) {
getPart() ->addCommand( m );
}
}
dia->deleteLater();
}
void View::slotAddRelation( Node *par, Node *child, int linkType )
{
//debugPlan;
if ( linkType == Relation::FinishStart ||
linkType == Relation::StartStart ||
linkType == Relation::FinishFinish ) {
Relation * rel = new Relation( par, child, static_cast( linkType ) );
getPart() ->addCommand( new AddRelationCmd( getProject(), rel, kundo2_i18n( "Add task dependency" ) ) );
} else {
openRelationDialog( par, child );
}
}
void View::slotEditRelation( Relation *rel )
{
//debugPlan;
ModifyRelationDialog *dia = new ModifyRelationDialog( getProject(), rel, this );
connect(dia, &QDialog::finished, this, &View::slotModifyRelationFinished);
dia->show();
dia->raise();
dia->activateWindow();
}
void View::slotModifyRelationFinished( int result )
{
ModifyRelationDialog *dia = qobject_cast( sender() );
if ( dia == 0 ) {
return ;
}
if ( result == QDialog::Accepted) {
KUndo2Command *cmd = dia->buildCommand();
if ( cmd ) {
getPart() ->addCommand( cmd );
}
}
dia->deleteLater();
}
void View::slotModifyRelation( Relation *rel, int linkType )
{
//debugPlan;
if ( linkType == Relation::FinishStart ||
linkType == Relation::StartStart ||
linkType == Relation::FinishFinish ) {
getPart() ->addCommand( new ModifyRelationTypeCmd( rel, static_cast( linkType ) ) );
} else {
slotEditRelation( rel );
}
}
void View::slotModifyCurrentRelation()
{
ViewBase *v = dynamic_cast( m_tab->currentWidget() );
if ( v == 0 ) {
return;
}
Relation *rel = v->currentRelation();
if ( rel ) {
slotEditRelation( rel );
}
}
void View::slotDeleteRelation()
{
ViewBase *v = dynamic_cast( m_tab->currentWidget() );
if ( v == 0 ) {
return;
}
Relation *rel = v->currentRelation();
if ( rel ) {
getPart()->addCommand( new DeleteRelationCmd( getProject(), rel, kundo2_i18n( "Delete task dependency" ) ) );
}
}
void View::slotEditCurrentResource()
{
//debugPlan;
slotEditResource( currentResource() );
}
void View::slotEditResource( Resource *resource )
{
if ( resource == 0 ) {
return ;
}
ResourceDialog *dia = new ResourceDialog( getProject(), resource, this );
connect(dia, &QDialog::finished, this, &View::slotEditResourceFinished);
dia->show();
dia->raise();
dia->activateWindow();
}
void View::slotEditResourceFinished( int result )
{
//debugPlan;
ResourceDialog *dia = qobject_cast( sender() );
if ( dia == 0 ) {
return ;
}
if ( result == QDialog::Accepted) {
KUndo2Command * cmd = dia->buildCommand();
if ( cmd )
getPart() ->addCommand( cmd );
}
dia->deleteLater();
}
void View::slotDeleteResource( Resource *resource )
{
getPart()->addCommand( new RemoveResourceCmd( resource->parentGroup(), resource, kundo2_i18n( "Delete resource" ) ) );
}
void View::slotDeleteResourceGroup( ResourceGroup *group )
{
getPart()->addCommand( new RemoveResourceGroupCmd( group->project(), group, kundo2_i18n( "Delete resourcegroup" ) ) );
}
void View::slotDeleteResourceObjects( QObjectList lst )
{
//debugPlan;
foreach ( QObject *o, lst ) {
Resource *r = qobject_cast( o );
if ( r && r->isScheduled() ) {
KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel( this, i18n( "A resource that has been scheduled will be deleted. This will invalidate the schedule." ) );
if ( res == KMessageBox::Cancel ) {
return;
}
break;
}
ResourceGroup *g = qobject_cast( o );
if ( g && g->isScheduled() ) {
KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel( this, i18n( "A resource that has been scheduled will be deleted. This will invalidate the schedule." ) );
if ( res == KMessageBox::Cancel ) {
return;
}
break;
}
}
if ( lst.count() == 1 ) {
Resource *r = qobject_cast( lst.first() );
if ( r ) {
slotDeleteResource( r );
} else {
ResourceGroup *g = qobject_cast( lst.first() );
if ( g ) {
slotDeleteResourceGroup( g );
}
}
return;
}
// int num = 0;
MacroCommand *cmd = 0, *rc = 0, *gc = 0;
foreach ( QObject *o, lst ) {
Resource *r = qobject_cast( o );
if ( r ) {
if ( rc == 0 ) rc = new MacroCommand( KUndo2MagicString() );
rc->addCommand( new RemoveResourceCmd( r->parentGroup(), r ) );
continue;
}
ResourceGroup *g = qobject_cast( o );
if ( g ) {
if ( gc == 0 ) gc = new MacroCommand( KUndo2MagicString() );
gc->addCommand( new RemoveResourceGroupCmd( g->project(), g ) );
}
}
if ( rc || gc ) {
KUndo2MagicString s;
if ( rc && gc ) {
s = kundo2_i18n( "Delete resourcegroups and resources" );
} else if ( rc ) {
s = kundo2_i18np( "Delete resource", "Delete resources", lst.count() );
} else {
s = kundo2_i18np( "Delete resourcegroup", "Delete resourcegroups", lst.count() );
}
cmd = new MacroCommand( s );
}
if ( rc )
cmd->addCommand( rc );
if ( gc )
cmd->addCommand( gc );
if ( cmd )
getPart()->addCommand( cmd );
}
void View::updateReadWrite( bool readwrite )
{
m_readWrite = readwrite;
m_viewlist->setReadWrite( readwrite );
}
MainDocument *View::getPart() const
{
return ( MainDocument * ) koDocument();
}
KoPart *View::getKoPart() const
{
return m_partpart;
}
void View::slotConnectNode()
{
//debugPlan;
/* NodeItem *curr = ganttview->currentItem();
if (curr) {
debugPlan<<"node="<getNode().name();
}*/
}
QMenu * View::popupMenu( const QString& name )
{
//debugPlan;
if ( factory() ) {
return ( ( QMenu* ) factory() ->container( name, this ) );
}
debugPlan<<"No factory";
return 0L;
}
void View::slotUpdate()
{
//debugPlan<<"calculate="<currentWidget() );
}
void View::slotGuiActivated( ViewBase *view, bool activate )
{
//FIXME: Avoid unplug if possible, it flashes the gui
// always unplug, in case they already are plugged
foreach( const QString &name, view->actionListNames() ) {
unplugActionList( name );
}
if ( activate ) {
foreach( const QString &name, view->actionListNames() ) {
plugActionList( name, view->actionList( name ) );
}
foreach ( DockWidget *ds, view->dockers() ) {
m_dockers.append( ds );
ds->activate( mainWindow() );
}
if (!m_dockers.isEmpty()) {debugPlan<<"Added dockers:"<deactivate( mainWindow() );
}
}
}
void View::guiActivateEvent( bool activated )
{
if ( activated ) {
// plug my own actionlists, they may be gone
slotPlugScheduleActions();
}
// propagate to sub-view
ViewBase *v = dynamic_cast( m_tab->currentWidget() );
if ( v ) {
v->setGuiActive( activated );
}
}
void View::slotViewListItemRemoved( ViewListItem *item )
{
getPart()->removeViewListItem( this, item );
}
void View::removeViewListItem( const ViewListItem *item )
{
if ( item == 0 ) {
return;
}
ViewListItem *itm = m_viewlist->findItem( item->tag() );
if ( itm == 0 ) {
return;
}
m_viewlist->removeViewListItem( itm );
return;
}
void View::slotViewListItemInserted( ViewListItem *item, ViewListItem *parent, int index )
{
getPart()->insertViewListItem( this, item, parent, index );
}
void View::addViewListItem( const ViewListItem *item, const ViewListItem *parent, int index )
{
if ( item == 0 ) {
return;
}
if ( parent == 0 ) {
if ( item->type() != ViewListItem::ItemType_Category ) {
return;
}
m_viewlist->blockSignals( true );
ViewListItem *cat = m_viewlist->addCategory( item->tag(), item->text( 0 ) );
cat->setToolTip( 0, item->toolTip( 0 ) );
m_viewlist->blockSignals( false );
return;
}
ViewListItem *cat = m_viewlist->findCategory( parent->tag() );
if ( cat == 0 ) {
return;
}
m_viewlist->blockSignals( true );
createView( cat, item->viewType(), item->tag(), item->text( 0 ), item->toolTip( 0 ), index );
m_viewlist->blockSignals( false );
}
void View::createReportView(const QDomDocument &doc)
{
#ifdef PLAN_USE_KREPORT
QPointer