diff --git a/src/kptbuiltinschedulerplugin.cpp b/src/kptbuiltinschedulerplugin.cpp index 928b98a0..32db9e39 100644 --- a/src/kptbuiltinschedulerplugin.cpp +++ b/src/kptbuiltinschedulerplugin.cpp @@ -1,177 +1,177 @@ /* This file is part of the KDE project Copyright (C) 2009 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. */ #include "kptbuiltinschedulerplugin.h" #include "kptproject.h" #include "kptschedule.h" #include "kptxmlloaderobject.h" #include namespace KPlato { BuiltinSchedulerPlugin::BuiltinSchedulerPlugin(QObject *parent) : SchedulerPlugin(parent) { setName( i18nc( "Network = task dependency network", "Network Scheduler" ) ); setComment( xi18nc( "@info:tooltip", "Built-in network (PERT) based scheduler" ) ); } BuiltinSchedulerPlugin::~BuiltinSchedulerPlugin() { } QString BuiltinSchedulerPlugin::description() const { return xi18nc( "@info:whatsthis", "Network (PERT) Scheduler" "The network scheduler generally schedules tasks according to their dependencies." " When a task is scheduled it is scheduled in full, booking the allocated resources if available." " If overbooking is not allowed, subsequent tasks that requests the same resource" " will be scheduled later in time." "Tasks with time constraints will be scheduled first to minimize the problem" " with resource conflicts" "This scheduler does not handle resource conflicts well." "You can try a different scheduler if available." " You may also change resource allocations or add dummy dependencies to avoid the conflicts." ); } void BuiltinSchedulerPlugin::calculate( Project &project, ScheduleManager *sm, bool nothread ) { KPlatoScheduler *job = new KPlatoScheduler( &project, sm ); m_jobs << job; - connect(job, SIGNAL(jobStarted(SchedulerThread*)), SLOT(slotStarted(SchedulerThread*))); - connect(job, SIGNAL(jobFinished(SchedulerThread*)), SLOT(slotFinished(SchedulerThread*))); + connect(job, SIGNAL(jobStarted(KPlato::SchedulerThread*)), SLOT(slotStarted(KPlato::SchedulerThread*))); + connect(job, SIGNAL(jobFinished(KPlato::SchedulerThread*)), SLOT(slotFinished(KPlato::SchedulerThread*))); -// connect(this, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*)), &project, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*))); -// connect(this, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*)), &project, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*))); +// connect(this, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*)), &project, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*))); +// connect(this, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*)), &project, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*))); sm->setScheduling( true ); if ( nothread ) { connect(job, SIGNAL(maxProgressChanged(int)), sm, SLOT(setMaxProgress(int))); connect(job, SIGNAL(progressChanged(int)), sm, SLOT(setProgress(int))); job->doRun(); } else { job->start(); } m_synctimer.start(); } void BuiltinSchedulerPlugin::slotStarted( SchedulerThread *job ) { qDebug()<<"BuiltinSchedulerPlugin::slotStarted:"<mainProject()<mainManager(); emit sigCalculationStarted( job->mainProject(), job->mainManager() ); } void BuiltinSchedulerPlugin::slotFinished( SchedulerThread *job ) { ScheduleManager *sm = job->mainManager(); Project *mp = job->mainProject(); qDebug()<<"BuiltinSchedulerPlugin::slotFinished:"<isStopped(); if ( job->isStopped() ) { sm->setCalculationResult( ScheduleManager::CalculationCanceled ); } else { updateLog( job ); Project *tp = static_cast( job )->project(); ScheduleManager *tm = static_cast( job )->manager(); updateProject( tp, tm, mp, sm ); sm->setCalculationResult( ScheduleManager::CalculationDone ); } sm->setScheduling( false ); m_jobs.removeAt( m_jobs.indexOf( job ) ); if ( m_jobs.isEmpty() ) { m_synctimer.stop(); } emit sigCalculationFinished( mp, sm ); - disconnect(this, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*)), mp, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*))); - disconnect(this, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*)), mp, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*))); + disconnect(this, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*)), mp, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*))); + disconnect(this, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*)), mp, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*))); job->deleteLater(); qDebug()<<"BuiltinSchedulerPlugin::slotFinished: <<<"; } //-------------------- KPlatoScheduler::KPlatoScheduler( Project *project, ScheduleManager *sm, QObject *parent ) : SchedulerThread( project, sm, parent) { qDebug()<<"KPlatoScheduler::KPlatoScheduler:"<name()<stopcalculation = true; } } void KPlatoScheduler::run() { if ( m_haltScheduling ) { deleteLater(); return; } if ( m_stopScheduling ) { return; } { // mutex --> m_projectMutex.lock(); m_managerMutex.lock(); m_project = new Project(); loadProject( m_project, m_pdoc ); m_project->setName( "Schedule: " + m_project->name() ); //Debug m_manager = m_project->scheduleManager( m_mainmanagerId ); Q_ASSERT( m_manager ); Q_ASSERT( m_manager->expected() ); Q_ASSERT( m_manager != m_mainmanager ); Q_ASSERT( m_manager->scheduleId() == m_mainmanager->scheduleId() ); Q_ASSERT( m_manager->expected() != m_mainmanager->expected() ); m_manager->setName( "Schedule: " + m_manager->name() ); //Debug m_managerMutex.unlock(); m_projectMutex.unlock(); } // <--- mutex connect(m_project, SIGNAL(maxProgress(int)), this, SLOT(setMaxProgress(int))); connect(m_project, SIGNAL(sigProgress(int)), this, SLOT(setProgress(int))); - bool x = connect(m_manager, SIGNAL(sigLogAdded(Schedule::Log)), this, SLOT(slotAddLog(Schedule::Log))); + bool x = connect(m_manager, SIGNAL(sigLogAdded(KPlato::Schedule::Log)), this, SLOT(slotAddLog(KPlato::Schedule::Log))); Q_ASSERT( x ); Q_UNUSED( x ); m_project->calculate( *m_manager ); if ( m_haltScheduling ) { deleteLater(); } } } //namespace KPlato diff --git a/src/kptbuiltinschedulerplugin.h b/src/kptbuiltinschedulerplugin.h index 57389631..b0939643 100644 --- a/src/kptbuiltinschedulerplugin.h +++ b/src/kptbuiltinschedulerplugin.h @@ -1,80 +1,80 @@ /* This file is part of the KDE project Copyright (C) 2009 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 KPTBUILTINSCHEDULERPLUGIN_H #define KPTBUILTINSCHEDULERPLUGIN_H #include "plan_export.h" #include "kptschedulerplugin.h" #include "kptschedule.h" namespace KPlato { class KPlatoScheduler; class Project; class ScheduleManager; class PLAN_EXPORT BuiltinSchedulerPlugin : public SchedulerPlugin { Q_OBJECT public: explicit BuiltinSchedulerPlugin(QObject *parent); virtual ~BuiltinSchedulerPlugin(); virtual QString description() const; /// Calculate the project virtual void calculate( Project &project, ScheduleManager *sm, bool nothread = false ); Q_SIGNALS: - void sigCalculationStarted( Project*, ScheduleManager* ); - void sigCalculationFinished( Project*, ScheduleManager* ); - void maxProgress( int, ScheduleManager* ); - void sigProgress( int, ScheduleManager* ); + void sigCalculationStarted(KPlato::Project*, KPlato::ScheduleManager*); + void sigCalculationFinished(KPlato::Project*, KPlato::ScheduleManager*); + void maxProgress(int, KPlato::ScheduleManager*); + void sigProgress(int, KPlato::ScheduleManager*); protected Q_SLOTS: - void slotStarted( SchedulerThread *job ); - void slotFinished( SchedulerThread *job ); + void slotStarted(KPlato::SchedulerThread *job); + void slotFinished(KPlato::SchedulerThread *job); }; class KPlatoScheduler : public SchedulerThread { Q_OBJECT public: KPlatoScheduler( Project *project, ScheduleManager *sm, QObject *parent = 0 ); ~KPlatoScheduler(); public Q_SLOTS: /// Stop scheduling. virtual void stopScheduling(); /// Halt scheduling virtual void haltScheduling() { m_haltScheduling = true; stopScheduling(); } protected: void run(); }; } //namespace KPlato #endif diff --git a/src/kptmaindocument.cpp b/src/kptmaindocument.cpp index 2953ca12..45c6781f 100644 --- a/src/kptmaindocument.cpp +++ b/src/kptmaindocument.cpp @@ -1,1579 +1,1579 @@ /* 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 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. */ #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 "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); QTimer::singleShot ( 5000, this, SLOT(autoCheckForWorkPackages()) ); } 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, SIGNAL(pluginLoaded(QString,SchedulerPlugin*)), this, SLOT(addSchedulerPlugin(QString,SchedulerPlugin*))); + connect(loader, SIGNAL(pluginLoaded(QString,KPlato::SchedulerPlugin*)), this, SLOT(addSchedulerPlugin(QString,KPlato::SchedulerPlugin*))); 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, SIGNAL(projectChanged()), this, SIGNAL(changed()) ); delete m_project; } m_project = project; if ( m_project ) { connect( m_project, SIGNAL(projectChanged()), this, SIGNAL(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); 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; QDomDocument document( "plan" ); document.appendChild( document.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) ); QDomElement doc = document.createElement( "plan" ); doc.setAttribute( "editor", "Plan" ); doc.setAttribute( "mime", "application/x-vnd.kde.plan" ); doc.setAttribute( "version", PLAN_FILE_SYNTAX_VERSION ); document.appendChild( doc ); // Save the project m_project->save( doc ); return document; } QDomDocument MainDocument::saveWorkPackageXML( const Node *node, long id, Resource *resource ) { debugPlan; QDomDocument document( "plan" ); document.appendChild( document.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) ); QDomElement doc = document.createElement( "planwork" ); doc.setAttribute( "editor", "Plan" ); doc.setAttribute( "mime", "application/x-vnd.kde.plan.work" ); doc.setAttribute( "version", PLANWORK_FILE_SYNTAX_VERSION ); doc.setAttribute( "plan-version", PLAN_FILE_SYNTAX_VERSION ); document.appendChild( doc ); // Work package info QDomElement wp = document.createElement( "workpackage" ); if ( resource ) { wp.setAttribute( "owner", resource->name() ); wp.setAttribute( "owner-id", resource->id() ); } wp.setAttribute( "time-tag", QDateTime::currentDateTime().toString( Qt::ISODate ) ); 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; 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"; delete store; return false; } node->documents().saveToStore( store ); debugPlan <<"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; 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 << " 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*/ ) { 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!"; setErrorMessage( i18n( "Invalid document. No mimetype specified." ) ); return 0; } else if ( value == "application/x-vnd.kde.kplato.work" ) { m_xmlLoader.setMimetype( value ); m_xmlLoader.setWorkVersion( plan.attribute( "version", "0.0.0" ) ); proj = new Project(); KPlatoXmlLoader loader( m_xmlLoader, proj ); ok = loader.loadWorkpackage( plan ); if ( ! ok ) { setErrorMessage( loader.errorMessage() ); delete proj; return 0; } package = loader.package(); package->timeTag = QDateTime::fromString( loader.timeTag(), Qt::ISODate ); } else if ( value != "application/x-vnd.kde.plan.work" ) { debugPlan << "Unknown mime type " << value; setErrorMessage( i18n( "Invalid document. Expected mimetype application/x-vnd.kde.plan.work, got %1", value ) ); return 0; } else { QString syntaxVersion = plan.attribute( "version", "0.0.0" ); m_xmlLoader.setWorkVersion( syntaxVersion ); if ( syntaxVersion > 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" ); //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(); } 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 ) { delete proj; delete package; return 0; } 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()<<"->"<numChildren() == 0 ) { return; } m_checkingForWorkPackages = true; if ( ! keep ) { qDeleteAll( m_mergedPackages ); m_mergedPackages.clear(); } QDir dir( m_config.retrieveUrl().path(), "*.planwork" ); m_infoList = dir.entryInfoList( QDir::Files | QDir::Readable, QDir::Time ); checkForWorkPackage(); return; } void MainDocument::checkForWorkPackage() { if ( ! m_infoList.isEmpty() ) { loadWorkPackage( *m_project, QUrl::fromLocalFile( m_infoList.takeLast().absoluteFilePath() ) ); if ( ! m_infoList.isEmpty() ) { QTimer::singleShot ( 0, this, SLOT(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, SIGNAL(finished(int)), SLOT(workPackageMergeDialogFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } } } void MainDocument::workPackageMergeDialogFinished( int result ) { WorkPackageMergeDialog *dlg = qobject_cast( sender() ); if ( dlg == 0 ) { return; } if ( result == KoDialog::Yes ) { // merge the oldest first foreach( int i, dlg->checkedList() ) { mergeWorkPackage( m_workpackages.values().at( i ) ); } // 'Yes' was hit so terminate all packages foreach( const Package *p, m_workpackages.values() ) { terminateWorkPackage( p ); } } qDeleteAll( m_workpackages ); m_workpackages.clear(); m_checkingForWorkPackages = false; dlg->deleteLater(); } void MainDocument::mergeWorkPackages() { foreach ( Package *package, m_workpackages ) { mergeWorkPackage( package ); } } void MainDocument::terminateWorkPackage( const Package *package ) { 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() ); 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 foreach ( const QDate &d, org.entries().keys() ) { if ( ! curr.entries().contains( d ) ) { debugPlan<<"remove entry "<addCommand( new RemoveCompletionEntryCmd( org, d ) ); } } // add new entries / modify existing foreach ( const QDate &d, curr.entries().keys() ) { if ( org.entries().contains( d ) && curr.entry( d ) == org.entry( d ) ) { continue; } 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, SIGNAL(completed()), SLOT(insertFileCompleted())); connect(doc, SIGNAL(canceled(QString)), SLOT(insertFileCancelled(QString))); 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, SIGNAL(completed()), SLOT(insertResourcesFileCompleted())); connect(doc, SIGNAL(canceled(QString)), SLOT(insertFileCancelled(QString))); 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() { for (Resource *r : m_project->resourceList()) { r->clearExternalAppointments(); } } void MainDocument::loadResourceAssignments(QUrl url) { insertSharedProjects(url); 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, SIGNAL(completed()), SLOT(insertSharedProjectCompleted())); connect(doc, SIGNAL(canceled(QString)), SLOT(insertSharedProjectCancelled(QString))); 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; for (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) { for (Resource *r : p.resourceList()) { Resource *res = m_project->resource(r->id()); if (res && res->isShared()) { Appointment *app = new Appointment(); app->setAuxcilliaryInfo(p.name()); for (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 for (Node *n : project.childNodeIterator()) { debugPlanShared<<"Project not empty, delete node:"<name(); NodeDeleteCmd cmd(n); cmd.execute(); } for (ScheduleManager *m : project.scheduleManagers()) { debugPlanShared<<"Project not empty, delete schedule:"<name(); DeleteScheduleManagerCmd cmd(project, m); cmd.execute(); } for (Account *a : project.accounts().accountList()) { debugPlanShared<<"Project not empty, delete account:"<name(); RemoveAccountCmd cmd(project, a); cmd.execute(); } // Mark all resources / groups as shared for (ResourceGroup *g : project.resourceGroups()) { g->setShared(true); } for (Resource *r : project.resourceList()) { r->setShared(true); } // Mark all calendars shared for (Calendar *c : project.allCalendars()) { c->setShared(true); } // check if any shared stuff has been removed QList removedGroups; QList removedResources; QList removedCalendars; QStringList removed; for (ResourceGroup *g : m_project->resourceGroups()) { if (g->isShared() && !project.findResourceGroup(g->id())) { removedGroups << g; removed << i18n("Group: %1", g->name()); } } for (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 : 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 : removedResources) { RemoveResourceCmd cmd(r->parentGroup(), r); cmd.redo(); } for (ResourceGroup *g : 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 : removedCalendars) { CalendarRemoveCmd cmd(m_project, c); cmd.redo(); } break; case KMessageBox::No: // Convert for (Resource *r : removedResources) { r->setShared(false); m_project->removeResourceId(r->id()); r->setId(m_project->uniqueResourceId()); m_project->insertResourceId(r->id(), r); } for (ResourceGroup *g : removedGroups) { g->setShared(false); m_project->removeResourceGroupId(g->id()); g->setId(m_project->uniqueResourceGroupId()); m_project->insertResourceGroupId(g->id(), g); } for (Calendar *c : 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; for (ResourceGroup *g : project.resourceGroups()) { l1 << g->id(); } QStringList l2; for (ResourceGroup *g : m_project->resourceGroups()) { l2 << g->id(); } debugPlanShared< removegroups; for (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; for (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; for (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 : removeresources) { debugPlanShared<<"Delete resource:"<id(); RemoveResourceCmd cmd(r->parentGroup(), r); cmd.execute(); } for (ResourceGroup *g : 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().values() ) { 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 0ab4a045..4b9871b5 100644 --- a/src/kptmaindocument.h +++ b/src/kptmaindocument.h @@ -1,249 +1,249 @@ /* 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 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 "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 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(); using KoDocument::setModified; public Q_SLOTS: void setModified( bool mod ); /// Inserts an item into all other views than @p view - void insertViewListItem( View *view, const ViewListItem *item, const ViewListItem *parent, int index ); + 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( View *view, const ViewListItem *item ); + void removeViewListItem(KPlato::View *view, const KPlato::ViewListItem *item); /// View selector has been modified void viewlistModified(); /// Check for workpackages /// If @p keep is true, packages that has been refused will not be checked for again void checkForWorkPackages( bool keep = false ); 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 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); bool isTaskModule() const; Q_SIGNALS: void changed(); void workPackageLoaded(); void viewlistModified( bool ); - void viewListItemAdded(const ViewListItem *item, const ViewListItem *parent, int index); - void viewListItemRemoved(const ViewListItem *item); + 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&, SchedulerPlugin *plugin ); + void addSchedulerPlugin(const QString&, KPlato::SchedulerPlugin *plugin); void autoCheckForWorkPackages(); 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; 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/kptpart.h b/src/kptpart.h index 2e0849d3..7d9bf12c 100644 --- a/src/kptpart.h +++ b/src/kptpart.h @@ -1,78 +1,78 @@ /* This file is part of the KDE project Copyright (C) 2012 C. Boemann 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 KPTPART_H #define KPTPART_H #include #include "plan_export.h" #include class KoView; class QStackedWidget; /// The main namespace. namespace KPlato { class MainDocument; class HtmlView; class PLAN_EXPORT Part : public KoPart { Q_OBJECT public: explicit Part(QObject *parent); virtual ~Part(); void setDocument(KPlato::MainDocument *document); /// reimplemented virtual KoView *createViewInstance(KoDocument *document, QWidget *parent); /// reimplemented virtual KoMainWindow *createMainWindow(); virtual void showStartUpWidget(KoMainWindow *parent); protected Q_SLOTS: void finish(); void slotShowIntroduction(); - void slotOpenUrlRequest( HtmlView *v, const QUrl &url ); + void slotOpenUrlRequest(KPlato::HtmlView *v, const QUrl &url); virtual void openTemplate( const QUrl& url ); void openTaskModule(const QUrl& url); void slotHelpContents(); protected: void createStarUpWidget(KoMainWindow *parent); QWidget *createWelcomeView(KoMainWindow *parent); QWidget *createIntroductionView(); private: KPlato::MainDocument *m_document; QPointer startUpWidget; bool m_toolbarVisible; }; } //KPlato namespace #endif diff --git a/src/kptschedulerpluginloader.h b/src/kptschedulerpluginloader.h index 11acd072..24c52fcf 100644 --- a/src/kptschedulerpluginloader.h +++ b/src/kptschedulerpluginloader.h @@ -1,49 +1,49 @@ /* This file is part of the KDE project Copyright (C) 2009 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 KPTSCHEDULERPLUGINLOADER_H #define KPTSCHEDULERPLUGINLOADER_H #include #include "kptschedulerplugin_macros.h" /// The main namespace. namespace KPlato { class SchedulerPlugin; class SchedulerPluginLoader : public QObject { Q_OBJECT public: explicit SchedulerPluginLoader(QObject * parent); virtual ~SchedulerPluginLoader(); void loadAllPlugins(); Q_SIGNALS: - void pluginLoaded( const QString &key, SchedulerPlugin *plugin); + void pluginLoaded( const QString &key, KPlato::SchedulerPlugin *plugin); }; } //namespace KPlato #endif diff --git a/src/kptschedulesdocker.h b/src/kptschedulesdocker.h index 22923c06..c77506eb 100644 --- a/src/kptschedulesdocker.h +++ b/src/kptschedulesdocker.h @@ -1,77 +1,77 @@ /* This file is part of the KDE project * Copyright (C) 2009 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 KPTSCHEDULESDOCKER_H #define KPTSCHEDULESDOCKER_H #include #include #include "kptschedulemodel.h" #include class QTreeView; namespace KPlato { class Project; class ScheduleManager; class SchedulesDocker : public QDockWidget { Q_OBJECT public: explicit SchedulesDocker(); ~SchedulesDocker(); ScheduleManager *selectedSchedule() const; Q_SIGNALS: - void selectionChanged( ScheduleManager *sm ); + void selectionChanged(KPlato::ScheduleManager *sm); public Q_SLOTS: - void setProject( Project *project ); - void setSelectedSchedule( ScheduleManager *sm ); + void setProject(KPlato::Project *project); + void setSelectedSchedule(KPlato::ScheduleManager *sm); protected Q_SLOTS: void slotSelectionChanged(); private: QTreeView *m_view; QSortFilterProxyModel m_sfModel; ScheduleItemModel m_model; }; class SchedulesDockerFactory : public KoDockFactoryBase { public: SchedulesDockerFactory(); virtual QString id() const; virtual QDockWidget* createDockWidget(); /// @return the dock widget area the widget should appear in by default virtual KoDockFactoryBase::DockPosition defaultDockPosition() const { return DockLeft; } }; } //namespace KPlato #endif diff --git a/src/kptview.cpp b/src/kptview.cpp index 33c5a134..d1f88bda 100644 --- a/src/kptview.cpp +++ b/src/kptview.cpp @@ -1,3247 +1,3247 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999, 2000 Torben Weis Copyright (C) 2002 - 2011 Dag Andersen Copyright (C) 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptview.h" #include #include #include "KoDocumentInfo.h" #include "KoMainWindow.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kptlocale.h" #include "kptviewbase.h" #include "kptaccountsview.h" #include "kptaccountseditor.h" #include "kptcalendareditor.h" #include "kptfactory.h" #include "kptmilestoneprogressdialog.h" #include "kpttaskdescriptiondialog.h" #include "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 "kpthtmlview.h" #include "about/aboutpage.h" #include "kptlocaleconfigmoneydialog.h" #include "kptflatproxymodel.h" #include "kpttaskstatusmodel.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, SIGNAL(selectionChanged(ScheduleManager*)), SLOT(slotSelectionChanged(ScheduleManager*)) ); - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), m_viewlist, SLOT(setSelectedSchedule(ScheduleManager*)) ); - connect( m_viewlist, SIGNAL(updateViewInfo(ViewListItem*)), SLOT(slotUpdateViewInfo(ViewListItem*)) ); + connect( m_viewlist, SIGNAL(selectionChanged(KPlato::ScheduleManager*)), SLOT(slotSelectionChanged(KPlato::ScheduleManager*))); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), m_viewlist, SLOT(setSelectedSchedule(KPlato::ScheduleManager*))); + connect( m_viewlist, SIGNAL(updateViewInfo(KPlato::ViewListItem*)), SLOT(slotUpdateViewInfo(KPlato::ViewListItem*))); } 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(ScheduleManager*)), SLOT(slotSelectionChanged(ScheduleManager*)) ); - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), sd, SLOT(setSelectedSchedule(ScheduleManager*)) ); + connect(sd, SIGNAL(selectionChanged(KPlato::ScheduleManager*)), SLOT(slotSelectionChanged(KPlato::ScheduleManager*))); + connect(this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), 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, SIGNAL(triggered(bool)), SLOT(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, SIGNAL(triggered(bool)), SLOT(slotViewSelector(bool)) ); // ------ Insert // ------ Project actionEditMainProject = new QAction(koIcon("view-time-schedule-edit"), i18n("Edit Main Project..."), this); actionCollection()->addAction("project_edit", actionEditMainProject ); connect( actionEditMainProject, SIGNAL(triggered(bool)), SLOT(slotProjectEdit()) ); actionEditStandardWorktime = new QAction(koIcon("configure"), i18n("Define Estimate Conversions..."), this); actionCollection()->addAction("project_worktime", actionEditStandardWorktime ); connect( actionEditStandardWorktime, SIGNAL(triggered(bool)), SLOT(slotProjectWorktime()) ); // ------ Tools actionDefineWBS = new QAction(koIcon("configure"), i18n("Define WBS Pattern..."), this); actionCollection()->addAction("tools_define_wbs", actionDefineWBS ); connect( actionDefineWBS, SIGNAL(triggered(bool)), SLOT(slotDefineWBS()) ); actionInsertFile = new QAction(koIcon("document-import"), i18n("Insert Project File..."), this); actionCollection()->addAction("insert_file", actionInsertFile ); connect( actionInsertFile, SIGNAL(triggered(bool)), SLOT(slotInsertFile()) ); // ------ Settings actionConfigure = new QAction(koIcon("configure"), i18n("Configure Plan..."), this); actionCollection()->addAction("configure", actionConfigure ); connect( actionConfigure, SIGNAL(triggered(bool)), SLOT(slotConfigure()) ); actionCurrencyConfig = new QAction(koIcon("configure"), i18n("Define Currency..."), this); actionCollection()->addAction( "config_currency", actionCurrencyConfig ); connect( actionCurrencyConfig, SIGNAL(triggered(bool)), SLOT(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, SIGNAL(triggered(bool)), SLOT(slotOpenReportFile()) ); #endif // ------ Help actionIntroduction = new QAction(koIcon("dialog-information"), i18n("Introduction to Plan"), this); actionCollection()->addAction("plan_introduction", actionIntroduction ); connect( actionIntroduction, SIGNAL(triggered(bool)), SLOT(slotIntroduction()) ); // ------ Popup actionOpenNode = new QAction(koIcon("document-edit"), i18n("Edit..."), this); actionCollection()->addAction("node_properties", actionOpenNode ); connect( actionOpenNode, SIGNAL(triggered(bool)), SLOT(slotOpenNode()) ); actionTaskProgress = new QAction(koIcon("document-edit"), i18n("Progress..."), this); actionCollection()->addAction("task_progress", actionTaskProgress ); connect( actionTaskProgress, SIGNAL(triggered(bool)), SLOT(slotTaskProgress()) ); actionDeleteTask = new QAction(koIcon("edit-delete"), i18n("Delete Task"), this); actionCollection()->addAction("delete_task", actionDeleteTask ); connect( actionDeleteTask, SIGNAL(triggered(bool)), SLOT(slotDeleteTask()) ); actionTaskDescription = new QAction(koIcon("document-edit"), i18n("Description..."), this); actionCollection()->addAction("task_description", actionTaskDescription ); connect( actionTaskDescription, SIGNAL(triggered(bool)), SLOT(slotTaskDescription()) ); actionIndentTask = new QAction(koIcon("format-indent-more"), i18n("Indent Task"), this); actionCollection()->addAction("indent_task", actionIndentTask ); connect( actionIndentTask, SIGNAL(triggered(bool)), SLOT(slotIndentTask()) ); actionUnindentTask= new QAction(koIcon("format-indent-less"), i18n("Unindent Task"), this); actionCollection()->addAction("unindent_task", actionUnindentTask ); connect( actionUnindentTask, SIGNAL(triggered(bool)), SLOT(slotUnindentTask()) ); actionMoveTaskUp = new QAction(koIcon("arrow-up"), i18n("Move Task Up"), this); actionCollection()->addAction("move_task_up", actionMoveTaskUp ); connect( actionMoveTaskUp, SIGNAL(triggered(bool)), SLOT(slotMoveTaskUp()) ); actionMoveTaskDown = new QAction(koIcon("arrow-down"), i18n("Move Task Down"), this); actionCollection()->addAction("move_task_down", actionMoveTaskDown ); connect( actionMoveTaskDown, SIGNAL(triggered(bool)), SLOT(slotMoveTaskDown()) ); actionEditResource = new QAction(koIcon("document-edit"), i18n("Edit Resource..."), this); actionCollection()->addAction("edit_resource", actionEditResource ); connect( actionEditResource, SIGNAL(triggered(bool)), SLOT(slotEditResource()) ); actionEditRelation = new QAction(koIcon("document-edit"), i18n("Edit Dependency..."), this); actionCollection()->addAction("edit_dependency", actionEditRelation ); connect( actionEditRelation, SIGNAL(triggered(bool)), SLOT(slotModifyRelation()) ); actionDeleteRelation = new QAction(koIcon("edit-delete"), i18n("Delete Dependency"), this); actionCollection()->addAction("delete_dependency", actionDeleteRelation ); connect( actionDeleteRelation, SIGNAL(triggered(bool)), SLOT(slotDeleteRelation()) ); // Viewlist popup connect( m_viewlist, SIGNAL(createView()), SLOT(slotCreateView()) ); m_estlabel = new QLabel( "", 0 ); if ( statusBar() ) { addStatusBarItem( m_estlabel, 0, true ); } - connect( &getProject(), SIGNAL(scheduleChanged(MainSchedule*)), SLOT(slotScheduleChanged(MainSchedule*)) ); + connect( &getProject(), SIGNAL(scheduleChanged(KPlato::MainSchedule*)), SLOT(slotScheduleChanged(KPlato::MainSchedule*)) ); - connect( &getProject(), SIGNAL(scheduleAdded(const MainSchedule*)), SLOT(slotScheduleAdded(const MainSchedule*)) ); - connect( &getProject(), SIGNAL(scheduleRemoved(const MainSchedule*)), SLOT(slotScheduleRemoved(const MainSchedule*)) ); + connect( &getProject(), SIGNAL(scheduleAdded(const KPlato::MainSchedule*)), SLOT(slotScheduleAdded(const KPlato::MainSchedule*)) ); + connect( &getProject(), SIGNAL(scheduleRemoved(const KPlato::MainSchedule*)), SLOT(slotScheduleRemoved(const KPlato::MainSchedule*)) ); slotPlugScheduleActions(); connect( doc, SIGNAL(changed()), SLOT(slotUpdate()) ); connect( m_scheduleActionGroup, SIGNAL(triggered(QAction*)), SLOT(slotViewSchedule(QAction*)) ); connect( getPart(), SIGNAL(workPackageLoaded()), SLOT(slotWorkPackageLoaded()) ); // hide unused dockers QTimer::singleShot( 0, this, SLOT(hideToolDocker()) ); // create views after dockers hidden, views take time for large projects QTimer::singleShot( 100, this, SLOT(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, SIGNAL(created(QString)), this, SLOT(taskModuleFileChanged(QString))); connect(&m_dirwatch, SIGNAL(deleted(QString)), this, SLOT(taskModuleFileChanged(QString))); } } //debugPlan<<" end"; } View::~View() { ViewBase *view = currentView(); if (view) { // deactivate view to remove dockers etc slotGuiActivated(view, false); } /* removeStatusBarItem( m_estlabel ); delete m_estlabel;*/ } // hackish way to get rid of unused dockers, but as long as no official way exists... void View::hideToolDocker() { if ( mainWindow() ) { QStringList lst; lst << "KPlatoViewList" << "Scripting"; QStringList names; foreach ( QDockWidget *w, mainWindow()->dockWidgets() ) { if ( ! lst.contains( w->objectName() ) ) { names << w->windowTitle(); w->setFeatures( QDockWidget::DockWidgetClosable ); w->hide(); } } foreach(const KActionCollection *c, KActionCollection::allCollections()) { KActionMenu *a = qobject_cast(c->action("settings_dockers_menu")); if ( a ) { QList actions = a->menu()->actions(); foreach ( QAction *act, actions ) { if ( names.contains( act->text() ) ) { a->removeAction( act ); } } a->addSeparator(); break; } } } } void View::initiateViews() { QApplication::setOverrideCursor( Qt::WaitCursor ); createViews(); connect( m_viewlist, SIGNAL(activated(ViewListItem*,ViewListItem*)), SLOT(slotViewActivated(ViewListItem*,ViewListItem*)) ); // after createViews() !! connect( m_viewlist, SIGNAL(viewListItemRemoved(ViewListItem*)), SLOT(slotViewListItemRemoved(ViewListItem*)) ); // after createViews() !! connect( m_viewlist, SIGNAL(viewListItemInserted(ViewListItem*,ViewListItem*,int)), SLOT(slotViewListItemInserted(ViewListItem*,ViewListItem*,int)) ); QDockWidget *docker = qobject_cast( m_viewlist->parent() ); if ( docker ) { // after createViews() !! connect( m_viewlist, SIGNAL(modified()), docker, SLOT(slotModified())); connect( m_viewlist, SIGNAL(modified()), getPart(), SLOT(viewlistModified())); connect(getPart(), SIGNAL(viewlistModified(bool)), docker, SLOT(updateWindowTitle(bool))); } connect( m_tab, SIGNAL(currentChanged(int)), this, SLOT(slotCurrentChanged(int)) ); 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"; 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 ); createResourceEditor( cat, "ResourceEditor", QString(), TIP_USE_DEFAULT_TEXT ); createTaskEditor( cat, "TaskEditor", QString(), TIP_USE_DEFAULT_TEXT ); 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 ); createTaskStatusView( cat, "TaskStatusView", QString(), TIP_USE_DEFAULT_TEXT ); createTaskView( cat, "TaskView", QString(), TIP_USE_DEFAULT_TEXT ); 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, SIGNAL(openUrlRequest(HtmlView*,QUrl)), SLOT(slotOpenUrlRequest(HtmlView*,QUrl)) ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), v, SLOT(setScheduleManager(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), v, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); connect( v, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), v, SLOT(setScheduleManager(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), v, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); connect( v, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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 ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); connect( resourceeditor, SIGNAL(deleteObjectList(QObjectList)), SLOT(slotDeleteResourceObjects(QObjectList)) ); connect( resourceeditor, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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 ); m_tab->addWidget( taskeditor ); m_defaultView = m_tab->count() - 1; 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, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), taskeditor, SLOT(setScheduleManager(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), taskeditor, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); connect( taskeditor, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); connect( taskeditor, SIGNAL(addTask()), SLOT(slotAddTask()) ); connect( taskeditor, SIGNAL(addMilestone()), SLOT(slotAddMilestone()) ); connect( taskeditor, SIGNAL(addSubtask()), SLOT(slotAddSubTask()) ); connect( taskeditor, SIGNAL(addSubMilestone()), SLOT(slotAddSubMilestone()) ); connect( taskeditor, SIGNAL(deleteTaskList(QList)), SLOT(slotDeleteTask(QList)) ); connect( taskeditor, SIGNAL(moveTaskUp()), SLOT(slotMoveTaskUp()) ); connect( taskeditor, SIGNAL(moveTaskDown()), SLOT(slotMoveTaskDown()) ); connect( taskeditor, SIGNAL(indentTask()), SLOT(slotIndentTask()) ); connect( taskeditor, SIGNAL(unindentTask()), SLOT(slotUnindentTask()) ); - connect(taskeditor, SIGNAL(saveTaskModule(QUrl,Project*)), SLOT(saveTaskModule(QUrl,Project*))); + connect(taskeditor, SIGNAL(saveTaskModule(QUrl,KPlato::Project*)), SLOT(saveTaskModule(QUrl,KPlato::Project*))); connect(taskeditor, SIGNAL(removeTaskModule(QUrl)), SLOT(removeTaskModule(QUrl))); - connect(taskeditor, SIGNAL(openDocument(QUrl)), static_cast(m_partpart), SLOT(openTaskModule(QUrl))); + connect(taskeditor, SIGNAL(openDocument(QUrl)), static_cast(m_partpart), SLOT(openTaskModule(QUrl))); connect(this, SIGNAL(taskModulesChanged(QStringList)), taskeditor, SLOT(setTaskModules(QStringList))); connect( taskeditor, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); connect( calendareditor, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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(), SIGNAL(addScheduleManager(Project*)), SLOT(slotAddScheduleManager(Project*)) ); - connect( handler->scheduleEditor(), SIGNAL(deleteScheduleManager(Project*,ScheduleManager*)), SLOT(slotDeleteScheduleManager(Project*,ScheduleManager*)) ); - connect( handler->scheduleEditor(), SIGNAL(moveScheduleManager(ScheduleManager*,ScheduleManager*,int)), SLOT(slotMoveScheduleManager(ScheduleManager*,ScheduleManager*,int))); + connect( handler->scheduleEditor(), SIGNAL(addScheduleManager(KPlato::Project*)), SLOT(slotAddScheduleManager(KPlato::Project*)) ); + connect( handler->scheduleEditor(), SIGNAL(deleteScheduleManager(KPlato::Project*,ScheduleManager*)), SLOT(slotDeleteScheduleManager(KPlato::Project*,ScheduleManager*)) ); + connect( handler->scheduleEditor(), SIGNAL(moveScheduleManager(KPlato::ScheduleManager*,KPlato::ScheduleManager*,int)), SLOT(slotMoveScheduleManager(KPlato::ScheduleManager*,KPlato::ScheduleManager*,int))); - connect( handler->scheduleEditor(), SIGNAL(calculateSchedule(Project*,ScheduleManager*)), SLOT(slotCalculateSchedule(Project*,ScheduleManager*)) ); + connect( handler->scheduleEditor(), SIGNAL(calculateSchedule(KPlato::Project*,KPlato::ScheduleManager*)), SLOT(slotCalculateSchedule(KPlato::Project*,KPlato::ScheduleManager*)) ); - connect( handler->scheduleEditor(), SIGNAL(baselineSchedule(Project*,ScheduleManager*)), SLOT(slotBaselineSchedule(Project*,ScheduleManager*)) ); + connect( handler->scheduleEditor(), SIGNAL(baselineSchedule(KPlato::Project*,KPlato::ScheduleManager*)), SLOT(slotBaselineSchedule(KPlato::Project*,KPlato::ScheduleManager*)) ); connect( handler, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), handler, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), handler, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)) ); connect( handler, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); - connect(handler, SIGNAL(editNode(Node*)), this, SLOT(slotOpenNode(Node*))); - connect(handler, SIGNAL(editResource(Resource*)), this, SLOT(slotEditResource(Resource*))); + connect(handler, SIGNAL(editNode(KPlato::Node*)), this, SLOT(slotOpenNode(KPlato::Node*))); + connect(handler, SIGNAL(editResource(KPlato::Resource*)), this, SLOT(slotEditResource(KPlato::Resource*))); handler->draw( getProject() ); handler->updateReadWrite( m_readWrite ); return handler; } ScheduleEditor *View::createScheduleEditor( QWidget *parent ) { ScheduleEditor *scheduleeditor = new ScheduleEditor(getKoPart(), getPart(), parent ); - connect( scheduleeditor, SIGNAL(addScheduleManager(Project*)), SLOT(slotAddScheduleManager(Project*)) ); - connect( scheduleeditor, SIGNAL(deleteScheduleManager(Project*,ScheduleManager*)), SLOT(slotDeleteScheduleManager(Project*,ScheduleManager*)) ); + connect( scheduleeditor, SIGNAL(addScheduleManager(KPlato::Project*)), SLOT(slotAddScheduleManager(KPlato::Project*)) ); + connect( scheduleeditor, SIGNAL(deleteScheduleManager(KPlato::Project*,KPlato::ScheduleManager*)), SLOT(slotDeleteScheduleManager(KPlato::Project*,KPlato::ScheduleManager*)) ); - connect( scheduleeditor, SIGNAL(calculateSchedule(Project*,ScheduleManager*)), SLOT(slotCalculateSchedule(Project*,ScheduleManager*)) ); + connect( scheduleeditor, SIGNAL(calculateSchedule(KPlato::Project*,KPlato::ScheduleManager*)), SLOT(slotCalculateSchedule(KPlato::Project*,KPlato::ScheduleManager*)) ); - connect( scheduleeditor, SIGNAL(baselineSchedule(Project*,ScheduleManager*)), SLOT(slotBaselineSchedule(Project*,ScheduleManager*)) ); + connect( scheduleeditor, SIGNAL(baselineSchedule(KPlato::Project*,KPlato::ScheduleManager*)), SLOT(slotBaselineSchedule(KPlato::Project*,KPlato::ScheduleManager*)) ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); - connect( scheduleeditor, SIGNAL(addScheduleManager(Project*)), SLOT(slotAddScheduleManager(Project*)) ); + connect( scheduleeditor, SIGNAL(addScheduleManager(KPlato::Project*)), SLOT(slotAddScheduleManager(KPlato::Project*)) ); - connect( scheduleeditor, SIGNAL(deleteScheduleManager(Project*,ScheduleManager*)), SLOT(slotDeleteScheduleManager(Project*,ScheduleManager*)) ); + connect( scheduleeditor, SIGNAL(deleteScheduleManager(KPlato::Project*,KPlato::ScheduleManager*)), SLOT(slotDeleteScheduleManager(KPlato::Project*,KPlato::ScheduleManager*)) ); - connect( scheduleeditor, SIGNAL(calculateSchedule(Project*,ScheduleManager*)), SLOT(slotCalculateSchedule(Project*,ScheduleManager*)) ); + connect( scheduleeditor, SIGNAL(calculateSchedule(KPlato::Project*,KPlato::ScheduleManager*)), SLOT(slotCalculateSchedule(KPlato::Project*,KPlato::ScheduleManager*)) ); - connect( scheduleeditor, SIGNAL(baselineSchedule(Project*,ScheduleManager*)), SLOT(slotBaselineSchedule(Project*,ScheduleManager*)) ); + connect( scheduleeditor, SIGNAL(baselineSchedule(KPlato::Project*,KPlato::ScheduleManager*)), SLOT(slotBaselineSchedule(KPlato::Project*,KPlato::ScheduleManager*)) ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); - connect( editor, SIGNAL(addRelation(Node*,Node*,int)), SLOT(slotAddRelation(Node*,Node*,int)) ); - connect( editor, SIGNAL(modifyRelation(Relation*,int)), SLOT(slotModifyRelation(Relation*,int)) ); - connect( editor, SIGNAL(modifyRelation(Relation*)), SLOT(slotModifyRelation(Relation*)) ); + connect( editor, SIGNAL(addRelation(KPlato::Node*,KPlato::Node*,int)), SLOT(slotAddRelation(KPlato::Node*,KPlato::Node*,int)) ); + connect( editor, SIGNAL(modifyRelation(KPlato::Relation*,int)), SLOT(slotModifyRelation(KPlato::Relation*,int)) ); + connect( editor, SIGNAL(modifyRelation(KPlato::Relation*)), SLOT(slotModifyRelation(KPlato::Relation*)) ); - connect( editor, SIGNAL(editNode(Node*)), SLOT(slotOpenNode(Node*)) ); + connect( editor, SIGNAL(editNode(KPlato::Node*)), SLOT(slotOpenNode(KPlato::Node*)) ); connect( editor, SIGNAL(addTask()), SLOT(slotAddTask()) ); connect( editor, SIGNAL(addMilestone()), SLOT(slotAddMilestone()) ); connect( editor, SIGNAL(addSubMilestone()), SLOT(slotAddSubMilestone()) ); connect( editor, SIGNAL(addSubtask()), SLOT(slotAddSubTask()) ); connect( editor, SIGNAL(deleteTaskList(QList)), SLOT(slotDeleteTask(QList)) ); - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), editor, SLOT(setScheduleManager(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), editor, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); connect( editor, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), v, SLOT(setScheduleManager(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), v, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), v, SLOT(setScheduleManager(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), v, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); connect( v, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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 ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), taskstatusview, SLOT(setScheduleManager(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), taskstatusview, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); connect( taskstatusview, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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 ); 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, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), v, SLOT(setScheduleManager(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), v, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); connect( v, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); connect( v, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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 ); 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, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), v, SLOT(setScheduleManager(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), v, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); connect( v, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); connect( v, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); - connect( v, SIGNAL(mailWorkpackage(Node*,Resource*)), SLOT(slotMailWorkpackage(Node*,Resource*)) ); - connect( v, SIGNAL(mailWorkpackages(QList,Resource*)), SLOT(slotMailWorkpackages(QList,Resource*)) ); + connect( v, SIGNAL(mailWorkpackage(KPlato::Node*,KPlato::Resource*)), SLOT(slotMailWorkpackage(KPlato::Node*,KPlato::Resource*)) ); + connect( v, SIGNAL(mailWorkpackages(QList,KPlato::Resource*)), SLOT(slotMailWorkpackages(QList,KPlato::Resource*)) ); connect(v, SIGNAL(checkForWorkPackages()), getPart(), SLOT(checkForWorkPackages())); v->updateReadWrite( m_readWrite ); return v; } ViewBase *View::createGanttView( ViewListItem *cat, const QString &tag, const QString &name, const QString &tip, int index ) { GanttView *ganttview = new GanttView(getKoPart(), getPart(), m_tab, koDocument()->isReadWrite() ); m_tab->addWidget( ganttview ); ViewListItem *i = m_viewlist->addView( cat, tag, name, ganttview, getPart(), "", index ); ViewInfo vi = defaultViewInfo( "GanttView" ); if ( name.isEmpty() ) { i->setText( 0, vi.name ); } if ( tip == TIP_USE_DEFAULT_TEXT ) { i->setToolTip( 0, vi.tip ); } else { i->setToolTip( 0, tip ); } ganttview->setProject( &( getProject() ) ); ganttview->setScheduleManager( currentScheduleManager() ); connect( ganttview, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); /* TODO: Review these - connect( ganttview, SIGNAL(addRelation(Node*,Node*,int)), SLOT(slotAddRelation(Node*,Node*,int)) ); - connect( ganttview, SIGNAL(modifyRelation(Relation*,int)), SLOT(slotModifyRelation(Relation*,int)) ); - connect( ganttview, SIGNAL(modifyRelation(Relation*)), SLOT(slotModifyRelation(Relation*)) ); + 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(Node*,QString)), this, SLOT(slotRenameNode(Node*,QString)) );*/ + connect( ganttview, SIGNAL(itemRenamed(KPlato::Node*,QString)), this, SLOT(slotRenameNode(KPlato::Node*,QString)) );*/ - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), ganttview, SLOT(setScheduleManager(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), ganttview, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); connect( ganttview, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), ganttview, SLOT(setScheduleManager(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), ganttview, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); connect( ganttview, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), accountsview, SLOT(setScheduleManager(ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), accountsview, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); connect( accountsview, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); 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, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); connect( resourceAssignmentView, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), v, SLOT(setScheduleManager(ScheduleManager*)) ); - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), v, SLOT(slotRefreshView())); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), v, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), v, SLOT(slotRefreshView())); v->setScheduleManager( currentScheduleManager() ); connect( v, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); connect( v, SIGNAL(requestPopupMenu(QString,QPoint)), this, SLOT(slotPopupMenu(QString,QPoint)) ); 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, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), v, SLOT(setScheduleManager(ScheduleManager*)) ); - connect( this, SIGNAL(currentScheduleManagerChanged(ScheduleManager*)), v, SLOT(slotRefreshView())); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), v, SLOT(setScheduleManager(KPlato::ScheduleManager*)) ); + connect( this, SIGNAL(currentScheduleManagerChanged(KPlato::ScheduleManager*)), v, SLOT(slotRefreshView())); v->setScheduleManager( currentScheduleManager() ); connect( v, SIGNAL(guiActivated(ViewBase*,bool)), SLOT(slotGuiActivated(ViewBase*,bool)) ); v->updateReadWrite( m_readWrite ); return v; #else 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, SIGNAL(finished(int)), SLOT(slotInsertFileFinished(int))); 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::slotProjectEdit() { slotOpenNode( &getProject() ); } void View::slotProjectWorktime() { StandardWorktimeDialog *dia = new StandardWorktimeDialog( getProject(), this ); connect(dia, SIGNAL(finished(int)), this, SLOT(slotProjectWorktimeFinished(int))); 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<expected() ); if ( idx < 0 ) { debugPlan<expected(); return; } QAction *a = m_scheduleActions.keys().at( idx ); Q_ASSERT( a ); a->setChecked( true ); // this doesn't trigger QActionGroup slotViewSchedule( a ); } QList View::sortedActionList() { QMap lst; foreach ( QAction *a, m_scheduleActions.keys() ) { lst.insert( a->objectName(), a ); } return lst.values(); } void View::slotScheduleRemoved( const MainSchedule *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.keys().first()->setChecked( true ); } } slotViewSchedule( m_scheduleActionGroup->checkedAction() ); } void View::slotScheduleAdded( const MainSchedule *sch ) { if ( sch->type() != Schedule::Expected ) { return; // Only view expected } MainSchedule *s = const_cast( sch ); // debugPlan<name()<<" deleted="<isDeleted()<<"scheduled="<isScheduled(); QAction *checked = m_scheduleActionGroup->checkedAction(); if ( ! sch->isDeleted() && sch->isScheduled() ) { unplugActionList( "view_schedule_list" ); QAction *act = addScheduleAction( s ); plugActionList( "view_schedule_list", sortedActionList() ); if ( checked ) { checked->setChecked( true ); } else if ( act ) { act->setChecked( true ); } else if ( ! m_scheduleActions.isEmpty() ) { m_scheduleActions.keys().first()->setChecked( true ); } } slotViewSchedule( m_scheduleActionGroup->checkedAction() ); } void View::slotScheduleChanged( MainSchedule *sch ) { // debugPlan<name()<<" deleted="<isDeleted()<<"scheduled="<isScheduled(); if ( sch->isDeleted() || ! sch->isScheduled() ) { slotScheduleRemoved( sch ); return; } if ( m_scheduleActions.values().contains( sch ) ) { slotScheduleRemoved( sch ); // hmmm, how to avoid this? } slotScheduleAdded( sch ); } QAction *View::addScheduleAction( Schedule *sch ) { QAction *act = 0; if ( ! sch->isDeleted() && sch->isScheduled() ) { QString n = sch->name(); act = new KToggleAction( n, this); actionCollection()->addAction(n, act ); m_scheduleActions.insert( act, sch ); m_scheduleActionGroup->addAction( act ); //debugPlan<<"Add:"<manager(); } setLabel( 0 ); slotViewScheduleManager(sm); } void View::slotActionDestroyed( QObject *o ) { //debugPlan<name(); m_scheduleActions.remove( static_cast( o ) ); // slotViewSchedule( m_scheduleActionGroup->checkedAction() ); } void View::slotPlugScheduleActions() { //debugPlan<removeAction( act ); delete act; } m_scheduleActions.clear(); QAction *ca = 0; foreach( ScheduleManager *sm, getProject().allScheduleManagers() ) { Schedule *sch = sm->expected(); if ( sch == 0 ) { continue; } QAction *act = addScheduleAction( sch ); if ( act && id == sch->id() ) { ca = act; } } plugActionList( "view_schedule_list", sortedActionList() ); if ( ca == 0 && m_scheduleActionGroup->actions().count() > 0 ) { ca = m_scheduleActionGroup->actions().first(); } if ( ca ) { ca->setChecked( true ); } slotViewSchedule( ca ); } void View::slotProjectCalculated( ScheduleManager *sm ) { // we only get here if current schedule was calculated if ( sm->isScheduled() ) { slotSelectionChanged( sm ); } } 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; } if ( sm == currentScheduleManager() ) { - connect( project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); + connect( project, SIGNAL(projectCalculated(KPlato::ScheduleManager*)), this, SLOT(slotProjectCalculated(KPlato::ScheduleManager*)) ); } 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, SIGNAL(finished(int)), SLOT(slotAddSubTaskFinished(int))); 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, SIGNAL(finished(int)), SLOT(slotAddTaskFinished(int))); 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, SIGNAL(finished(int)), SLOT(slotAddMilestoneFinished(int))); 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, SIGNAL(finished(int)), SLOT(slotAddSubMilestoneFinished(int))); 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, SIGNAL(finished(int)), SLOT(slotDefineWBSFinished(int))); 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::slotOpenNode() { //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, SIGNAL(dialogFinished(int)), SLOT(slotProjectEditFinished(int))); connect(dia, SIGNAL(sigLoadSharedResources(const QString&, const QUrl&, bool)), this, SLOT(slotInsertResourcesFile(const QString&, const QUrl&))); 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, SIGNAL(finished(int)), SLOT(slotTaskEditFinished(int))); 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, SIGNAL(finished(int)), SLOT(slotTaskEditFinished(int))); 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, SIGNAL(finished(int)), SLOT(slotSummaryTaskEditFinished(int))); 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 { Schedule *s = m_scheduleActions.value( m_scheduleActionGroup->checkedAction() ); return s == 0 ? 0 : s->manager(); } long View::activeScheduleId() const { Schedule *s = m_scheduleActions.value( m_scheduleActionGroup->checkedAction() ); return s == 0 ? -1 : s->id(); } void View::setActiveSchedule( long id ) { if ( id != -1 ) { QMap::const_iterator it = m_scheduleActions.constBegin(); for (; it != m_scheduleActions.constEnd(); ++it ) { if ( it.value()->id() == 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, SIGNAL(finished(int)), SLOT(slotTaskProgressFinished(int))); 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, SIGNAL(finished(int)), SLOT(slotMilestoneProgressFinished(int))); 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_Project: { break; } case Node::Type_Subproject: //TODO break; case Node::Type_Task: case Node::Type_Milestone: case Node::Type_Summarytask: { Task *task = dynamic_cast( node ); Q_ASSERT( task ); TaskDescriptionDialog *dia = new TaskDescriptionDialog( *task, this ); connect(dia, SIGNAL(finished(int)), SLOT(slotTaskDescriptionFinished(int))); 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::slotDeleteTask( 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::slotDeleteTask() { //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::slotAddRelation( Node *par, Node *child ) { //debugPlan; Relation * rel = new Relation( par, child ); AddRelationDialog *dia = new AddRelationDialog( getProject(), rel, this ); connect(dia, SIGNAL(finished(int)), SLOT(slotAddRelationFinished(int))); 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 { slotAddRelation( par, child ); } } void View::slotModifyRelation( Relation *rel ) { //debugPlan; ModifyRelationDialog *dia = new ModifyRelationDialog( getProject(), rel, this ); connect(dia, SIGNAL(finished(int)), SLOT(slotModifyRelationFinished(int))); 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 { slotModifyRelation( rel ); } } void View::slotModifyRelation() { ViewBase *v = dynamic_cast( m_tab->currentWidget() ); if ( v == 0 ) { return; } Relation *rel = v->currentRelation(); if ( rel ) { slotModifyRelation( 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::slotEditResource() { //debugPlan; slotEditResource( currentResource() ); } void View::slotEditResource( Resource *resource ) { if ( resource == 0 ) { return ; } ResourceDialog *dia = new ResourceDialog( getProject(), resource, this ); connect(dia, SIGNAL(finished(int)), SLOT(slotEditResourceFinished(int))); dia->show(); dia->raise(); dia->activateWindow(); } void View::slotEditResourceFinished( int result ) { //debugPlan; ResourceDialog *dia = qobject_cast( sender() ); if ( dia == 0 ) { return ; } if ( result == QDialog::Accepted) { KUndo2Command * cmd = dia->buildCommand(); if ( cmd ) getPart() ->addCommand( cmd ); } dia->deleteLater(); } void View::slotDeleteResource( Resource *resource ) { getPart()->addCommand( new RemoveResourceCmd( resource->parentGroup(), resource, kundo2_i18n( "Delete resource" ) ) ); } void View::slotDeleteResourceGroup( ResourceGroup *group ) { getPart()->addCommand( new RemoveResourceGroupCmd( group->project(), group, kundo2_i18n( "Delete resourcegroup" ) ) ); } void View::slotDeleteResourceObjects( QObjectList lst ) { //debugPlan; foreach ( QObject *o, lst ) { Resource *r = qobject_cast( o ); if ( r && r->isScheduled() ) { KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel( this, i18n( "A resource that has been scheduled will be deleted. This will invalidate the schedule." ) ); if ( res == KMessageBox::Cancel ) { return; } break; } ResourceGroup *g = qobject_cast( o ); if ( g && g->isScheduled() ) { KMessageBox::ButtonCode res = KMessageBox::warningContinueCancel( this, i18n( "A resource that has been scheduled will be deleted. This will invalidate the schedule." ) ); if ( res == KMessageBox::Cancel ) { return; } break; } } if ( lst.count() == 1 ) { Resource *r = qobject_cast( lst.first() ); if ( r ) { slotDeleteResource( r ); } else { ResourceGroup *g = qobject_cast( lst.first() ); if ( g ) { slotDeleteResourceGroup( g ); } } return; } // int num = 0; MacroCommand *cmd = 0, *rc = 0, *gc = 0; foreach ( QObject *o, lst ) { Resource *r = qobject_cast( o ); if ( r ) { if ( rc == 0 ) rc = new MacroCommand( KUndo2MagicString() ); rc->addCommand( new RemoveResourceCmd( r->parentGroup(), r ) ); continue; } ResourceGroup *g = qobject_cast( o ); if ( g ) { if ( gc == 0 ) gc = new MacroCommand( KUndo2MagicString() ); gc->addCommand( new RemoveResourceGroupCmd( g->project(), g ) ); } } if ( rc || gc ) { KUndo2MagicString s; if ( rc && gc ) { s = kundo2_i18n( "Delete resourcegroups and resources" ); } else if ( rc ) { s = kundo2_i18np( "Delete resource", "Delete resources", lst.count() ); } else { s = kundo2_i18np( "Delete resourcegroup", "Delete resourcegroups", lst.count() ); } cmd = new MacroCommand( s ); } if ( rc ) cmd->addCommand( rc ); if ( gc ) cmd->addCommand( gc ); if ( cmd ) getPart()->addCommand( cmd ); } void View::updateReadWrite( bool readwrite ) { m_readWrite = readwrite; m_viewlist->setReadWrite( readwrite ); } MainDocument *View::getPart() const { return ( MainDocument * ) koDocument(); } KoPart *View::getKoPart() const { return m_partpart; } void View::slotConnectNode() { //debugPlan; /* NodeItem *curr = ganttview->currentItem(); if (curr) { debugPlan<<"node="<getNode().name(); }*/ } QMenu * View::popupMenu( const QString& name ) { //debugPlan; if ( factory() ) { return ( ( QMenu* ) factory() ->container( name, this ) ); } debugPlan<<"No factory"; return 0L; } void View::slotUpdate() { //debugPlan<<"calculate="<currentWidget() ); } void View::slotGuiActivated( ViewBase *view, bool activate ) { //FIXME: Avoid unplug if possible, it flashes the gui // always unplug, in case they already are plugged foreach( const QString &name, view->actionListNames() ) { unplugActionList( name ); } if ( activate ) { foreach( const QString &name, view->actionListNames() ) { plugActionList( name, view->actionList( name ) ); } foreach ( DockWidget *ds, view->dockers() ) { m_dockers.append( ds ); ds->activate( mainWindow() ); } if (!m_dockers.isEmpty()) {debugPlan<<"Added dockers:"<deactivate( mainWindow() ); } } } void View::guiActivateEvent( bool activated ) { if ( activated ) { // plug my own actionlists, they may be gone slotPlugScheduleActions(); } // propagate to sub-view ViewBase *v = dynamic_cast( m_tab->currentWidget() ); if ( v ) { v->setGuiActive( activated ); } } void View::slotViewListItemRemoved( ViewListItem *item ) { getPart()->removeViewListItem( this, item ); } void View::removeViewListItem( const ViewListItem *item ) { if ( item == 0 ) { return; } ViewListItem *itm = m_viewlist->findItem( item->tag() ); if ( itm == 0 ) { return; } m_viewlist->removeViewListItem( itm ); return; } void View::slotViewListItemInserted( ViewListItem *item, ViewListItem *parent, int index ) { getPart()->insertViewListItem( this, item, parent, index ); } void View::addViewListItem( const ViewListItem *item, const ViewListItem *parent, int index ) { if ( item == 0 ) { return; } if ( parent == 0 ) { if ( item->type() != ViewListItem::ItemType_Category ) { return; } m_viewlist->blockSignals( true ); ViewListItem *cat = m_viewlist->addCategory( item->tag(), item->text( 0 ) ); cat->setToolTip( 0, item->toolTip( 0 ) ); m_viewlist->blockSignals( false ); return; } ViewListItem *cat = m_viewlist->findCategory( parent->tag() ); if ( cat == 0 ) { return; } m_viewlist->blockSignals( true ); createView( cat, item->viewType(), item->tag(), item->text( 0 ), item->toolTip( 0 ), index ); m_viewlist->blockSignals( false ); } void View::createReportView(const QDomDocument &doc) { #ifdef PLAN_USE_KREPORT QPointer vd = new ViewListReportsDialog( this, *m_viewlist, doc, this ); vd->exec(); // FIXME make non-crash delete vd; #endif } void View::slotOpenReportFile() { #ifdef PLAN_USE_KREPORT QFileDialog *dlg = new QFileDialog(this); connect(dlg, SIGNAL(finished(int)), SLOT(slotOpenReportFileFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); #endif } void View::slotOpenReportFileFinished( int result ) { #ifdef PLAN_USE_KREPORT QFileDialog *fdlg = qobject_cast( sender() ); if ( fdlg == 0 || result != QDialog::Accepted ) { return; } QString fn = fdlg->selectedFiles().value(0); if ( fn.isEmpty() ) { return; } QFile file( fn ); if ( ! file.open( QIODevice::ReadOnly | QIODevice::Text ) ) { KMessageBox::sorry( this, xi18nc( "@info", "Cannot open file:
%1", fn ) ); return; } QDomDocument doc; doc.setContent( &file ); createReportView(doc); #endif } void View::slotReportDesignFinished( int /*result */) { #ifdef PLAN_USE_KREPORT if ( sender() ) { sender()->deleteLater(); } #endif } void View::slotCreateView() { ViewListDialog *dlg = new ViewListDialog( this, *m_viewlist, this ); connect(dlg, SIGNAL(finished(int)), SLOT(slotCreateViewFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } void View::slotCreateViewFinished( int ) { if ( sender() ) { sender()->deleteLater(); } } void View::slotViewActivated( ViewListItem *item, ViewListItem *prev ) { QApplication::setOverrideCursor( Qt::WaitCursor ); if ( prev && prev->type() == ViewListItem::ItemType_Category && m_viewlist->previousViewItem() ) { // A view is shown anyway... ViewBase *v = qobject_cast( m_viewlist->previousViewItem()->view() ); if ( v ) { v->setGuiActive( false ); } } else if ( prev && prev->type() == ViewListItem::ItemType_SubView ) { ViewBase *v = qobject_cast( prev->view() ); if ( v ) { v->setGuiActive( false ); } } if ( item && item->type() == ViewListItem::ItemType_SubView ) { //debugPlan<<"Activate:"<setCurrentWidget( item->view() ); // Add sub-view specific gui ViewBase *v = dynamic_cast( m_tab->currentWidget() ); if ( v ) { v->setGuiActive( true ); } } QApplication::restoreOverrideCursor(); } QWidget *View::canvas() const { return m_tab->currentWidget();//KoView::canvas(); } KoPageLayout View::pageLayout() const { return currentView()->pageLayout(); } void View::setPageLayout(const KoPageLayout &pageLayout) { currentView()->setPageLayout(pageLayout); } QPrintDialog *View::createPrintDialog( KoPrintJob *printJob, QWidget *parent ) { debugPlan<( printJob ); if ( ! job ) { return 0; } QPrintDialog *dia = KoView::createPrintDialog( job, parent ); PrintingDialog *j = dynamic_cast( job ); if ( j ) { new PrintingControlPrivate( j, dia ); } return dia; } void View::slotCurrentChanged( int view ) { m_visitedViews << view; ViewListItem *item = m_viewlist->findItem( qobject_cast( m_tab->currentWidget() ) ); m_viewlist->setCurrentItem( item ); } void View::slotSelectDefaultView() { m_tab->setCurrentIndex(qMin(m_defaultView, m_tab->count()-1)); } void View::updateView( QWidget * ) { QApplication::setOverrideCursor( Qt::WaitCursor ); //setScheduleActionsEnabled(); QWidget *widget2; widget2 = m_viewlist->findView( "ResourceAssignmentView" ); if ( widget2 && m_updateResourceAssignmentView ) static_cast( widget2 ) ->draw( getProject() ); m_updateResourceAssignmentView = false; QApplication::restoreOverrideCursor(); } void View::slotRenameNode( Node *node, const QString& name ) { //debugPlan<type() ) { case Node::Type_Task: s = kundo2_i18n( "Modify task name" ); break; case Node::Type_Milestone: s = kundo2_i18n( "Modify milestone name" ); break; case Node::Type_Summarytask: s = kundo2_i18n( "Modify summarytask name" ); break; case Node::Type_Project: s = kundo2_i18n( "Modify project name" ); break; } NodeModifyNameCmd * cmd = new NodeModifyNameCmd( *node, name, s ); getPart() ->addCommand( cmd ); } } void View::slotPopupMenu( const QString& menuname, const QPoint & pos ) { QMenu * menu = this->popupMenu( menuname ); if ( menu ) { //debugPlan<actions().count(); ViewBase *v = qobject_cast( m_tab->currentWidget() ); //debugPlan< lst; if ( v ) { lst = v->contextActionList(); debugPlan<addSeparator(); foreach ( QAction *a, lst ) { menu->addAction( a ); } } } menu->exec( pos ); foreach ( QAction *a, lst ) { menu->removeAction( a ); } } } void View::slotPopupMenu( const QString& menuname, const QPoint &pos, ViewListItem *item ) { //debugPlan<context(); if ( ctx == 0 || ! ctx->isLoaded() ) { return false; } KoXmlElement n = ctx->context(); QString cv = n.attribute( "current-view" ); if ( ! cv.isEmpty() ) { m_viewlist->setSelected( m_viewlist->findItem( cv ) ); } else debugPlan<<"No current view"; long id = n.attribute( "current-schedule", "-1" ).toLong(); if ( id != -1 ) { setActiveSchedule( id ); } else debugPlan<<"No current schedule"; return true; } void View::saveContext( QDomElement &me ) const { //debugPlan; long id = activeScheduleId(); if ( id != -1 ) { me.setAttribute( "current-schedule", QString::number((qlonglong)id) ); } ViewListItem *item = m_viewlist->findItem( qobject_cast( m_tab->currentWidget() ) ); if ( item ) { me.setAttribute("current-view", item->tag() ); } m_viewlist->save( me ); } bool View::loadWorkPackage( Project &project, const QUrl &url ) { return getPart()->loadWorkPackage( project, url ); } void View::setLabel( ScheduleManager *sm ) { //debugPlan; Schedule *s = sm == 0 ? 0 : sm->expected(); if ( s && !s->isDeleted() && s->isScheduled() ) { m_estlabel->setText( sm->name() ); return; } m_estlabel->setText( xi18nc( "@info:status", "Not scheduled" ) ); } void View::slotWorkPackageLoaded() { debugPlan<workPackages(); } void View::slotMailWorkpackage( Node *node, Resource *resource ) { debugPlan; QTemporaryFile tmpfile(QDir::tempPath() + QLatin1String("/calligraplanwork_XXXXXX") + QLatin1String( ".planwork" )); tmpfile.setAutoRemove( false ); if ( ! tmpfile.open() ) { debugPlan<<"Failed to open file"; KMessageBox::error(0, i18n("Failed to open temporary file" ) ); return; } QUrl url = QUrl::fromLocalFile( tmpfile.fileName() ); if ( ! getPart()->saveWorkPackageUrl( url, node, activeScheduleId(), resource ) ) { debugPlan<<"Failed to save to file"; KMessageBox::error(0, xi18nc( "@info", "Failed to save to temporary file:
%1", url.url() ) ); return; } QStringList attachURLs; attachURLs << url.url(); QString to = resource == 0 ? node->leader() : ( resource->name() + " <" + resource->email() + '>' ); QString cc; QString bcc; QString subject = i18n( "Work Package: %1", node->name() ); QString body = i18nc( "1=project name, 2=task name", "%1\n%2", getProject().name(), node->name() ); QString messageFile; KToolInvocation::invokeMailer( to, cc, bcc, subject, body, messageFile, attachURLs ); } void View::slotMailWorkpackages( const QList &nodes, Resource *resource ) { debugPlan; if ( resource == 0 ) { warnPlan<<"No resource, we don't handle node->leader() yet"; return; } QString to = resource->name() + " <" + resource->email() + '>'; QString subject = i18n( "Work Package for project: %1", getProject().name() ); QString body; QStringList attachURLs; foreach ( Node *n, nodes ) { QTemporaryFile tmpfile(QDir::tempPath() + QLatin1String("/calligraplanwork_XXXXXX") + QLatin1String( ".planwork" )); tmpfile.setAutoRemove( false ); if ( ! tmpfile.open() ) { debugPlan<<"Failed to open file"; KMessageBox::error(0, i18n("Failed to open temporary file" ) ); return; } QUrl url = QUrl::fromLocalFile( tmpfile.fileName() ); if ( ! getPart()->saveWorkPackageUrl( url, n, activeScheduleId(), resource ) ) { debugPlan<<"Failed to save to file"; KMessageBox::error(0, xi18nc( "@info", "Failed to save to temporary file:
%1", url.url() ) ); return; } attachURLs << url.url(); body += n->name() + '\n'; } QString cc; QString bcc; QString messageFile; KToolInvocation::invokeMailer( to, cc, bcc, subject, body, messageFile, attachURLs ); } void View::slotCurrencyConfig() { LocaleConfigMoneyDialog *dlg = new LocaleConfigMoneyDialog( getProject().locale(), this ); connect(dlg, SIGNAL(finished(int)), SLOT(slotCurrencyConfigFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } void View::slotCurrencyConfigFinished( int result ) { LocaleConfigMoneyDialog *dlg = qobject_cast( sender() ); if ( dlg == 0 ) { return; } if ( result == QDialog::Accepted ) { KUndo2Command *c = dlg->buildCommand( getProject() ); if ( c ) { getPart()->addCommand( c ); } } dlg->deleteLater(); } void View::saveTaskModule( const QUrl &url, Project *project ) { // NOTE: workaround: KoResourcePaths::saveLocation( "calligraplan_taskmodules" ); does not work const QString dir = KoResourcePaths::saveLocation( "appdata", "taskmodules/" ); debugPlan<<"dir="<setDocument( doc ); doc->disconnect(); // doc shall not handle feedback from openUrl() doc->setAutoSave( 0 ); //disable doc->insertProject( *project, 0, 0 ); // FIXME: destroys project, find better way doc->getProject().setName( project->name() ); doc->getProject().setLeader( project->leader() ); doc->getProject().setDescription( project->description() ); doc->saveNativeFormat( dir + url.fileName() ); part->deleteLater(); // also deletes document debugPlan<" "" "" "%1" "" "" "predefined" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "") .arg( i18n( "Report" ), i18nc( "Project manager", "Manager:" ), i18n( "Project:" ), i18n( "Task Status Report" ), i18nc( "As in: Page 1 of 2", "of" ), i18n( "Page" ), i18nc( "Task name", "Name" ), i18nc( "Task completion", "Completion (%)" ) ); #endif return s; } } //KPlato namespace diff --git a/src/kptview.h b/src/kptview.h index 13c755cc..f9a898bc 100644 --- a/src/kptview.h +++ b/src/kptview.h @@ -1,452 +1,452 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999, 2000 Torben Weis Copyright (C) 2002 - 2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTVIEW_H #define KPTVIEW_H #include "plan_export.h" #include #include "kptcontext.h" #include "kptviewbase.h" #include #include #include #include #include class QMenu; class QPrintDialog; class QStackedWidget; class QSplitter; class QUrl; class KUndo2Command; class QAction; class KToggleAction; class QLabel; class KConfigSkeleton; class KConfigSkeletonItem; class KoView; namespace KPlato { class View; class ViewBase; class ViewListItem; class ViewListWidget; struct ViewInfo; class AccountsView; class GanttView; class PertEditor; class AccountsEditor; class TaskEditor; class CalendarEditor; class ScheduleEditor; class ScheduleManager; class CalculateScheduleCmd; class ResourceAssignmentView; class TaskStatusView; class Calendar; class MainDocument; class Part; class Node; class Project; class Task; class MainSchedule; class Schedule; class Resource; class ResourceGroup; class Relation; class Context; class ViewAdaptor; class HtmlView; class ReportView; class ReportDesignDialog; class DockWidget; class ConfigDialog : public KConfigDialog { Q_OBJECT public: ConfigDialog( QWidget *parent, const QString &name, KConfigSkeleton *config ); protected Q_SLOTS: /// Return true if any widget has changed virtual bool hasChanged(); /** * Update the settings from the dialog. * Virtual function for custom additions. * * Example use: User clicks Ok or Apply button in a configure dialog. */ virtual void updateSettings(); /** * Update the dialog based on the settings. * Virtual function for custom additions. * * Example use: Initialisation of dialog. * Example use: User clicks Reset button in a configure dialog. */ virtual void updateWidgets(); /** * Update the dialog based on the default settings. * Virtual function for custom additions. * * Example use: User clicks Defaults button in a configure dialog. */ virtual void updateWidgetsDefault(); /** * Returns whether the current state of the dialog is * the same as the default configuration. */ virtual bool isDefault(); private: KConfigSkeleton *m_config; QMap m_signalsmap; QMap m_itemmap; QMap m_propertymap; }; //------------- class PLAN_EXPORT View : public KoView { Q_OBJECT public: explicit View(KoPart *part, MainDocument *doc, QWidget *parent = 0); ~View(); MainDocument *getPart() const; KoPart *getKoPart() const; Project& getProject() const; QMenu *popupMenu( const QString& name ); virtual bool loadContext(); virtual void saveContext( QDomElement &context ) const; /// Load the workpackage from @p url into @p project. Return true if successful, else false. bool loadWorkPackage( Project &project, const QUrl &url ); QWidget *canvas() const; KoPageLayout pageLayout() const; void setPageLayout(const KoPageLayout &pageLayout); ScheduleManager *currentScheduleManager() const; long activeScheduleId() const; void setActiveSchedule( long id ); /// Returns the default view information like standard name and tooltip for view type @p type ViewInfo defaultViewInfo( const QString &type ) const; /// Returns the default category information like standard name and tooltip for category type @p type ViewInfo defaultCategoryInfo( const QString &type ) const; ViewBase *createTaskEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createResourceEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createAccountsEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createCalendarEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createScheduleHandler( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ScheduleEditor *createScheduleEditor( QWidget *parent ); ViewBase *createScheduleEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createDependencyEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createPertEditor( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createProjectStatusView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createPerformanceStatusView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createTaskStatusView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createTaskView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createTaskWorkPackageView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createGanttView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createMilestoneGanttView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createResourceAppointmentsView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createResourceAppointmentsGanttView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createAccountsView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createResourceAssignmentView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createChartView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createReportView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); ViewBase *createReportsGeneratorView( ViewListItem *cat, const QString &tag, const QString &name = QString(), const QString &tip = QString(), int index = -1 ); KoPrintJob * createPrintJob(); QPrintDialog* createPrintDialog(KoPrintJob*, QWidget*); Q_SIGNALS: - void currentScheduleManagerChanged( ScheduleManager *sm ); + void currentScheduleManagerChanged(KPlato::ScheduleManager *sm); void taskModulesChanged(const QStringList &modules); public Q_SLOTS: void slotUpdate(); void slotCreateNewProject(); void slotEditResource(); - void slotEditResource( Resource *resource ); + void slotEditResource(KPlato::Resource *resource); void slotEditCut(); void slotEditCopy(); void slotEditPaste(); void slotRefreshView(); void slotViewSelector( bool show ); void slotAddTask(); void slotAddSubTask(); void slotAddMilestone(); void slotAddSubMilestone(); void slotProjectEdit(); void slotDefineWBS(); void slotCurrencyConfig(); void slotCreateView(); void slotConfigure(); void slotIntroduction(); - void slotAddRelation( Node *par, Node *child ); - void slotModifyRelation( Relation *rel ); - void slotAddRelation( Node *par, Node *child, int linkType ); - void slotModifyRelation( Relation *rel, int linkType ); + void slotAddRelation(KPlato::Node *par, KPlato::Node *child); + void slotModifyRelation(KPlato::Relation *rel); + void slotAddRelation(KPlato::Node *par, KPlato::Node *child, int linkType); + void slotModifyRelation(KPlato::Relation *rel, int linkType); void slotModifyRelation(); void slotDeleteRelation(); - void slotRenameNode( Node *node, const QString& name ); + void slotRenameNode(KPlato::Node *node, const QString& name); void slotPopupMenu( const QString& menuname, const QPoint &pos ); - void slotPopupMenu( const QString& menuname, const QPoint &pos, ViewListItem *item ); + void slotPopupMenu( const QString& menuname, const QPoint &pos, KPlato::ViewListItem *item ); - void addViewListItem( const ViewListItem *item, const ViewListItem *parent, int index ); - void removeViewListItem( const ViewListItem *item ); + void addViewListItem(const KPlato::ViewListItem *item, const KPlato::ViewListItem *parent, int index); + void removeViewListItem(const KPlato::ViewListItem *item); void slotOpenReportFile(); protected Q_SLOTS: - void slotGuiActivated( ViewBase *view, bool ); - void slotViewActivated( ViewListItem*, ViewListItem* ); + void slotGuiActivated(KPlato::ViewBase *view, bool); + void slotViewActivated(KPlato::ViewListItem*, KPlato::ViewListItem*); void slotPlugScheduleActions(); void slotViewSchedule( QAction *act ); - void slotScheduleChanged( MainSchedule* ); - void slotScheduleAdded( const MainSchedule * ); - void slotScheduleRemoved( const MainSchedule * ); - void slotSelectionChanged( ScheduleManager *sm ); + void slotScheduleChanged(KPlato::MainSchedule*); + void slotScheduleAdded(const KPlato::MainSchedule*); + void slotScheduleRemoved( const KPlato::MainSchedule*); + void slotSelectionChanged(KPlato::ScheduleManager *sm); - void slotAddScheduleManager( Project *project ); - void slotDeleteScheduleManager( Project *project, ScheduleManager *sm ); - void slotMoveScheduleManager( ScheduleManager *sm, ScheduleManager *parent, int index ); - void slotCalculateSchedule( Project*, ScheduleManager* ); - void slotBaselineSchedule( Project *project, ScheduleManager *sm ); + void slotAddScheduleManager(KPlato::Project *project); + void slotDeleteScheduleManager(KPlato::Project *project, KPlato::ScheduleManager *sm); + void slotMoveScheduleManager(KPlato::ScheduleManager *sm, KPlato::ScheduleManager *parent, int index); + void slotCalculateSchedule(KPlato::Project*, KPlato::ScheduleManager*); + void slotBaselineSchedule(KPlato::Project *project, KPlato::ScheduleManager *sm); void slotProjectWorktime(); void slotOpenNode(); - void slotOpenNode( Node *node ); + void slotOpenNode(KPlato::Node *node); void slotTaskProgress(); void slotTaskDescription(); - void slotDeleteTask( QList lst ); - void slotDeleteTask( Node *node ); + void slotDeleteTask(QList lst); + void slotDeleteTask(KPlato::Node *node); void slotDeleteTask(); void slotIndentTask(); void slotUnindentTask(); void slotMoveTaskUp(); void slotMoveTaskDown(); void slotConnectNode(); - void slotDeleteResource( Resource *resource ); - void slotDeleteResourceGroup( ResourceGroup *group ); + void slotDeleteResource(KPlato::Resource *resource); + void slotDeleteResourceGroup(KPlato::ResourceGroup *group); void slotDeleteResourceObjects( QObjectList ); void slotCurrentChanged( int ); void slotSelectDefaultView(); void slotInsertResourcesFile(const QString&, const QUrl &projects); void slotInsertFile(); void slotWorkPackageLoaded(); - void slotMailWorkpackage( Node *node, Resource *resource = 0 ); - void slotMailWorkpackages( const QList &nodes, Resource *resource = 0 ); + void slotMailWorkpackage(KPlato::Node *node, KPlato::Resource *resource = 0); + void slotMailWorkpackages(const QList &nodes, KPlato::Resource *resource = 0 ); - void slotOpenUrlRequest( HtmlView *v, const QUrl &url ); + void slotOpenUrlRequest(KPlato::HtmlView *v, const QUrl &url); - void slotProjectCalculated( ScheduleManager *sm ); + void slotProjectCalculated(KPlato::ScheduleManager *sm); - void slotUpdateViewInfo( ViewListItem *itm ); + void slotUpdateViewInfo(KPlato::ViewListItem *itm); void createReportView(const QDomDocument &doc); - void saveTaskModule( const QUrl &url, Project *project ); + void saveTaskModule(const QUrl &url, KPlato::Project *project); void removeTaskModule( const QUrl &url ); void taskModuleFileChanged(const QString &path); protected: virtual void guiActivateEvent( bool activated ); virtual void updateReadWrite( bool readwrite ); QList sortedActionList(); QAction *addScheduleAction( Schedule *sch ); void setLabel( ScheduleManager *sm = 0 ); Task *currentTask() const; Node *currentNode() const; Resource *currentResource(); ResourceGroup *currentResourceGroup(); Calendar *currentCalendar(); void updateView( QWidget *widget ); ViewBase *currentView() const; ViewBase *createIntroductionView(); private Q_SLOTS: void slotActionDestroyed( QObject *o ); - void slotViewListItemRemoved( ViewListItem *item ); - void slotViewListItemInserted( ViewListItem *item, ViewListItem *parent, int index ); + void slotViewListItemRemoved(KPlato::ViewListItem *item); + void slotViewListItemInserted(KPlato::ViewListItem *item, KPlato::ViewListItem *parent, int index); void slotProjectEditFinished( int result ); void slotTaskEditFinished( int result ); void slotSummaryTaskEditFinished( int result ); void slotEditResourceFinished( int result ); void slotProjectWorktimeFinished( int result ); void slotDefineWBSFinished( int result ); void slotCurrencyConfigFinished( int result ); void slotInsertFileFinished( int result ); void slotAddSubTaskFinished( int result ); void slotAddTaskFinished( int result ); void slotAddSubMilestoneFinished( int result ); void slotAddMilestoneFinished( int result ); void slotTaskProgressFinished( int result ); void slotMilestoneProgressFinished( int result ); void slotTaskDescriptionFinished( int result ); void slotAddRelationFinished( int result ); void slotModifyRelationFinished( int result ); void slotReportDesignFinished( int result ); void slotOpenReportFileFinished( int result ); void slotCreateViewFinished( int result ); void slotRemoveCommands(); void hideToolDocker(); void initiateViews(); - void slotViewScheduleManager(ScheduleManager *sm); + void slotViewScheduleManager(KPlato::ScheduleManager *sm); private: void createViews(); ViewBase *createView( ViewListItem *cat, const QString &type, const QString &tag, const QString &name, const QString &tip, int index = -1 ); QString standardTaskStatusReport() const; private: QSplitter *m_sp; QStackedWidget *m_tab; ViewListWidget *m_viewlist; ViewListItem *m_viewlistItem; // requested popupmenu item //QDockWidget *m_toolbox; int m_viewGrp; int m_defaultFontSize; int m_currentEstimateType; bool m_updateAccountsview; bool m_updateResourceAssignmentView; bool m_updatePertEditor; QLabel *m_estlabel; ViewAdaptor* m_dbus; QActionGroup *m_scheduleActionGroup; QMap m_scheduleActions; QMultiMap m_calculationcommands; QList m_undocommands; bool m_readWrite; int m_defaultView; QList m_visitedViews; QList m_dockers; // ------ File QAction *actionCreateTemplate; QAction *actionCreateNewProject; // ------ Edit QAction *actionCut; QAction *actionCopy; QAction *actionPaste; // ------ View KToggleAction *actionViewSelector; // ------ Insert // ------ Project QAction *actionEditMainProject; // ------ Tools QAction *actionEditStandardWorktime; QAction *actionDefineWBS; QAction *actionInsertFile; QAction *actionCurrencyConfig; QAction *actionOpenReportFile; // ------ Settings QAction *actionConfigure; // ------ Help QAction *actionIntroduction; // ------ Popup QAction *actionOpenNode; QAction *actionTaskProgress; QAction *actionTaskDescription; QAction *actionDeleteTask; QAction *actionIndentTask; QAction *actionUnindentTask; QAction *actionMoveTaskUp; QAction *actionMoveTaskDown; QAction *actionEditResource; QAction *actionEditRelation; QAction *actionDeleteRelation; //Test QAction *actNoInformation; QMap m_reportActionMap; KoPart *m_partpart; KDirWatch m_dirwatch; }; } //Kplato namespace #endif diff --git a/src/kptviewlist.h b/src/kptviewlist.h index ebb28fb2..dbd1d75c 100644 --- a/src/kptviewlist.h +++ b/src/kptviewlist.h @@ -1,222 +1,222 @@ /* This file is part of the KDE project Copyright (C) 2007 - 2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTVIEWLIST_H #define KPTVIEWLIST_H #include "plan_export.h" #include "kptschedulemodel.h" #include class QDomElement; class KoDocument; class KoView; class QComboBox; namespace KPlato { class View; class ViewBase; class ViewListItem; class ViewListWidget; class MainDocument; class Context; class ScheduleManager; #define TIP_USE_DEFAULT_TEXT "TIP_USE_DEFAULT_TEXT" //-------------- struct ViewInfo { QString name; QString tip; }; //-------------- class PLAN_EXPORT ViewListItem : public QTreeWidgetItem { public: enum ItemType { ItemType_Category = Type, ItemType_SubView = UserType }; enum DataRole { DataRole_View = Qt::UserRole, DataRole_Document }; ViewListItem( const QString &tag, const QStringList &strings, int type = ItemType_Category ); ViewListItem( QTreeWidget *parent, const QString &tag, const QStringList &strings, int type = ItemType_Category ); ViewListItem( QTreeWidgetItem *parent, const QString &tag, const QStringList &strings, int type = ItemType_Category ); void setView( ViewBase *view ); ViewBase *view() const; void setDocument( KoDocument *doc ); KoDocument *document() const; void setViewInfo( const ViewInfo &vi ) { m_viewinfo = vi; } QString viewType() const; QString tag() const { return m_tag; } void save( QDomElement &element ) const; void setReadWrite( bool rw ); private: QString m_tag; ViewInfo m_viewinfo; }; class PLAN_EXPORT ViewListTreeWidget : public QTreeWidget { Q_OBJECT public: explicit ViewListTreeWidget( QWidget *parent ); ViewListItem *findCategory( const QString &cat ); /// Return the category of @p view ViewListItem *category( const KoView *view ) const; void save( QDomElement &element ) const; protected: void drawRow( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const; virtual void mousePressEvent ( QMouseEvent *event ); /// Setup drop enabled/disabled dependent on the selected item virtual void startDrag( Qt::DropActions supportedActions ); /// If modified by the drop, emit modified void dropEvent( QDropEvent *event ); Q_SIGNALS: void activated( QTreeWidgetItem* ); - void updateViewInfo( ViewListItem *itm ); + void updateViewInfo(KPlato::ViewListItem *itm); void modified(); private Q_SLOTS: void handleMousePress( QTreeWidgetItem *item ); }; class PLAN_EXPORT ViewListWidget : public QWidget { Q_OBJECT public: ViewListWidget( MainDocument *part, QWidget *parent );//QString name, KXmlGuiWindow *parent ); ~ViewListWidget(); /// Set read/write permission on all views. void setReadWrite( bool rw ); /// Add a category if it does not already exist ViewListItem *addCategory( const QString &tag, const QString& name ); /// Return a list of all categories QList categories() const; /// Return the category with @p tag ViewListItem *findCategory( const QString &tag ) const; /// Return the category of @p view ViewListItem *category( const KoView *view ) const; /// Create a unique tag QString uniqueTag( const QString &seed ) const; /// Add a sub-view ViewListItem *addView(QTreeWidgetItem *category, const QString &tag, const QString &name, ViewBase *view, KoDocument *doc, const QString &iconName = QString(), int index = -1 ); void setSelected( QTreeWidgetItem *item ); ViewListItem *currentItem() const; void setCurrentItem( QTreeWidgetItem *item ); ViewListItem *currentCategory() const; KoView *findView( const QString &tag ) const; ViewListItem *findItem( const QString &tag ) const; ViewListItem *findItem( const QString &tag, QTreeWidgetItem* parent ) const; ViewListItem *findItem( const ViewBase *view, QTreeWidgetItem* parent = 0 ) const; /// Remove @p item, don't emit signal int removeViewListItem( ViewListItem *item ); /// Add @p item to @p parent at @p index, don't emit signal void addViewListItem( ViewListItem *item, QTreeWidgetItem *parent, int index ); /// Remove @p item, emit signal int takeViewListItem( ViewListItem *item ); /// Add @p item to @p parent at @ index, emit signal void insertViewListItem( ViewListItem *item, QTreeWidgetItem *parent, int index ); void save( QDomElement &element ) const; ViewListItem *previousViewItem() const { return m_prev; } ScheduleManager *selectedSchedule() const; Q_SIGNALS: - void activated( ViewListItem*, ViewListItem* ); + void activated(KPlato::ViewListItem*, KPlato::ViewListItem*); void createView(); - void viewListItemRemoved( ViewListItem *item ); - void viewListItemInserted( ViewListItem *item, ViewListItem *parent, int index ); + void viewListItemRemoved(KPlato::ViewListItem *item); + void viewListItemInserted(KPlato::ViewListItem *item, KPlato::ViewListItem *parent, int index); - void selectionChanged( ScheduleManager* ); + void selectionChanged(KPlato::ScheduleManager*); - void updateViewInfo( ViewListItem *itm ); + void updateViewInfo(KPlato::ViewListItem *itm); void modified(); public Q_SLOTS: - void setProject( Project *project ); - void setSelectedSchedule( ScheduleManager *sm ); + void setProject(KPlato::Project *project); + void setSelectedSchedule(KPlato::ScheduleManager *sm); void setModified(); protected Q_SLOTS: void slotActivated( QTreeWidgetItem *item, QTreeWidgetItem *prev ); void slotItemChanged( QTreeWidgetItem *item, int col ); void renameCategory(); void slotAddView(); void slotRemoveCategory(); void slotRemoveView(); void slotEditViewTitle(); void slotEditDocumentTitle(); void slotConfigureItem(); void slotCurrentScheduleChanged( int ); - void slotScheduleManagerAdded( ScheduleManager* ); + void slotScheduleManagerAdded(KPlato::ScheduleManager*); void slotDialogFinished( int result ); protected: virtual void contextMenuEvent ( QContextMenuEvent *event ); private: void setupContextMenus(); private: MainDocument *m_part; ViewListTreeWidget *m_viewlist; QComboBox *m_currentSchedule; ScheduleSortFilterModel m_sfModel; ScheduleItemModel m_model; ViewListItem *m_contextitem; QList m_categoryactions; QList m_viewactions; QList m_listactions; ViewListItem *m_prev; ScheduleManager *m_temp; }; } //Kplato namespace #endif diff --git a/src/kptviewlistdialog.cpp b/src/kptviewlistdialog.cpp index 3352033f..a1bcdbe5 100644 --- a/src/kptviewlistdialog.cpp +++ b/src/kptviewlistdialog.cpp @@ -1,674 +1,674 @@ /* This file is part of the KDE project Copyright (C) 2007 - 2010 Dag Andersen Copyright (C) 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kptviewlistdialog.h" #include "kptviewlist.h" #include "kptview.h" #ifdef PLAN_USE_KREPORT #include "reports/reportview.h" #endif #include #include #include namespace KPlato { ViewListDialog::ViewListDialog( View *view, ViewListWidget &viewlist, QWidget *parent ) : KoDialog(parent) { setCaption( i18nc( "@title:window", "Add View") ); setButtons( KoDialog::Ok | KoDialog::Cancel ); setDefaultButton( Ok ); m_panel = new AddViewPanel( view, viewlist, this ); setMainWidget( m_panel ); enableButtonOk(false); connect(this,SIGNAL(okClicked()),this,SLOT(slotOk())); connect( m_panel, SIGNAL(enableButtonOk(bool)), SLOT(enableButtonOk(bool)) ); - connect( m_panel, SIGNAL(viewCreated(ViewBase*)), SIGNAL(viewCreated(ViewBase*)) ); + connect( m_panel, SIGNAL(viewCreated(KPlato::ViewBase*)), SIGNAL(viewCreated(KPlato::ViewBase*)) ); - connect(&viewlist, SIGNAL(viewListItemRemoved(ViewListItem*)), SLOT(slotViewListItemRemoved(ViewListItem*))); + connect(&viewlist, SIGNAL(viewListItemRemoved(KPlato::ViewListItem*)), SLOT(slotViewListItemRemoved(KPlato::ViewListItem*))); } void ViewListDialog::slotViewListItemRemoved( ViewListItem * ) { reject(); } void ViewListDialog::slotOk() { if ( m_panel->ok() ) { accept(); } } //------------------------ AddViewPanel::AddViewPanel( View *view, ViewListWidget &viewlist, QWidget *parent ) : QWidget( parent ), m_view( view ), m_viewlist( viewlist ), m_viewnameChanged( false ), m_viewtipChanged( false ) { widget.setupUi( this ); // NOTE: these lists must match switch in ok() FIXME: refactor m_viewtypes << "ResourceEditor" << "TaskEditor" << "CalendarEditor" << "AccountsEditor" << "DependencyEditor" << "PertEditor" << "ScheduleHandlerView" << "TaskStatusView" << "TaskView" << "TaskWorkPackageView" << "GanttView" << "MilestoneGanttView" << "ResourceAppointmentsView" << "ResourceAppointmentsGanttView" << "AccountsView" << "ProjectStatusView" << "PerformanceStatusView" << "ReportsGeneratorView"; #ifdef PLAN_USE_KREPORT m_viewtypes << "ReportView"; #endif QStringList lst; lst << i18n( "Resource Editor" ) << i18n( "Task Editor" ) << i18n( "Work & Vacation Editor" ) << i18n( "Accounts Editor" ) << i18n( "Dependency Editor (Graphic)" ) << i18n( "Dependency Editor (List)" ) << i18n( "Schedule Handler" ) << i18n( "Task Status" ) << i18n( "Task View" ) << i18n( "Work Package View" ) << i18n( "Gantt View" ) << i18n( "Milestone Gantt View" ) << i18n( "Resource Assignments" ) << i18n( "Resource Assignments (Gantt)" ) << i18n( "Cost Breakdown" ) << i18n( "Project Performance Chart" ) << i18n( "Tasks Performance Chart" ) << i18n("Reports generator"); #ifdef PLAN_USE_KREPORT lst << i18n( "Report" ); #endif widget.viewtype->addItems( lst ); foreach ( ViewListItem *item, m_viewlist.categories() ) { m_categories.insert( item->text( 0 ), item ); } widget.category->addItems( m_categories.keys() ); ViewListItem *curr = m_viewlist.currentCategory(); if ( curr ) { widget.category->setCurrentIndex( m_categories.values().indexOf( curr ) ); } fillAfter( m_categories.value( widget.category->currentText() ) ); viewtypeChanged( widget.viewtype->currentIndex() ); connect( widget.viewname, SIGNAL(textChanged(QString)), SLOT(changed()) ); connect( widget.tooltip, SIGNAL(textChanged(QString)), SLOT(changed()) ); connect( widget.viewname, SIGNAL(textChanged(QString)), SLOT(viewnameChanged(QString)) ); connect( widget.tooltip, SIGNAL(textChanged(QString)), SLOT(viewtipChanged(QString)) ); connect( widget.insertAfter, SIGNAL(currentIndexChanged(int)), SLOT(changed()) ); connect( widget.viewtype, SIGNAL(currentIndexChanged(int)), SLOT(viewtypeChanged(int)) ); connect( widget.category, SIGNAL(editTextChanged(QString)), SLOT(categoryChanged()) ); QString categoryWhatsThis = xi18nc("@info:whatsthis", "The category of the view" "The view is placed under this category in the view selector." "You can edit the category name to create a new category."); widget.categoryLabel->setWhatsThis(categoryWhatsThis); widget.category->setWhatsThis(categoryWhatsThis); } void AddViewPanel::viewnameChanged( const QString &text ) { m_viewnameChanged = ! text.isEmpty(); } void AddViewPanel::viewtipChanged( const QString &text ) { m_viewtipChanged = ! text.isEmpty(); } void AddViewPanel::viewtypeChanged( int idx ) { ViewInfo vi = m_view->defaultViewInfo( m_viewtypes.value( idx ) ); if ( widget.viewname->text().isEmpty() ) { m_viewnameChanged = false; } if ( ! m_viewnameChanged ) { widget.viewname->setText( vi.name ); m_viewnameChanged = false; } if ( widget.tooltip->text().isEmpty() ) { m_viewtipChanged = false; } if ( ! m_viewtipChanged ) { QTextEdit e; e.setText(vi.tip); widget.tooltip->setText(e.toPlainText()); m_viewtipChanged = false; } } void AddViewPanel::categoryChanged() { debugPlan<currentText(); fillAfter( m_categories.value( widget.category->currentText() ) ); changed(); } void AddViewPanel::fillAfter( ViewListItem *cat ) { debugPlan<clear(); if ( cat ) { widget.insertAfter->addItem( i18n( "Top" ) ); // int idx = 0; for ( int i = 0; i < cat->childCount(); ++i ) { ViewListItem *itm = static_cast( cat->child( i ) ); widget.insertAfter->addItem( itm->text( 0 ), QVariant::fromValue( (void*)itm ) ); } if ( cat == m_viewlist.currentCategory() ) { ViewListItem *v = m_viewlist.currentItem(); if ( v && v->type() != ViewListItem::ItemType_Category ) { widget.insertAfter->setCurrentIndex( cat->indexOfChild( v ) + 1 ); } } } } bool AddViewPanel::ok() { QString n = widget.category->currentText(); ViewListItem *curr = m_categories.value( n ); QString c = curr == 0 ? n : curr->tag(); ViewListItem *cat = m_viewlist.addCategory( c, n ); if ( cat == 0 ) { return false; } ViewBase *v = 0; int index = widget.insertAfter->currentIndex(); int viewtype = widget.viewtype->currentIndex(); switch ( viewtype ) { case 0: { // Resource editor v = m_view->createResourceEditor( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 1: { // Task editor v = m_view->createTaskEditor( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 2: { // Work & Vacation Editor v = m_view->createCalendarEditor( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 3: { // Accounts Editor v = m_view->createAccountsEditor( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 4: { // Dependency Editor (Graphic) v = m_view->createDependencyEditor( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 5: { // Dependency Editor (List) v = m_view->createPertEditor( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 6: { // Schedules Handler v = m_view->createScheduleHandler( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 7: { // Task status v = m_view->createTaskStatusView( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 8: { // Task status v = m_view->createTaskView( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 9: { // Task work package v = m_view->createTaskWorkPackageView( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 10: { // Gantt View v = m_view->createGanttView( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 11: { // Milestone Gantt View v = m_view->createMilestoneGanttView( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 12: { // Resource Assignments v = m_view->createResourceAppointmentsView( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 13: { // Resource Assignments (Gantt) v = m_view->createResourceAppointmentsGanttView( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 14: { // Cost Breakdown v = m_view->createAccountsView( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 15: { // Project Performance Chart v = m_view->createProjectStatusView( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 16: { // Task Performance Chart v = m_view->createPerformanceStatusView( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } case 17: { // Reports generator v = m_view->createReportsGeneratorView(cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index); break; } #ifdef PLAN_USE_KREPORT case 18: { // Report view v = m_view->createReportView( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); break; } #endif default: errorPlan<<"Unknown view type!"; break; } emit viewCreated( v ); return true; } void AddViewPanel::changed() { bool disable = widget.viewname->text().isEmpty() | widget.viewtype->currentText().isEmpty() | widget.category->currentText().isEmpty(); emit enableButtonOk( ! disable ); } //------------------------ ViewListEditViewDialog::ViewListEditViewDialog( ViewListWidget &viewlist, ViewListItem *item, QWidget *parent ) : KoDialog(parent) { setCaption( i18nc( "@title:window", "Configure View" ) ); setButtons( KoDialog::Ok | KoDialog::Cancel ); setDefaultButton( Ok ); m_panel = new EditViewPanel( viewlist, item, this ); setMainWidget( m_panel ); enableButtonOk(false); connect(this,SIGNAL(okClicked()),this,SLOT(slotOk())); connect( m_panel, SIGNAL(enableButtonOk(bool)), SLOT(enableButtonOk(bool)) ); connect(&viewlist, SIGNAL(viewListItemRemoved(ViewListItem*)), SLOT(slotViewListItemRemoved(ViewListItem*))); } void ViewListEditViewDialog::slotViewListItemRemoved( ViewListItem * ) { reject(); } void ViewListEditViewDialog::slotOk() { if ( m_panel->ok() ) { accept(); } } EditViewPanel::EditViewPanel( ViewListWidget &viewlist, ViewListItem *item, QWidget *parent ) : QWidget( parent ), m_item( item ), m_viewlist( viewlist ) { widget.setupUi( this ); widget.viewname->setText( item->text( 0 ) ); QTextEdit e; e.setText(item->toolTip(0)); widget.tooltip->setText(e.toPlainText()); foreach ( ViewListItem *item, m_viewlist.categories() ) { m_categories.insert( item->text( 0 ), item ); } widget.category->addItems( m_categories.keys() ); ViewListItem *curr = m_viewlist.currentCategory(); if ( curr ) { widget.category->setCurrentIndex( m_categories.values().indexOf( curr ) ); } categoryChanged(); connect( widget.viewname, SIGNAL(textChanged(QString)), SLOT(changed()) ); connect( widget.tooltip, SIGNAL(textChanged(QString)), SLOT(changed()) ); connect( widget.insertAfter, SIGNAL(currentIndexChanged(int)), SLOT(changed()) ); connect( widget.category, SIGNAL(editTextChanged(QString)), SLOT(categoryChanged()) ); QString categoryWhatsThis = xi18nc("@info:whatsthis", "The category of the view" "The view is placed under this category in the view selector." "Selecting a different category will move the view to the new category." "You can edit the category name to create a new category."); widget.categoryLabel->setWhatsThis(categoryWhatsThis); widget.category->setWhatsThis(categoryWhatsThis); } bool EditViewPanel::ok() { QString n = widget.category->currentText(); ViewListItem *curr = m_categories.value( n ); QString c = curr == 0 ? n : curr->tag(); ViewListItem *cat = m_viewlist.addCategory( c, n ); if ( cat == 0 ) { warnPlan<<"No category"; return false; } if ( widget.viewname->text() != m_item->text( 0 ) ) { m_item->setText( 0, widget.viewname->text() ); } if ( widget.tooltip->text() != m_item->toolTip( 0 ) ) { m_item->setToolTip( 0, widget.tooltip->text() ); } m_viewlist.removeViewListItem( m_item ); int index = qMin( widget.insertAfter->currentIndex(), cat->childCount() ); m_viewlist.addViewListItem( m_item, cat, index ); return true; } void EditViewPanel::changed() { bool disable = widget.viewname->text().isEmpty() | widget.category->currentText().isEmpty(); emit enableButtonOk( ! disable ); } void EditViewPanel::categoryChanged() { debugPlan<currentText(); fillAfter( m_categories.value( widget.category->currentText() ) ); changed(); } void EditViewPanel::fillAfter( ViewListItem *cat ) { debugPlan<clear(); if ( cat ) { widget.insertAfter->addItem( i18n( "Top" ) ); // int idx = 0; for ( int i = 0; i < cat->childCount(); ++i ) { ViewListItem *itm = static_cast( cat->child( i ) ); widget.insertAfter->addItem( itm->text( 0 ), QVariant::fromValue( (void*)itm ) ); } if ( cat == m_viewlist.currentCategory() ) { ViewListItem *v = m_viewlist.currentItem(); if ( v && v->type() != ViewListItem::ItemType_Category ) { widget.insertAfter->setCurrentIndex( cat->indexOfChild( v ) + 1 ); } } } } //------------------------ ViewListEditCategoryDialog::ViewListEditCategoryDialog( ViewListWidget &viewlist, ViewListItem *item, QWidget *parent ) : KoDialog(parent) { setCaption( i18nc( "@title:window", "Configure Category" ) ); setButtons( KoDialog::Ok | KoDialog::Cancel ); setDefaultButton( Ok ); m_panel = new EditCategoryPanel( viewlist, item, this ); setMainWidget( m_panel ); enableButtonOk(false); connect(this,SIGNAL(okClicked()),this,SLOT(slotOk())); connect( m_panel, SIGNAL(enableButtonOk(bool)), SLOT(enableButtonOk(bool)) ); - connect(&viewlist, SIGNAL(viewListItemRemoved(ViewListItem*)), SLOT(slotViewListItemRemoved(ViewListItem*))); + connect(&viewlist, SIGNAL(viewListItemRemoved(KPlato::ViewListItem*)), SLOT(slotViewListItemRemoved(KPlato::ViewListItem*))); } void ViewListEditCategoryDialog::slotViewListItemRemoved( ViewListItem * ) { reject(); } void ViewListEditCategoryDialog::slotOk() { if ( m_panel->ok() ) { accept(); } } EditCategoryPanel::EditCategoryPanel( ViewListWidget &viewlist, ViewListItem *item, QWidget *parent ) : QWidget( parent ), m_item( item ), m_viewlist( viewlist ) { widget.setupUi( this ); widget.viewname->setText( item->text( 0 ) ); QTextEdit e; e.setText(item->toolTip(0)); widget.tooltip->setText(e.toPlainText()); fillAfter(); connect( widget.viewname, SIGNAL(textChanged(QString)), SLOT(changed()) ); connect( widget.tooltip, SIGNAL(textChanged(QString)), SLOT(changed()) ); connect( widget.insertAfter, SIGNAL(currentIndexChanged(int)), SLOT(changed()) ); } bool EditCategoryPanel::ok() { if ( widget.viewname->text() != m_item->text( 0 ) ) { m_item->setText( 0, widget.viewname->text() ); } if ( widget.tooltip->text() != m_item->toolTip( 0 ) ) { m_item->setToolTip( 0, widget.tooltip->text() ); } bool ex = m_item->isExpanded(); m_viewlist.removeViewListItem( m_item ); int index = widget.insertAfter->currentIndex(); m_viewlist.addViewListItem( m_item, 0, index ); m_item->setExpanded( ex ); return true; } void EditCategoryPanel::changed() { bool disable = widget.viewname->text().isEmpty(); emit enableButtonOk( ! disable ); } void EditCategoryPanel::fillAfter() { debugPlan; widget.insertAfter->clear(); widget.insertAfter->addItem( i18n( "Top" ) ); int idx = 0; QList lst = m_viewlist.categories(); for ( int i = 0; i < lst.count(); ++i ) { ViewListItem *itm = lst[ i ]; if ( m_item == itm ) { idx = i; } else { widget.insertAfter->addItem( itm->text( 0 ), QVariant::fromValue( (void*)itm ) ); } } widget.insertAfter->setCurrentIndex( idx ); } #ifdef PLAN_USE_KREPORT //------ Reports ViewListReportsDialog::ViewListReportsDialog( View *view, ViewListWidget &viewlist, const QDomDocument &doc, QWidget *parent ) : KoDialog(parent) { setCaption( i18nc( "@title:window", "Add Report" ) ); setButtons( KoDialog::Ok | KoDialog::Cancel ); setDefaultButton( Ok ); m_panel = new AddReportsViewPanel( view, viewlist, doc, this ); setMainWidget( m_panel ); enableButtonOk(true); connect(this,SIGNAL(okClicked()),this,SLOT(slotOk())); connect( m_panel, SIGNAL(enableButtonOk(bool)), SLOT(enableButtonOk(bool)) ); - connect( m_panel, SIGNAL(viewCreated(ViewBase*)), SIGNAL(viewCreated(ViewBase*)) ); + connect( m_panel, SIGNAL(viewCreated(KPlato::ViewBase*)), SIGNAL(viewCreated(KPlato::ViewBase*))); - connect(&viewlist, SIGNAL(viewListItemRemoved(ViewListItem*)), SLOT(slotViewListItemRemoved(ViewListItem*))); + connect(&viewlist, SIGNAL(viewListItemRemoved(KPlato::ViewListItem*)), SLOT(slotViewListItemRemoved(KPlato::ViewListItem*))); } void ViewListReportsDialog::slotViewListItemRemoved( ViewListItem * ) { reject(); } void ViewListReportsDialog::slotOk() { if ( m_panel->ok() ) { accept(); } } //------------------------ AddReportsViewPanel::AddReportsViewPanel( View *view, ViewListWidget &viewlist, const QDomDocument &doc, QWidget *parent ) : QWidget( parent ), m_view( view ), m_viewlist( viewlist ), m_viewnameChanged( false ), m_viewtipChanged( false ), m_data(doc) { widget.setupUi( this ); // NOTE: these lists must match switch in ok() FIXME: refactor m_viewtypes << "ReportView"; QStringList lst; lst << i18n( "Report" ); widget.viewtype->addItems( lst ); foreach ( ViewListItem *item, m_viewlist.categories() ) { m_categories.insert( item->text( 0 ), item ); } widget.category->addItems( m_categories.keys() ); ViewListItem *curr = m_viewlist.currentCategory(); if ( curr ) { widget.category->setCurrentIndex( m_categories.values().indexOf( curr ) ); } fillAfter( m_categories.value( widget.category->currentText() ) ); viewtypeChanged( widget.viewtype->currentIndex() ); connect( widget.viewname, SIGNAL(textChanged(QString)), SLOT(changed()) ); connect( widget.tooltip, SIGNAL(textChanged(QString)), SLOT(changed()) ); connect( widget.viewname, SIGNAL(textChanged(QString)), SLOT(viewnameChanged(QString)) ); connect( widget.tooltip, SIGNAL(textChanged(QString)), SLOT(viewtipChanged(QString)) ); connect( widget.insertAfter, SIGNAL(currentIndexChanged(int)), SLOT(changed()) ); connect( widget.viewtype, SIGNAL(currentIndexChanged(int)), SLOT(viewtypeChanged(int)) ); connect( widget.category, SIGNAL(editTextChanged(QString)), SLOT(categoryChanged()) ); } void AddReportsViewPanel::viewnameChanged( const QString &text ) { m_viewnameChanged = ! text.isEmpty(); } void AddReportsViewPanel::viewtipChanged( const QString &text ) { m_viewtipChanged = ! text.isEmpty(); } void AddReportsViewPanel::viewtypeChanged( int idx ) { ViewInfo vi = m_view->defaultViewInfo( m_viewtypes.value( idx ) ); if ( widget.viewname->text().isEmpty() ) { m_viewnameChanged = false; } if ( ! m_viewnameChanged ) { widget.viewname->setText( vi.name ); m_viewnameChanged = false; } if ( widget.tooltip->text().isEmpty() ) { m_viewtipChanged = false; } if ( ! m_viewtipChanged ) { QTextEdit e; e.setText(vi.tip); widget.tooltip->setText(e.toPlainText()); m_viewtipChanged = false; } } void AddReportsViewPanel::categoryChanged() { debugPlan<currentText(); fillAfter( m_categories.value( widget.category->currentText() ) ); changed(); } void AddReportsViewPanel::fillAfter( ViewListItem *cat ) { debugPlan<clear(); if ( cat ) { widget.insertAfter->addItem( i18n( "Top" ) ); // int idx = 0; for ( int i = 0; i < cat->childCount(); ++i ) { ViewListItem *itm = static_cast( cat->child( i ) ); widget.insertAfter->addItem( itm->text( 0 ), QVariant::fromValue( (void*)itm ) ); } if ( cat == m_viewlist.currentCategory() ) { ViewListItem *v = m_viewlist.currentItem(); if ( v && v->type() != ViewListItem::ItemType_Category ) { widget.insertAfter->setCurrentIndex( cat->indexOfChild( v ) + 1 ); } } } } bool AddReportsViewPanel::ok() { QString n = widget.category->currentText(); ViewListItem *curr = m_categories.value( n ); QString c = curr == 0 ? n : curr->tag(); ViewListItem *cat = m_viewlist.addCategory( c, n ); if ( cat == 0 ) { return false; } ViewBase *v = 0; int index = widget.insertAfter->currentIndex(); int viewtype = widget.viewtype->currentIndex(); switch ( viewtype ) { case 0: { // Report view v = m_view->createReportView( cat, m_viewtypes.value( viewtype ), widget.viewname->text(), widget.tooltip->text(), index ); static_cast(v)->loadXML(m_data); break; } default: errorPlan<<"Unknown view type!"; break; } emit viewCreated( v ); return true; } void AddReportsViewPanel::changed() { bool disable = widget.viewname->text().isEmpty() | widget.viewtype->currentText().isEmpty() | widget.category->currentText().isEmpty(); emit enableButtonOk( ! disable ); } #endif } //KPlato namespace diff --git a/src/kptviewlistdialog.h b/src/kptviewlistdialog.h index df5dbb70..56b0b8ec 100644 --- a/src/kptviewlistdialog.h +++ b/src/kptviewlistdialog.h @@ -1,227 +1,227 @@ /* This file is part of the KDE project Copyright (C) 2007 - 2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTVIEWLISTDIALOG_H #define KPTVIEWLISTDIALOG_H #include "ui_kptviewlistaddview.h" #include "ui_kptviewlisteditview.h" #include "ui_kptviewlisteditcategory.h" #include #include #include namespace KPlato { class View; class ViewListWidget; class ViewListItem; class AddViewPanel; class EditViewPanel; class EditCategoryPanel; class ViewBase; class AddReportsViewPanel; class ViewListDialog : public KoDialog { Q_OBJECT public: ViewListDialog( View *view, ViewListWidget &viewlist, QWidget *parent=0 ); protected Q_SLOTS: void slotOk(); - void slotViewListItemRemoved( ViewListItem * ); + void slotViewListItemRemoved(KPlato::ViewListItem *); Q_SIGNALS: - void viewCreated( ViewBase *view ); + void viewCreated(KPlato::ViewBase *view); private: AddViewPanel *m_panel; }; class AddViewPanel : public QWidget { Q_OBJECT public: AddViewPanel( View *view, ViewListWidget &viewlist, QWidget *parent ); bool ok(); Ui::AddViewPanel widget; Q_SIGNALS: void enableButtonOk( bool ); - void viewCreated( ViewBase *view ); + void viewCreated(KPlato::ViewBase *view); protected Q_SLOTS: void changed(); void viewtypeChanged( int idx ); void categoryChanged(); - void fillAfter( ViewListItem *cat ); + void fillAfter(KPlato::ViewListItem *cat); void viewnameChanged( const QString &text ); void viewtipChanged( const QString &text ); private: View *m_view; ViewListWidget &m_viewlist; QMap m_categories; QStringList m_viewtypes; bool m_viewnameChanged; bool m_viewtipChanged; }; class ViewListEditViewDialog : public KoDialog { Q_OBJECT public: ViewListEditViewDialog( ViewListWidget &viewlist, ViewListItem *item, QWidget *parent=0 ); protected Q_SLOTS: void slotOk(); - void slotViewListItemRemoved( ViewListItem * ); + void slotViewListItemRemoved(KPlato::ViewListItem*); private: EditViewPanel *m_panel; }; class EditViewPanel : public QWidget { Q_OBJECT public: EditViewPanel( ViewListWidget &viewlist, ViewListItem *item, QWidget *parent ); bool ok(); Ui::EditViewPanel widget; Q_SIGNALS: void enableButtonOk( bool ); protected Q_SLOTS: void changed(); void categoryChanged(); - void fillAfter( ViewListItem *cat ); + void fillAfter(KPlato::ViewListItem *cat ); private: ViewListItem *m_item; ViewListWidget &m_viewlist; QMap m_categories; }; class ViewListEditCategoryDialog : public KoDialog { Q_OBJECT public: ViewListEditCategoryDialog( ViewListWidget &viewlist, ViewListItem *item, QWidget *parent=0 ); protected Q_SLOTS: void slotOk(); - void slotViewListItemRemoved( ViewListItem * ); + void slotViewListItemRemoved(KPlato::ViewListItem*); private: EditCategoryPanel *m_panel; }; class EditCategoryPanel : public QWidget { Q_OBJECT public: EditCategoryPanel( ViewListWidget &viewlist, ViewListItem *item, QWidget *parent ); bool ok(); Ui::EditCategoryPanel widget; Q_SIGNALS: void enableButtonOk( bool ); protected Q_SLOTS: void changed(); void fillAfter(); private: ViewListItem *m_item; ViewListWidget &m_viewlist; }; #ifdef PLAN_USE_KREPORT //-------- Reports class ViewListReportsDialog : public KoDialog { Q_OBJECT public: ViewListReportsDialog( View *view, ViewListWidget &viewlist, const QDomDocument &doc, QWidget *parent=0 ); protected Q_SLOTS: void slotOk(); - void slotViewListItemRemoved( ViewListItem * ); + void slotViewListItemRemoved(KPlato::ViewListItem*); Q_SIGNALS: - void viewCreated( ViewBase *view ); + void viewCreated(KPlato::ViewBase *view); private: AddReportsViewPanel *m_panel; }; class AddReportsViewPanel : public QWidget { Q_OBJECT public: AddReportsViewPanel( View *view, ViewListWidget &viewlist, const QDomDocument &doc, QWidget *parent ); bool ok(); Ui::AddViewPanel widget; Q_SIGNALS: void enableButtonOk( bool ); - void viewCreated( ViewBase *view ); + void viewCreated(KPlato::ViewBase *view); protected Q_SLOTS: void changed(); void viewtypeChanged( int idx ); void categoryChanged(); - void fillAfter( ViewListItem *cat ); + void fillAfter(KPlato::ViewListItem *cat); void viewnameChanged( const QString &text ); void viewtipChanged( const QString &text ); private: View *m_view; ViewListWidget &m_viewlist; QMap m_categories; QStringList m_viewtypes; bool m_viewnameChanged; bool m_viewtipChanged; QDomDocument m_data; }; #endif } //KPlato namespace #endif // CONFIGDIALOG_H diff --git a/src/libs/kernel/kptaccount.h b/src/libs/kernel/kptaccount.h index b5fe97ee..3e2e628a 100644 --- a/src/libs/kernel/kptaccount.h +++ b/src/libs/kernel/kptaccount.h @@ -1,298 +1,298 @@ /* This file is part of the KDE project Copyright (C) 2005 - 2007 Dag Andersen Copyright (C) 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTACCOUNT_H #define KPTACCOUNT_H #include "plankernel_export.h" #include #include #include "kptglobal.h" #include "kpteffortcostmap.h" #include "kptnode.h" #include "kptresource.h" #include class QDomElement; class QStringList; namespace KPlato { class Accounts; class Account; /** * Account holds one account. * An account can have any number of sub-accounts. * Account names must be unique. */ class PLANKERNEL_EXPORT Account { public: /** * Constructor. */ Account(); /** * */ explicit Account(const QString& name, const QString& description=QString()); /** * Destructor. */ ~Account(); QString name() const { return m_name; } void setName(const QString& name); QString description() const { return m_description; } void setDescription(const QString& desc); bool isElement() const { return m_accountList.isEmpty(); } bool isDefaultAccount() const; Accounts *list() const { return m_list; } void setList(Accounts *list) { m_list = list; } Account *parent() const { return m_parent; } void setParent(Account *parent) { m_parent = parent; } void clear() { m_accountList.clear(); } void insert(Account *account, int index = -1); void take(Account *account); bool isChildOf( const Account *account ) const; void insertChildren(); int indexOf( Account *account ) const { return m_accountList.indexOf( account ); } bool isBaselined( long id = BASELINESCHEDULE ) const; bool load(KoXmlElement &element, Project &project); void save(QDomElement &element) const; const QList &accountList() const { return m_accountList; } int childCount() const { return m_accountList.count(); } Account *childAt( int index ) const { return m_accountList.value( index ); } Account *findAccount() const { return findAccount(m_name); } Account *findAccount(const QString &id) const; bool removeId() { return removeId(m_name); } bool removeId(const QString &id); bool insertId(); bool insertId(Account *account); void changed(); class CostPlace { public: /// Create an empty cost place CostPlace() : m_account(0), m_objectId(), m_node(0), m_resource(0), m_running(false), m_startup(false), m_shutdown(false) {} /// Create an empty cost place for account @p acc explicit CostPlace(Account *acc) : m_account(acc), m_objectId(), m_node(0), m_resource(0), m_running(false), m_startup(false), m_shutdown(false) {} /// Create a cost place for a task CostPlace(Account *acc, Node *node, bool running=false, bool strtup=false, bool shutdown=false); /// Create a cost place for a resource CostPlace(Account *acc, Resource *resource, bool running=false); explicit CostPlace(CostPlace *cp) { m_account = cp->m_account; m_objectId = cp->m_objectId; m_node = cp->m_node; m_resource = cp->m_resource; m_running = cp->m_running; m_startup = cp->m_startup; m_shutdown = cp->m_shutdown; } ~CostPlace(); bool isBaselined( long id = BASELINESCHEDULE ) const; bool isEmpty() { return !(m_running || m_startup || m_shutdown); } Node *node() const { return m_node; } void setNode( Node *node ); Resource *resource() const { return m_resource; } void setResource( Resource *resource ); bool running() const { return m_running; } void setRunning(bool on ); bool startup() const { return m_startup; } void setStartup(bool on); bool shutdown() const { return m_shutdown; } void setShutdown(bool on); bool load(KoXmlElement &element, Project &project); void save(QDomElement &element) const; // for loading xml void setObjectId( const QString &id ); QString objectId() const; private: Account *m_account; QString m_objectId; Node *m_node; Resource *m_resource; bool m_running; bool m_startup; bool m_shutdown; }; void append(CostPlace *cp) { m_costPlaces.append(cp); } const QList &costPlaces() const {return m_costPlaces; } Account::CostPlace *findCostPlace(const Node &node) const; Account::CostPlace *findCostPlace(const Resource &resource) const; CostPlace *findRunning(const Resource &resource) const; void removeRunning(const Resource &resource); void addRunning(Resource &resource); CostPlace *findRunning(const Node &node) const; void removeRunning(const Node &node); void addRunning(Node &node); CostPlace *findStartup(const Node &node) const; void removeStartup(const Node &node); void addStartup(Node &node); CostPlace *findShutdown(const Node &node) const; void removeShutdown(const Node &node); void addShutdown(Node &node); void deleteCostPlace(CostPlace *cp); EffortCostMap plannedCost(long id = BASELINESCHEDULE) const; EffortCostMap plannedCost(const QDate &start, const QDate &end, long id = BASELINESCHEDULE) const; EffortCostMap actualCost(long id = BASELINESCHEDULE) const; EffortCostMap actualCost(const QDate &start, const QDate &end, long id = BASELINESCHEDULE) const; protected: EffortCostMap plannedCost(const CostPlace &cp, const QDate &start, const QDate &end, long id ) const; EffortCostMap actualCost(const Account::CostPlace &cp, const QDate &start, const QDate &end, long id) const; private: QString m_name; QString m_description; friend class Accounts; Accounts *m_list; Account *m_parent; QList m_accountList; QList m_costPlaces; #ifndef NDEBUG public: void printDebug(const QString& indent); #endif }; typedef QList AccountList; typedef QListIterator AccountListIterator; /** * Accounts administrates all accounts. */ class PLANKERNEL_EXPORT Accounts : public QObject { Q_OBJECT public: explicit Accounts(Project &project); ~Accounts(); Account *defaultAccount() const { return m_defaultAccount; } void setDefaultAccount(Account *account); /// Return the planned cost from all cost places of this account added to cost from all sub-accounts EffortCostMap plannedCost(const Account &account, long id = BASELINESCHEDULE) const; /// Return the planned cost from all cost places of this account added to cost from all sub-accounts /// for the interval @p start to @p end inclusive EffortCostMap plannedCost(const Account &account, const QDate &start, const QDate &end, long id = BASELINESCHEDULE) const; /// Return the actual cost from all cost places of this account added to cost from all sub-accounts EffortCostMap actualCost(const Account &account, long id = BASELINESCHEDULE) const; /// Return the actual cost from all cost places of this account added to cost from all sub-accounts /// for the interval @p start to @p end inclusive EffortCostMap actualCost(const Account &account, const QDate &start, const QDate &end, long id = BASELINESCHEDULE) const; void clear() { m_accountList.clear(); m_idDict.clear(); } void insert(Account *account, Account *parent=0, int index = -1); void take(Account *account); bool load(KoXmlElement &element, Project &project); void save(QDomElement &element) const; QStringList costElements() const; QStringList nameList() const; const AccountList &accountList() const { return m_accountList; } int accountCount() const { return m_accountList.count(); } Account *accountAt( int index ) const { return m_accountList.value( index ); } int indexOf( Account *account ) const { return m_accountList.indexOf( account ); } Account *findRunningAccount(const Resource &resource) const; Account *findRunningAccount(const Node &node) const; Account *findStartupAccount(const Node &node) const; Account *findShutdownAccount(const Node &node) const; Account *findAccount(const QString &id) const; bool insertId(Account *account); bool removeId(const QString &id); QString uniqueId( const QString &seed ) const; void accountDeleted(Account *account); void accountChanged( Account *account ); QList allAccounts() const { return m_idDict.values(); } QList allNodes() const; Q_SIGNALS: - void accountAdded( const Account * ); - void accountToBeAdded( const Account *, int ); - void accountRemoved( const Account * ); - void accountToBeRemoved( const Account * ); - void changed( Account *); + void accountAdded(const KPlato::Account*); + void accountToBeAdded(const KPlato::Account*, int); + void accountRemoved(const KPlato::Account*); + void accountToBeRemoved(const KPlato::Account*); + void changed(KPlato::Account*); void defaultAccountChanged(); private: Project &m_project; AccountList m_accountList; QMap m_idDict; Account *m_defaultAccount; #ifndef NDEBUG public: void printDebug(const QString& indent); #endif }; } //namespace KPlato #endif diff --git a/src/libs/kernel/kptcalendar.h b/src/libs/kernel/kptcalendar.h index 0b3c2ef7..14feefe3 100644 --- a/src/libs/kernel/kptcalendar.h +++ b/src/libs/kernel/kptcalendar.h @@ -1,695 +1,695 @@ /* This file is part of the KDE project Copyright (C) 2003 - 2007 Dag Andersen Copyright (C) 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTCALENDAR_H #define KPTCALENDAR_H #include "kptdatetime.h" #include "kptduration.h" #include "kptdebug.h" #include "plankernel_export.h" #include #include #include #include #include #ifdef HAVE_KHOLIDAYS namespace KHolidays { class HolidayRegion; } #endif class KUndo2Command; class QDomElement; class QStringList; /// The main namespace. namespace KPlato { class Calendar; class Project; class IntMap; //class DateTime; class Project; class Schedule; class XMLLoaderObject; class AppointmentIntervalList; class PLANKERNEL_EXPORT DateTimeInterval : public std::pair { public: DateTimeInterval() : std::pair() {} DateTimeInterval( const DateTime &t1, const DateTime &t2 ) : std::pair( t1, t2 ) {} DateTimeInterval &operator=( const DateTimeInterval &other ) { first = other.first; second = other.second; return *this; } bool isValid() const { return first.isValid() && second.isValid(); } void limitTo( const DateTime &start, const DateTime &end ) { if ( ! first.isValid() || ( start.isValid() && start > first ) ) { first = start; } if ( ! second.isValid() || ( end.isValid() && end < second ) ) { second = end; } if ( isValid() && first > second ) { first = second = DateTime(); } } void limitTo( const DateTimeInterval &interval ) { limitTo( interval.first, interval.second ); } DateTimeInterval limitedTo( const DateTime &start, const DateTime &end ) const { DateTimeInterval i = *this; i.limitTo( start, end ); return i; } DateTimeInterval limitedTo( const DateTimeInterval &interval ) const { return limitedTo( interval.first, interval.second ); } QString toString() const { return QStringLiteral( "%1 to %2" ) .arg( first.isValid()?first.toString():QStringLiteral("''") ) .arg( second.isValid()?second.toString():QStringLiteral("''") ); } }; /// TimeInterval is defined as a start time and a length. /// The end time (start + length) must not exceed midnight class PLANKERNEL_EXPORT TimeInterval : public std::pair { public: TimeInterval() : std::pair( QTime(), -1 ) {} explicit TimeInterval( std::pair value ) : std::pair( value ) { init(); } TimeInterval( QTime start, int length ) : std::pair( start, length ) { init(); } TimeInterval( const TimeInterval &value ) : std::pair( value.first, value.second ) { init(); } /// Return the intervals start time QTime startTime() const { return first; } /// Return the intervals calculated end time. Note: It may return QTime(0,0,0) QTime endTime() const { return first.addMSecs( second ); } double hours() const { return (double)(second) / ( 1000. * 60. * 60. ); } /// Returns true if this interval ends at midnight, and thus endTime() returns QTime(0,0,0) bool endsMidnight() const { return endTime() == QTime( 0, 0, 0 ); } bool isValid() const { return first.isValid() && second > 0; } bool isNull() const { return first.isNull() || second < 0; } TimeInterval &operator=( const TimeInterval &ti ) { first = ti.first; second = ti.second; return *this; } /// Returns true if the intervals overlap in any way bool intersects( const TimeInterval &ti ) const { if ( ! isValid() || ! ti.isValid() ) { return false; } if ( endsMidnight() && ti.endsMidnight() ) { return true; } if ( endsMidnight() ) { return first < ti.endTime(); } if ( ti.endsMidnight() ) { return ti.first < endTime(); } return ( first < ti.endTime() && endTime() > ti.first ) || ( ti.first < endTime() && ti.endTime() > first ); } protected: void init() { int s = QTime( 0, 0, 0 ).msecsTo( first ); if ( ( s + second ) > 86400000 ) { second = 86400000 - s; errorPlan<<"Overflow, limiting length to"< timeIntervals() const { return m_timeIntervals; } void addInterval( QTime t1, int length ) { addInterval( new TimeInterval( t1, length ) ); } /** * Caller needs to ensure that intervals are not overlapping. */ void addInterval(TimeInterval *interval); void addInterval(TimeInterval interval) { addInterval(new TimeInterval(interval)); } void clearIntervals() { m_timeIntervals.clear(); } void setIntervals(const QList &intervals) { m_timeIntervals.clear(); m_timeIntervals = intervals; } void removeInterval( TimeInterval *interval ); bool hasInterval( const TimeInterval *interval ) const; int numIntervals() const; DateTime start() const; DateTime end() const; QDate date() const { return m_date; } void setDate(QDate date) { m_date = date; } int state() const { return m_state; } void setState(int state) { m_state = state; } bool operator==(const CalendarDay *day) const; bool operator==(const CalendarDay &day) const; bool operator!=(const CalendarDay *day) const; bool operator!=(const CalendarDay &day) const; Duration workDuration() const; /** * Returns the amount of 'worktime' that can be done on * this day between the times start and end. */ Duration effort(QTime start, int length, const QTimeZone &timeZone, Schedule *sch=0); /** * Returns the amount of 'worktime' that can be done on * this day between the times start and end. */ Duration effort(QDate date, QTime start, int length, const QTimeZone &timeZone, Schedule *sch=0); /** * Returns the actual 'work interval' for the interval start to end. * If no 'work interval' exists, returns the interval start, end. * Use @ref hasInterval() to check if a 'work interval' exists. */ TimeInterval interval(QTime start, int length, const QTimeZone &timeZone, Schedule *sch=0) const; /** * Returns the actual 'work interval' for the interval start to end. * If no 'work interval' exists, returns the interval start, end. * Use @ref hasInterval() to check if a 'work interval' exists. */ TimeInterval interval(QDate date, QTime start, int length, const QTimeZone &timeZone, Schedule *sch=0) const; bool hasInterval() const; /** * Returns true if at least a part of a 'work interval' exists * for the interval start to end. */ bool hasInterval(QTime start, int length, const QTimeZone &timeZone, Schedule *sch=0) const; /** * Returns true if at least a part of a 'work interval' exists * for the interval @p start to @p start + @p length. * Assumes this day is date. (Used by weekday hasInterval().) * If @p sch is not 0, the schedule is checked for availability. */ bool hasInterval(QDate date, QTime start, int length, const QTimeZone &timeZone, Schedule *sch=0) const; Duration duration() const; const CalendarDay ©(const CalendarDay &day); static QString stateToString( int st, bool trans = false ); static QStringList stateList( bool trans = false ); private: QDate m_date; //NOTE: inValid if used for weekdays int m_state; Calendar *m_calendar; QList m_timeIntervals; #ifndef NDEBUG public: void printDebug(const QString& indent=QString()); #endif }; class PLANKERNEL_EXPORT CalendarWeekdays { public: CalendarWeekdays(); explicit CalendarWeekdays( const CalendarWeekdays *weekdays ); ~CalendarWeekdays(); bool load( KoXmlElement &element, XMLLoaderObject &status ); void save(QDomElement &element) const; const QList weekdays() const { QList lst = m_weekdays.values(); return lst; } /** * Returns the pointer to CalendarDay for day. * @param day The weekday number, must be between 1 (monday) and 7 (sunday) */ CalendarDay *weekday(int day) const; CalendarDay *weekday(QDate date) const { return weekday(date.dayOfWeek()); } static int dayOfWeek( const QString &name ); const QMap &weekdayMap() const; IntMap stateMap() const; // void setWeekday(IntMap::iterator it, int state) { m_weekdays.at(it.key())->setState(state); } int state(QDate date) const; int state(int weekday) const; void setState(int weekday, int state); QList intervals(int weekday) const; void setIntervals(int weekday, const QList &intervals); void clearIntervals(int weekday); bool operator==(const CalendarWeekdays *weekdays) const; bool operator!=(const CalendarWeekdays *weekdays) const; Duration effort(QDate date, QTime start, int length, const QTimeZone &timeZone, Schedule *sch=0); /** * Returns the actual 'work interval' on the weekday defined by date * for the interval @p start to @p start + @p length. * If no 'work interval' exists, returns the interval start, end. * Use @ref hasInterval() to check if a 'work interval' exists. * If @p sch is not 0, the schedule is checked for availability. */ TimeInterval interval(QDate date, QTime start, int length, const QTimeZone &timeZone, Schedule *sch) const; /** * Returns true if at least a part of a 'work interval' exists * on the weekday defined by date for the interval start to end. */ bool hasInterval(QDate date, QTime start, int length, const QTimeZone &timeZone, Schedule *sch) const; bool hasInterval() const; Duration duration() const; Duration duration(int weekday) const; const CalendarWeekdays ©(const CalendarWeekdays &weekdays); int indexOf( const CalendarDay *day ) const; private: Calendar *m_calendar; QMap m_weekdays; #ifndef NDEBUG public: void printDebug(const QString& indent=QString()); #endif }; /** * Calendar defines the working and nonworking days and hours. * A day can have the three states Undefined, NonWorking, or Working. * A calendar can have a parent calendar that defines the days that are * undefined in this calendar. * If a calendar have no parent, an undefined day defaults to Nonworking. * A Working day has one or more work intervals to define the work hours. * * The definition can consist of two parts: Weekdays and Day. * Day has highest priority. * * A typical calendar hierarchy could include calendars on 4 levels: * 1. Definition of normal weekdays and national holidays/vacation days. * 2. Definition of the company's special workdays/-time and vacation days. * 3. Definitions for groups of resources. * 4. Definitions for individual resources. * * A calendar can define a timezone different from the projects. * This enables planning with resources that does not recide in the same place. * */ class PLANKERNEL_EXPORT Calendar : public QObject { Q_OBJECT public: Calendar(); explicit Calendar(const QString& name, Calendar *parent=0); //Calendar( const Calendar &c ); QObject doesn't allow a copy constructor ~Calendar(); const Calendar &operator=(const Calendar &calendar ) { return copy( calendar ); } QString name() const { return m_name; } void setName(const QString& name); Calendar *parentCal() const { return m_parent; } /** * Set parent calendar to @p parent. * Removes myself from current parent and * inserts myself as child to new parent. */ void setParentCal( Calendar *parent, int pos = -1 ); bool isChildOf( const Calendar *cal ) const; Project *project() const { return m_project; } void setProject(Project *project); QString id() const { return m_id; } void setId(const QString& id); const QList &calendars() const { return m_calendars; } void addCalendar( Calendar *calendar, int pos = -1 ); void takeCalendar( Calendar *calendar ); int indexOf( const Calendar *calendar ) const; /// Return number of children int childCount() const { return m_calendars.count(); } /// Return child calendar at @p index, 0 if index out of bounds Calendar *childAt( int index ) const { return m_calendars.value( index ); } bool load( KoXmlElement &element, XMLLoaderObject &status ); void save(QDomElement &element) const; int state(QDate date) const; void setState( CalendarDay *day, CalendarDay::State state ); void addWorkInterval( CalendarDay *day, TimeInterval *ti ); void takeWorkInterval( CalendarDay *day, TimeInterval *ti ); void setWorkInterval( TimeInterval *ti, const TimeInterval &value ); /** * Find the definition for the day @p date. * If @p skipUndefined = true the day is NOT returned if it has state Undefined. */ CalendarDay *findDay(QDate date, bool skipUndefined=false) const; void addDay(CalendarDay *day); CalendarDay *takeDay(CalendarDay *day); const QList &days() const { return m_days; } QList > consecutiveVacationDays() const; QList workingDays() const; int indexOf( const CalendarDay *day ) const { return m_days.indexOf( const_cast( day ) ); } CalendarDay *dayAt( int index ) { return m_days.value( index ); } int numDays() const { return m_days.count(); } void setDate( CalendarDay *day, QDate date ); CalendarDay *day( QDate date ) const; IntMap weekdayStateMap() const; CalendarWeekdays *weekdays() const { return m_weekdays; } CalendarDay *weekday(int day) const { return m_weekdays->weekday(day); } int indexOfWeekday( const CalendarDay *day ) const { return m_weekdays->indexOf( day ); } const QList weekdayList() const { return m_weekdays->weekdays(); } int numWeekdays() const { return weekdayList().count(); } /// Sets the @p weekday data to the data in @p day void setWeekday( int weekday, const CalendarDay &day ); QString parentId() const { return m_parentId; } void setParentId(const QString& id) { m_parentId = id; } bool hasParent(Calendar *cal); /** * Returns the work intervals in the interval from @p start to @p end * Sets the load of each interval to @p load */ AppointmentIntervalList workIntervals(const DateTime &start, const DateTime &end, double load) const; /** * Returns the amount of 'worktime' that can be done in the * interval from @p start to @p end * If @p sch is not 0, the schedule is checked for availability. */ Duration effort(const DateTime &start, const DateTime &end, Schedule *sch=0) const; /** * Returns the first 'work interval' for the interval * starting at @p start and ending at @p end. * If no 'work interval' exists, returns an interval with invalid DateTime. * You can also use @ref hasInterval() to check if a 'work interval' exists. * If @p sch is not 0, the schedule is checked for availability. */ DateTimeInterval firstInterval(const DateTime &start, const DateTime &end, Schedule *sch=0) const; /** * Returns true if at least a part of a 'work interval' exists * for the interval starting at @p start and ending at @p end. * If @p sch is not 0, the schedule is checked for availability. */ bool hasInterval(const DateTime &start, const DateTime &end, Schedule *sch=0) const; /** * Find the first available time after @p time before @p limit. * Return invalid datetime if not available. * If @p sch is not 0, the schedule is checked for availability. */ DateTime firstAvailableAfter(const DateTime &time, const DateTime &limit, Schedule *sch = 0); /** * Find the first available time backwards from @p time. Search until @p limit. * Return invalid datetime if not available. * If @p sch is not 0, the schedule is checked for availability. */ DateTime firstAvailableBefore(const DateTime &time, const DateTime &limit, Schedule *sch = 0); Calendar *findCalendar() const { return findCalendar(m_id); } Calendar *findCalendar(const QString &id) const; bool removeId() { return removeId(m_id); } bool removeId(const QString &id); void insertId(const QString &id); QTimeZone timeZone() const { return m_timeZone; } void setTimeZone( const QTimeZone &tz ); /// Return the project timezone, or local timezone if no project QTimeZone projectTimeZone() const; void setDefault( bool on ); bool isDefault() const { return m_default; } int cacheVersion() const; void incCacheVersion(); void setCacheVersion( int version ); bool loadCacheVersion( KoXmlElement &element, XMLLoaderObject &status ); void saveCacheVersion( QDomElement &element ) const; /// A calendar can be local to this project, or /// defined externally and shared with other projects bool isShared() const; /// Set calendar to be local if on = false, or shared if on = true void setShared(bool on); #ifdef HAVE_KHOLIDAYS bool isHoliday(QDate date) const; KHolidays::HolidayRegion *holidayRegion() const; void setHolidayRegion(const QString &code); QString holidayRegionCode() const; QStringList holidayRegionCodes() const; #endif Q_SIGNALS: - void changed( Calendar* ); - void changed( CalendarDay* ); - void changed( TimeInterval* ); - - void weekdayToBeAdded( CalendarDay *day, int index ); - void weekdayAdded( CalendarDay *day ); - void weekdayToBeRemoved( CalendarDay *day ); - void weekdayRemoved( CalendarDay *day ); - - void dayToBeAdded( CalendarDay *day, int index ); - void dayAdded( CalendarDay *day ); - void dayToBeRemoved( CalendarDay *day ); - void dayRemoved( CalendarDay *day ); - - void workIntervalToBeAdded( CalendarDay*, TimeInterval*, int index ); - void workIntervalAdded( CalendarDay*, TimeInterval* ); - void workIntervalToBeRemoved( CalendarDay*, TimeInterval* ); - void workIntervalRemoved( CalendarDay*, TimeInterval* ); + void changed(KPlato::Calendar*); + void changed(KPlato::CalendarDay*); + void changed(KPlato::TimeInterval*); + + void weekdayToBeAdded(KPlato::CalendarDay *day, int index); + void weekdayAdded(KPlato::CalendarDay *day); + void weekdayToBeRemoved(KPlato::CalendarDay *day); + void weekdayRemoved(KPlato::CalendarDay *day); + + void dayToBeAdded(KPlato::CalendarDay *day, int index); + void dayAdded(KPlato::CalendarDay *day); + void dayToBeRemoved(KPlato::CalendarDay *day); + void dayRemoved(KPlato::CalendarDay *day); + + void workIntervalToBeAdded(KPlato::CalendarDay*, KPlato::TimeInterval*, int index); + void workIntervalAdded(KPlato::CalendarDay*, KPlato::TimeInterval*); + void workIntervalToBeRemoved(KPlato::CalendarDay*, KPlato::TimeInterval*); + void workIntervalRemoved(KPlato::CalendarDay*, KPlato::TimeInterval*); protected: void init(); const Calendar ©(const Calendar &calendar); /** * Returns the amount of 'worktime' that can be done on * the @p date between the times @p start and @p start + @p length. * The date and times are in timespecification @p spec. * If @p sch is not 0, the schedule is checked for availability. */ Duration effort(QDate date, QTime start, int length, Schedule *sch=0) const; /** * Returns the amount of 'worktime' that can be done in the * interval from @p start to @p end * If @p sch is not 0, the schedule is checked for availability. */ Duration effort(const QDateTime &start, const QDateTime &end, Schedule *sch=0) const; /** * Returns the first 'work interval' on date for the interval * starting at @p start and ending at @p start + @p length. * If no 'work interval' exists, returns a null interval. * You can also use @ref hasInterval() to check if a 'work interval' exists. * The date and times are in timespecification spec. * If @p sch is not 0, the schedule is checked for availability. */ TimeInterval firstInterval(QDate date, QTime start, int length, Schedule *sch=0) const; /** * Returns the first 'work interval' for the interval * starting at @p start and ending at @p end. * If no 'work interval' exists, returns an interval with invalid DateTime. */ DateTimeInterval firstInterval( const QDateTime &start, const QDateTime &end, Schedule *sch=0) const; /** * Returns true if at least a part of a 'work interval' exists * for the interval on date, starting at @p start and ending at @p start + @p length. * If @p sch is not 0, the schedule is checked for availability. */ bool hasInterval(QDate date, QTime start, int length, Schedule *sch=0) const; /** * Returns the work intervals in the interval from @p start to @p end * Sets the load of each interval to @p load */ AppointmentIntervalList workIntervals(const QDateTime &start, const QDateTime &end, double load) const; /** * Find the first available time backwards from @p time. Search until @p limit. * Return invalid datetime if not available. * If @p sch is not 0, the schedule is checked for availability. */ DateTime firstAvailableBefore(const QDateTime &time, const QDateTime &limit, Schedule *sch = 0); private: QString m_name; Calendar *m_parent; Project *m_project; bool m_deleted; QString m_id; QString m_parentId; QList m_days; CalendarWeekdays *m_weekdays; QList m_calendars; QTimeZone m_timeZone; bool m_default; // this is the default calendar, only used for save/load bool m_shared; #ifdef HAVE_KHOLIDAYS KHolidays::HolidayRegion *m_region; QString m_regionCode; #endif int m_cacheversion; // incremented every time a calendar is changed friend class Project; int m_blockversion; // don't update if true #ifndef NDEBUG public: void printDebug(const QString& indent=QString()); #endif }; class PLANKERNEL_EXPORT StandardWorktime { public: explicit StandardWorktime( Project *project = 0 ); explicit StandardWorktime(StandardWorktime* worktime); ~StandardWorktime(); /// Set Project void setProject( Project *project ) { m_project = project; } /// The work time of a normal year. Duration durationYear() const { return m_year; } /// The work time of a normal year. double year() const { return m_year.toDouble(Duration::Unit_h); } /// Set the work time of a normal year. void setYear(const Duration year) { m_year = year; } /// Set the work time of a normal year. void setYear(double hours) { m_year = Duration((qint64)(hours*60.0*60.0*1000.0)); } /// The work time of a normal month Duration durationMonth() const { return m_month; } /// The work time of a normal month double month() const { return m_month.toDouble(Duration::Unit_h); } /// Set the work time of a normal month void setMonth(const Duration month) { m_month = month; } /// Set the work time of a normal month void setMonth(double hours) { m_month = Duration((qint64)(hours*60.0*60.0*1000.0)); } /// The work time of a normal week Duration durationWeek() const { return m_week; } /// The work time of a normal week double week() const { return m_week.toDouble(Duration::Unit_h); } /// Set the work time of a normal week void setWeek(const Duration week) { m_week = week; } /// Set the work time of a normal week void setWeek(double hours) { m_week = Duration((qint64)(hours*60.0*60.0*1000.0)); } /// The work time of a normal day Duration durationDay() const { return m_day; } /// The work time of a normal day double day() const { return m_day.toDouble(Duration::Unit_h); } /// Set the work time of a normal day void setDay(const Duration day) { m_day = day; changed(); } /// Set the work time of a normal day void setDay(double hours) { m_day = Duration(hours, Duration::Unit_h); changed(); } QList scales() const; bool load( KoXmlElement &element, XMLLoaderObject &status ); void save(QDomElement &element) const; void changed(); protected: void init(); private: Project *m_project; Duration m_year; Duration m_month; Duration m_week; Duration m_day; }; } //KPlato namespace #endif diff --git a/src/libs/kernel/kptnode.cpp b/src/libs/kernel/kptnode.cpp index 1ce3ecc0..7bcc7d54 100644 --- a/src/libs/kernel/kptnode.cpp +++ b/src/libs/kernel/kptnode.cpp @@ -1,1868 +1,1868 @@ /* This file is part of the KDE project Copyright (C) 2001 Thomas zander Copyright (C) 2002 - 2010, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptnode.h" #include "kptappointment.h" #include "kptaccount.h" #include "kptwbsdefinition.h" #include "kptresource.h" #include "kptschedule.h" #include "kptxmlloaderobject.h" #include "kptdebug.h" #include #include #include namespace KPlato { Node::Node(Node *parent) : QObject( 0 ), // We don't use qobjects parent m_nodes(), m_dependChildNodes(), m_dependParentNodes(), m_estimate( 0 ), m_blockChanged(false) { //debugPlan<<"("<removeRunning(*this); if (m_startupAccount) m_startupAccount->removeStartup(*this); if (m_shutdownAccount) m_shutdownAccount->removeShutdown(*this); foreach (Schedule *s, m_schedules) { delete s; } m_schedules.clear(); m_parent = 0; //safety } void Node::init() { m_documents.node = this; m_currentSchedule = 0; m_name=""; m_constraint = Node::ASAP; m_estimate = 0; m_visitedForward = false; m_visitedBackward = false; m_runningAccount = 0; m_startupAccount = 0; m_shutdownAccount = 0; m_startupCost = 0.0; m_shutdownCost = 0.0; } QString Node::typeToString( bool trans ) const { return typeToString( (Node::NodeTypes)type(), trans ); } // static QString Node::typeToString( Node::NodeTypes typ, bool trans ) { return typeToStringList( trans ).at( typ ); } // static QStringList Node::typeToStringList( bool trans ) { return QStringList() << ( trans ? i18n( "None" ) : QString( "None" ) ) << ( trans ? i18n( "Project" ) : QString( "Project" ) ) << ( trans ? i18n( "Sub-Project" ) : QString( "Sub-Project" ) ) << ( trans ? i18n( "Task" ) : QString( "Task" ) ) << ( trans ? i18n( "Milestone" ) : QString( "Milestone" ) ) << ( trans ? i18n( "Periodic" ) : QString( "Periodic" ) ) << ( trans ? i18n( "Summary" ) : QString( "Summary-Task" ) ); } void Node::setName(const QString &n) { #ifndef NDEBUG setObjectName( n ); #endif m_name = n; changed(this); } void Node::setLeader(const QString &l) { m_leader = l; changed(this); } void Node::setDescription(const QString &d) { m_description = d; changed(this); } Node *Node::projectNode() { if ((type() == Type_Project) || (type() == Type_Subproject)) { return this; } if (m_parent) return m_parent->projectNode(); // This happens for default tasks return 0; } const Node *Node::projectNode() const { if ((type() == Type_Project) || (type() == Type_Subproject)) { return this; } if (m_parent) return m_parent->projectNode(); // This happens for default tasks return 0; } void Node::takeChildNode( Node *node) { //debugPlan<<"find="<setParentNode(0); if ( t != type() ) { changed( Type ); } } void Node::takeChildNode( int number ) { int t = type(); if (number >= 0 && number < m_nodes.size()) { Node *n = m_nodes.takeAt(number); //debugPlan<<(n?n->id():"null")<<" :"<<(n?n->name():""); if (n) { n->setParentNode( 0 ); } } if ( t != type() ) { changed( Type ); } } void Node::insertChildNode( int index, Node *node ) { int t = type(); if (index == -1) m_nodes.append(node); else m_nodes.insert(index,node); node->setParentNode( this ); if ( t != type() ) { changed( Type ); } } void Node::addChildNode( Node *node, Node *after) { int t = type(); int index = m_nodes.indexOf(after); if (index == -1) { m_nodes.append(node); node->setParentNode( this ); if ( t != type() ) { changed( Type ); } return; } m_nodes.insert(index+1, node); node->setParentNode(this); if ( t != type() ) { changed( Type ); } } int Node::findChildNode( const Node* node ) const { return m_nodes.indexOf( const_cast( node ) ); } bool Node::isChildOf( const Node* node ) const { if ( node == 0 || m_parent == 0 ) { return false; } if ( node == m_parent ) { return true; } return m_parent->isChildOf( node ); } Node* Node::childNode(int number) { //debugPlan<= m_nodes.count() ) { return 0; } return m_nodes.at( number ); } int Node::indexOf( const Node *node ) const { return m_nodes.indexOf( const_cast(node) ); } Duration *Node::getDelay() { /* TODO Calculate the delay of this node. Use the calculated startTime and the set startTime. */ return 0L; } void Node::addDependChildNode( Node *node, Relation::Type p) { addDependChildNode(node,p,Duration()); } void Node::addDependChildNode( Node *node, Relation::Type p, Duration lag) { Relation *relation = new Relation(this, node, p, lag); if (node->addDependParentNode(relation)) m_dependChildNodes.append(relation); else delete relation; } void Node::insertDependChildNode( unsigned int index, Node *node, Relation::Type p) { Relation *relation = new Relation(this, node, p, Duration()); if (node->addDependParentNode(relation)) m_dependChildNodes.insert(index, relation); else delete relation; } bool Node::addDependChildNode( Relation *relation) { if(m_dependChildNodes.indexOf(relation) != -1) return false; m_dependChildNodes.append(relation); return true; } void Node::takeDependChildNode( Relation *rel ) { int i = m_dependChildNodes.indexOf(rel); if ( i != -1 ) { //debugPlan<addDependChildNode(relation)) m_dependParentNodes.append(relation); else delete relation; } void Node::insertDependParentNode( unsigned int index, Node *node, Relation::Type p) { Relation *relation = new Relation(this, node, p, Duration()); if (node->addDependChildNode(relation)) m_dependParentNodes.insert(index,relation); else delete relation; } bool Node::addDependParentNode( Relation *relation) { if(m_dependParentNodes.indexOf(relation) != -1) return false; m_dependParentNodes.append(relation); return true; } void Node::takeDependParentNode( Relation *rel ) { int i = m_dependParentNodes.indexOf(rel); if ( i != -1 ) { //debugPlan<( node ) ) != -1) return true; QListIterator nit(childNodeIterator()); while (nit.hasNext()) { if (nit.next()->isParentOf(node)) return true; } return false; } Relation *Node::findParentRelation( const Node *node ) const { for (int i=0; iparent() == node) return rel; } return (Relation *)0; } Relation *Node::findChildRelation( const Node *node) const { for (int i=0; ichild() == node) return rel; } return (Relation *)0; } Relation *Node::findRelation( const Node *node ) const { Relation *rel = findParentRelation(node); if (!rel) rel = findChildRelation(node); return rel; } bool Node::isDependChildOf( const Node *node ) const { //debugPlan<<" '"<name()<<"'"; for (int i=0; iparent() == node) return true; if (rel->parent()->isDependChildOf(node)) return true; } return false; } QList Node::getParentNodes() { this->m_parentNodes.clear(); foreach(Relation * currentRelation, this->dependParentNodes()) { if (!this->m_parentNodes.contains(currentRelation->parent())) { this->m_parentNodes.append(currentRelation->parent()); } } return this->m_parentNodes; } bool Node::canMoveTo( const Node *newParent ) const { if ( m_parent == newParent ) { return true; } if ( newParent->isChildOf( this ) ) { return false; } if ( isDependChildOf( newParent ) || newParent->isDependChildOf( this ) ) { debugPlan<<"Can't move, node is dependent on new parent"; return false; } foreach ( Node *n, m_nodes ) { if ( !n->canMoveTo( newParent ) ) { return false; } } return true; } void Node::makeAppointments() { QListIterator nit(m_nodes); while (nit.hasNext()) { nit.next()->makeAppointments(); } } void Node::calcResourceOverbooked() { QListIterator nit(m_nodes); while (nit.hasNext()) { nit.next()->calcResourceOverbooked(); } } // Returns the (previously) calculated duration Duration Node::duration( long id ) const { Schedule *s = schedule( id ); return s ? s->duration : Duration::zeroDuration; } double Node::variance( long id, Duration::Unit unit ) const { double d = deviation( id, unit ); return d * d; } double Node::deviation( long id, Duration::Unit unit ) const { Schedule *s = schedule( id ); double d = 0.0; if ( s && m_estimate ) { d = s->duration.toDouble( unit ); double o = ( d * ( 100 + m_estimate->optimisticRatio() ) ) / 100; double p = ( d * ( 100 + m_estimate->pessimisticRatio() ) ) / 100; d = ( p - o ) / 6; } return d; } DateTime Node::startTime( long id ) const { Schedule *s = schedule( id ); return s ? s->startTime : DateTime(); } DateTime Node::endTime( long id ) const { Schedule *s = schedule( id ); return s ? s->endTime : DateTime(); } DateTime Node::appointmentStartTime( long id ) const { Schedule *s = schedule( id ); return s ? s->appointmentStartTime() : DateTime(); } DateTime Node::appointmentEndTime( long id ) const { Schedule *s = schedule( id ); return s ? s->appointmentEndTime() : DateTime(); } void Node::setDuration(const Duration &duration, long id ) { Schedule *s = schedule( id ); if ( s ) { s->duration = duration; } } void Node::setEarlyStart(const DateTime &dt, long id ) { Schedule *s = schedule( id ); if ( s ) s->earlyStart = dt; } DateTime Node::earlyStart( long id ) const { Schedule *s = schedule( id ); return s ? s->earlyStart : DateTime(); } void Node::setLateStart(const DateTime &dt, long id ) { Schedule *s = schedule( id ); if ( s ) s->lateStart = dt; } DateTime Node::lateStart( long id ) const { Schedule *s = schedule( id ); return s ? s->lateStart : DateTime(); } void Node::setEarlyFinish(const DateTime &dt, long id ) { Schedule *s = schedule( id ); if ( s ) s->earlyFinish = dt; } DateTime Node::earlyFinish( long id ) const { Schedule *s = schedule( id ); return s ? s->earlyFinish : DateTime(); } void Node::setLateFinish(const DateTime &dt, long id ) { Schedule *s = schedule( id ); if ( s ) s->lateFinish = dt; } DateTime Node::lateFinish( long id ) const { Schedule *s = schedule( id ); return s ? s->lateFinish : DateTime(); } DateTime Node::workStartTime( long id ) const { Schedule *s = schedule( id ); return s ? s->workStartTime : DateTime(); } void Node::setWorkStartTime(const DateTime &dt, long id ) { Schedule *s = schedule( id ); if ( s ) s->workStartTime = dt; } DateTime Node::workEndTime( long id ) const { Schedule *s = schedule( id ); return s ? s->workEndTime : DateTime(); } void Node::setWorkEndTime(const DateTime &dt, long id ) { Schedule *s = schedule( id ); if ( s ) s->workEndTime = dt; } bool Node::inCriticalPath( long id ) const { Schedule *s = schedule( id ); return s ? s->inCriticalPath : false; } QStringList Node::schedulingStatus( long id, bool trans ) const { Schedule *s = schedule( id ); QStringList lst; if ( s ) { lst = s->state(); } if ( lst.isEmpty() ) { lst.append( trans ? i18n( "Not scheduled" ) : QString( "Not scheduled" ) ); } return lst; } bool Node::resourceError( long id ) const { Schedule *s = schedule( id ); return s ? s->resourceError : false; } bool Node::resourceOverbooked( long id ) const { Schedule *s = schedule( id ); return s ? s->resourceOverbooked : false; } bool Node::resourceNotAvailable( long id ) const { Schedule *s = schedule( id ); return s ? s->resourceNotAvailable : false; } bool Node::constraintError( long id ) const { Schedule *s = schedule( id ); return s ? s->constraintError : false; } bool Node::schedulingError( long id ) const { Schedule *s = schedule( id ); return s ? s->schedulingError : false; } bool Node::notScheduled( long id ) const { if ( type() == Type_Summarytask ) { // i am scheduled if al least on child is scheduled foreach ( Node *n, m_nodes ) { if ( ! n->notScheduled( id ) ) { return false; } } return true; } Schedule *s = schedule( id ); return s == 0 || s->isDeleted() || s->notScheduled; } QStringList Node::overbookedResources( long id ) const { Schedule *s = schedule( id ); return s ? s->overbookedResources() : QStringList(); } void Node::saveWorkPackageXML( QDomElement &, long ) const { return; } void Node::saveRelations(QDomElement &element) const { QListIterator it(m_dependChildNodes); while (it.hasNext()) { it.next()->save(element); } QListIterator nodes(m_nodes); while (nodes.hasNext()) { nodes.next()->saveRelations(element); } } void Node::setConstraint(Node::ConstraintType type) { m_constraint = type; changed( this ); } void Node::setConstraint(const QString &type) { // Do not i18n these, they are used in load() if (type == "ASAP") setConstraint(ASAP); else if (type == "ALAP") setConstraint(ALAP); else if (type == "MustStartOn") setConstraint(MustStartOn); else if (type == "MustFinishOn") setConstraint(MustFinishOn); else if (type == "StartNotEarlier") setConstraint(StartNotEarlier); else if (type == "FinishNotLater") setConstraint(FinishNotLater); else if (type == "FixedInterval") setConstraint(FixedInterval); else setConstraint(ASAP); // default } QString Node::constraintToString( bool trans ) const { return constraintList( trans ).at( m_constraint ); } QStringList Node::constraintList( bool trans ) { // keep theses in the same order as the enum! return QStringList() << (trans ? i18n("As Soon As Possible") : QString("ASAP")) << (trans ? i18n("As Late As Possible") : QString("ALAP")) << (trans ? i18n("Must Start On") : QString("MustStartOn")) << (trans ? i18n("Must Finish On") : QString("MustFinishOn")) << (trans ? i18n("Start Not Earlier") : QString("StartNotEarlier")) << (trans ? i18n("Finish Not Later") : QString("FinishNotLater")) << (trans ? i18n("Fixed Interval") : QString("FixedInterval")); } void Node::propagateEarliestStart(DateTime &time) { if (m_currentSchedule == 0) { return; } if ( type() != Type_Project ) { m_currentSchedule->earlyStart = time; if ( m_currentSchedule->lateStart.isValid() && m_currentSchedule->lateStart < time ) { m_currentSchedule->lateStart = time; } //m_currentSchedule->logDebug( "propagateEarliestStart: " + time.toString() ); switch ( m_constraint ) { case FinishNotLater: case MustFinishOn: if ( m_constraintEndTime < time ) { m_currentSchedule->logWarning("Task constraint outside project constraint"); #ifndef PLAN_NLOGDEBUG m_currentSchedule->logDebug( QString( "%1: end constraint %2 < %3" ).arg( constraintToString( true ) ).arg( m_constraintEndTime.toString() ).arg( time.toString() ) ); #endif } break; case MustStartOn: case FixedInterval: if ( m_constraintStartTime < time ) { m_currentSchedule->logWarning("Task constraint outside project constraint"); #ifndef PLAN_NLOGDEBUG m_currentSchedule->logDebug( QString( "%1: start constraint %2 < %3" ).arg( constraintToString( true ) ).arg( m_constraintEndTime.toString() ).arg( time.toString() ) ); #endif } break; default: break; } } //debugPlan<earlyStart; QListIterator it = m_nodes; while (it.hasNext()) { it.next()->propagateEarliestStart(time); } } void Node::propagateLatestFinish(DateTime &time) { if (m_currentSchedule == 0) { return; } if ( type() != Type_Project ) { m_currentSchedule->lateFinish = time; if ( m_currentSchedule->earlyFinish.isValid() && m_currentSchedule->earlyFinish > time ) { m_currentSchedule->earlyFinish = time; } switch ( m_constraint ) { case StartNotEarlier: case MustStartOn: if ( m_constraintStartTime > time ) { m_currentSchedule->logWarning("Task constraint outside project constraint"); #ifndef PLAN_NLOGDEBUG m_currentSchedule->logDebug( QString( "%1: start constraint %2 < %3" ).arg( constraintToString( true ) ).arg( m_constraintEndTime.toString() ).arg( time.toString() ) ); #endif } break; case MustFinishOn: case FixedInterval: if ( m_constraintEndTime > time ) { m_currentSchedule->logWarning("Task constraint outside project constraint"); #ifndef PLAN_NLOGDEBUG m_currentSchedule->logDebug( QString( "%1: end constraint %2 > %3" ).arg( constraintToString( true ) ).arg( m_constraintEndTime.toString() ).arg( time.toString() ) ); #endif } break; default: break; } } //debugPlan<lateFinish; QListIterator it = m_nodes; while (it.hasNext()) { it.next()->propagateLatestFinish(time); } } void Node::moveEarliestStart(DateTime &time) { if (m_currentSchedule == 0) return; if (m_currentSchedule->earlyStart < time) { //m_currentSchedule->logDebug( "moveEarliestStart: " + m_currentSchedule->earlyStart.toString() + " -> " + time.toString() ); m_currentSchedule->earlyStart = time; } QListIterator it = m_nodes; while (it.hasNext()) { it.next()->moveEarliestStart(time); } } void Node::moveLatestFinish(DateTime &time) { if (m_currentSchedule == 0) return; if (m_currentSchedule->lateFinish > time) m_currentSchedule->lateFinish = time; QListIterator it = m_nodes; while (it.hasNext()) { it.next()->moveLatestFinish(time); } } void Node::initiateCalculation(MainSchedule &sch) { m_visitedForward = false; m_visitedBackward = false; m_durationForward = Duration::zeroDuration; m_durationBackward = Duration::zeroDuration; m_earlyStart = DateTime(); m_earlyFinish = DateTime(); m_lateFinish = DateTime(); QListIterator it = m_nodes; while (it.hasNext()) { it.next()->initiateCalculation(sch); } } void Node::resetVisited() { m_visitedForward = false; m_visitedBackward = false; QListIterator it = m_nodes; while (it.hasNext()) { it.next()->resetVisited(); } } Node *Node::siblingBefore() { //debugPlan; if (parentNode()) return parentNode()->childBefore(this); return 0; } Node *Node::childBefore(Node *node) { //debugPlan; int index = m_nodes.indexOf(node); if (index > 0){ return m_nodes.at(index-1); } return 0; } Node *Node::siblingAfter() { //debugPlan; if (parentNode()) return parentNode()->childAfter(this); return 0; } Node *Node::childAfter(Node *node) { //debugPlan; Q_ASSERT( m_nodes.contains( node ) ); int index = m_nodes.indexOf(node); if (index < m_nodes.count()-1) { return m_nodes.at(index+1); } return 0; } bool Node::moveChildUp(Node* node) { if (findChildNode(node) == -1) return false; // not my node! Node *sib = node->siblingBefore(); if (!sib) return false; sib = sib->siblingBefore(); takeChildNode(node); if (sib) { addChildNode(node, sib); } else { insertChildNode(0, node); } return true; } bool Node::moveChildDown(Node* node) { if (findChildNode(node) == -1) return false; // not my node! Node *sib = node->siblingAfter(); if (!sib) return false; takeChildNode(node); addChildNode(node, sib); return true; } bool Node::legalToLink( const Node *node ) const { Node *p = const_cast(this)->projectNode(); if (p) return p->legalToLink(this, node); return false; } bool Node::isEndNode() const { return m_dependChildNodes.isEmpty(); } bool Node::isStartNode() const { return m_dependParentNodes.isEmpty(); } void Node::setId(const QString& id) { //debugPlan<startTime = startTime; } void Node::setEndTime(const DateTime &endTime, long id ) { Schedule *s = schedule( id ); if ( s ) s->endTime = endTime; } void Node::saveAppointments(QDomElement &element, long id) const { //debugPlan<id()<<","<add(appointment); } void Node::addAppointment(ResourceSchedule *resource, const DateTime &start, const DateTime &end, double load) { Schedule *node = findSchedule(resource->id()); if (node == 0) { node = createSchedule(resource->parent()); } node->setCalculationMode( resource->calculationMode() ); node->addAppointment(resource, start, end, load); } bool Node::isBaselined( long id ) const { Schedule *s = schedule( id ); return s ? s->isBaselined() : false; } void Node::takeSchedule(const Schedule *schedule) { if (schedule == 0) return; if (m_currentSchedule == schedule) m_currentSchedule = 0; m_schedules.take(schedule->id()); } void Node::addSchedule(Schedule *schedule) { if (schedule == 0) return; m_schedules.insert(schedule->id(), schedule); } Schedule *Node::createSchedule(const QString& name, Schedule::Type type, long id) { //debugPlan<removeStartup( *this ); } m_startupAccount = acc; changed(); } void Node::setShutdownCost(double cost) { m_shutdownCost = cost; changed(ShutdownCost); } void Node::setShutdownAccount(Account *acc) { //debugPlan<removeShutdown( *this ); } m_shutdownAccount = acc; changed(); } void Node::setRunningAccount(Account *acc) { //debugPlan<removeRunning( *this ); } m_runningAccount = acc; changed(); } void Node::blockChanged(bool on) { m_blockChanged = on; } void Node::changed(Node *node, int property) { if (m_blockChanged) { return; } switch ( property) { case Type: case StartupCost: case ShutdownCost: case CompletionEntry: case CompletionStarted: case CompletionFinished: case CompletionStartTime: case CompletionFinishTime: case CompletionPercentage: case CompletionRemainingEffort: case CompletionActualEffort: case CompletionUsedEffort: foreach ( Schedule *s, m_schedules ) { s->clearPerformanceCache(); } break; default: break; } if (m_parent) { m_parent->changed(node, property); } } Duration Node::plannedEffort( const Resource *resource, long id, EffortCostCalculationType type ) const { Duration e; foreach ( Node *n, m_nodes ) { e += n->plannedEffort( resource, id, type ); } return e; } Duration Node::plannedEffort( const Resource *resource, QDate date, long id, EffortCostCalculationType type ) const { Duration e; foreach ( Node *n, m_nodes ) { e += n->plannedEffort( resource, date, id, type ); } return e; } Duration Node::plannedEffortTo( const Resource *resource, QDate date, long id, EffortCostCalculationType type ) const { Duration e; foreach ( Node *n, m_nodes ) { e += n->plannedEffortTo( resource, date, id, type ); } return e; } EffortCost Node::plannedCost( long id, EffortCostCalculationType type ) const { EffortCost ec; foreach ( Node *n, m_nodes ) { ec += n->plannedCost( id, type ); } return ec; } EffortCostMap Node::bcwsPrDay( long int id, EffortCostCalculationType type ) const { return const_cast( this )->bcwsPrDay( id, type ); } EffortCostMap Node::bcwsPrDay( long int id, EffortCostCalculationType type ) { Schedule *s = schedule( id ); if ( s == 0 ) { return EffortCostMap(); } EffortCostCache &ec = s->bcwsPrDayCache( type ); if ( ! ec.cached ) { ec.effortcostmap = EffortCostMap(); foreach ( Node *n, m_nodes ) { ec.effortcostmap += n->bcwsPrDay( id, type ); } ec.cached = true; } return ec.effortcostmap; } EffortCostMap Node::bcwpPrDay( long int id, EffortCostCalculationType type ) const { return const_cast( this )->bcwpPrDay( id, type); } EffortCostMap Node::bcwpPrDay( long int id, EffortCostCalculationType type ) { Schedule *s = schedule( id ); if ( s == 0 ) { return EffortCostMap(); } EffortCostCache &ec = s->bcwpPrDayCache( type ); if ( ! ec.cached ) { ec.effortcostmap = EffortCostMap(); foreach ( Node *n, m_nodes ) { ec.effortcostmap += n->bcwpPrDay( id, type ); } ec.cached = true; } return ec.effortcostmap; } EffortCostMap Node::acwp( long id, EffortCostCalculationType type ) const { return const_cast( this )->acwp( id, type ); } EffortCostMap Node::acwp( long id, EffortCostCalculationType type ) { Schedule *s = schedule( id ); if ( s == 0 ) { return EffortCostMap(); } EffortCostCache &ec = s->acwpCache( type ); if ( ! ec.cached ) { ec.effortcostmap = EffortCostMap(); foreach ( Node *n, m_nodes ) { ec.effortcostmap += n->acwp( id, type ); } ec.cached = true; } return ec.effortcostmap; } EffortCost Node::acwp( QDate date, long id ) const { EffortCost ec; foreach ( Node *n, m_nodes ) { ec += n->acwp( date, id ); } return ec; } -void Node::slotStandardWorktimeChanged( StandardWorktime* ) +void Node::slotStandardWorktimeChanged(KPlato::StandardWorktime*) { //debugPlan<m_expectedCached = false; m_estimate->m_optimisticCached = false; m_estimate->m_pessimisticCached = false; } } void Node::emitDocumentAdded( Node *node, Document *doc, int idx ) { if ( m_parent ) { m_parent->emitDocumentAdded( node, doc, idx ); } } void Node::emitDocumentRemoved( Node *node, Document *doc, int idx ) { if ( m_parent ) { m_parent->emitDocumentRemoved( node, doc, idx ); } } void Node::emitDocumentChanged( Node *node, Document *doc, int idx ) { if ( m_parent ) { m_parent->emitDocumentChanged( node, doc, idx ); } } ////////////////////////// Estimate ///////////////////////////////// Estimate::Estimate( Node *parent ) : m_parent( parent ) { m_pertCached = false; setUnit( Duration::Unit_h ); setExpectedEstimate( 8.0 ); setPessimisticEstimate( 8.0 ); setOptimisticEstimate( 8.0 ); m_type = Type_Effort; m_calendar = 0; m_risktype = Risk_None; } Estimate::Estimate(const Estimate &estimate, Node *parent) : m_parent( parent ) { copy( estimate ); } Estimate::~Estimate() { } void Estimate::clear() { m_pertCached = false; setExpectedEstimate( 0.0 ); setPessimisticEstimate( 0.0 ); setOptimisticEstimate( 0.0 ); m_type = Type_Effort; m_calendar = 0; m_risktype = Risk_None; m_unit = Duration::Unit_h; changed(); } Estimate &Estimate::operator=( const Estimate &estimate ) { copy( estimate ); return *this; } void Estimate::copy( const Estimate &estimate ) { //m_parent = 0; // don't touch m_expectedEstimate = estimate.m_expectedEstimate; m_optimisticEstimate = estimate.m_optimisticEstimate; m_pessimisticEstimate = estimate.m_pessimisticEstimate; m_expectedValue = estimate.m_expectedValue; m_optimisticValue = estimate.m_optimisticValue; m_pessimisticValue = estimate.m_pessimisticValue; m_expectedCached = estimate.m_expectedCached; m_optimisticCached = estimate.m_optimisticCached; m_pessimisticCached = estimate.m_pessimisticCached; m_pertExpected = estimate.m_pertExpected; m_pertCached = estimate.m_pertCached; m_type = estimate.m_type; m_calendar = estimate.m_calendar; m_risktype = estimate.m_risktype; m_unit = estimate.m_unit; changed(); } double Estimate::variance() const { double d = deviation(); return d * d; } double Estimate::variance( Duration::Unit unit ) const { double d = deviation( unit ); return d * d; } double Estimate::deviation() const { return ( m_pessimisticEstimate - m_optimisticEstimate ) / 6; } double Estimate::deviation( Duration::Unit unit ) const { if ( unit == m_unit ) { return deviation(); } double p = pessimisticValue().toDouble( unit ); double o = optimisticValue().toDouble( unit ); double v = ( p - o ) / 6; return v; } Duration Estimate::pertExpected() const { if (m_risktype == Risk_Low) { if ( ! m_pertCached ) { m_pertExpected = (optimisticValue() + pessimisticValue() + (expectedValue()*4))/6; m_pertCached = true; } return m_pertExpected; } else if (m_risktype == Risk_High) { if ( ! m_pertCached ) { m_pertExpected = (optimisticValue() + (pessimisticValue()*2) + (expectedValue()*4))/7; m_pertCached = true; } return m_pertExpected; } return expectedValue(); // risk==none } Duration Estimate::pertOptimistic() const { if (m_risktype != Risk_None) { return pertExpected() - Duration( variance( Duration::Unit_ms ) ); } return optimisticValue(); } Duration Estimate::pertPessimistic() const { if (m_risktype != Risk_None) { return pertExpected() + Duration( variance( Duration::Unit_ms ) ); } return pessimisticValue(); } Duration Estimate::value(int valueType, bool pert) const { if (valueType == Estimate::Use_Expected) { return pert ? pertExpected() : expectedValue(); } else if (valueType == Estimate::Use_Optimistic) { return pert ? pertOptimistic() : optimisticValue(); } else if (valueType == Estimate::Use_Pessimistic) { return pert ? pertPessimistic() : pessimisticValue(); } return expectedValue(); } void Estimate::setUnit( Duration::Unit unit ) { m_unit = unit; m_expectedCached = false; m_optimisticCached = false; m_pessimisticCached = false; m_pertCached = false; changed(); } bool Estimate::load(KoXmlElement &element, XMLLoaderObject &status) { setType(element.attribute("type")); setRisktype(element.attribute("risk")); if ( status.version() <= "0.6" ) { m_unit = (Duration::Unit)(element.attribute("display-unit", QString().number(Duration::Unit_h) ).toInt()); QList s = status.project().standardWorktime()->scales(); m_expectedEstimate = scale( Duration::fromString(element.attribute("expected")), m_unit, s ); m_optimisticEstimate = scale( Duration::fromString(element.attribute("optimistic")), m_unit, s ); m_pessimisticEstimate = scale( Duration::fromString(element.attribute("pessimistic")), m_unit, s ); } else { if ( status.version() <= "0.6.2" ) { // 0 pos in unit is now Unit_Y, so add 3 to get the correct new unit m_unit = (Duration::Unit)(element.attribute("unit", QString().number(Duration::Unit_ms - 3) ).toInt() + 3); } else { m_unit = Duration::unitFromString( element.attribute( "unit" ) ); } m_expectedEstimate = element.attribute("expected", "0.0").toDouble(); m_optimisticEstimate = element.attribute("optimistic", "0.0").toDouble(); m_pessimisticEstimate = element.attribute("pessimistic", "0.0").toDouble(); m_calendar = status.project().findCalendar(element.attribute("calendar-id")); } return true; } void Estimate::save(QDomElement &element) const { QDomElement me = element.ownerDocument().createElement("estimate"); element.appendChild(me); me.setAttribute("expected", QString::number(m_expectedEstimate)); me.setAttribute("optimistic", QString::number(m_optimisticEstimate)); me.setAttribute("pessimistic", QString::number(m_pessimisticEstimate)); me.setAttribute("type", typeToString()); if ( m_calendar ) { me.setAttribute("calendar-id", m_calendar->id() ); } me.setAttribute("risk", risktypeToString()); me.setAttribute("unit", Duration::unitToString( m_unit ) ); } QString Estimate::typeToString( bool trans ) const { return typeToStringList( trans ).at( m_type ); } QString Estimate::typeToString( Estimate::Type typ, bool trans ) { return typeToStringList( trans ).value( typ ); } QStringList Estimate::typeToStringList( bool trans ) { return QStringList() << (trans ? i18n("Effort") : QString("Effort")) << (trans ? i18n("Duration") : QString("Duration")); } void Estimate::setType(Type type) { m_type = type; m_expectedCached = false; m_optimisticCached = false; m_pessimisticCached = false; m_pertCached = false; changed(); } void Estimate::setType(const QString& type) { if (type == "Effort") setType(Type_Effort); else if (type == "Duration" || /*old format*/ type == "FixedDuration") setType(Type_Duration); else if (/*old format*/type == "Length") setType(Type_Duration); else if (type == "Type_FixedDuration") // Typo, keep old xml files working setType(Type_Duration); else setType(Type_Effort); // default } QString Estimate::risktypeToString( bool trans ) const { return risktypeToStringList( trans ).at( m_risktype ); } QStringList Estimate::risktypeToStringList( bool trans ) { return QStringList() << (trans ? i18n("None") : QString("None")) << (trans ? i18n("Low") : QString("Low")) << (trans ? i18n("High") : QString("High")); } void Estimate::setRisktype(const QString& type) { if (type == "High") setRisktype(Risk_High); else if (type == "Low") setRisktype(Risk_Low); else setRisktype(Risk_None); // default } void Estimate::setRisktype(Risktype type) { m_pertCached = false; m_risktype = type; changed(); } void Estimate::setCalendar( Calendar *calendar ) { m_calendar = calendar; m_expectedCached = false; m_optimisticCached = false; m_pessimisticCached = false; m_pertCached = false; changed(); } void Estimate::setExpectedEstimate( double value) { m_expectedEstimate = value; m_expectedCached = false; m_pertCached = false; changed(); } void Estimate::setOptimisticEstimate( double value ) { m_optimisticEstimate = value; m_optimisticCached = false; m_pertCached = false; changed(); } void Estimate::setPessimisticEstimate( double value ) { m_pessimisticEstimate = value; m_pessimisticCached = false; m_pertCached = false; changed(); } void Estimate::setOptimisticRatio(int percent) { int p = percent>0 ? -percent : percent; m_optimisticValue = expectedValue()*(100+p)/100; m_optimisticEstimate = scale( m_optimisticValue, m_unit, scales() ); m_optimisticCached = true; m_pertCached = false; changed(); } int Estimate::optimisticRatio() const { if (m_expectedEstimate == 0.0) return 0; return (int)((optimisticValue()*100)/expectedValue())-100; } void Estimate::setPessimisticRatio(int percent) { int p = percent<0 ? -percent : percent; m_pessimisticValue = expectedValue()*(100+p)/100; m_pessimisticEstimate = scale( m_pessimisticValue, m_unit, scales() ); m_pessimisticCached = true; m_pertCached = false; changed(); } int Estimate::pessimisticRatio() const { if (m_expectedEstimate == 0.0) return 0; return (int)((pessimisticValue()*100)/expectedValue())-100; } // internal void Estimate::setOptimisticValue() { m_optimisticValue = scale( m_optimisticEstimate, m_unit, scales() ); m_optimisticCached = true; m_pertCached = false; } // internal void Estimate::setExpectedValue() { m_expectedValue = scale( m_expectedEstimate, m_unit, scales() ); m_expectedCached = true; m_pertCached = false; } // internal void Estimate::setPessimisticValue() { m_pessimisticValue = scale( m_pessimisticEstimate, m_unit, scales() ); m_pessimisticCached = true; m_pertCached = false; } Duration Estimate::optimisticValue() const { if ( ! m_optimisticCached ) { const_cast(this)->setOptimisticValue(); } return m_optimisticValue; } Duration Estimate::pessimisticValue() const { if ( ! m_pessimisticCached ) { const_cast(this)->setPessimisticValue(); } return m_pessimisticValue; } Duration Estimate::expectedValue() const { if ( ! m_expectedCached ) { const_cast(this)->setExpectedValue(); } return m_expectedValue; } double Estimate::scale( const Duration &value, Duration::Unit unit, const QList &scales ) { //debugPlan< lst = scales; switch ( lst.count() ) { case Duration::Unit_Y: lst << (qint64)(365 * 24) * 60 * 60 * 1000; // add milliseconds in a year case Duration::Unit_M: lst << (qint64)(30 * 24) * 60 * 60 * 1000; // add milliseconds in a month case Duration::Unit_w: lst << (qint64)(7 * 24) * 60 * 60 * 1000; // add milliseconds in a week case Duration::Unit_d: lst << 24 * 60 * 60 * 1000; // add milliseconds in day case Duration::Unit_h: lst << 60 * 60 * 1000; // add milliseconds in hour case Duration::Unit_m: lst << 60 * 1000; // add milliseconds in minute case Duration::Unit_s: lst << 1000; // add milliseconds in second case Duration::Unit_ms: lst << 1; // add milliseconds in a millisecond default: break; } double v = ( double )( value.milliseconds() ); v /= lst[ unit ]; //debugPlan< &scales ) { //debugPlan< lst = scales; switch ( lst.count() ) { case Duration::Unit_Y: lst << (qint64)(365 * 24) * 60 * 60 * 1000; // add milliseconds in a year case Duration::Unit_M: lst << (qint64)(30 * 24) * 60 * 60 * 1000; // add milliseconds in a month case Duration::Unit_w: lst << (qint64)(7 * 24) * 60 * 60 * 1000; // add milliseconds in a week case Duration::Unit_d: lst << 24 * 60 * 60 * 1000; // add milliseconds in day case Duration::Unit_h: lst << 60 * 60 * 1000; // add milliseconds in hour case Duration::Unit_m: lst << 60 * 1000; // add milliseconds in minute case Duration::Unit_s: lst << 1000; // add milliseconds in second case Duration::Unit_ms: lst << 1; // add milliseconds in a millisecond default: break; } qint64 v = ( qint64 )( value * lst[ unit ] ); //debugPlan< Estimate::defaultScales() { QList lst; lst << (qint64)(365 * 24) * 60 * 60 * 1000 // add milliseconds in a year << (qint64)(30 * 24) * 60 * 60 * 1000 // add milliseconds in a month << (qint64)(7 * 24) * 60 * 60 * 1000 // add milliseconds in a week << 24 * 60 * 60 * 1000 // add milliseconds in day << 60 * 60 * 1000 // add milliseconds in hour << 60 * 1000 // add milliseconds in minute << 1000 // add milliseconds in second << 1; // add milliseconds in a millisecond return lst; } QList Estimate::scales() const { QList s; if ( m_type == Type_Duration && m_calendar == 0 ) { return s; // Use default scaling ( 24h a day...) } if ( m_parent == 0 ) { return s; } Project *p = static_cast( m_parent->projectNode() ); if ( p == 0 ) { return s; } s << p->standardWorktime()->scales(); return s; } } //KPlato namespace diff --git a/src/libs/kernel/kptnode.h b/src/libs/kernel/kptnode.h index 343fb585..4f28fb15 100644 --- a/src/libs/kernel/kptnode.h +++ b/src/libs/kernel/kptnode.h @@ -1,879 +1,879 @@ /* This file is part of the KDE project Copyright (C) 2001 Thomas Zander zander@kde.org Copyright (C) 2004 - 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTNODE_H #define KPTNODE_H #include "plankernel_export.h" #include "kptglobal.h" #include "kptrelation.h" #include "kptduration.h" #include "kptdatetime.h" #include "kptschedule.h" #include "kptdocuments.h" #include "kptresource.h" #include #include #include #include class QDomElement; /// The main namespace. namespace KPlato { class Account; class Project; class Appointment; class ResourceGroup; class Resource; class ResourceGroupRequest; class Estimate; class EffortCostMap; class EffortCost; class Calendar; class KPlatoXmlLoaderBase; /** * This class represents any node in the project, a node can be a project or * a subproject or any task. * This class is basically an abstract interface to make the design more OO. */ class PLANKERNEL_EXPORT Node : public QObject { Q_OBJECT public: enum ConstraintType { ASAP, ALAP, MustStartOn, MustFinishOn, StartNotEarlier, FinishNotLater, FixedInterval }; enum State { State_None = 0, State_Started = 1, State_StartedLate = 2, State_StartedEarly = 4, State_Finished = 8, State_FinishedLate = 16, State_FinishedEarly = 32, State_Running = 64, State_RunningLate = 128, State_RunningEarly = 256, State_ReadyToStart = 512, // all preceding tasks finished (if any) State_NotReadyToStart = 1024, // all preceding tasks not finished (must be one or more) State_NotScheduled = 2048, State_Late = 4096 }; enum Properties { Type, StartupCost, ShutdownCost, CompletionEntry, CompletionStarted, CompletionFinished, CompletionStartTime, CompletionFinishTime, CompletionPercentage, CompletionRemainingEffort, CompletionActualEffort, CompletionUsedEffort }; explicit Node(Node *parent = 0); Node(const Node &node, Node *parent = 0); // Declare the class abstract virtual ~Node() = 0; void setId(const QString& id); QString id() const { return m_id; } // unique identity enum NodeTypes { Type_Node = 0, Type_Project = 1, Type_Subproject = 2, Type_Task = 3, Type_Milestone = 4, Type_Periodic = 5, Type_Summarytask = 6 }; virtual int type() const = 0; QString typeToString( bool trans = false ) const; static QString typeToString( NodeTypes typ, bool trans = false ); static QStringList typeToStringList( bool trans ); /** * Returns a pointer to the project node (main- or sub-project) * Returns 0 if no project exists. */ virtual Node *projectNode(); /** * Returns a pointer to the project node (main- or sub-project) * Returns 0 if no project exists. */ virtual const Node *projectNode() const; // The load and save methods virtual bool load(KoXmlElement &, XMLLoaderObject &) { return true; } virtual void save(QDomElement &element) const = 0; /// Save me and my childrens relations. virtual void saveRelations(QDomElement &element) const; /// Save a workpackage document containing @p node with schedule identity @p id virtual void saveWorkPackageXML( QDomElement &element, long id ) const; // simple child node management // Child nodes are things like subtasks, basically a task can exists of // several sub-tasks. Creating a table has 4 subtasks, 1) measuring // 2) cutting 3) building 4) painting. Node *parentNode() const { return m_parent; } void setParentNode( Node* newParent ) { m_parent = newParent;} const QList &childNodeIterator() const { return m_nodes; } int numChildren() const { return m_nodes.count(); } virtual void addChildNode(Node *node, Node *after=0); virtual void insertChildNode(int index, Node *node); void takeChildNode(Node *node ); void takeChildNode(int number ); Node* childNode(int number); const Node* childNode(int number) const; int findChildNode( const Node* node ) const; bool isChildOf( const Node *node ) const; int indexOf( const Node *node ) const; // Time-dependent child-node-management. // list all nodes that are dependent upon this one. // Building a house requires the table to be finished, therefore the // house-building is time dependent on the table-building. So a child // of the table-building node is the house-building node. int numDependChildNodes() const { return m_dependChildNodes.count(); } /// Adds relation of type @p p to both this node and @p node virtual void addDependChildNode( Node *node, Relation::Type p=Relation::FinishStart); /// Adds relation of type @p p with @p lag to both this node and @p node virtual void addDependChildNode( Node *node, Relation::Type p, Duration lag); /// Adds @p relation only to this node virtual bool addDependChildNode( Relation *relation); /// Inserts relation to this node at index @p index and appends relation to @p node virtual void insertDependChildNode( unsigned int index, Node *node, Relation::Type p=Relation::FinishStart); /** * Takes the relation rel from this node only. */ void takeDependChildNode( Relation *rel ); Relation *getDependChildNode( int number ) const { return m_dependChildNodes.at(number); } QList dependChildNodes() const { return m_dependChildNodes; } int numDependParentNodes() const { return m_dependParentNodes.count(); } /// Adds relation if type @p to both this node and @p node virtual void addDependParentNode(Node *node, Relation::Type p=Relation::FinishStart); /// Adds relation to both this node and @p node virtual void addDependParentNode( Node *node, Relation::Type p, Duration lag); /// Adds relation only to this node virtual bool addDependParentNode( Relation *relation); /// Inserts relation to this node at index and appends relation to @p node virtual void insertDependParentNode( unsigned int index, Node *node, Relation::Type p=Relation::FinishStart); /** * Takes the relation @p rel from this node only. */ void takeDependParentNode( Relation *rel ); Relation *getDependParentNode( int number ) const { return m_dependParentNodes.at(number); } QList dependParentNodes() const { return m_dependParentNodes; } QList getParentNodes(); bool isParentOf( const Node *node ) const; bool isDependChildOf( const Node *node ) const; virtual bool canMoveTo( const Node *newParent ) const; Relation *findParentRelation( const Node *node) const; Relation *findChildRelation( const Node *node ) const; Relation *findRelation( const Node *node ) const; /// Set the scheduled start time void setStartTime(const DateTime &startTime, long id = CURRENTSCHEDULE ); /// Return the scheduled start time virtual DateTime startTime( long id = CURRENTSCHEDULE ) const; /// Set the scheduled end time void setEndTime(const DateTime &endTime, long id = CURRENTSCHEDULE ); /// Return the scheduled end time virtual DateTime endTime( long id = CURRENTSCHEDULE ) const; /// Set the scheduled duration void setDuration(const Duration &duration, long id = CURRENTSCHEDULE ); DateTime appointmentStartTime( long id = CURRENTSCHEDULE) const; DateTime appointmentEndTime( long id = CURRENTSCHEDULE ) const; /// Return the estimate for this node Estimate *estimate() const { return m_estimate; } /** * Instead of using the expected duration, generate a random value using * the Distribution of each Task. This can be used for Monte-Carlo * estimation of Project duration. */ virtual Duration *getRandomDuration() = 0; /** * Calculate the delay of this node. * It is the difference between the actual startTime and scheduled startTime. */ Duration *getDelay(); // TODO QString &name() { return m_name; } QString &leader() { return m_leader; } QString &description() { return m_description; } const QString &name() const { return m_name; } const QString &leader() const { return m_leader; } const QString &description() const { return m_description; } void setName(const QString &n); void setLeader(const QString &l); void setDescription(const QString &d); void setConstraint(Node::ConstraintType type); void setConstraint(const QString &type); int constraint() const { return m_constraint; } QString constraintToString( bool trans=false ) const; static QStringList constraintList( bool trans ); virtual void setConstraintStartTime(const DateTime &time) { m_constraintStartTime = time; changed( this ); } virtual void setConstraintEndTime(const DateTime &time) { m_constraintEndTime = time; changed( this ); } virtual DateTime constraintStartTime() const { return m_constraintStartTime; } virtual DateTime constraintEndTime() const { return m_constraintEndTime; } virtual DateTime startNotEarlier() const { return m_constraintStartTime; } virtual DateTime finishNotLater() const { return m_constraintEndTime; } virtual DateTime mustStartOn() const { return m_constraintStartTime; } virtual DateTime mustFinishOn() const { return m_constraintEndTime; } virtual ResourceGroupRequest *resourceGroupRequest(const ResourceGroup * /*group*/) const { return 0; } virtual QStringList requestNameList() const { return QStringList(); } virtual bool containsRequest( const QString &/*identity*/ ) const { return false; } virtual ResourceRequest *resourceRequest( const QString &/*name*/ ) const { return 0; } /// Return the list of resources assigned to this task virtual QStringList assignedNameList( long /*id*/ = CURRENTSCHEDULE ) const { return QStringList(); } virtual void makeAppointments(); /// Calculates if the assigned resource is overbooked /// within the duration of this node virtual void calcResourceOverbooked(); /// Return the scheduling status of schedule @p id. If @p trans is true, text is translated QStringList schedulingStatus( long id, bool trans = false ) const; /// EstimateType == Estimate, but no resource is requested bool resourceError( long id = CURRENTSCHEDULE ) const; /// The assigned resource is overbooked virtual bool resourceOverbooked( long id = CURRENTSCHEDULE ) const; /// The requested resource is not available bool resourceNotAvailable( long id = CURRENTSCHEDULE ) const; /// The task cannot be scheduled to fulfil all the constraints virtual bool constraintError( long id = CURRENTSCHEDULE ) const; /// The task cannot be scheduled correctly virtual bool schedulingError( long id = CURRENTSCHEDULE ) const; /// The node has not been scheduled bool notScheduled( long id = CURRENTSCHEDULE ) const; /// Return a list of overbooked resources virtual QStringList overbookedResources( long id = CURRENTSCHEDULE ) const; /// The assigned resources can not fulfil the estimated effort. virtual bool effortMetError( long /*id*/ = CURRENTSCHEDULE ) const { return false; } virtual EffortCostMap plannedEffortCostPrDay(QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const=0; virtual EffortCostMap plannedEffortCostPrDay(const Resource *resource, QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const=0; /// Returns the total planned effort for @p resource on this task (or subtasks) virtual Duration plannedEffort( const Resource *resource, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the total planned effort for this task (or subtasks) virtual Duration plannedEffort( long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const { Q_UNUSED(id); return Duration::zeroDuration; } /// Returns the total planned effort for this task (or subtasks) on date virtual Duration plannedEffort(QDate , long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const { Q_UNUSED(id); return Duration::zeroDuration; } /// Returns the total planned effort for @p resource on this task (or subtasks) on date virtual Duration plannedEffort( const Resource *resource, QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the planned effort up to and including date virtual Duration plannedEffortTo(QDate , long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const { Q_UNUSED(id); return Duration::zeroDuration; } /// Returns the planned effort for @p resource up to and including date virtual Duration plannedEffortTo( const Resource *resource, QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the total actual effort for this task (or subtasks) virtual Duration actualEffort() const { return Duration::zeroDuration; } /// Returns the total actual effort for this task (or subtasks) on date virtual Duration actualEffort(QDate /*date*/ ) const { return Duration::zeroDuration; } /// Returns the total actual effort for this task (or subtasks) up to and including date virtual Duration actualEffortTo(QDate /*date*/ ) const { return Duration::zeroDuration; } virtual EffortCostMap actualEffortCostPrDay(QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const=0; /// Returns the actual effort and cost pr day used by @p resource virtual EffortCostMap actualEffortCostPrDay(const Resource *resource, QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const=0; /** * Planned cost is the sum total of all resources and other costs * planned for this node. */ virtual EffortCost plannedCost( long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /** * Planned cost from start of activity up to and including date * is the sum of all resource costs and other costs planned for this node. */ virtual double plannedCostTo(QDate /*date*/, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const { Q_UNUSED(id); return 0; } /// Actual cost up to and including date virtual EffortCost actualCostTo( long int /*id*/, QDate /*date*/) const { return EffortCost(); } /// Returns the effort planned to be used to reach the actual percent finished virtual Duration budgetedWorkPerformed( QDate , long = CURRENTSCHEDULE ) const = 0; /// Returns the cost planned to be used to reach the actual percent finished virtual double budgetedCostPerformed( QDate , long = CURRENTSCHEDULE ) const { return 0.0; }; /// Return map of Budgeted Cost of Work Scheduled pr day virtual EffortCostMap bcwsPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ); /// Return map of Budgeted Cost of Work Scheduled pr day virtual EffortCostMap bcwsPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ) const; /// Budgeted Cost of Work Scheduled virtual double bcws( QDate /*date*/, long id = CURRENTSCHEDULE ) const { Q_UNUSED(id); return 0.0; } /// Return map of Budgeted Cost of Work Scheduled pr day (also includes bcws pr day) virtual EffortCostMap bcwpPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ); /// Return map of Budgeted Cost of Work Scheduled pr day (also includes bcws pr day) virtual EffortCostMap bcwpPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ) const; /// Budgeted Cost of Work Performed virtual double bcwp( long id ) const { Q_UNUSED(id); return 0.0; } /// Budgeted Cost of Work Performed ( up to @p date ) virtual double bcwp( QDate /*date*/, long id = CURRENTSCHEDULE ) const { Q_UNUSED(id); return 0.0; } /// Return a map of Actual effort and Cost of Work Performed virtual EffortCostMap acwp( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ); /// Return a map of Actual effort and Cost of Work Performed virtual EffortCostMap acwp( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ) const; /// Return Actual effort and Cost of Work Performed upto @date virtual EffortCost acwp( QDate date, long id = CURRENTSCHEDULE ) const; /// Effort based performance index virtual double effortPerformanceIndex(QDate /*date*/, long /*id*/ = CURRENTSCHEDULE ) const { return 0.0; } /// Schedule performance index virtual double schedulePerformanceIndex(QDate /*date*/, long /*id*/ = CURRENTSCHEDULE ) const { return 0.0; } /// Cost performance index virtual double costPerformanceIndex( long int /*id*/, QDate /*date*/, bool * /*error=0*/ ) const { return 0.0; } virtual void initiateCalculationLists(MainSchedule &sch) = 0; virtual DateTime calculateForward(int /*use*/) = 0; virtual DateTime calculateEarlyFinish(int /*use*/) { return DateTime(); } virtual DateTime calculateBackward(int /*use*/) = 0; virtual DateTime calculateLateStart(int /*use*/) { return DateTime(); } virtual DateTime scheduleForward(const DateTime &, int /*use*/) = 0; virtual DateTime scheduleFromStartTime(int /*use*/) { return DateTime(); } virtual DateTime scheduleBackward(const DateTime &, int /*use*/) = 0; virtual DateTime scheduleFromEndTime(int /*use*/) { return DateTime(); } virtual void adjustSummarytask() = 0; /// Returns the (previously) calculated duration Duration duration( long id = CURRENTSCHEDULE ) const; /** * The variance is calculated based on * the optimistic/pessimistic ratio specified for the estimate. */ double variance( long id = CURRENTSCHEDULE, Duration::Unit unit = Duration::Unit_ms ) const; /** * The standard deviation is calculated based on * the optimistic/pessimistic ratio specified for the estimate. */ double deviation( long id = CURRENTSCHEDULE, Duration::Unit unit = Duration::Unit_ms ) const; Node *siblingBefore(); Node *childBefore(Node *node); Node *siblingAfter(); Node *childAfter(Node *node); bool moveChildUp(Node *node); bool moveChildDown(Node *node); /// Check if this node can be linked to node bool legalToLink( const Node *node ) const; /// Check if node par can be linked to node child. (Reimplement) virtual bool legalToLink( const Node *, const Node *) const { return false; } /// Save appointments for schedule with id virtual void saveAppointments(QDomElement &element, long id) const; ///Return the list of appointments for schedule with id. QList appointments( long id = CURRENTSCHEDULE ); /// Adds appointment to this node only (not to resource) virtual bool addAppointment(Appointment *appointment, Schedule &main); /// Return list of all resources with appointments to this task for schedule with @p id. QList assignedResources( long id ) const; /// Find the node with my id virtual Node *findNode() const { return findNode(m_id); } /// Find the node with identity id virtual Node *findNode(const QString &id) const { return (m_parent ? m_parent->findNode(id) : 0); } /// Remove myself from the id register virtual bool removeId() { return removeId(m_id); } /// Remove the registered identity @p id virtual bool removeId(const QString &id) { return (m_parent ? m_parent->removeId(id) : false); } /** * This is when work can start on this node in accordance with * the calendar of allocated resources. Normally this is the same * as @ref startTime(), but may differ if timing constraints are set. */ virtual DateTime workStartTime( long id = CURRENTSCHEDULE ) const; void setWorkStartTime(const DateTime &dt, long id = CURRENTSCHEDULE ); /** * This is when work can finish on this node in accordance with * the calendar of allocated resources. Normally this is the same * as @ref endTime(), but may differ if timing constraints are set. */ virtual DateTime workEndTime( long id = CURRENTSCHEDULE ) const; void setWorkEndTime(const DateTime &dt, long id = CURRENTSCHEDULE ); /// Returns true if this node is critical virtual bool isCritical( long id = CURRENTSCHEDULE ) const { Q_UNUSED(id); return false; } /// Returns true if this node is in a critical path virtual bool inCriticalPath( long id = CURRENTSCHEDULE ) const; /// Returns the level this node is in the hierarchy. Top node is level 0. virtual int level() const; /// Generate WBS Code virtual QString generateWBSCode( QList &indexes, bool sortable = false ) const; /// Returns the Work Breakdown Structure Code QString wbsCode(bool sortable = false) const; double startupCost() const { return m_startupCost; } void setStartupCost(double cost); Account *startupAccount() const { return m_startupAccount; } void setStartupAccount(Account *acc); double shutdownCost() const { return m_shutdownCost; } void setShutdownCost(double cost); Account *shutdownAccount() const { return m_shutdownAccount; } void setShutdownAccount(Account *acc); Account *runningAccount() const { return m_runningAccount; } void setRunningAccount(Account *acc); bool isBaselined( long int id = BASELINESCHEDULE ) const; /** * Return schedule with @p id * If @p id == CURRENTSCHEDULE, return m_currentSchedule * Return 0 if schedule with @p id doesn't exist. */ Schedule *schedule( long id = CURRENTSCHEDULE ) const; /// Return current schedule Schedule *currentSchedule() const { return m_currentSchedule; } /// Set current schedule to schedule with identity @p id, for me and my children virtual void setCurrentSchedule(long id); /// Return true if this node has a valid schedule with identity == @p id bool isScheduled( long id = CURRENTSCHEDULE ) const; /// Return the list of schedules for this node QHash &schedules() { return m_schedules; } /// Find schedule matching name and type. Does not return deleted schedule. Schedule *findSchedule(const QString &name, const Schedule::Type type); /// Find schedule matching name. Does not return deleted schedule. Schedule *findSchedule(const QString &name); /// Find schedule matching type. Does not return deleted schedule. Schedule *findSchedule(const Schedule::Type type); /// Find schedule matching id. Also returns deleted schedule. Schedule *findSchedule(long id) const; /// Take, don't delete (as in destruct). void takeSchedule(const Schedule *schedule); /// Add schedule to list, replace if schedule with same id already exists. void addSchedule(Schedule *schedule); /// Create a new schedule. Schedule *createSchedule(const QString& name, Schedule::Type type, long id); /// Create a new schedule. Schedule *createSchedule(Schedule *parent); /// Set deleted = onoff for schedule with id void setScheduleDeleted(long id, bool onoff); /// Set parent schedule recursively virtual void setParentSchedule(Schedule *sch); const ResourceRequestCollection &requests() const { return m_requests; } ResourceRequestCollection &requests() { return m_requests; } virtual uint state( long ) const { return State_None; } const Documents &documents() const { return m_documents; } Documents &documents() { return m_documents; } virtual void emitDocumentAdded( Node *node, Document *doc, int idx ); virtual void emitDocumentRemoved( Node *node, Document *doc, int idx ); virtual void emitDocumentChanged( Node *node, Document *doc, int idx ); void blockChanged(bool on = true); public: // These shouldn't be available to other than those who inherits /// Calculate the critical path virtual bool calcCriticalPath(bool fromEnd); virtual void calcFreeFloat(); /// Check if this node has any dependent child nodes virtual bool isEndNode() const; /// Check if this node has any dependent parent nodes virtual bool isStartNode() const; virtual void initiateCalculation(MainSchedule &sch); virtual void resetVisited(); void propagateEarliestStart(DateTime &time); void propagateLatestFinish(DateTime &time); void moveEarliestStart(DateTime &time); void moveLatestFinish(DateTime &time); // Reimplement this virtual Duration summarytaskDurationForward(const DateTime &/*time*/) { return Duration::zeroDuration; } // Reimplement this virtual DateTime summarytaskEarliestStart() { return DateTime(); } // Reimplement this virtual Duration summarytaskDurationBackward(const DateTime &/*time*/) { return Duration::zeroDuration; } // Reimplement this virtual DateTime summarytaskLatestFinish() { return DateTime(); } /** * earlyStart() returns earliest time this node can start * given the constraints of the network. */ DateTime earlyStart( long id = CURRENTSCHEDULE ) const; /** * setEarlyStart() sets earliest time this node can start */ void setEarlyStart(const DateTime &dt, long id = CURRENTSCHEDULE ); /** * lateStart() returns latest time this node can start * given the constraints of the network. */ DateTime lateStart( long id = CURRENTSCHEDULE ) const; /** * setLateStart() sets the earliest time this node can start */ void setLateStart(const DateTime &dt, long id = CURRENTSCHEDULE ); /** * earlyFinish() returns earliest time this node can finish * given the constraints of the network. */ DateTime earlyFinish( long id = CURRENTSCHEDULE ) const; /** * setEarlyFinish() sets earliest time this node can finish */ void setEarlyFinish(const DateTime &dt, long id = CURRENTSCHEDULE ); /** * lateFinish() returns latest time this node can finish * given the constraints of the network. */ DateTime lateFinish( long id = CURRENTSCHEDULE ) const; /** * setLateFinish() sets latest time this node can finish */ void setLateFinish(const DateTime &dt, long id = CURRENTSCHEDULE ); /// Adds appointment to both this node and resource virtual void addAppointment(ResourceSchedule *resource, const DateTime &start, const DateTime &end, double load=100); virtual void clearProxyRelations() {} virtual void addParentProxyRelations( const QList & ) {} virtual void addChildProxyRelations( const QList & ) {} virtual void addParentProxyRelation(Node *, const Relation *) {} virtual void addChildProxyRelation(Node *, const Relation *) {} virtual void changed( int property = -1 ) { changed( this, property ); } Duration getmDurationForward(){ return this->m_durationForward;} public Q_SLOTS: - void slotStandardWorktimeChanged( StandardWorktime* ); + void slotStandardWorktimeChanged(KPlato::StandardWorktime*); protected: friend class KPlatoXmlLoaderBase; /** * Calculates and returns the duration of the node. * Reimplement. */ virtual Duration duration(const DateTime &/*time*/, int /*use*/, bool /*backward*/) { return Duration::zeroDuration; } // NOTE: Cannot use setCurrentSchedule() due to overload/casting problems void setCurrentSchedulePtr(Schedule *schedule) { m_currentSchedule = schedule; } virtual void changed(Node *node, int property = -1 ); QList m_nodes; QList m_dependChildNodes; QList m_dependParentNodes; QListm_parentNodes; Node *m_parent; QString m_id; // unique id QString m_name; // Name of this node QString m_leader; // Person or group responsible for this node QString m_description; // Description of this node Estimate *m_estimate; ConstraintType m_constraint; /** * m_constraintTime is used if any of the constraints * FixedInterval, StartNotEarlier, MustStartOn or FixedInterval is selected */ DateTime m_constraintStartTime; /** * m_constraintEndTime is used if any of the constraints * FixedInterval, FinishNotLater, MustFinishOn or FixedInterval is selected */ DateTime m_constraintEndTime; bool m_visitedForward; bool m_visitedBackward; Duration m_durationForward; Duration m_durationBackward; DateTime m_earlyStart; DateTime m_earlyFinish; DateTime m_lateFinish; QHash m_schedules; Schedule *m_currentSchedule; double m_startupCost; Account *m_startupAccount; double m_shutdownCost; Account *m_shutdownAccount; Account *m_runningAccount; Documents m_documents; ResourceRequestCollection m_requests; private: void init(); bool m_blockChanged; }; //////////////////////////////// Estimate //////////////////////////////// /** * The Estimate class stores how much time (or effort) it takes to complete a Task. * The estimate which is needed to complete the task is not simply a single value but * is stored as an optimistic, a pessimistic and an expected value. * With statistical calculations using the PERT distribution, one can arrive at a more * realistic estimate than when using the expected value alone. */ class PLANKERNEL_EXPORT Estimate { public: /// Constructor explicit Estimate( Node *parent = 0 ); /// Copy constructor. Estimate (const Estimate &estimate, Node *parent = 0); /// Destructor ~Estimate(); /// Reset estimate void clear(); /// Copy values from @p estimate Estimate &operator=( const Estimate &estimate ); /// Type defines the types of estimates enum Type { Type_Effort, /// Changing amount of resources changes the task duration Type_Duration /// Changing amount of resources will not change the tasks duration }; /// Return the node that owns this Estimate Node *parentNode() const { return m_parent; } /// Set the node that owns this Estimate void setParentNode( Node* parent ) { m_parent = parent; } /// Return estimate Type Type type() const { return m_type; } /// Set estimate type to @p type void setType(Type type); /// Set estimate type to type represented by the string @p type void setType(const QString& type); /// Return estimate type as a string. If @p trans is true, it's translated QString typeToString( bool trans=false ) const; /// Return estimate type @p typ as a string. If @p trans is true, it's translated static QString typeToString( Estimate::Type typ, bool trans=false ); /// Return a stringlist of all estimate types. Translated if @p trans = true. static QStringList typeToStringList( bool trans=false ); /// Return the calendar used when Type is Duration Calendar *calendar() const { return m_calendar; } /// Set the calendar to be used when Type is Duration void setCalendar( Calendar *calendar ); enum Risktype { Risk_None, Risk_Low, Risk_High }; Risktype risktype() const { return m_risktype; } void setRisktype(Risktype type); void setRisktype(const QString& type); QString risktypeToString( bool trans=false ) const; static QStringList risktypeToStringList( bool trans=false ); /// Use defines which value to access enum Use { Use_Expected=0, Use_Optimistic=1, Use_Pessimistic=2 }; /// Return estimate (scaled) of type @p valueType. /// If @p pert is true the pert value is calculated and returned Duration value(int valueType, bool pert) const; /// Return unscaled value Duration optimisticValue() const; /// Return unscaled value Duration pessimisticValue() const; /// Return unscaled value Duration expectedValue() const; /// The unit in which the estimates were entered. Duration::Unit unit() const { return m_unit; } /// Set display unit. void setUnit( Duration::Unit unit ); /// Return the expected estimate (normally entered by user) double expectedEstimate() const { return m_expectedEstimate; } /// Return the optimistic estimate (normally entered by user) double optimisticEstimate() const { return m_optimisticEstimate; } /// Return the pessimistic estimate (normally entered by user) double pessimisticEstimate() const { return m_pessimisticEstimate; } /// Set the expected estimate void setExpectedEstimate( double value ); /// Set the optimistic estimate void setOptimisticEstimate( double value ); /// Set the pessimistic estimate void setPessimisticEstimate( double value ); /** * Set the optimistic estimate as a deviation from "expected" in percent * @param percent should be a negative value. */ void setOptimisticRatio(int percent); /** * Return the "optimistic" estimate as deviation from "expected" in percent. * This should be a negative value. */ int optimisticRatio() const; /** * Set the pessimistic estimate as a deviation from "expected" in percent * @param percent should be a positive value. */ void setPessimisticRatio(int percent); /** * Return the "pessimistic" estimate as the deviation from "expected" in percent. * This should be a positive value. */ int pessimisticRatio() const; /** * The variance is calculated based on * the optimistic/pessimistic estimates, scaled to current unit. */ double variance() const; /** * The variance is calculated based on * the optimistic/pessimistic estimates, scaled to @p unit */ double variance( Duration::Unit unit ) const; /** * The standard deviation is calculated based on * the optimistic/pessimistic estimates, scaled to current unit. */ double deviation() const; /** * The standard deviation is calculated based on * the optimistic/pessimistic estimates, scaled to @p unit */ double deviation( Duration::Unit unit ) const; /// Returns the expected duration. Calculated based on the estimates expected, optimistic and pessimistic Duration pertExpected() const; /// Returns the most optimistic duration. Calculated based on the estimates expected, optimistic and pessimistic Duration pertOptimistic() const; /// Returns the most pessimistic duration. Calculated based on the estimates expected, optimistic and pessimistic Duration pertPessimistic() const; /// Convert the duration @p value (in milliseconds) to a value in @p unit, using the scaling factors in @p scales static double scale( const Duration &value, Duration::Unit unit, const QList &scales ); /// Convert the duration @p value (in @p unit) to a value in milliseconds (base unit), using the scaling factors in @p scales static Duration scale( double value, Duration::Unit unit, const QList &scales ); /// Return a list of default scales scaling factors static QList defaultScales(); /// Return a list of scaling factors fetched from the projects standard worktime QList scales() const; /// Load from xml document bool load(KoXmlElement &element, XMLLoaderObject &status); /// Save to xml document void save(QDomElement &element) const; protected: /// Set (calculate) cached value void setOptimisticValue(); /// Set (calculate) cached value void setExpectedValue(); /// Set (calculate) cached value void setPessimisticValue(); /// Notify parent of changes void changed() { if ( m_parent ) m_parent->changed(); } /// Copy @p estimate, parentNode is not copied void copy( const Estimate &estimate ); private: friend class Node; Node *m_parent; /// Holds the unit entered by user Duration::Unit m_unit; /// Holds the value entered by user, in unit m_unit double m_expectedEstimate; /// Holds the value entered by user, in unit m_unit double m_optimisticEstimate; /// Holds the value entered by user, in unit m_unit double m_pessimisticEstimate; mutable bool m_expectedCached, m_optimisticCached, m_pessimisticCached, m_pertCached; /// Cached value in base unit (milliseconds) Duration m_expectedValue; /// Cached value in base unit (milliseconds) Duration m_optimisticValue; /// Cached value in base unit (milliseconds) Duration m_pessimisticValue; /// Cached pert expected value mutable Duration m_pertExpected; Type m_type; Risktype m_risktype; /// Calendar may be used when Type is Type_Duration Calendar *m_calendar; }; } //KPlato namespace #endif diff --git a/src/libs/kernel/kptproject.cpp b/src/libs/kernel/kptproject.cpp index ec430dab..133fe64c 100644 --- a/src/libs/kernel/kptproject.cpp +++ b/src/libs/kernel/kptproject.cpp @@ -1,2939 +1,2939 @@ /* This file is part of the KDE project Copyright (C) 2001 Thomas zander Copyright (C) 2004 - 2010, 2012 Dag Andersen Copyright (C) 2007 Florian Piquemal Copyright (C) 2007 Alexis Ménard This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptproject.h" #include "kptlocale.h" #include "kptappointment.h" #include "kpttask.h" #include "kptdatetime.h" #include "kpteffortcostmap.h" #include "kptschedule.h" #include "kptwbsdefinition.h" #include "kptxmlloaderobject.h" #include "kptschedulerplugin.h" #include "kptdebug.h" #include #include #include #include #include #include namespace KPlato { Project::Project( Node *parent ) : Node( parent ), m_accounts( *this ), m_defaultCalendar( 0 ), m_config( &emptyConfig ), m_schedulerPlugins(), m_useSharedResources(false), m_sharedResourcesLoaded(false), m_loadProjectsAtStartup(false) { //debugPlan<<"("<setDefaultValues(*this); } Project::Project( ConfigBase &config, bool useDefaultValues, Node *parent ) : Node( parent ), m_accounts( *this ), m_defaultCalendar( 0 ), m_config( &config ), m_schedulerPlugins(), m_useSharedResources(false), m_sharedResourcesLoaded(false), m_loadProjectsAtStartup(false) { debugPlan<<"("<setDefaultValues(*this); } } void Project::init() { m_refCount = 1; // always used by creator m_constraint = Node::MustStartOn; m_standardWorktime = new StandardWorktime(); m_timeZone = QTimeZone::systemTimeZone(); // local timezone as default //debugPlan<= 0 ); if ( m_refCount <= 0 ) { emit aboutToBeDeleted(); deleteLater(); } } Project::~Project() { debugPlan<<"("<blockChanged(); } for (Resource *r : resourceIdDict) { r->blockChanged(); } for (ResourceGroup *g : resourceGroupIdDict) { g->blockChanged(); } delete m_standardWorktime; while ( !m_resourceGroups.isEmpty() ) delete m_resourceGroups.takeFirst(); while ( !m_calendars.isEmpty() ) delete m_calendars.takeFirst(); while ( !m_managers.isEmpty() ) delete m_managers.takeFirst(); m_config = 0; //not mine, don't delete } int Project::type() const { return Node::Type_Project; } void Project::generateUniqueNodeIds() { foreach ( Node *n, nodeIdDict ) { debugPlan<name()<<"old"<id(); QString uid = uniqueNodeId(); nodeIdDict.remove( n->id() ); n->setId( uid ); nodeIdDict[ uid ] = n; debugPlan<name()<<"new"<id(); } } void Project::generateUniqueIds() { generateUniqueNodeIds(); foreach ( ResourceGroup *g, resourceGroupIdDict ) { if (g->isShared()) { continue; } resourceGroupIdDict.remove( g->id() ); g->setId( uniqueResourceGroupId() ); resourceGroupIdDict[ g->id() ] = g; } foreach ( Resource *r, resourceIdDict ) { if (r->isShared()) { continue; } resourceIdDict.remove( r->id() ); r->setId( uniqueResourceId() ); resourceIdDict[ r->id() ] = r; } foreach ( Calendar *c, calendarIdDict ) { if (c->isShared()) { continue; } calendarIdDict.remove( c->id() ); c->setId( uniqueCalendarId() ); calendarIdDict[ c->id() ] = c; } } void Project::calculate( Schedule *schedule, const DateTime &dt ) { if ( schedule == 0 ) { errorPlan << "Schedule == 0, cannot calculate"; return ; } m_currentSchedule = schedule; calculate( dt ); } void Project::calculate( const DateTime &dt ) { if ( m_currentSchedule == 0 ) { errorPlan << "No current schedule to calculate"; return ; } stopcalculation = false; QLocale locale; DateTime time = dt.isValid() ? dt : DateTime( QDateTime::currentDateTime() ); MainSchedule *cs = static_cast( m_currentSchedule ); Estimate::Use estType = ( Estimate::Use ) cs->type(); if ( type() == Type_Project ) { cs->setPhaseName( 0, i18n( "Init" ) ); cs->logInfo( i18n( "Schedule project from: %1", locale.toString(dt, QLocale::ShortFormat) ), 0 ); initiateCalculation( *cs ); initiateCalculationLists( *cs ); // must be after initiateCalculation() !! propagateEarliestStart( time ); // Calculate lateFinish from time. If a task has started, remainingEffort is used. cs->setPhaseName( 1, i18nc( "Schedule project forward", "Forward" ) ); cs->logInfo( i18n( "Calculate finish" ), 1 ); cs->lateFinish = calculateForward( estType ); cs->lateFinish = checkEndConstraints( cs->lateFinish ); propagateLatestFinish( cs->lateFinish ); // Calculate earlyFinish. If a task has started, remainingEffort is used. cs->setPhaseName( 2, i18nc( "Schedule project backward","Backward" ) ); cs->logInfo( i18n( "Calculate start" ), 2 ); calculateBackward( estType ); // Schedule. If a task has started, remainingEffort is used and appointments are copied from parent cs->setPhaseName( 3, i18n( "Schedule" ) ); cs->logInfo( i18n( "Schedule tasks forward" ), 3 ); cs->endTime = scheduleForward( cs->startTime, estType ); cs->logInfo( i18n( "Scheduled finish: %1", locale.toString(cs->endTime, QLocale::ShortFormat) ), 3 ); if ( cs->endTime > m_constraintEndTime ) { cs->logError( i18n( "Could not finish project in time: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 3 ); } else if ( cs->endTime == m_constraintEndTime ) { cs->logWarning( i18n( "Finished project exactly on time: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 3 ); } else { cs->logInfo( i18n( "Finished project before time: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 3 ); } calcCriticalPath( false ); calcResourceOverbooked(); cs->notScheduled = false; calcFreeFloat(); emit scheduleChanged( cs ); emit projectChanged(); } else if ( type() == Type_Subproject ) { warnPlan << "Subprojects not implemented"; } else { errorPlan << "Illegal project type: " << type(); } } void Project::calculate( ScheduleManager &sm ) { emit sigCalculationStarted( this, &sm ); sm.setScheduling( true ); m_progress = 0; int nodes = 0; foreach ( Node *n, nodeIdDict ) { if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) { nodes++; } } int maxprogress = nodes * 3; if ( sm.recalculate() ) { emit maxProgress( maxprogress ); sm.setMaxProgress( maxprogress ); incProgress(); if ( sm.parentManager() ) { sm.expected()->startTime = sm.parentManager()->expected()->startTime; sm.expected()->earlyStart = sm.parentManager()->expected()->earlyStart; } incProgress(); calculate( sm.expected(), sm.recalculateFrom() ); } else { emit maxProgress( maxprogress ); sm.setMaxProgress( maxprogress ); calculate( sm.expected() ); emit scheduleChanged( sm.expected() ); setCurrentSchedule( sm.expected()->id() ); } emit sigProgress( maxprogress ); emit sigCalculationFinished( this, &sm ); emit scheduleManagerChanged( &sm ); emit projectCalculated( &sm ); emit projectChanged(); sm.setScheduling( false ); } void Project::calculate( Schedule *schedule ) { if ( schedule == 0 ) { errorPlan << "Schedule == 0, cannot calculate"; return ; } m_currentSchedule = schedule; calculate(); } void Project::calculate() { if ( m_currentSchedule == 0 ) { errorPlan << "No current schedule to calculate"; return ; } stopcalculation = false; MainSchedule *cs = static_cast( m_currentSchedule ); bool backwards = false; if ( cs->manager() ) { backwards = cs->manager()->schedulingDirection(); } QLocale locale; Estimate::Use estType = ( Estimate::Use ) cs->type(); if ( type() == Type_Project ) { QTime timer; timer.start(); initiateCalculation( *cs ); initiateCalculationLists( *cs ); // must be after initiateCalculation() !! if ( ! backwards ) { cs->setPhaseName( 0, i18n( "Init" ) ); cs->logInfo( i18n( "Schedule project forward from: %1", locale.toString(m_constraintStartTime, QLocale::ShortFormat) ), 0 ); cs->startTime = m_constraintStartTime; cs->earlyStart = m_constraintStartTime; // Calculate from start time propagateEarliestStart( cs->earlyStart ); cs->setPhaseName( 1, i18nc( "Schedule project forward", "Forward" ) ); cs->logInfo( i18n( "Calculate late finish" ), 1 ); cs->lateFinish = calculateForward( estType ); // cs->lateFinish = checkEndConstraints( cs->lateFinish ); cs->logInfo( i18n( "Late finish calculated: %1", locale.toString(cs->lateFinish, QLocale::ShortFormat) ), 1 ); propagateLatestFinish( cs->lateFinish ); cs->setPhaseName( 2, i18nc( "Schedule project backward", "Backward" ) ); cs->logInfo( i18n( "Calculate early start" ), 2 ); calculateBackward( estType ); cs->setPhaseName( 3, i18n( "Schedule" ) ); cs->logInfo( i18n( "Schedule tasks forward" ), 3 ); cs->endTime = scheduleForward( cs->startTime, estType ); cs->duration = cs->endTime - cs->startTime; cs->logInfo( i18n( "Scheduled finish: %1", locale.toString(cs->endTime, QLocale::ShortFormat) ), 3 ); if ( cs->endTime > m_constraintEndTime ) { cs->constraintError = true; cs->logError( i18n( "Could not finish project in time: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 3 ); } else if ( cs->endTime == m_constraintEndTime ) { cs->logWarning( i18n( "Finished project exactly on time: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 3 ); } else { cs->logInfo( i18n( "Finished project before time: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 3 ); } calcCriticalPath( false ); } else { cs->setPhaseName( 0, i18n( "Init" ) ); cs->logInfo( i18n( "Schedule project backward from: %1", locale.toString(m_constraintEndTime, QLocale::ShortFormat) ), 0 ); // Calculate from end time propagateLatestFinish( m_constraintEndTime ); cs->setPhaseName( 1, i18nc( "Schedule project backward", "Backward" ) ); cs->logInfo( i18n( "Calculate early start" ), 1 ); cs->earlyStart = calculateBackward( estType ); // cs->earlyStart = checkStartConstraints( cs->earlyStart ); cs->logInfo( i18n( "Early start calculated: %1", locale.toString(cs->earlyStart, QLocale::ShortFormat) ), 1 ); propagateEarliestStart( cs->earlyStart ); cs->setPhaseName( 2, i18nc( "Schedule project forward", "Forward" ) ); cs->logInfo( i18n( "Calculate late finish" ), 2 ); cs->lateFinish = qMax( m_constraintEndTime, calculateForward( estType ) ); cs->logInfo( i18n( "Late finish calculated: %1", locale.toString(cs->lateFinish, QLocale::ShortFormat) ), 2 ); cs->setPhaseName( 3, i18n( "Schedule" ) ); cs->logInfo( i18n( "Schedule tasks backward" ), 3 ); cs->startTime = scheduleBackward( cs->lateFinish, estType ); cs->endTime = cs->startTime; foreach ( Node *n, allNodes() ) { if ( n->type() == Type_Task || n->type() == Type_Milestone ) { DateTime e = n->endTime( cs->id() ); if ( cs->endTime < e ) { cs->endTime = e; } } } if ( cs->endTime > m_constraintEndTime ) { cs->constraintError = true; cs->logError( i18n( "Failed to finish project within target time" ), 3 ); } cs->duration = cs->endTime - cs->startTime; cs->logInfo( i18n( "Scheduled start: %1, target time: %2", locale.toString(cs->startTime, QLocale::ShortFormat), locale.toString(m_constraintStartTime, QLocale::ShortFormat) ), 3 ); if ( cs->startTime < m_constraintStartTime ) { cs->constraintError = true; cs->logError( i18n( "Must start project early in order to finish in time: %1", locale.toString(m_constraintStartTime, QLocale::ShortFormat) ), 3 ); } else if ( cs->startTime == m_constraintStartTime ) { cs->logWarning( i18n( "Start project exactly on time: %1", locale.toString(m_constraintStartTime, QLocale::ShortFormat) ), 3 ); } else { cs->logInfo( i18n( "Can start project later than time: %1", locale.toString(m_constraintStartTime, QLocale::ShortFormat) ), 3 ); } calcCriticalPath( true ); } cs->logInfo( i18n( "Calculation took: %1", KFormat().formatDuration( timer.elapsed() ) ) ); // TODO: fix this uncertainty, manager should *always* be available if (cs->manager()) { finishCalculation(*(cs->manager())); } } else if ( type() == Type_Subproject ) { warnPlan << "Subprojects not implemented"; } else { errorPlan << "Illegal project type: " << type(); } } void Project::finishCalculation( ScheduleManager &sm ) { MainSchedule *cs = sm.expected(); if (nodeIdDict.count() > 1) { // calculate project duration cs->startTime = m_constraintEndTime; cs->endTime = m_constraintStartTime; for (const Node *n : nodeIdDict) { cs->startTime = qMin(cs->startTime, n->startTime(cs->id())); cs->endTime = qMax(cs->endTime, n->endTime(cs->id())); } cs->duration = cs->endTime - cs->startTime; } calcCriticalPath( false ); calcResourceOverbooked(); cs->notScheduled = false; calcFreeFloat(); emit scheduleChanged( cs ); emit projectChanged(); debugPlan<startTime<endTime<<"-------------------------"; } void Project::setProgress( int progress, ScheduleManager *sm ) { m_progress = progress; if ( sm ) { sm->setProgress( progress ); } emit sigProgress( progress ); } void Project::setMaxProgress( int max, ScheduleManager *sm ) { if ( sm ) { sm->setMaxProgress( max ); } emitMaxProgress( max ); } void Project::incProgress() { m_progress += 1; emit sigProgress( m_progress ); } void Project::emitMaxProgress( int value ) { emit maxProgress( value ); } bool Project::calcCriticalPath( bool fromEnd ) { //debugPlan; MainSchedule *cs = static_cast( m_currentSchedule ); if ( cs == 0 ) { return false; } if ( fromEnd ) { QListIterator startnodes = cs->startNodes(); while ( startnodes.hasNext() ) { startnodes.next() ->calcCriticalPath( fromEnd ); } } else { QListIterator endnodes = cs->endNodes(); while ( endnodes.hasNext() ) { endnodes.next() ->calcCriticalPath( fromEnd ); } } calcCriticalPathList( cs ); return false; } void Project::calcCriticalPathList( MainSchedule *cs ) { //debugPlan<name(); cs->clearCriticalPathList(); foreach ( Node *n, allNodes() ) { if ( n->numDependParentNodes() == 0 && n->inCriticalPath( cs->id() ) ) { cs->addCriticalPath(); cs->addCriticalPathNode( n ); calcCriticalPathList( cs, n ); } } cs->criticalPathListCached = true; //debugPlan<<*(criticalPathList( cs->id() )); } void Project::calcCriticalPathList( MainSchedule *cs, Node *node ) { //debugPlan<name()<<", "<id(); bool newPath = false; QList lst = *( cs->currentCriticalPath() ); foreach ( Relation *r, node->dependChildNodes() ) { if ( r->child()->inCriticalPath( cs->id() ) ) { if ( newPath ) { cs->addCriticalPath( &lst ); //debugPlan<name()<<" new path"; } cs->addCriticalPathNode( r->child() ); calcCriticalPathList( cs, r->child() ); newPath = true; } } } const QList< QList > *Project::criticalPathList( long id ) { Schedule *s = schedule( id ); if ( s == 0 ) { //debugPlan<<"No schedule with id="<( s ); if ( ! ms->criticalPathListCached ) { initiateCalculationLists( *ms ); calcCriticalPathList( ms ); } return ms->criticalPathList(); } QList Project::criticalPath( long id, int index ) { Schedule *s = schedule( id ); if ( s == 0 ) { //debugPlan<<"No schedule with id="<(); } MainSchedule *ms = static_cast( s ); if ( ! ms->criticalPathListCached ) { initiateCalculationLists( *ms ); calcCriticalPathList( ms ); } return ms->criticalPath( index ); } DateTime Project::startTime( long id ) const { Schedule *s = schedule( id ); return s ? s->startTime : m_constraintStartTime; } DateTime Project::endTime( long id ) const { Schedule *s = schedule( id ); return s ? s->endTime : m_constraintEndTime; } Duration Project::duration( long id ) const { Schedule *s = schedule( id ); return s ? s->duration : Duration::zeroDuration; } Duration *Project::getRandomDuration() { return 0L; } DateTime Project::checkStartConstraints( const DateTime &dt ) const { DateTime t = dt; foreach ( Node *n, nodeIdDict ) { if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) { switch ( n->constraint() ) { case Node::FixedInterval: case Node::StartNotEarlier: case Node::MustStartOn: t = qMin( t, qMax( n->constraintStartTime(), m_constraintStartTime ) ); break; default: break; } } } return t; } DateTime Project::checkEndConstraints( const DateTime &dt ) const { DateTime t = dt; foreach ( Node *n, nodeIdDict ) { if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) { switch ( n->constraint() ) { case Node::FixedInterval: case Node::FinishNotLater: case Node::MustFinishOn: t = qMax( t, qMin( n->constraintEndTime(), m_constraintEndTime ) ); break; default: break; } } } return t; } #ifndef PLAN_NLOGDEBUG bool Project::checkParent( Node *n, const QList &list, QList &checked ) { if ( n->isStartNode() ) { debugPlan< lst = list; lst << n; foreach ( Relation *r, n->dependParentNodes() ) { if ( checked.contains( r ) ) { debugPlan<<"Depend:"<parent()<<": checked"; continue; } checked << r; if ( ! checkParent( r->parent(), lst, checked ) ) { return false; } } Task *t = static_cast( n ); foreach ( Relation *r, t->parentProxyRelations() ) { if ( checked.contains( r ) ) { debugPlan<<"Depend:"<parent()<<": checked"; continue; } checked << r; debugPlan<<"Proxy:"<parent()<<":"<parent(), lst, checked ) ) { return false; } } return true; } bool Project::checkChildren( Node *n, const QList &list, QList &checked ) { if ( n->isEndNode() ) { debugPlan< lst = list; lst << n; foreach ( Relation *r, n->dependChildNodes() ) { if ( checked.contains( r ) ) { debugPlan<<"Depend:"<parent()<<": checked"; continue; } checked << r; if ( ! checkChildren( r->child(), lst, checked ) ) { return false; } } Task *t = static_cast( n ); foreach ( Relation *r, t->childProxyRelations() ) { if ( checked.contains( r ) ) { debugPlan<<"Depend:"<parent()<<": checked"; continue; } debugPlan<<"Proxy:"<parent()<<":"<child(), lst, checked ) ) { return false; } } return true; } #endif void Project::tasksForward() { m_hardConstraints.clear(); m_softConstraints.clear(); m_terminalNodes.clear(); foreach ( Task *t, allTasks() ) { switch ( t->constraint() ) { case Node::MustStartOn: case Node::MustFinishOn: case Node::FixedInterval: m_hardConstraints.append( t ); break; case Node::StartNotEarlier: case Node::FinishNotLater: m_softConstraints.append( t ); break; default: if ( t->isEndNode() ) { m_terminalNodes.append( t ); } break; } } #ifndef PLAN_NLOGDEBUG debugPlan<<"End nodes:"< lst; QList rel; Q_ASSERT( checkParent( n, lst, rel ) ); Q_UNUSED( n ); } #endif } void Project::tasksBackward() { m_hardConstraints.clear(); m_softConstraints.clear(); m_terminalNodes.clear(); foreach ( Task *t, allTasks() ) { switch ( t->constraint() ) { case Node::MustStartOn: case Node::MustFinishOn: case Node::FixedInterval: m_hardConstraints.append( t ); break; case Node::StartNotEarlier: case Node::FinishNotLater: m_softConstraints.append( t ); break; default: if ( t->isStartNode() ) { m_terminalNodes.append( t ); } break; } } #ifndef PLAN_NLOGDEBUG debugPlan<<"Start nodes:"< lst; QList rel; Q_ASSERT( checkChildren( n, lst, rel ) ); Q_UNUSED( n ); } #endif } DateTime Project::calculateForward( int use ) { //debugPlan<( m_currentSchedule ); if ( cs == 0 ) { return finish; } if ( type() == Node::Type_Project ) { QTime timer; timer.start(); cs->logInfo( i18n( "Start calculating forward" ) ); m_visitedForward = true; if ( ! m_visitedBackward ) { // setup tasks tasksForward(); // Do all hard constrained first foreach ( Node *n, m_hardConstraints ) { cs->logDebug( "Calculate task with hard constraint:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateEarlyFinish( use ); // do not do predeccessors if ( time > finish ) { finish = time; } } // do the predeccessors foreach ( Node *n, m_hardConstraints ) { cs->logDebug( "Calculate predeccessors to hard constrained task:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateForward( use ); if ( time > finish ) { finish = time; } } // now try to schedule soft constrained *with* predeccessors foreach ( Node *n, m_softConstraints ) { cs->logDebug( "Calculate task with soft constraint:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateForward( use ); if ( time > finish ) { finish = time; } } // and then the rest using the end nodes to calculate everything (remaining) foreach ( Task *n, m_terminalNodes ) { cs->logDebug( "Calculate using end task:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateForward( use ); if ( time > finish ) { finish = time; } } } else { // tasks have been calculated backwards in this order foreach ( Node *n, cs->backwardNodes() ) { DateTime time = n->calculateForward( use ); if ( time > finish ) { finish = time; } } } cs->logInfo( i18n( "Finished calculating forward: %1 ms", timer.elapsed() ) ); } else { //TODO: subproject } return finish; } DateTime Project::calculateBackward( int use ) { //debugPlan<( m_currentSchedule ); if ( cs == 0 ) { return start; } if ( type() == Node::Type_Project ) { QTime timer; timer.start(); cs->logInfo( i18n( "Start calculating backward" ) ); m_visitedBackward = true; if ( ! m_visitedForward ) { // setup tasks tasksBackward(); // Do all hard constrained first foreach ( Task *n, m_hardConstraints ) { cs->logDebug( "Calculate task with hard constraint:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateLateStart( use ); // do not do predeccessors if ( ! start.isValid() || time < start ) { start = time; } } // then do the predeccessors foreach ( Task *n, m_hardConstraints ) { cs->logDebug( "Calculate predeccessors to hard constrained task:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateBackward( use ); if ( ! start.isValid() || time < start ) { start = time; } } // now try to schedule soft constrained *with* predeccessors foreach ( Task *n, m_softConstraints ) { cs->logDebug( "Calculate task with soft constraint:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateBackward( use ); if ( ! start.isValid() || time < start ) { start = time; } } // and then the rest using the start nodes to calculate everything (remaining) foreach ( Task *n, m_terminalNodes ) { cs->logDebug( "Calculate using start task:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->calculateBackward( use ); if ( ! start.isValid() || time < start ) { start = time; } } } else { // tasks have been calculated forwards in this order foreach ( Node *n, cs->forwardNodes() ) { DateTime time = n->calculateBackward( use ); if ( ! start.isValid() || time < start ) { start = time; } } } cs->logInfo( i18n( "Finished calculating backward: %1 ms", timer.elapsed() ) ); } else { //TODO: subproject } return start; } DateTime Project::scheduleForward( const DateTime &earliest, int use ) { DateTime end; MainSchedule *cs = static_cast( m_currentSchedule ); if ( cs == 0 || stopcalculation ) { return DateTime(); } QTime timer; timer.start(); cs->logInfo( i18n( "Start scheduling forward" ) ); resetVisited(); // Schedule in the same order as calculated forward // Do all hard constrained first foreach ( Node *n, m_hardConstraints ) { cs->logDebug( "Schedule task with hard constraint:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->scheduleFromStartTime( use ); // do not do predeccessors if ( time > end ) { end = time; } } foreach ( Node *n, cs->forwardNodes() ) { cs->logDebug( "Schedule task:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->scheduleForward( earliest, use ); if ( time > end ) { end = time; } } // Fix summarytasks adjustSummarytask(); cs->logInfo( i18n( "Finished scheduling forward: %1 ms", timer.elapsed() ) ); foreach ( Node *n, allNodes() ) { if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) { Q_ASSERT( n->isScheduled() ); } } return end; } DateTime Project::scheduleBackward( const DateTime &latest, int use ) { DateTime start; MainSchedule *cs = static_cast( m_currentSchedule ); if ( cs == 0 || stopcalculation ) { return start; } QTime timer; timer.start(); cs->logInfo( i18n( "Start scheduling backward" ) ); resetVisited(); // Schedule in the same order as calculated backward // Do all hard constrained first foreach ( Node *n, m_hardConstraints ) { cs->logDebug( "Schedule task with hard constraint:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->scheduleFromEndTime( use ); // do not do predeccessors if ( ! start.isValid() || time < start ) { start = time; } } foreach ( Node *n, cs->backwardNodes() ) { cs->logDebug( "Schedule task:" + n->name() + " : " + n->constraintToString() ); DateTime time = n->scheduleBackward( latest, use ); if ( ! start.isValid() || time < start ) { start = time; } } // Fix summarytasks adjustSummarytask(); cs->logInfo( i18n( "Finished scheduling backward: %1 ms", timer.elapsed() ) ); foreach ( Node *n, allNodes() ) { if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) { Q_ASSERT( n->isScheduled() ); } } return start; } void Project::adjustSummarytask() { MainSchedule *cs = static_cast( m_currentSchedule ); if ( cs == 0 || stopcalculation ) { return; } QListIterator it( cs->summaryTasks() ); while ( it.hasNext() ) { it.next() ->adjustSummarytask(); } } void Project::initiateCalculation( MainSchedule &sch ) { //debugPlan< git( m_resourceGroups ); while ( git.hasNext() ) { git.next() ->initiateCalculation( sch ); } Node::initiateCalculation( sch ); } void Project::initiateCalculationLists( MainSchedule &sch ) { //debugPlan< it = childNodeIterator(); while ( it.hasNext() ) { it.next() ->initiateCalculationLists( sch ); } } else { //TODO: subproject } } bool Project::load( KoXmlElement &element, XMLLoaderObject &status ) { //debugPlan<<"--->"; m_useSharedResources = false; // default should off in case old project // load locale first KoXmlNode n = element.firstChild(); for ( ; ! n.isNull(); n = n.nextSibling() ) { if ( ! n.isElement() ) { continue; } KoXmlElement e = n.toElement(); if ( e.tagName() == "locale" ) { Locale *l = locale(); l->setCurrencySymbol(e.attribute( "currency-symbol", "")); if ( e.hasAttribute( "currency-digits" ) ) { l->setMonetaryDecimalPlaces(e.attribute("currency-digits").toInt()); } QLocale::Language language = QLocale::AnyLanguage; QLocale::Country country = QLocale::AnyCountry; if (e.hasAttribute("language")) { language = static_cast(e.attribute("language").toInt()); } if (e.hasAttribute("country")) { country = static_cast(e.attribute("country").toInt()); } l->setCurrencyLocale(language, country); } else if (e.tagName() == "shared-resources") { m_useSharedResources = e.attribute("use", "0").toInt(); m_sharedResourcesFile = e.attribute("file"); m_sharedProjectsUrl = QUrl(e.attribute("projects-url")); m_loadProjectsAtStartup = (bool)e.attribute("projects-loadatstartup", "0").toInt(); } } QList cals; QString s; bool ok = false; setName( element.attribute( "name" ) ); removeId( m_id ); m_id = element.attribute( "id" ); registerNodeId( this ); m_leader = element.attribute( "leader" ); m_description = element.attribute( "description" ); QTimeZone tz( element.attribute( "timezone" ).toLatin1() ); if ( tz.isValid() ) { m_timeZone = tz; } else warnPlan<<"No timezone specified, using default (local)"; status.setProjectTimeZone( m_timeZone ); // Allow for both numeric and text s = element.attribute( "scheduling", "0" ); m_constraint = ( Node::ConstraintType ) s.toInt( &ok ); if ( !ok ) setConstraint( s ); if ( m_constraint != Node::MustStartOn && m_constraint != Node::MustFinishOn ) { errorPlan << "Illegal constraint: " << constraintToString(); setConstraint( Node::MustStartOn ); } s = element.attribute( "start-time" ); if ( !s.isEmpty() ) m_constraintStartTime = DateTime::fromString( s, m_timeZone ); s = element.attribute( "end-time" ); if ( !s.isEmpty() ) m_constraintEndTime = DateTime::fromString( s, m_timeZone ); status.setProgress( 10 ); // Load the project children // Do calendars first, they only reference other calendars //debugPlan<<"Calendars--->"; n = element.firstChild(); for ( ; ! n.isNull(); n = n.nextSibling() ) { if ( ! n.isElement() ) { continue; } KoXmlElement e = n.toElement(); if ( e.tagName() == "calendar" ) { // Load the calendar. // Referenced by resources Calendar * child = new Calendar(); child->setProject( this ); if ( child->load( e, status ) ) { cals.append( child ); // temporary, reorder later } else { // TODO: Complain about this errorPlan << "Failed to load calendar"; delete child; } } else if ( e.tagName() == "standard-worktime" ) { // Load standard worktime StandardWorktime * child = new StandardWorktime(); if ( child->load( e, status ) ) { setStandardWorktime( child ); } else { errorPlan << "Failed to load standard worktime"; delete child; } } } // calendars references calendars in arbritary saved order bool added = false; do { added = false; QList lst; while ( !cals.isEmpty() ) { Calendar *c = cals.takeFirst(); c->m_blockversion = true; if ( c->parentId().isEmpty() ) { addCalendar( c, status.baseCalendar() ); // handle pre 0.6 version added = true; //debugPlan<<"added to project:"<name(); } else { Calendar *par = calendar( c->parentId() ); if ( par ) { par->m_blockversion = true; addCalendar( c, par ); added = true; //debugPlan<<"added:"<name()<<" to parent:"<name(); par->m_blockversion = false; } else { lst.append( c ); // treat later //debugPlan<<"treat later:"<name(); } } c->m_blockversion = false; } cals = lst; } while ( added ); if ( ! cals.isEmpty() ) { errorPlan<<"All calendars not saved!"; } //debugPlan<<"Calendars<---"; status.setProgress( 15 ); // Resource groups and resources, can reference calendars n = element.firstChild(); for ( ; ! n.isNull(); n = n.nextSibling() ) { if ( ! n.isElement() ) { continue; } KoXmlElement e = n.toElement(); if ( e.tagName() == "resource-group" ) { // Load the resources // References calendars ResourceGroup * child = new ResourceGroup(); if ( child->load( e, status ) ) { addResourceGroup( child ); } else { // TODO: Complain about this delete child; } } } status.setProgress( 20 ); // The main stuff n = element.firstChild(); for ( ; ! n.isNull(); n = n.nextSibling() ) { if ( ! n.isElement() ) { continue; } KoXmlElement e = n.toElement(); if ( e.tagName() == "project" ) { //debugPlan<<"Sub project--->"; /* // Load the subproject Project * child = new Project( this ); if ( child->load( e ) ) { if ( !addTask( child, this ) ) { delete child; // TODO: Complain about this } } else { // TODO: Complain about this delete child; }*/ } else if ( e.tagName() == "task" ) { //debugPlan<<"Task--->"; // Load the task (and resourcerequests). // Depends on resources already loaded Task * child = new Task( this ); if ( child->load( e, status ) ) { if ( !addTask( child, this ) ) { delete child; // TODO: Complain about this } } else { // TODO: Complain about this delete child; } } } status.setProgress( 70 ); // These go last n = element.firstChild(); for ( ; ! n.isNull(); n = n.nextSibling() ) { debugPlan<"; // Load accounts // References tasks if ( !m_accounts.load( e, *this ) ) { errorPlan << "Failed to load accounts"; } } else if ( e.tagName() == "relation" ) { //debugPlan<<"Relation--->"; // Load the relation // References tasks Relation * child = new Relation(); if ( !child->load( e, *this ) ) { // TODO: Complain about this errorPlan << "Failed to load relation"; delete child; } //debugPlan<<"Relation<---"; } else if ( e.tagName() == "schedules" ) { //debugPlan<<"Project schedules & task appointments--->"; // References tasks and resources KoXmlNode sn = e.firstChild(); for ( ; ! sn.isNull(); sn = sn.nextSibling() ) { if ( ! sn.isElement() ) { continue; } KoXmlElement el = sn.toElement(); //debugPlan<loadXML( el, status ) ) { if ( add ) addScheduleManager( sm ); } else { errorPlan << "Failed to load schedule manager"; delete sm; } } else { debugPlan<<"No schedule manager ?!"; } } //debugPlan<<"Node schedules<---"; } else if ( e.tagName() == "resource-teams" ) { //debugPlan<<"Resource teams--->"; // References other resources KoXmlNode tn = e.firstChild(); for ( ; ! tn.isNull(); tn = tn.nextSibling() ) { if ( ! tn.isElement() ) { continue; } KoXmlElement el = tn.toElement(); if ( el.tagName() == "team" ) { Resource *r = findResource( el.attribute( "team-id" ) ); Resource *tm = findResource( el.attribute( "member-id" ) ); if ( r == 0 || tm == 0 ) { errorPlan<<"resource-teams: cannot find resources"; continue; } if ( r == tm ) { errorPlan<<"resource-teams: a team cannot be a member of itself"; continue; } r->addTeamMemberId( tm->id() ); } else { errorPlan<<"resource-teams: unhandled tag"<currencySymbolExplicit().isEmpty()) { loc.setAttribute("currency-symbol", l->currencySymbolExplicit()); } loc.setAttribute("currency-digits", l->monetaryDecimalPlaces()); loc.setAttribute("language", l->currencyLanguage()); loc.setAttribute("country", l->currencyCountry()); QDomElement share = me.ownerDocument().createElement( "shared-resources" ); me.appendChild(share); share.setAttribute("use", m_useSharedResources); share.setAttribute("file", m_sharedResourcesFile); share.setAttribute("projects-url", QString(m_sharedProjectsUrl.toEncoded())); share.setAttribute("projects-loadatstartup", m_loadProjectsAtStartup); m_accounts.save( me ); // save calendars foreach ( Calendar *c, calendarIdDict ) { c->save( me ); } // save standard worktime if ( m_standardWorktime ) m_standardWorktime->save( me ); // save project resources, must be after calendars QListIterator git( m_resourceGroups ); while ( git.hasNext() ) { git.next() ->save( me ); } // Only save parent relations QListIterator it( m_dependParentNodes ); while ( it.hasNext() ) { it.next() ->save( me ); } for ( int i = 0; i < numChildren(); i++ ) // Save all children childNode( i ) ->save( me ); // Now we can save relations assuming no tasks have relations outside the project QListIterator nodes( m_nodes ); while ( nodes.hasNext() ) { nodes.next() ->saveRelations( me ); } if ( !m_managers.isEmpty() ) { QDomElement el = me.ownerDocument().createElement( "schedules" ); me.appendChild( el ); foreach ( ScheduleManager *sm, m_managers ) { sm->saveXML( el ); } } // save resource teams QDomElement el = me.ownerDocument().createElement( "resource-teams" ); me.appendChild( el ); foreach ( Resource *r, resourceIdDict ) { if ( r->type() != Resource::Type_Team ) { continue; } foreach ( const QString &id, r->teamMemberIds() ) { QDomElement e = el.ownerDocument().createElement( "team" ); el.appendChild( e ); e.setAttribute( "team-id", r->id() ); e.setAttribute( "member-id", id ); } } } void Project::saveWorkPackageXML( QDomElement &element, const Node *node, long id ) const { QDomElement me = element.ownerDocument().createElement( "project" ); element.appendChild( me ); me.setAttribute( "name", m_name ); me.setAttribute( "leader", m_leader ); me.setAttribute( "id", m_id ); me.setAttribute( "description", m_description ); me.setAttribute( "timezone", m_timeZone.isValid() ? QString::fromLatin1(m_timeZone.id()) : QString() ); me.setAttribute( "scheduling", constraintToString() ); me.setAttribute( "start-time", m_constraintStartTime.toString( Qt::ISODate ) ); me.setAttribute( "end-time", m_constraintEndTime.toString( Qt::ISODate ) ); QListIterator git( m_resourceGroups ); while ( git.hasNext() ) { git.next() ->saveWorkPackageXML( me, node->assignedResources( id ) ); } if ( node == 0 ) { return; } node->saveWorkPackageXML( me, id ); foreach ( ScheduleManager *sm, m_managerIdMap ) { if ( sm->scheduleId() == id ) { QDomElement el = me.ownerDocument().createElement( "schedules" ); me.appendChild( el ); sm->saveWorkPackageXML( el, *node ); break; } } } void Project::setParentSchedule( Schedule *sch ) { QListIterator it = m_nodes; while ( it.hasNext() ) { it.next() ->setParentSchedule( sch ); } } void Project::addResourceGroup( ResourceGroup *group, int index ) { int i = index == -1 ? m_resourceGroups.count() : index; emit resourceGroupToBeAdded( group, i ); m_resourceGroups.insert( i, group ); setResourceGroupId( group ); group->setProject( this ); foreach ( Resource *r, group->resources() ) { setResourceId( r ); r->setProject( this ); } emit resourceGroupAdded( group ); emit projectChanged(); } ResourceGroup *Project::takeResourceGroup( ResourceGroup *group ) { int i = m_resourceGroups.indexOf( group ); Q_ASSERT( i != -1 ); if ( i == -1 ) { return 0; } emit resourceGroupToBeRemoved( group ); ResourceGroup *g = m_resourceGroups.takeAt( i ); Q_ASSERT( group == g ); g->setProject( 0 ); removeResourceGroupId( g->id() ); foreach ( Resource *r, g->resources() ) { r->setProject( 0 ); removeResourceId( r->id() ); } emit resourceGroupRemoved( g ); emit projectChanged(); return g; } QList &Project::resourceGroups() { return m_resourceGroups; } void Project::addResource( ResourceGroup *group, Resource *resource, int index ) { int i = index == -1 ? group->numResources() : index; emit resourceToBeAdded( group, i ); group->addResource( i, resource, 0 ); setResourceId( resource ); emit resourceAdded( resource ); emit projectChanged(); } Resource *Project::takeResource( ResourceGroup *group, Resource *resource ) { emit resourceToBeRemoved( resource ); bool result = removeResourceId( resource->id() ); Q_ASSERT( result == true ); if (!result) { warnPlan << "Could not remove resource with id" << resource->id(); } resource->removeRequests(); // not valid anymore Resource *r = group->takeResource( resource ); Q_ASSERT( resource == r ); if (resource != r) { warnPlan << "Could not take resource from group"; } emit resourceRemoved( resource ); emit projectChanged(); return r; } void Project::moveResource( ResourceGroup *group, Resource *resource ) { if ( group == resource->parentGroup() ) { return; } takeResource( resource->parentGroup(), resource ); addResource( group, resource ); return; } QMap< QString, QString > Project::externalProjects() const { QMap< QString, QString > map; foreach ( Resource *r, resourceList() ) { for( QMapIterator it( r->externalProjects() ); it.hasNext(); ) { it.next(); if ( ! map.contains( it.key() ) ) { map[ it.key() ] = it.value(); } } } return map; } bool Project::addTask( Node* task, Node* position ) { // we want to add a task at the given position. => the new node will // become next sibling right after position. if ( 0 == position ) { return addSubTask( task, this ); } //debugPlan<<"Add"<name()<<" after"<name(); // in case we want to add to the main project, we make it child element // of the root element. if ( Node::Type_Project == position->type() ) { return addSubTask( task, position ); } // find the position // we have to tell the parent that we want to delete one of its children Node* parentNode = position->parentNode(); if ( !parentNode ) { debugPlan <<"parent node not found???"; return false; } int index = parentNode->findChildNode( position ); if ( -1 == index ) { // ok, it does not exist debugPlan <<"Task not found???"; return false; } return addSubTask( task, index + 1, parentNode ); } bool Project::addSubTask( Node* task, Node* parent ) { // append task to parent return addSubTask( task, -1, parent ); } bool Project::addSubTask( Node* task, int index, Node* parent, bool emitSignal ) { // we want to add a subtask to the node "parent" at the given index. // If parent is 0, add to this Node *p = parent; if ( 0 == p ) { p = this; } if ( !registerNodeId( task ) ) { errorPlan << "Failed to register node id, can not add subtask: " << task->name(); return false; } int i = index == -1 ? p->numChildren() : index; if ( emitSignal ) emit nodeToBeAdded( p, i ); p->insertChildNode( i, task ); - connect( this, SIGNAL(standardWorktimeChanged(StandardWorktime*)), task, SLOT(slotStandardWorktimeChanged(StandardWorktime*)) ); + connect( this, SIGNAL(standardWorktimeChanged(KPlato::StandardWorktime*)), task, SLOT(slotStandardWorktimeChanged(KPlato::StandardWorktime*)) ); if ( emitSignal ) { emit nodeAdded( task ); emit projectChanged(); if ( p != this && p->numChildren() == 1 ) { emit nodeChanged( p ); } } return true; } void Project::takeTask( Node *node, bool emitSignal ) { //debugPlan<name(); Node * parent = node->parentNode(); if ( parent == 0 ) { debugPlan <<"Node must have a parent!"; return; } removeId( node->id() ); if ( emitSignal ) emit nodeToBeRemoved( node ); - disconnect( this, SIGNAL(standardWorktimeChanged(StandardWorktime*)), node, SLOT(slotStandardWorktimeChanged(StandardWorktime*)) ); + disconnect( this, SIGNAL(standardWorktimeChanged(KPlato::StandardWorktime*)), node, SLOT(slotStandardWorktimeChanged(KPlato::StandardWorktime*)) ); parent->takeChildNode( node ); if ( emitSignal ) { emit nodeRemoved( node ); emit projectChanged(); if ( parent != this && parent->type() != Node::Type_Summarytask ) { emit nodeChanged( parent ); } } } bool Project::canMoveTask( Node* node, Node *newParent ) { //debugPlan<name()<<" to"<name(); if ( node == this ) { return false; } Node *p = newParent; while ( p && p != this ) { if ( ! node->canMoveTo( p ) ) { return false; } p = p->parentNode(); } return true; } bool Project::moveTask( Node* node, Node *newParent, int newPos ) { //debugPlan<name()<<" to"<name()<<","<parentNode(); int oldPos = oldParent->indexOf( node ); int i = newPos < 0 ? newParent->numChildren() : newPos; if ( oldParent == newParent && i == oldPos ) { // no need to move to where it already is return false; } int newRow = i; if ( oldParent == newParent && newPos > oldPos ) { ++newRow; // itemmodels wants new row *before* node is removed from old position } debugPlan<name()<<"at"<indexOf( node )<<"to"<name()<numChildren() == 0 ) { emit nodeChanged( oldParent ); } if ( newParent != this && newParent->numChildren() == 1 ) { emit nodeChanged( newParent ); } return true; } bool Project::canIndentTask( Node* node ) { if ( 0 == node ) { // should always be != 0. At least we would get the Project, // but you never know who might change that, so better be careful return false; } if ( node->type() == Node::Type_Project ) { //debugPlan<<"The root node cannot be indented"; return false; } // we have to find the parent of task to manipulate its list of children Node* parentNode = node->parentNode(); if ( !parentNode ) { return false; } if ( parentNode->findChildNode( node ) == -1 ) { errorPlan << "Tasknot found???"; return false; } Node *sib = node->siblingBefore(); if ( !sib ) { //debugPlan<<"new parent node not found"; return false; } if ( node->findParentRelation( sib ) || node->findChildRelation( sib ) ) { //debugPlan<<"Cannot have relations to parent"; return false; } return true; } bool Project::indentTask( Node* node, int index ) { if ( canIndentTask( node ) ) { Node * newParent = node->siblingBefore(); int i = index == -1 ? newParent->numChildren() : index; moveTask( node, newParent, i ); //debugPlan; return true; } return false; } bool Project::canUnindentTask( Node* node ) { if ( 0 == node ) { // is always != 0. At least we would get the Project, but you // never know who might change that, so better be careful return false; } if ( Node::Type_Project == node->type() ) { //debugPlan<<"The root node cannot be unindented"; return false; } // we have to find the parent of task to manipulate its list of children // and we need the parent's parent too Node* parentNode = node->parentNode(); if ( !parentNode ) { return false; } Node* grandParentNode = parentNode->parentNode(); if ( !grandParentNode ) { //debugPlan<<"This node already is at the top level"; return false; } int index = parentNode->findChildNode( node ); if ( -1 == index ) { errorPlan << "Tasknot found???"; return false; } return true; } bool Project::unindentTask( Node* node ) { if ( canUnindentTask( node ) ) { Node * parentNode = node->parentNode(); Node *grandParentNode = parentNode->parentNode(); int i = grandParentNode->indexOf( parentNode ) + 1; if ( i == 0 ) { i = grandParentNode->numChildren(); } moveTask( node, grandParentNode, i ); //debugPlan; return true; } return false; } bool Project::canMoveTaskUp( Node* node ) { if ( node == 0 ) return false; // safety // we have to find the parent of task to manipulate its list of children Node* parentNode = node->parentNode(); if ( !parentNode ) { //debugPlan<<"No parent found"; return false; } if ( parentNode->findChildNode( node ) == -1 ) { errorPlan << "Tasknot found???"; return false; } if ( node->siblingBefore() ) { return true; } return false; } bool Project::moveTaskUp( Node* node ) { if ( canMoveTaskUp( node ) ) { moveTask( node, node->parentNode(), node->parentNode()->indexOf( node ) - 1 ); return true; } return false; } bool Project::canMoveTaskDown( Node* node ) { if ( node == 0 ) return false; // safety // we have to find the parent of task to manipulate its list of children Node* parentNode = node->parentNode(); if ( !parentNode ) { return false; } if ( parentNode->findChildNode( node ) == -1 ) { errorPlan << "Tasknot found???"; return false; } if ( node->siblingAfter() ) { return true; } return false; } bool Project::moveTaskDown( Node* node ) { if ( canMoveTaskDown( node ) ) { moveTask( node, node->parentNode(), node->parentNode()->indexOf( node ) + 1 ); return true; } return false; } Task *Project::createTask() { Task * node = new Task(); node->setId( uniqueNodeId() ); reserveId( node->id(), node ); return node; } Task *Project::createTask( const Task &def ) { Task * node = new Task( def ); node->setId( uniqueNodeId() ); reserveId( node->id(), node ); return node; } Node *Project::findNode( const QString &id ) const { if ( m_parent == 0 ) { if ( nodeIdDict.contains( id ) ) { return nodeIdDict[ id ]; } return 0; } return m_parent->findNode( id ); } bool Project::nodeIdentExists( const QString &id ) const { return nodeIdDict.contains( id ) || nodeIdReserved.contains( id ); } QString Project::uniqueNodeId( int seed ) const { Q_UNUSED(seed); QString s = QDateTime::currentDateTime().toString( Qt::ISODate ) + ' '; QString ident = s + KRandom::randomString( 10 ); // int i = seed; while ( nodeIdentExists( ident ) ) { ident = s + KRandom::randomString( 10 ); } return ident; } QString Project::uniqueNodeId( const QList &existingIds, int seed ) { QString id = uniqueNodeId( seed ); while ( existingIds.contains( id ) ) { id = uniqueNodeId( seed ); } return id; } bool Project::removeId( const QString &id ) { //debugPlan <<"id=" << id; if ( m_parent ) { return m_parent->removeId( id ); } //debugPlan << "id=" << id<< nodeIdDict.contains(id); return nodeIdDict.remove( id ); } void Project::reserveId( const QString &id, Node *node ) { //debugPlan <<"id=" << id << node->name(); nodeIdReserved.insert( id, node ); } bool Project::registerNodeId( Node *node ) { nodeIdReserved.remove( node->id() ); if ( node->id().isEmpty() ) { warnPlan << "Node id is empty, cannot register it"; return false; } Node *rn = findNode( node->id() ); if ( rn == 0 ) { //debugPlan <<"id=" << node->id() << node->name(); nodeIdDict.insert( node->id(), node ); return true; } if ( rn != node ) { errorPlan << "Id already exists for different task: " << node->id(); return false; } //debugPlan<<"Already exists" <<"id=" << node->id() << node->name(); return true; } QList Project::allNodes() const { QList lst = nodeIdDict.values(); int me = lst.indexOf( const_cast( this ) ); if ( me != -1 ) { lst.removeAt( me ); } return lst; } QList Project::allTasks( const Node *parent ) const { QList lst; const Node *p = parent ? parent : this; foreach ( Node *n, p->childNodeIterator() ) { if ( n->type() == Node::Type_Task || n->type() == Type_Milestone ) { lst << static_cast( n ); } lst += allTasks( n ); } return lst; } bool Project::setResourceGroupId( ResourceGroup *group ) { if ( group == 0 ) { return false; } if ( ! group->id().isEmpty() ) { ResourceGroup *g = findResourceGroup( group->id() ); if ( group == g ) { return true; } else if ( g == 0 ) { insertResourceGroupId( group->id(), group ); return true; } } QString id = uniqueResourceGroupId(); group->setId( id ); if ( id.isEmpty() ) { return false; } insertResourceGroupId( id, group ); return true; } QString Project::uniqueResourceGroupId() const { QString s = QDateTime::currentDateTime().toString( Qt::ISODate ) + ' '; QString id = s + KRandom::randomString( 10 ); while ( resourceGroupIdDict.contains( id ) ) { id = s + KRandom::randomString( 10 ); } return id; } ResourceGroup *Project::group( const QString& id ) { return findResourceGroup( id ); } ResourceGroup *Project::groupByName( const QString& name ) const { foreach ( ResourceGroup *g, resourceGroupIdDict ) { if ( g->name() == name ) { return g; } } return 0; } QList Project::autoAllocateResources() const { QList lst; foreach ( Resource *r, resourceIdDict ) { if ( r->autoAllocate() ) { lst << r; } } return lst; } void Project::insertResourceId( const QString &id, Resource *resource ) { resourceIdDict.insert( id, resource ); } bool Project::removeResourceId( const QString &id ) { return resourceIdDict.remove( id ); } bool Project::setResourceId( Resource *resource ) { if ( resource == 0 ) { return false; } if ( ! resource->id().isEmpty() ) { Resource *r = findResource( resource->id() ); if ( resource == r ) { return true; } else if ( r == 0 ) { insertResourceId( resource->id(), resource ); return true; } } QString id = uniqueResourceId(); resource->setId( id ); if ( id.isEmpty() ) { return false; } insertResourceId( id, resource ); return true; } QString Project::uniqueResourceId() const { QString s = QDateTime::currentDateTime().toString( Qt::ISODate ) + ' '; QString id = s + KRandom::randomString( 10 ); while ( resourceIdDict.contains( id ) ) { id = s + KRandom::randomString( 10 ); } return id; } Resource *Project::resource( const QString& id ) { return findResource( id ); } Resource *Project::resourceByName( const QString& name ) const { foreach ( const QString &k, resourceIdDict.keys() ) { Resource *r = resourceIdDict[ k ]; if ( r->name() == name ) { Q_ASSERT( k == r->id() ); return r; } } return 0; } QStringList Project::resourceNameList() const { QStringList lst; foreach ( Resource *r, resourceIdDict ) { lst << r->name(); } return lst; } EffortCostMap Project::plannedEffortCostPrDay( QDate start, QDate end, long id, EffortCostCalculationType typ ) const { //debugPlan< it( childNodeIterator() ); while ( it.hasNext() ) { ec += it.next() ->plannedEffortCostPrDay( start, end, id, typ ); } return ec; } EffortCostMap Project::plannedEffortCostPrDay( const Resource *resource, QDate start, QDate end, long id, EffortCostCalculationType typ ) const { //debugPlan< it( childNodeIterator() ); while ( it.hasNext() ) { ec += it.next() ->plannedEffortCostPrDay( resource, start, end, id, typ ); } return ec; } EffortCostMap Project::actualEffortCostPrDay( QDate start, QDate end, long id, EffortCostCalculationType typ ) const { //debugPlan< it( childNodeIterator() ); while ( it.hasNext() ) { ec += it.next() ->actualEffortCostPrDay( start, end, id, typ ); } return ec; } EffortCostMap Project::actualEffortCostPrDay( const Resource *resource, QDate start, QDate end, long id, EffortCostCalculationType typ ) const { //debugPlan< it( childNodeIterator() ); while ( it.hasNext() ) { ec += it.next() ->actualEffortCostPrDay( resource, start, end, id, typ ); } return ec; } // Returns the total planned effort for this project (or subproject) Duration Project::plannedEffort( long id, EffortCostCalculationType typ ) const { //debugPlan; Duration eff; QListIterator it( childNodeIterator() ); while ( it.hasNext() ) { eff += it.next() ->plannedEffort( id, typ ); } return eff; } // Returns the total planned effort for this project (or subproject) on date Duration Project::plannedEffort( QDate date, long id, EffortCostCalculationType typ ) const { //debugPlan; Duration eff; QListIterator it( childNodeIterator() ); while ( it.hasNext() ) { eff += it.next() ->plannedEffort( date, id, typ ); } return eff; } // Returns the total planned effort for this project (or subproject) upto and including date Duration Project::plannedEffortTo( QDate date, long id, EffortCostCalculationType typ ) const { //debugPlan; Duration eff; QListIterator it( childNodeIterator() ); while ( it.hasNext() ) { eff += it.next() ->plannedEffortTo( date, id, typ ); } return eff; } // Returns the total actual effort for this project (or subproject) upto and including date Duration Project::actualEffortTo( QDate date ) const { //debugPlan; Duration eff; QListIterator it( childNodeIterator() ); while ( it.hasNext() ) { eff += it.next() ->actualEffortTo( date ); } return eff; } // Returns the total planned effort for this project (or subproject) upto and including date double Project::plannedCostTo( QDate date, long id, EffortCostCalculationType typ ) const { //debugPlan; double c = 0; QListIterator it( childNodeIterator() ); while ( it.hasNext() ) { c += it.next() ->plannedCostTo( date, id, typ ); } return c; } // Returns the total actual cost for this project (or subproject) upto and including date EffortCost Project::actualCostTo( long int id, QDate date ) const { //debugPlan; EffortCost c; QListIterator it( childNodeIterator() ); while ( it.hasNext() ) { c += it.next() ->actualCostTo( id, date ); } return c; } Duration Project::budgetedWorkPerformed( QDate date, long id ) const { //debugPlan; Duration e; foreach (Node *n, childNodeIterator()) { e += n->budgetedWorkPerformed( date, id ); } return e; } double Project::budgetedCostPerformed( QDate date, long id ) const { //debugPlan; double c = 0.0; foreach (Node *n, childNodeIterator()) { c += n->budgetedCostPerformed( date, id ); } return c; } double Project::effortPerformanceIndex( QDate date, long id ) const { //debugPlan; debugPlan< 0.0 ) { r = p / s; } debugPlan< date ? end : date), id ); double budgetAtCompletion; double plannedCompleted; double budgetedCompleted; bool useEffort = false; //FIXME if ( useEffort ) { budgetAtCompletion = plan.totalEffort().toDouble( Duration::Unit_h ); plannedCompleted = plan.effortTo( date ).toDouble( Duration::Unit_h ); //actualCompleted = actual.effortTo( date ).toDouble( Duration::Unit_h ); budgetedCompleted = budgetedWorkPerformed( date, id ).toDouble( Duration::Unit_h ); } else { budgetAtCompletion = plan.totalCost(); plannedCompleted = plan.costTo( date ); budgetedCompleted = budgetedCostPerformed( date, id ); } double c = 0.0; if ( budgetAtCompletion > 0.0 ) { double percentageCompletion = budgetedCompleted / budgetAtCompletion; c = budgetAtCompletion * percentageCompletion; //?? debugPlan<name()<<","<<(parent?parent->name():"No parent"); int row = parent == 0 ? m_calendars.count() : parent->calendars().count(); if ( index >= 0 && index < row ) { row = index; } emit calendarToBeAdded( parent, row ); calendar->setProject( this ); if ( parent == 0 ) { calendar->setParentCal( 0 ); // in case m_calendars.insert( row, calendar ); } else { calendar->setParentCal( parent, row ); } if ( calendar->isDefault() ) { setDefaultCalendar( calendar ); } setCalendarId( calendar ); emit calendarAdded( calendar ); emit projectChanged(); } void Project::takeCalendar( Calendar *calendar ) { emit calendarToBeRemoved( calendar ); removeCalendarId( calendar->id() ); if ( calendar == m_defaultCalendar ) { m_defaultCalendar = 0; } if ( calendar->parentCal() == 0 ) { int i = indexOf( calendar ); if ( i != -1 ) { m_calendars.removeAt( i ); } } else { calendar->setParentCal( 0 ); } emit calendarRemoved( calendar ); calendar->setProject( 0 ); emit projectChanged(); } int Project::indexOf( const Calendar *calendar ) const { return m_calendars.indexOf( const_cast(calendar) ); } Calendar *Project::calendar( const QString& id ) const { return findCalendar( id ); } Calendar *Project::calendarByName( const QString& name ) const { foreach( Calendar *c, calendarIdDict ) { if ( c->name() == name ) { return c; } } return 0; } const QList &Project::calendars() const { return m_calendars; } QList Project::allCalendars() const { return calendarIdDict.values(); } QStringList Project::calendarNames() const { QStringList lst; foreach( Calendar *c, calendarIdDict ) { lst << c->name(); } return lst; } bool Project::setCalendarId( Calendar *calendar ) { if ( calendar == 0 ) { return false; } if ( ! calendar->id().isEmpty() ) { Calendar *c = findCalendar( calendar->id() ); if ( calendar == c ) { return true; } else if ( c == 0 ) { insertCalendarId( calendar->id(), calendar ); return true; } } QString id = uniqueCalendarId(); calendar->setId( id ); if ( id.isEmpty() ) { return false; } insertCalendarId( id, calendar ); return true; } QString Project::uniqueCalendarId() const { QString s = QDateTime::currentDateTime().toString( Qt::ISODate ) + ' '; QString id = s + KRandom::randomString( 10 ); while ( calendarIdDict.contains( id ) ) { id = s + KRandom::randomString( 10 ); } return id; } void Project::setDefaultCalendar( Calendar *cal ) { if ( m_defaultCalendar ) { m_defaultCalendar->setDefault( false ); } m_defaultCalendar = cal; if ( cal ) { cal->setDefault( true ); } emit defaultCalendarChanged( cal ); emit projectChanged(); } void Project::setStandardWorktime( StandardWorktime * worktime ) { if ( m_standardWorktime != worktime ) { delete m_standardWorktime; m_standardWorktime = worktime; m_standardWorktime->setProject( this ); emit standardWorktimeChanged( worktime ); } } void Project::emitDocumentAdded( Node *node , Document *doc , int index ) { emit documentAdded( node, doc, index ); } void Project::emitDocumentRemoved( Node *node , Document *doc , int index ) { emit documentRemoved( node, doc, index ); } void Project::emitDocumentChanged( Node *node , Document *doc , int index ) { emit documentChanged( node, doc, index ); } bool Project::linkExists( const Node *par, const Node *child ) const { if ( par == 0 || child == 0 || par == child || par->isDependChildOf( child ) ) { return false; } foreach ( Relation *r, par->dependChildNodes() ) { if ( r->child() == child ) { return true; } } return false; } bool Project::legalToLink( const Node *par, const Node *child ) const { //debugPlan<isDependChildOf( child ) ) { return false; } if ( linkExists( par, child ) ) { return false; } bool legal = true; // see if par/child is related if ( legal && ( par->isParentOf( child ) || child->isParentOf( par ) ) ) { legal = false; } if ( legal ) legal = legalChildren( par, child ); if ( legal ) legal = legalParents( par, child ); if ( legal ) { foreach ( Node *p, par->childNodeIterator() ) { if ( ! legalToLink( p, child ) ) { return false; } } } return legal; } bool Project::legalParents( const Node *par, const Node *child ) const { bool legal = true; //debugPlan<name()<<" ("<numDependParentNodes()<<" parents)"<name()<<" ("<numDependChildNodes()<<" children)"; for ( int i = 0; i < par->numDependParentNodes() && legal; ++i ) { Node *pNode = par->getDependParentNode( i ) ->parent(); if ( child->isParentOf( pNode ) || pNode->isParentOf( child ) ) { //debugPlan<<"Found:"<name()<<" is related to"<name(); legal = false; } else { legal = legalChildren( pNode, child ); } if ( legal ) legal = legalParents( pNode, child ); } return legal; } bool Project::legalChildren( const Node *par, const Node *child ) const { bool legal = true; //debugPlan<name()<<" ("<numDependParentNodes()<<" parents)"<name()<<" ("<numDependChildNodes()<<" children)"; for ( int j = 0; j < child->numDependChildNodes() && legal; ++j ) { Node *cNode = child->getDependChildNode( j ) ->child(); if ( par->isParentOf( cNode ) || cNode->isParentOf( par ) ) { //debugPlan<<"Found:"<name()<<" is related to"<name(); legal = false; } else { legal = legalChildren( par, cNode ); } } return legal; } WBSDefinition &Project::wbsDefinition() { return m_wbsDefinition; } void Project::setWbsDefinition( const WBSDefinition &def ) { //debugPlan; m_wbsDefinition = def; emit wbsDefinitionChanged(); emit projectChanged(); } QString Project::generateWBSCode( QList &indexes, bool sortable ) const { QString code = m_wbsDefinition.projectCode(); if (sortable) { int fw = (nodeIdDict.count() / 10) + 1; QLatin1Char fc('0'); foreach ( int index, indexes ) { code += ".%1"; code = code.arg(QString::number(index), fw, fc); } debugPlan< hash = resourceIdDict; foreach ( Resource * r, hash ) { r->setCurrentSchedule( id ); } emit currentScheduleChanged(); emit projectChanged(); } ScheduleManager *Project::scheduleManager( long id ) const { foreach ( ScheduleManager *sm, m_managers ) { if ( sm->scheduleId() == id ) { return sm; } } return 0; } ScheduleManager *Project::scheduleManager( const QString &id ) const { return m_managerIdMap.value( id ); } ScheduleManager *Project::findScheduleManagerByName( const QString &name ) const { //debugPlan; ScheduleManager *m = 0; foreach( ScheduleManager *sm, m_managers ) { m = sm->findManager( name ); if ( m ) { break; } } return m; } QList Project::allScheduleManagers() const { QList lst; foreach ( ScheduleManager *sm, m_managers ) { lst << sm; lst << sm->allChildren(); } return lst; } QString Project::uniqueScheduleName() const { //debugPlan; QString n = i18n( "Plan" ); bool unique = findScheduleManagerByName( n ) == 0; if ( unique ) { return n; } n += " %1"; int i = 1; for ( ; true; ++i ) { unique = findScheduleManagerByName( n.arg( i ) ) == 0; if ( unique ) { break; } } return n.arg( i ); } void Project::addScheduleManager( ScheduleManager *sm, ScheduleManager *parent, int index ) { int row = parent == 0 ? m_managers.count() : parent->childCount(); if ( index >= 0 && index < row ) { row = index; } if ( parent == 0 ) { emit scheduleManagerToBeAdded( parent, row ); m_managers.insert( row, sm ); } else { emit scheduleManagerToBeAdded( parent, row ); sm->setParentManager( parent, row ); } if ( sm->managerId().isEmpty() ) { sm->setManagerId( uniqueScheduleManagerId() ); } Q_ASSERT( ! m_managerIdMap.contains( sm->managerId() ) ); m_managerIdMap.insert( sm->managerId(), sm ); emit scheduleManagerAdded( sm ); emit projectChanged(); //debugPlan<<"Added:"<name()<<", now"<children() ) { takeScheduleManager( s ); } if ( sm->scheduling() ) { sm->stopCalculation(); } int index = -1; if ( sm->parentManager() ) { int index = sm->parentManager()->indexOf( sm ); if ( index >= 0 ) { emit scheduleManagerToBeRemoved( sm ); sm->setParentManager( 0 ); m_managerIdMap.remove( sm->managerId() ); emit scheduleManagerRemoved( sm ); emit projectChanged(); } } else { index = indexOf( sm ); if ( index >= 0 ) { emit scheduleManagerToBeRemoved( sm ); m_managers.removeAt( indexOf( sm ) ); m_managerIdMap.remove( sm->managerId() ); emit scheduleManagerRemoved( sm ); emit projectChanged(); } } return index; } void Project::moveScheduleManager( ScheduleManager *sm, ScheduleManager *newparent, int newindex ) { //debugPlan<name()<parentManager() ) { m_managers.removeAt( indexOf( sm ) ); } sm->setParentManager( newparent, newindex ); if ( ! newparent ) { m_managers.insert( newindex, sm ); } emit scheduleManagerMoved( sm, newindex ); } bool Project::isScheduleManager( void *ptr ) const { const ScheduleManager *sm = static_cast( ptr ); if ( indexOf( sm ) >= 0 ) { return true; } foreach ( ScheduleManager *p, m_managers ) { if ( p->isParentOf( sm ) ) { return true; } } return false; } ScheduleManager *Project::createScheduleManager( const QString &name ) { //debugPlan<isBaselined() ) { return true; } } return false; } Schedule *s = schedule( id ); return s == 0 ? false : s->isBaselined(); } MainSchedule *Project::createSchedule( const QString& name, Schedule::Type type ) { //debugPlan<<"No of schedules:"<setName( name ); sch->setType( type ); addMainSchedule( sch ); return sch; } void Project::addMainSchedule( MainSchedule *sch ) { if ( sch == 0 ) { return; } //debugPlan<<"No of schedules:"<setId( i ); sch->setNode( this ); addSchedule( sch ); } bool Project::removeCalendarId( const QString &id ) { //debugPlan <<"id=" << id; return calendarIdDict.remove( id ); } void Project::insertCalendarId( const QString &id, Calendar *calendar ) { //debugPlan <<"id=" << id <<":" << calendar->name(); calendarIdDict.insert( id, calendar ); } void Project::changed( Node *node, int property ) { if ( m_parent == 0 ) { Node::changed( node, property ); // reset cache if ( property != Node::Type ) { // add/remove node is handled elsewhere emit nodeChanged( node ); emit projectChanged(); } return; } Node::changed( node, property ); } void Project::changed( ResourceGroup *group ) { //debugPlan; emit resourceGroupChanged( group ); emit projectChanged(); } void Project::changed( ScheduleManager *sm ) { emit scheduleManagerChanged( sm ); emit projectChanged(); } void Project::changed( MainSchedule *sch ) { //debugPlan<id(); emit scheduleChanged( sch ); emit projectChanged(); } void Project::sendScheduleToBeAdded( const ScheduleManager *sm, int row ) { emit scheduleToBeAdded( sm, row ); } void Project::sendScheduleAdded( const MainSchedule *sch ) { //debugPlan<id(); emit scheduleAdded( sch ); emit projectChanged(); } void Project::sendScheduleToBeRemoved( const MainSchedule *sch ) { //debugPlan<id(); emit scheduleToBeRemoved( sch ); } void Project::sendScheduleRemoved( const MainSchedule *sch ) { //debugPlan<id(); emit scheduleRemoved( sch ); emit projectChanged(); } void Project::changed( Resource *resource ) { emit resourceChanged( resource ); emit projectChanged(); } void Project::changed( Calendar *cal ) { emit calendarChanged( cal ); emit projectChanged(); } void Project::changed( StandardWorktime *w ) { emit standardWorktimeChanged( w ); emit projectChanged(); } bool Project::addRelation( Relation *rel, bool check ) { if ( rel->parent() == 0 || rel->child() == 0 ) { return false; } if ( check && !legalToLink( rel->parent(), rel->child() ) ) { return false; } emit relationToBeAdded( rel, rel->parent()->numDependChildNodes(), rel->child()->numDependParentNodes() ); rel->parent()->addDependChildNode( rel ); rel->child()->addDependParentNode( rel ); emit relationAdded( rel ); emit projectChanged(); return true; } void Project::takeRelation( Relation *rel ) { emit relationToBeRemoved( rel ); rel->parent() ->takeDependChildNode( rel ); rel->child() ->takeDependParentNode( rel ); emit relationRemoved( rel ); emit projectChanged(); } void Project::setRelationType( Relation *rel, Relation::Type type ) { emit relationToBeModified( rel ); rel->setType( type ); emit relationModified( rel ); emit projectChanged(); } void Project::setRelationLag( Relation *rel, const Duration &lag ) { emit relationToBeModified( rel ); rel->setLag( lag ); emit relationModified( rel ); emit projectChanged(); } QList Project::flatNodeList( Node *parent ) { QList lst; Node *p = parent == 0 ? this : parent; //debugPlan<name()<childNodeIterator() ) { lst.append( n ); if ( n->numChildren() > 0 ) { lst += flatNodeList( n ); } } return lst; } void Project::setSchedulerPlugins( const QMap &plugins ) { m_schedulerPlugins = plugins; debugPlan< Copyright (C) 2007 Florian Piquemal Copyright (C) 2007 Alexis Ménard This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTPROJECT_H #define KPTPROJECT_H #include "plankernel_export.h" #include "kptnode.h" #include "kptglobal.h" #include "kptaccount.h" #include "kptcalendar.h" #include "kptdatetime.h" #include "kptduration.h" #include "kptresource.h" #include "kptwbsdefinition.h" #include "kptconfigbase.h" #include #include #include #include #include /// The main namespace. namespace KPlato { class Locale; class Schedule; class StandardWorktime; class ScheduleManager; class XMLLoaderObject; class Task; class SchedulerPlugin; class KPlatoXmlLoaderBase; /** * Project is the main node in a project, it contains child nodes and * possibly sub-projects. A sub-project is just another instantiation of this * node however. * * A note on timezones: * To be able to handle resources working in different timezones and * to facilitate data exchange with other applications like PIMs or * and groupware servers, the project has a timezone that is used for * all datetimes in nodes and schedules. * By default the local timezone is used. * * A resources timezone is defined by the associated calendar. * * Note that a projects datetimes are always displayed/modified in the timezone * it was originally created, not necessarily in your current local timezone. */ class PLANKERNEL_EXPORT Project : public Node { Q_OBJECT public: explicit Project( Node *parent = 0 ); explicit Project( ConfigBase &config, Node *parent = 0 ); explicit Project( ConfigBase &config, bool useDefaultValues, Node *parent = 0 ); ~Project(); /// Reference this project. void ref() { ++m_refCount; } /// De-reference this project. Deletes project of ref count <= 0 void deref(); /// Returns the node type. Can be Type_Project or Type_Subproject. virtual int type() const; /** * Calculate the schedules managed by the schedule manager * * @param sm Schedule manager */ void calculate( ScheduleManager &sm ); /** * Re-calculate the schedules managed by the schedule manager * * @param sm Schedule manager * @param dt The datetime from when the schedule shall be re-calculated */ void calculate( ScheduleManager &sm, const DateTime &dt ); virtual DateTime startTime( long id = -1 ) const; virtual DateTime endTime( long id = -1 ) const; /// Returns the calculated duration for schedule @p id Duration duration( long id = -1 ) const; using Node::duration; /** * Instead of using the expected duration, generate a random value using * the Distribution of each Task. This can be used for Monte-Carlo * estimation of Project duration. */ Duration *getRandomDuration(); virtual bool load( KoXmlElement &element, XMLLoaderObject &status ); virtual void save( QDomElement &element ) const; using Node::saveWorkPackageXML; /// Save a workpackage document containing @node with schedule identity @p id void saveWorkPackageXML( QDomElement &element, const Node *node, long id ) const; /** * Add the node @p task to the project, after node @p position * If @p position is zero or the project node, it will be added to this project. */ bool addTask( Node* task, Node* position ); /** * Add the node @p task to the @p parent */ bool addSubTask( Node* task, Node* parent ); /** * Add the node @p task to @p parent, in position @p index * If @p parent is zero, it will be added to this project. */ bool addSubTask( Node* task, int index, Node* parent, bool emitSignal = true ); /** * Remove the @p node. * The node is not deleted. */ void takeTask( Node *node, bool emitSignal = true ); bool canMoveTask( Node* node, Node *newParent ); bool moveTask( Node* node, Node *newParent, int newPos ); bool canIndentTask( Node* node ); bool indentTask( Node* node, int index = -1 ); bool canUnindentTask( Node* node ); bool unindentTask( Node* node ); bool canMoveTaskUp( Node* node ); bool moveTaskUp( Node* node ); bool canMoveTaskDown( Node* node ); bool moveTaskDown( Node* node ); /** * Create a task with a unique id. * The task is not added to the project. Do this with addSubTask(). */ Task *createTask(); /** * Create a copy of @p def with a unique id. * The task is not added to the project. Do this with addSubTask(). */ Task *createTask( const Task &def ); int resourceGroupCount() const { return m_resourceGroups.count(); } QList &resourceGroups(); /// Adds the resource group to the project. virtual void addResourceGroup( ResourceGroup *resource, int index = -1 ); /** * Removes the resource group @p resource from the project. * The resource group is not deleted. */ ResourceGroup *takeResourceGroup( ResourceGroup *resource ); int indexOf( ResourceGroup *resource ) const { return m_resourceGroups.indexOf( resource ); } ResourceGroup *resourceGroupAt( int pos ) const { return m_resourceGroups.value( pos ); } int numResourceGroups() const { return m_resourceGroups.count(); } /// Returns the resourcegroup with identity id. ResourceGroup *group( const QString& id ); /// Returns the resource group with the matching name, 0 if no match is found. ResourceGroup *groupByName( const QString& name ) const; /** * Adds the resource to the project and resource group. * Always use this to add resources. */ void addResource( ResourceGroup *group, Resource *resource, int index = -1 ); /** * Removes the resource from the project and resource group. * The resource is not deleted. * Always use this to remove resources. */ Resource *takeResource( ResourceGroup *group, Resource *resource ); /// Move @p resource to the new @p group. Requests are removed. void moveResource( ResourceGroup *group, Resource *resource ); /// Returns the resource with identity id. Resource *resource( const QString& id ); /// Returns the resource with matching name, 0 if no match is found. Resource *resourceByName( const QString& name ) const; QStringList resourceNameList() const; /// Returns a list of all resources QList resourceList() const { return resourceIdDict.values(); } virtual EffortCostMap plannedEffortCostPrDay( QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; virtual EffortCostMap plannedEffortCostPrDay(const Resource *resource, QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; using Node::plannedEffort; /// Returns the total planned effort for this project (or subproject) virtual Duration plannedEffort( long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the total planned effort for this project (or subproject) on date virtual Duration plannedEffort( QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; using Node::plannedEffortTo; /// Returns the planned effort up to and including date virtual Duration plannedEffortTo( QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the actual effort up to and including @p date virtual Duration actualEffortTo( QDate date ) const; /** * Planned cost up to and including date * @param date The cost is calculated from the start of the project upto including date. * @param id Identity of the schedule to be used. */ virtual double plannedCostTo( QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /** * Actual cost up to and including @p date * @param date The cost is calculated from the start of the project upto including date. */ virtual EffortCost actualCostTo( long int id, QDate date ) const; virtual EffortCostMap actualEffortCostPrDay( QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; virtual EffortCostMap actualEffortCostPrDay( const Resource *resource, QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; double effortPerformanceIndex( QDate date, long id ) const; double schedulePerformanceIndex( QDate date, long id ) const; /// Returns the effort planned to be used to reach the actual percent finished virtual Duration budgetedWorkPerformed( QDate date, long id = CURRENTSCHEDULE ) const; /// Returns the cost planned to be used to reach the actual percent finished virtual double budgetedCostPerformed( QDate date, long id = CURRENTSCHEDULE ) const; /// Budgeted Cost of Work Scheduled ( up to @p date ) virtual double bcws( QDate date, long id = BASELINESCHEDULE ) const; /// Budgeted Cost of Work Performed virtual double bcwp( long id = BASELINESCHEDULE ) const; /// Budgeted Cost of Work Performed ( up to @p date ) virtual double bcwp( QDate date, long id = BASELINESCHEDULE ) const; Calendar *defaultCalendar() const { return m_defaultCalendar; } void setDefaultCalendar( Calendar *cal ); const QList &calendars() const; void addCalendar( Calendar *calendar, Calendar *parent = 0, int index = -1 ); void takeCalendar( Calendar *calendar ); int indexOf( const Calendar *calendar ) const; /// Returns the calendar with identity id. Calendar *calendar( const QString& id ) const; /// Returns a list of all calendars QStringList calendarNames() const; /// Find calendar by name Calendar *calendarByName( const QString &name ) const; void changed( Calendar *cal ); QList allCalendars() const; /// Return number of calendars int calendarCount() const { return m_calendars.count(); } /// Return the calendar at @p index, 0 if index out of bounds Calendar *calendarAt( int index ) const { return m_calendars.value( index ); } /** * Defines the length of days, weeks, months and years * and the standard working week. * Used for estimation and calculation of effort, * and presentation in gantt chart. */ StandardWorktime *standardWorktime() { return m_standardWorktime; } void setStandardWorktime( StandardWorktime * worktime ); void changed( StandardWorktime* ); /// Check if a link exists between node @p par and @p child. bool linkExists( const Node *par, const Node *child ) const; /// Check if node @p par can be linked to node @p child. bool legalToLink( const Node *par, const Node *child ) const; using Node::legalToLink; virtual const QHash &nodeDict() { return nodeIdDict; } /// Return a list of all nodes in the project (excluding myself) QList allNodes() const; /// Return the number of all nodes in the project (excluding myself) int nodeCount() const { return nodeIdDict.count() - 1; } /// Return a list of all tasks and milestones int the wbs order QList allTasks( const Node *parent = 0 ) const; using Node::findNode; /// Find the node with identity id virtual Node *findNode( const QString &id ) const; using Node::removeId; /// Remove the node with identity id from the registers virtual bool removeId( const QString &id ); /// Reserve @p id for the @p node virtual void reserveId( const QString &id, Node *node ); /// Register @p node. The nodes id must be unique and non-empty. bool registerNodeId( Node *node ); /// Create a unique id. QString uniqueNodeId( int seed = 1 ) const; /// Check if node @p id is used bool nodeIdentExists( const QString &id ) const; /// Create a unique id. QString uniqueNodeId( const QList &existingIds, int seed = 1 ); ResourceGroup *findResourceGroup( const QString &id ) const { if ( resourceGroupIdDict.contains( id ) ) return resourceGroupIdDict[ id ]; return 0; } /// Remove the resourcegroup with identity id from the register bool removeResourceGroupId( const QString &id ) { if ( resourceGroupIdDict.contains( id ) ) return resourceGroupIdDict.remove( id ); return false; } /// Insert the resourcegroup with identity id void insertResourceGroupId( const QString &id, ResourceGroup* group ) { resourceGroupIdDict.insert( id, group ); } /// Generate, set and insert unique id bool setResourceGroupId( ResourceGroup *group); /// returns a unique resourcegroup id QString uniqueResourceGroupId() const; /// Return a list of resources that will be allocated to new tasks QList autoAllocateResources() const; Resource *findResource( const QString &id ) const { if ( resourceIdDict.contains( id ) ) return resourceIdDict[ id ]; return 0; } /// Remove the resource with identity id from the register bool removeResourceId( const QString &id ); /// Insert the resource with identity id void insertResourceId( const QString &id, Resource *resource ); /// Generate, set and insert unique id bool setResourceId( Resource *resource ); /// returns a unique resource id QString uniqueResourceId() const; /// Find the calendar with identity id virtual Calendar *findCalendar( const QString &id ) const { if ( id.isEmpty() || !calendarIdDict.contains( id ) ) return 0; return calendarIdDict[ id ]; } /// Remove the calendar with identity id from the register virtual bool removeCalendarId( const QString &id ); /// Insert the calendar with identity id virtual void insertCalendarId( const QString &id, Calendar *calendar ); /// Set and insert a unique id for calendar bool setCalendarId( Calendar *calendar ); /// returns a unique calendar id QString uniqueCalendarId() const; /// Return reference to WBS Definition WBSDefinition &wbsDefinition(); /// Set WBS Definition to @p def void setWbsDefinition( const WBSDefinition &def ); /// Generate WBS Code virtual QString generateWBSCode( QList &indexes, bool sortable = false ) const; Accounts &accounts() { return m_accounts; } const Accounts &accounts() const { return m_accounts; } /** * Set current schedule to the schedule with identity @p id, for me and my children * Note that this is used (and may be changed) when calculating schedules */ virtual void setCurrentSchedule( long id ); /// Create new schedule with unique name and id of type Expected. MainSchedule *createSchedule(); /// Create new schedule with unique id. MainSchedule *createSchedule( const QString& name, Schedule::Type type ); /// Add the schedule to the project. A fresh id will be generated for the schedule. void addMainSchedule( MainSchedule *schedule ); /// Set parent schedule for my children virtual void setParentSchedule( Schedule *sch ); /// Find the schedule manager that manages the Schedule with @p id ScheduleManager *scheduleManager( long id ) const; /// Find the schedule manager with @p id ScheduleManager *scheduleManager( const QString &id ) const; /// Create a unique schedule name (This may later be changed by the user) QString uniqueScheduleName() const; /// Create a unique schedule manager identity QString uniqueScheduleManagerId() const; ScheduleManager *createScheduleManager(); ScheduleManager *createScheduleManager( const QString &name ); /// Returns a list of all top level schedule managers QList scheduleManagers() const { return m_managers; } int numScheduleManagers() const { return m_managers.count(); } int indexOf( const ScheduleManager *sm ) const { return m_managers.indexOf( const_cast(sm) ); } bool isScheduleManager( void* ptr ) const; void addScheduleManager( ScheduleManager *sm, ScheduleManager *parent = 0, int index = -1 ); int takeScheduleManager( ScheduleManager *sm ); void moveScheduleManager( ScheduleManager *sm, ScheduleManager *newparent = 0, int newindex = -1 ); ScheduleManager *findScheduleManagerByName( const QString &name ) const; /// Returns a list of all schedule managers QList allScheduleManagers() const; /// Return true if schedule with identity @p id is baselined bool isBaselined( long id = ANYSCHEDULED ) const; void changed( ResourceGroup *group ); void changed( Resource *resource ); void changed( ScheduleManager *sm ); void changed( MainSchedule *sch ); void sendScheduleAdded( const MainSchedule *sch ); void sendScheduleToBeAdded( const ScheduleManager *manager, int row ); void sendScheduleRemoved( const MainSchedule *sch ); void sendScheduleToBeRemoved( const MainSchedule *sch ); /// Return the time zone used in this project QTimeZone timeZone() const { return m_timeZone; } /// Set the time zone to be used in this project void setTimeZone( const QTimeZone &tz ) { m_timeZone = tz; } /** * Add a relation between the nodes specified in the relation rel. * Emits signals relationToBeAdded() before the relation is added, * and relationAdded() after it has been added. * @param rel The relation to be added. * @param check If true, the relation is checked for validity * @return true if successful. */ bool addRelation( Relation *rel, bool check=true ); /** * Removes the relation @p rel without deleting it. * Emits signals relationToBeRemoved() before the relation is removed, * and relationRemoved() after it has been removed. */ void takeRelation( Relation *rel ); /** * Modify the @p type of the @p relation. */ void setRelationType( Relation *relation, Relation::Type type ); /** * Modify the @p lag of the @p relation. */ void setRelationLag( Relation *relation, const Duration &lag ); void calcCriticalPathList( MainSchedule *cs ); void calcCriticalPathList( MainSchedule *cs, Node *node ); /** * Returns the list of critical paths for schedule @p id */ const QList< QList > *criticalPathList( long id = CURRENTSCHEDULE ); QList criticalPath( long id = CURRENTSCHEDULE, int index = 0 ); /// Returns a flat list af all nodes QList flatNodeList( Node *parent = 0 ); void generateUniqueNodeIds(); void generateUniqueIds(); const ConfigBase &config() const { return m_config ? *m_config : emptyConfig; } /// Set configuration data void setConfig( ConfigBase *config ) { m_config = config; } const Task &taskDefaults() const { return config().taskDefaults(); } /// Return locale. (Used for currency, everything else is from KGlobal::locale) Locale *locale() { return const_cast(config()).locale(); } /// Return locale. (Used for currency, everything else is from KGlobal::locale) const Locale *locale() const { return config().locale(); } /// Signal that locale data has changed void emitLocaleChanged(); void setSchedulerPlugins( const QMap &plugins ); const QMap &schedulerPlugins() const { return m_schedulerPlugins; } void initiateCalculation( MainSchedule &sch ); void initiateCalculationLists( MainSchedule &sch ); void finishCalculation( ScheduleManager &sm ); void adjustSummarytask(); /// Increments progress and emits signal sigProgress() void incProgress(); /// Emits signal maxProgress() void emitMaxProgress( int value ); bool stopcalculation; /// return a map of all external projects QMap externalProjects() const; void emitDocumentAdded( Node*, Document*, int index ); void emitDocumentRemoved( Node*, Document*, int index ); void emitDocumentChanged( Node*, Document*, int index ); bool useSharedResources() const; void setUseSharedResources(bool on); bool isSharedResourcesLoaded() const; void setSharedResourcesLoaded(bool on); void setSharedResourcesFile(const QString &file); QString sharedResourcesFile() const; void setSharedProjectsUrl(const QUrl &url); QUrl sharedProjectsUrl() const; void setLoadProjectsAtStartup(bool value); bool loadProjectsAtStartup() const; public Q_SLOTS: /// Sets m_progress to @p progress and emits signal sigProgress() /// If @p sm is not 0, progress is also set for the schedule manager - void setProgress( int progress, ScheduleManager *sm = 0 ); + void setProgress(int progress, KPlato::ScheduleManager *sm = 0); /// Sets m_maxprogress to @p max and emits signal maxProgress() /// If @p sm is not 0, max progress is also set for the schedule manager - void setMaxProgress( int max, ScheduleManager *sm = 0 ); + void setMaxProgress(int max, KPlato::ScheduleManager *sm = 0 ); Q_SIGNALS: /// Emitted when the project is about to be deleted (The destroyed signal is disabled) void aboutToBeDeleted(); /// Emitted when anything in the project is changed (use with care) void projectChanged(); /// Emitted when the WBS code definition has changed. This may change all nodes. void wbsDefinitionChanged(); /// Emitted when a schedule has been calculated - void projectCalculated( ScheduleManager *sm ); + void projectCalculated(KPlato::ScheduleManager *sm); /// Emitted when the pointer to the current schedule has been changed void currentScheduleChanged(); /// Use to show progress during calculation void sigProgress( int ); /// Use to set the maximum progress (minimum always 0) void maxProgress( int ); /// Emitted when calculation starts - void sigCalculationStarted( Project *project, ScheduleManager *sm ); + void sigCalculationStarted(KPlato::Project *project, KPlato::ScheduleManager *sm); /// Emitted when calculation is finished - void sigCalculationFinished( Project *project, ScheduleManager *sm ); + void sigCalculationFinished(KPlato::Project *project, KPlato::ScheduleManager *sm); /// This signal is emitted when one of the nodes members is changed. - void nodeChanged( Node* ); + void nodeChanged(KPlato::Node*); /// This signal is emitted when the node is to be added to the project. - void nodeToBeAdded( Node*, int ); + void nodeToBeAdded(KPlato::Node*, int); /// This signal is emitted when the node has been added to the project. - void nodeAdded( Node* ); + void nodeAdded(KPlato::Node*); /// This signal is emitted when the node is to be removed from the project. - void nodeToBeRemoved( Node* ); + void nodeToBeRemoved(KPlato::Node*); /// This signal is emitted when the node has been removed from the project. - void nodeRemoved( Node* ); + void nodeRemoved(KPlato::Node*); /// This signal is emitted when the node is to be moved up, moved down, indented or unindented. - void nodeToBeMoved( Node* node, int pos, Node* newParent, int newPos ); + void nodeToBeMoved(KPlato::Node* node, int pos, KPlato::Node* newParent, int newPos); /// This signal is emitted when the node has been moved up, moved down, indented or unindented. - void nodeMoved( Node* ); + void nodeMoved(KPlato::Node*); /// This signal is emitted when a document is added - void documentAdded( Node*, Document*, int index ); + void documentAdded(KPlato::Node*, KPlato::Document*, int index); /// This signal is emitted when a document is removed - void documentRemoved( Node*, Document*, int index ); + void documentRemoved(KPlato::Node*, KPlato::Document*, int index); /// This signal is emitted when a document is changed - void documentChanged( Node*, Document*, int index ); - - void resourceGroupChanged( ResourceGroup *group ); - void resourceGroupAdded( const ResourceGroup *group ); - void resourceGroupToBeAdded( const ResourceGroup *group, int row ); - void resourceGroupRemoved( const ResourceGroup *group ); - void resourceGroupToBeRemoved( const ResourceGroup *group ); - - void resourceChanged( Resource *resource ); - void resourceAdded( const Resource *resource ); - void resourceToBeAdded( const ResourceGroup *group, int row ); - void resourceRemoved( const Resource *resource ); - void resourceToBeRemoved( const Resource *resource ); - - void scheduleManagerChanged( ScheduleManager *sch ); - void scheduleManagerAdded( const ScheduleManager *sch ); - void scheduleManagerToBeAdded( const ScheduleManager *sch, int row ); - void scheduleManagerRemoved( const ScheduleManager *sch ); - void scheduleManagerToBeRemoved( const ScheduleManager *sch ); - void scheduleManagerMoved( const ScheduleManager *sch, int row ); - void scheduleManagerToBeMoved( const ScheduleManager *sch ); - - void scheduleChanged( MainSchedule *sch ); - void scheduleToBeAdded( const ScheduleManager *manager, int row ); - void scheduleAdded( const MainSchedule *sch ); - void scheduleToBeRemoved( const MainSchedule *sch ); - void scheduleRemoved( const MainSchedule *sch ); + void documentChanged(KPlato::Node*, KPlato::Document*, int index); + + void resourceGroupChanged(KPlato::ResourceGroup *group); + void resourceGroupAdded(const KPlato::ResourceGroup *group); + void resourceGroupToBeAdded(const KPlato::ResourceGroup *group, int row); + void resourceGroupRemoved(const KPlato::ResourceGroup *group); + void resourceGroupToBeRemoved(const KPlato::ResourceGroup *group); + + void resourceChanged(KPlato::Resource *resource); + void resourceAdded(const KPlato::Resource *resource); + void resourceToBeAdded(const KPlato::ResourceGroup *group, int row); + void resourceRemoved(const KPlato::Resource *resource); + void resourceToBeRemoved(const KPlato::Resource *resource); + + void scheduleManagerChanged(KPlato::ScheduleManager *sch); + void scheduleManagerAdded(const KPlato::ScheduleManager *sch); + void scheduleManagerToBeAdded(const KPlato::ScheduleManager *sch, int row); + void scheduleManagerRemoved(const KPlato::ScheduleManager *sch); + void scheduleManagerToBeRemoved(const KPlato::ScheduleManager *sch); + void scheduleManagerMoved(const KPlato::ScheduleManager *sch, int row); + void scheduleManagerToBeMoved(const KPlato::ScheduleManager *sch); + + void scheduleChanged(KPlato::MainSchedule *sch); + void scheduleToBeAdded(const KPlato::ScheduleManager *manager, int row); + void scheduleAdded(const KPlato::MainSchedule *sch); + void scheduleToBeRemoved(const KPlato::MainSchedule *sch); + void scheduleRemoved(const KPlato::MainSchedule *sch); // void currentViewScheduleIdChanged( long id ); - void calendarChanged( Calendar *cal ); - void calendarToBeAdded( const Calendar *cal, int row ); - void calendarAdded( const Calendar *cal ); - void calendarToBeRemoved( const Calendar *cal ); - void calendarRemoved( const Calendar *cal ); + void calendarChanged(KPlato::Calendar *cal); + void calendarToBeAdded(const KPlato::Calendar *cal, int row); + void calendarAdded(const KPlato::Calendar *cal); + void calendarToBeRemoved(const KPlato::Calendar *cal); + void calendarRemoved(const KPlato::Calendar *cal); /** * Emitted when the default calendar pointer has changed * @parem cal The new default calendar. May be 0. */ - void defaultCalendarChanged( Calendar *cal ); + void defaultCalendarChanged(KPlato::Calendar *cal); /** * Emitted when the standard worktime has been changed. */ - void standardWorktimeChanged( StandardWorktime* ); + void standardWorktimeChanged(KPlato::StandardWorktime*); /// Emitted when the relation @p rel is about to be added. - void relationToBeAdded( Relation *rel, int parentIndex, int childIndex ); + void relationToBeAdded(KPlato::Relation *rel, int parentIndex, int childIndex); /// Emitted when the relation @p rel has been added. - void relationAdded( Relation *rel ); + void relationAdded(KPlato::Relation *rel); /// Emitted when the relation @p rel is about to be removed. - void relationToBeRemoved( Relation *rel ); + void relationToBeRemoved(KPlato::Relation *rel); /// Emitted when the relation @p rel has been removed. - void relationRemoved( Relation *rel ); + void relationRemoved(KPlato::Relation *rel); /// Emitted when the relation @p rel shall be modified. - void relationToBeModified( Relation *rel ); + void relationToBeModified(KPlato::Relation *rel); /// Emitted when the relation @p rel has been modified. - void relationModified( Relation *rel ); + void relationModified(KPlato::Relation *rel); /// Emitted when locale data has changed void localeChanged(); protected: /// Calculate the schedule. void calculate( Schedule *scedule ); /// Calculate current schedule void calculate(); /// Re-calculate the schedule from @p dt void calculate( Schedule *scedule, const DateTime &dt ); /// Calculate current schedule from @p dt (Always calculates forward) void calculate( const DateTime &dt ); /// Calculate critical path virtual bool calcCriticalPath( bool fromEnd ); /// Prepare task lists for scheduling void tasksForward(); /// Prepare task lists for scheduling void tasksBackward(); protected: friend class KPlatoXmlLoaderBase; using Node::changed; virtual void changed(Node *node, int property = -1); Accounts m_accounts; QList m_resourceGroups; QList m_calendars; Calendar * m_defaultCalendar; StandardWorktime *m_standardWorktime; DateTime calculateForward( int use ); DateTime calculateBackward( int use ); DateTime scheduleForward( const DateTime &earliest, int use ); DateTime scheduleBackward( const DateTime &latest, int use ); DateTime checkStartConstraints( const DateTime &dt ) const; DateTime checkEndConstraints( const DateTime &dt ) const; bool legalParents( const Node *par, const Node *child ) const; bool legalChildren( const Node *par, const Node *child ) const; #ifndef PLAN_NLOGDEBUG private: static bool checkParent( Node *n, const QList &list, QList &checked ); static bool checkChildren( Node *n, const QList &list, QList &checked ); #endif private: void init(); QHash resourceGroupIdDict; QHash resourceIdDict; QHash nodeIdDict; QMap nodeIdReserved; QMap calendarIdDict; QMap m_managerIdMap; QList m_managers; QTimeZone m_timeZone; WBSDefinition m_wbsDefinition; ConfigBase emptyConfig; QPointer m_config; // this one is not owned by me, don't delete int m_progress; QMap m_schedulerPlugins; int m_refCount; // make it possible to use the project by different threads QList m_hardConstraints; QList m_softConstraints; QList m_terminalNodes; bool m_useSharedResources; bool m_sharedResourcesLoaded; QString m_sharedResourcesFile; QUrl m_sharedProjectsUrl; bool m_loadProjectsAtStartup; }; } //KPlato namespace #endif diff --git a/src/libs/kernel/kptresource.h b/src/libs/kernel/kptresource.h index 31a76a9b..79b1ef93 100644 --- a/src/libs/kernel/kptresource.h +++ b/src/libs/kernel/kptresource.h @@ -1,902 +1,902 @@ /* This file is part of the KDE project Copyright (C) 2001 Thomas Zander zander@kde.org Copyright (C) 2004-2007 Dag Andersen Copyright (C) 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTRESOURCE_H #define KPTRESOURCE_H #include "plankernel_export.h" #include "kptglobal.h" #include "kptduration.h" #include "kptdatetime.h" #include "kptappointment.h" #include "kptcalendar.h" #include #include #include #include /// The main namespace. namespace KPlato { class Account; class Risk; class Effort; class Appointment; class Task; class Node; class Project; class Resource; class ResourceRequest; class ResourceGroupRequest; class ResourceRequestCollection; class Schedule; class ResourceSchedule; class Schedule; class XMLLoaderObject; class DateTimeInterval; /** * This class represents a group of similar resources to be assigned to a task * e.g. The list of employees, computer resources, etc */ /* IDEA; lets create a resourceGroup that has the intelligence to import PIM schedules * from the kroupware project and use the schedules to use the factory pattern to build * Resources (probably a derived class) which returns values on getFirstAvailableTime * and friends based on the schedules we got from the PIM projects. * (Thomas Zander mrt-2003 by suggestion of Shaheed) */ class PLANKERNEL_EXPORT ResourceGroup : public QObject { Q_OBJECT public: /// Default constructor explicit ResourceGroup(); explicit ResourceGroup( const ResourceGroup *group ); ~ResourceGroup(); enum Type { Type_Work, Type_Material }; QString id() const { return m_id; } void setId( const QString& id ); Project *project() { return m_project; } void setName( const QString& n ); const QString &name() const { return m_name;} void setType( Type type ); void setType(const QString &type); Type type() const { return m_type; } QString typeToString( bool trans = false ) const; static QStringList typeToStringList( bool trans = false ); bool isScheduled() const; /// Return true if any resource in this group is baselined bool isBaselined( long id = BASELINESCHEDULE ) const; /** Manage the resources in this list *

At some point we will have to look at not mixing types of resources * (e.g. you can't add a person to a list of computers * *

Risks must always be associated with a resource, so there is no option * to manipulate risks (@ref Risk) separately */ void addResource( int index, Resource*, Risk* ); Resource *takeResource( Resource *resource ); QList resources() const { return m_resources; } int indexOf( const Resource *resource ) const; Resource *resourceAt( int pos ) const { return m_resources.value( pos ); } int numResources() const { return m_resources.count(); } Risk* getRisk( int ); /** Manage the dependent resources. This is a list of the resource * groups that must have available resources for this resource to * perform the work *

see also @ref getRequiredResource, @ref getRequiredResource */ void addRequiredResource( ResourceGroup* ); /** Manage the dependent resources. This is a list of the resource * groups that must have available resources for this resource to * perform the work *

see also @ref addRequiredResource, @ref getRequiredResource */ ResourceGroup* getRequiredResource( int ); /** Manage the dependent resources. This is a list of the resource * groups that must have available resources for this resource to * perform the work *

see also @ref getRequiredResource, @ref addRequiredResource */ void deleteRequiredResource( int ); bool load( KoXmlElement &element, XMLLoaderObject &status ); void save( QDomElement &element ) const; /// Save workpackage document. Include only resources listed in @p lst void saveWorkPackageXML( QDomElement &element, const QList &lst ) const; void initiateCalculation( Schedule &sch ); void addNode( Node *node ) { m_nodes.append( node ); } void clearNodes() { m_nodes.clear(); } Calendar *defaultCalendar() { return m_defaultCalendar; } int units() const; void registerRequest( ResourceGroupRequest *request ) { m_requests.append( request ); } void unregisterRequest( ResourceGroupRequest *request ) { int i = m_requests.indexOf( request ); if ( i != -1 ) m_requests.removeAt( i ); } const QList &requests() const { return m_requests; } ResourceGroup *findId() const { return findId( m_id ); } ResourceGroup *findId( const QString &id ) const; bool removeId() { return removeId( m_id ); } bool removeId( const QString &id ); void insertId( const QString &id ); Appointment appointmentIntervals() const; // m_project is set when the resourcegroup is added to the project, // and reset when the resourcegroup is removed from the project void setProject( Project *project ); void copy( const ResourceGroup *group ); DateTime startTime( long id ) const; DateTime endTime( long id ) const; void blockChanged(bool on = true); /// A resource can be local to this project, or /// defined externally and shared with other projects bool isShared() const; /// Set resource to be shared if on = true, or local if on = false void setShared(bool on); #ifndef NDEBUG void printDebug( const QString& ident ); #endif protected: virtual void changed(); private: Project *m_project; QString m_id; // unique id QString m_name; QList m_resources; QList m_risks; QList m_requires; QList m_nodes; //The nodes that want resources from us Calendar *m_defaultCalendar; Type m_type; QList m_requests; bool m_blockChanged; bool m_shared; }; /** * Any resource that is used by a task. A resource can be a worker, or maybe wood. * If the resources is a worker or a piece of equipment which can be reused but * can only be used by one node in time, then we can use the scheduling methods of the * resource to schedule the resource available time for the project. * The Idea is that all nodes which need this resource point to it and the scheduling * code (partly implemented here) schedules the actual usage. * See also @ref ResourceGroup */ class PLANKERNEL_EXPORT Resource : public QObject { Q_OBJECT public: Resource(); explicit Resource(Resource *resource); virtual ~Resource(); QString id() const { return m_id; } void setId( const QString& id ); enum Type { Type_Work, Type_Material, Type_Team }; void setType( Type type ); void setType( const QString &type ); Type type() const { return m_type; } QString typeToString( bool trans = false ) const; static QStringList typeToStringList( bool trans = false ); void setName( const QString &n ); const QString &name() const { return m_name;} void setInitials( const QString &initials ); const QString &initials() const { return m_initials;} void setEmail( const QString &email ); const QString &email() const { return m_email;} /// Returns true if this resource will be allocated by default to new tasks bool autoAllocate() const; /// Set if this resource will be allocated by default to new tasks void setAutoAllocate( bool on ); void copy( Resource *resource ); void setParentGroup( ResourceGroup *parent ) { m_parent = parent; } ResourceGroup *parentGroup() const { return m_parent; } /// Set the time from when the resource is available to this project void setAvailableFrom( const DateTime &af ) { m_availableFrom = af; changed(); } /// Return the time when the resource is available to this project const DateTime &availableFrom() const { return m_availableFrom;} /// Set the time when the resource is no longer available to this project void setAvailableUntil( const DateTime &au ) { m_availableUntil = au; changed(); } /// Return the time when the resource is no longer available to this project. const DateTime &availableUntil() const { return m_availableUntil;} DateTime firstAvailableAfter( const DateTime &time, const DateTime &limit ) const; DateTime getBestAvailableTime( const Duration &duration ); DateTime getBestAvailableTime( const DateTime &after, const Duration &duration ); bool load( KoXmlElement &element, XMLLoaderObject &status ); void save( QDomElement &element ) const; /// Return the list of appointments for schedule @p id. QList appointments( long id = -1 ) const; /// Return the number of appointments (nodes) int numAppointments( long id = -1 ) const { return appointments( id ).count(); } /// Return the appointment at @p index for schedule @p id Appointment *appointmentAt( int index, long id = -1 ) const { return appointments( id ).value( index ); } int indexOf( Appointment *a, long id = -1 ) const { return appointments( id ).indexOf( a ); } /// Adds appointment to current schedule virtual bool addAppointment( Appointment *appointment ); /// Adds appointment to schedule sch virtual bool addAppointment( Appointment *appointment, Schedule &main ); /// Adds appointment to both this resource and node virtual void addAppointment( Schedule *node, const DateTime &start, const DateTime &end, double load = 100 ); void initiateCalculation( Schedule &sch ); bool isAvailable( Task *task ); void makeAppointment( Schedule *schedule, int load, const QList &required = QList() ); bool isOverbooked() const; /// check if overbooked on date. bool isOverbooked( const QDate &date ) const; /// check if overbooked within the interval start, end. bool isOverbooked( const DateTime &start, const DateTime &end ) const; double normalRate() const { return cost.normalRate; } void setNormalRate( double rate ) { cost.normalRate = rate; changed(); } double overtimeRate() const { return cost.overtimeRate; } void setOvertimeRate( double rate ) { cost.overtimeRate = rate; changed(); } /** * Return available units in percent */ int units() const { return m_units; } /** * Set available units in percent */ void setUnits( int units ); Project *project() const { return m_project; } /// Return the resources timespec. Defaults to local. QTimeZone timeZone() const; /** * Get the calendar for this resource. * Working resources may have a default calendar if the a calendar is marked as default, * this is checked if local=false. * If no calendar can be found for a working resource, the resource is not available. * * Material resources must have calendar explicitly set. * If there is no calendar set for a material resource, the resource is always available. */ Calendar *calendar( bool local = false ) const; //Calendar *calendar( const QString& id ) const; void setCalendar( Calendar *calendar ); /// Delete all requests for me void removeRequests(); /** * Used to clean up requests when the resource is deleted. */ void registerRequest( ResourceRequest *request ) { m_requests.append( request ); } void unregisterRequest( ResourceRequest *request ) { int i = m_requests.indexOf( request ); if ( i != -1 ) m_requests.removeAt( i ); } const QList &requests() const { return m_requests; } /// Returns a list of work intervals in the interval @p from, @p until. /// Appointments are subtracted if @p schedule is not 0 and overbooking is not allowed. AppointmentIntervalList workIntervals( const DateTime &from, const DateTime &until, Schedule *schedule ) const; /// Returns a list of work intervals in the interval @p from, @p until. AppointmentIntervalList workIntervals( const DateTime &from, const DateTime &until ) const; /// Updates work interval cache a list of work intervals extracted from the resource calendar /// with @p load in the interval @p from, @p until. /// The load of the intervals is set to m_units /// Note: The list may contain intervals outside @p from, @p until void calendarIntervals( const DateTime &from, const DateTime &until ) const; /// Load cache from @p element bool loadCalendarIntervalsCache( const KoXmlElement& element, KPlato::XMLLoaderObject& status ); /// Save cache to @p element void saveCalendarIntervalsCache( QDomElement &element ) const; /// Returns the effort that can be done starting at @p start within @p duration. /// The current schedule is used to check for appointments. /// If @p backward is true, checks backward in time. Duration effort( const DateTime &start, const Duration &duration, int units = 100, bool backward = false, const QList &required = QList() ) const; /// Returns the effort that can be done starting at @p start within @p duration. /// The schedule @p sch is used to check for appointments. /// If @p backward is true, checks backward in time. /// Status is returned in @p ok Duration effort( KPlato::Schedule* sch, const DateTime &start, const Duration& duration, int units = 100, bool backward = false, const QList< Resource* >& required = QList() ) const; /** * Find the first available time after @p time, within @p limit. * Returns invalid DateTime if not available. * Uses the current schedule to check for appointments. */ DateTime availableAfter( const DateTime &time, const DateTime &limit = DateTime() ) const; /** * Find the first available time before @p time, within @p limit. * Returns invalid DateTime if not available. * Uses the current schedule to check for appointments. */ DateTime availableBefore( const DateTime &time, const DateTime &limit = DateTime()) const; /** * Find the first available time after @p time, within @p limit. * Returns invalid DateTime if not available. * If @p sch == 0, Appointments are not checked. */ DateTime availableAfter( const DateTime &time, const DateTime &limit, Schedule *sch ) const; /** * Find the first available time before @p time, within @p limit. * Returns invalid DateTime if not available. * If @p sch == 0, Appointments are not checked. */ DateTime availableBefore( const DateTime &time, const DateTime &limit, Schedule *sch ) const; Resource *findId() const { return findId( m_id ); } Resource *findId( const QString &id ) const; bool removeId() { return removeId( m_id ); } bool removeId( const QString &id ); void insertId( const QString &id ); Calendar *findCalendar( const QString &id ) const; Appointment appointmentIntervals( long id ) const; Appointment appointmentIntervals() const; EffortCostMap plannedEffortCostPrDay( const QDate &start, const QDate &end, long id, EffortCostCalculationType = ECCT_All ); Duration plannedEffort( const QDate &date, EffortCostCalculationType = ECCT_All ) const; void setCurrentSchedulePtr( Schedule *schedule ) { m_currentSchedule = schedule; } void setCurrentSchedule( long id ) { m_currentSchedule = findSchedule( id ); } Schedule *currentSchedule() const { return m_currentSchedule; } bool isScheduled() const; QHash schedules() const { return m_schedules; } /** * Return schedule with @id * If @p id == CURRENTSCHEDULE, return m_currentSchedule * Return 0 if schedule with @p id doesn't exist. */ Schedule *schedule( long id = CURRENTSCHEDULE ) const; /// Returns true if schedule with @p id is baselined. /// if Team resource, if any of the team members is baselined /// By default returns true if any schedule is baselined bool isBaselined( long id = BASELINESCHEDULE ) const; /** * Return schedule with @id * Return 0 if schedule with @id doesn't exist. */ Schedule *findSchedule( long id ) const; /// Take, and delete. void deleteSchedule( Schedule *schedule ); /// Take, don't delete. void takeSchedule( const Schedule *schedule ); void addSchedule( Schedule *schedule ); ResourceSchedule *createSchedule( const QString& name, int type, long id ); ResourceSchedule *createSchedule( Schedule *parent ); // m_project is set when the resource (or the parent) is added to the project, // and reset when the resource is removed from the project void setProject( Project *project ); void addExternalAppointment( const QString &id, Appointment *a ); void addExternalAppointment( const QString &id, const QString &name, const DateTime &from, const DateTime &end, double load = 100 ); void subtractExternalAppointment( const QString &id, const DateTime &from, const DateTime &end, double load ); void clearExternalAppointments(); void clearExternalAppointments( const QString &id ); /// Take the external appointments with identity @p id from the list of external appointments Appointment *takeExternalAppointment( const QString &id ); /// Return external appointments with identity @p id AppointmentIntervalList externalAppointments( const QString &id ); AppointmentIntervalList externalAppointments( const DateTimeInterval &interval = DateTimeInterval() ) const; int numExternalAppointments() const { return m_externalAppointments.count(); } QList externalAppointmentList() const { return m_externalAppointments.values(); } /// return a map of project id, project name QMap externalProjects() const; /// Return a measure of how suitable the resource is for allocation long allocationSuitability( const DateTime &time, const Duration &duration, bool backward ); DateTime startTime( long id ) const; DateTime endTime( long id ) const; /// Returns the list of required resources. /// Note: This list is used as default for allocation dialog, not for scheduling. QList requiredResources() const; /// Set the list of the required resources's ids so they can be resolved when used /// A required resource may not exist in the project yet void setRequiredIds( const QStringList &lst ); /// Add a resource id to the required ids list void addRequiredId( const QString &id ); /// Returns the list of required resource ids. QStringList requiredIds() const { return m_requiredIds; } /// Return the list of team members. QList teamMembers() const; /// Return the list of team members. QStringList teamMemberIds() const; /// Clear the list of team members. void clearTeamMembers() { m_teamMembers.clear(); } /// Add resource @p id to the list of team members. void addTeamMemberId( const QString &id ); /// Remove resource @p id from the list of team members. void removeTeamMemberId( const QString &id ); /// Set the list of team members to @p ids void setTeamMemberIds(const QStringList &ids); /// Return the account Account *account() const { return cost.account; } /// Set the @p account void setAccount( Account *account ); void blockChanged(bool on = true); /// A resource group can be local to this project, or /// defined externally and shared with other projects bool isShared() const; /// Set resource group to be shared if on = true, or local if on = false void setShared(bool on); // for xml loading code class WorkInfoCache { public: WorkInfoCache() { clear(); } void clear() { start = end = DateTime(); effort = Duration::zeroDuration; intervals.clear(); version = -1; } bool isValid() const { return start.isValid() && end.isValid(); } DateTime firstAvailableAfter( const DateTime &time, const DateTime &limit, Calendar *cal, Schedule *sch ) const; DateTime firstAvailableBefore( const DateTime &time, const DateTime &limit, Calendar *cal, Schedule *sch ) const; DateTime start; DateTime end; Duration effort; AppointmentIntervalList intervals; int version; bool load( const KoXmlElement& element, KPlato::XMLLoaderObject& status ); void save( QDomElement &element ) const; }; const WorkInfoCache &workInfoCache() const { return m_workinfocache; } Q_SIGNALS: - void externalAppointmentToBeAdded( Resource *r, int row ); - void externalAppointmentAdded( Resource*, Appointment* ); - void externalAppointmentToBeRemoved( Resource *r, int row ); + void externalAppointmentToBeAdded(KPlato::Resource *r, int row); + void externalAppointmentAdded(KPlato::Resource*, KPlato::Appointment*); + void externalAppointmentToBeRemoved(KPlato::Resource *r, int row); void externalAppointmentRemoved(); - void externalAppointmentChanged( Resource *r, Appointment *a ); + void externalAppointmentChanged(KPlato::Resource *r, KPlato::Appointment *a); protected: DateTimeInterval requiredAvailable(Schedule *node, const DateTime &start, const DateTime &end ) const; void makeAppointment( Schedule *node, const DateTime &from, const DateTime &end, int load, const QList &required = QList() ); virtual void changed(); private: Project *m_project; ResourceGroup *m_parent; QHash m_schedules; QString m_id; // unique id QString m_name; QString m_initials; QString m_email; bool m_autoAllocate; DateTime m_availableFrom; DateTime m_availableUntil; QMap m_externalAppointments; int m_units; // available units in percent Type m_type; struct Cost { double normalRate; double overtimeRate; double fixed ; Account *account; } cost; Calendar *m_calendar; QList m_requests; QStringList m_requiredIds; QStringList m_teamMembers; Schedule *m_currentSchedule; mutable WorkInfoCache m_workinfocache; // return this if resource has no calendar and is a material resource Calendar m_materialCalendar; bool m_blockChanged; bool m_shared; #ifndef NDEBUG public: void printDebug( const QString& ident ); #endif }; PLANKERNEL_EXPORT QDebug operator<<( QDebug dbg, const KPlato::Resource::WorkInfoCache &c ); /** * Risk is associated with a resource/task pairing to indicate the planner's confidence in the * estimated effort. Risk can be one of none, low, or high. Some factors that may be taken into * account for risk are the experience of the person and the reliability of equipment. */ class Risk { public: enum RiskType { NONE = 0, LOW = 1, HIGH = 2 }; Risk( Node *n, Resource *r, RiskType rt = NONE ); ~Risk(); RiskType riskType() { return m_riskType; } Node *node() { return m_node; } Resource *resource() { return m_resource; } private: Node *m_node; Resource *m_resource; RiskType m_riskType; }; class PLANKERNEL_EXPORT ResourceRequest { public: explicit ResourceRequest( Resource *resource = 0, int units = 1 ); explicit ResourceRequest( const ResourceRequest &r ); ~ResourceRequest(); ResourceGroupRequest *parent() const { return m_parent; } void setParent( ResourceGroupRequest *parent ) { m_parent = parent; } Resource *resource() const { return m_resource; } void setResource( Resource* resource ) { m_resource = resource; } bool load( KoXmlElement &element, Project &project ); void save( QDomElement &element ) const; /** * Get amount of requested resource units in percent */ int units() const; void setUnits( int value ); void registerRequest() { if ( m_resource ) m_resource->registerRequest( this ); } void unregisterRequest() { if ( m_resource ) m_resource->unregisterRequest( this ); } void makeAppointment( Schedule *schedule, int amount ); void makeAppointment( Schedule *schedule ); Task *task() const; /// Return the datetime from when the resource is available. /// If it is not valid, the project constraint start time is used. /// For teams the earliest time for any team member is used. DateTime availableFrom(); /// Return the datetime until when the resource is available. /// If it is not valid, the project constraint end time is used. /// For teams the latest time for any team member is used. DateTime availableUntil(); Schedule *resourceSchedule( Schedule *ns, Resource *resource = 0 ); DateTime availableAfter(const DateTime &time, Schedule *ns); DateTime availableBefore(const DateTime &time, Schedule *ns); Duration effort( const DateTime &time, const Duration &duration, Schedule *ns, bool backward ); DateTime workTimeAfter(const DateTime &dt, Schedule *ns = 0); DateTime workTimeBefore(const DateTime &dt, Schedule *ns = 0); /// Resource is allocated dynamically by the group request bool isDynamicallyAllocated() const { return m_dynamic; } /// Set resource is allocated dynamically void setAllocatedDynaically( bool dyn ) { m_dynamic = dyn; } /// Return a measure of how suitable the resource is for allocation long allocationSuitability( const DateTime &time, const Duration &duration, Schedule *ns, bool backward ); /// Returns a list of all the required resources that will be used in scheduling. /// Note: This list overrides the resources own list which is just used as default for allocation dialog. QList requiredResources() const { return m_required; } /// Set the list of required resources that will be used in scheduling. void setRequiredResources( const QList &lst ) { m_required = lst; } private: friend class ResourceGroupRequest; QList teamMembers() const; protected: void changed(); void setCurrentSchedulePtr( Schedule *ns ); void setCurrentSchedulePtr( Resource *resource, Schedule *ns ); private: Resource *m_resource; int m_units; ResourceGroupRequest *m_parent; bool m_dynamic; QList m_required; mutable QList m_teamMembers; #ifndef NDEBUG public: void printDebug( const QString& ident ); #endif }; QDebug &operator<<( QDebug &dbg, const KPlato::ResourceRequest *r ); QDebug &operator<<( QDebug &dbg, const KPlato::ResourceRequest &r ); class PLANKERNEL_EXPORT ResourceGroupRequest { public: explicit ResourceGroupRequest( ResourceGroup *group = 0, int units = 0 ); explicit ResourceGroupRequest( const ResourceGroupRequest &group ); ~ResourceGroupRequest(); void setParent( ResourceRequestCollection *parent ) { m_parent = parent;} ResourceRequestCollection *parent() const { return m_parent; } ResourceGroup *group() const { return m_group; } void setGroup( ResourceGroup *group ) { m_group = group; } void unregister( const ResourceGroup *group ) { if ( group == m_group ) m_group = 0; } /// Return a list of resource requests. /// If @p resolveTeam is true, include the team members, /// if @p resolveTeam is false, include the team resource itself. QList resourceRequests( bool resolveTeam=true ) const; void addResourceRequest( ResourceRequest *request ); void deleteResourceRequest( ResourceRequest *request ); int count() const { return m_resourceRequests.count(); } ResourceRequest *requestAt( int idx ) const { return m_resourceRequests.value( idx ); } ResourceRequest *takeResourceRequest( ResourceRequest *request ); ResourceRequest *find( const Resource *resource ) const; ResourceRequest *resourceRequest( const QString &name ); /// Return a list of allocated resources, allocation to group is not included by default. QStringList requestNameList( bool includeGroup = false ) const; /// Return a list of allocated resources. /// Allocations to groups are not included. /// Team resources are included but *not* the team members. /// Any dynamically allocated resource is not included. QList requestedResources() const; bool load( KoXmlElement &element, XMLLoaderObject &status ); void save( QDomElement &element ) const; /// The number of requested resources int units() const; void setUnits( int value ) { m_units = value; changed(); } /** * Returns the duration needed to do the @p effort starting at @p start. */ Duration duration( const DateTime &start, const Duration &effort, Schedule *ns, bool backward = false ); DateTime availableAfter( const DateTime &time, Schedule *ns ); DateTime availableBefore( const DateTime &time, Schedule *ns ); DateTime workTimeAfter(const DateTime &dt, Schedule *ns = 0); DateTime workTimeBefore(const DateTime &dt, Schedule *ns = 0); /** * Makes appointments for task @param task to the * requested resources for the duration found in @ref duration(). */ void makeAppointments( Schedule *schedule ); /** * Reserves the requested resources for the specified interval */ void reserve( const DateTime &start, const Duration &duration ); bool isEmpty() const; Task *task() const; void changed(); /// Reset dynamic resource allocations void resetDynamicAllocations(); /// Allocate dynamic requests. Do nothing if already allocated. void allocateDynamicRequests( const DateTime &time, const Duration &effort, Schedule *ns, bool backward ); private: ResourceGroup *m_group; int m_units; ResourceRequestCollection *m_parent; QList m_resourceRequests; DateTime m_start; Duration m_duration; #ifndef NDEBUG public: void printDebug( const QString& ident ); #endif }; class PLANKERNEL_EXPORT ResourceRequestCollection { public: explicit ResourceRequestCollection( Task *task = 0 ); ~ResourceRequestCollection(); QList requests() const { return m_requests; } void addRequest( ResourceGroupRequest *request ); void deleteRequest( ResourceGroupRequest *request ) { int i = m_requests.indexOf( request ); if ( i != -1 ) m_requests.removeAt( i ); delete request; changed(); } int takeRequest( ResourceGroupRequest *request ) { int i = m_requests.indexOf( request ); if ( i != -1 ) { m_requests.removeAt( i ); changed(); } return i; } ResourceGroupRequest *find( const ResourceGroup *resource ) const; ResourceRequest *find( const Resource *resource ) const; ResourceRequest *resourceRequest( const QString &name ) const; /// The ResourceRequestCollection has no requests bool isEmpty() const; /// Empty the ResourceRequestCollection of all requets void clear() { m_requests.clear(); } /// Reset dynamic resource allocations void resetDynamicAllocations(); bool contains( const QString &identity ) const; ResourceGroupRequest *findGroupRequestById( const QString &id ) const; /// Return a list of names of allocated resources. /// Allocations to groups are not included by default. /// Team resources are included but *not* the team members. /// Any dynamically allocated resource is not included. QStringList requestNameList( bool includeGroup = false ) const; /// Return a list of allocated resources. /// Allocations to groups are not included. /// Team resources are included but *not* the team members. /// Any dynamically allocated resource is not included. QList requestedResources() const; /// Return a list of all resource requests. /// If @p resolveTeam is true, include the team members, /// if @p resolveTeam is false, include the team resource itself. QList resourceRequests( bool resolveTeam=true ) const; //bool load(KoXmlElement &element, Project &project); void save( QDomElement &element ) const; /** * Returns the duration needed to do the @p effort starting at @p time. */ Duration duration( const DateTime &time, const Duration &effort, Schedule *sch, bool backward = false ); DateTime availableAfter( const DateTime &time, Schedule *ns ); DateTime availableBefore( const DateTime &time, Schedule *ns ); DateTime workTimeAfter(const DateTime &dt, Schedule *ns = 0) const; DateTime workTimeBefore(const DateTime &dt, Schedule *ns = 0) const; DateTime workStartAfter(const DateTime &time, Schedule *ns); DateTime workFinishBefore(const DateTime &time, Schedule *ns); /** * Makes appointments for the task @param task to the requested resources. * Assumes that @ref duration() has been run. */ void makeAppointments( Schedule *schedule ); /** * Reserves the requested resources for the specified interval */ void reserve( const DateTime &start, const Duration &duration ); Task *task() const { return m_task; } void setTask( Task *t ) { m_task = t; } void changed(); Duration effort( const QList &lst, const DateTime &time, const Duration &duration, Schedule *ns, bool backward ) const; int numDays(const QList &lst, const DateTime &time, bool backward) const; Duration duration(const QList &lst, const DateTime &time, const Duration &_effort, Schedule *ns, bool backward); private: Task *m_task; QList m_requests; }; } //KPlato namespace #endif diff --git a/src/libs/kernel/kptschedule.h b/src/libs/kernel/kptschedule.h index 45bd22fb..bd6af430 100644 --- a/src/libs/kernel/kptschedule.h +++ b/src/libs/kernel/kptschedule.h @@ -1,735 +1,735 @@ /* This file is part of the KDE project Copyright (C) 2005 - 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KPTSCHEDULE_H #define KPTSCHEDULE_H #include "plankernel_export.h" #include "kptglobal.h" #include "kptcalendar.h" #include "kpteffortcostmap.h" #include "kptresource.h" #include #include #include //#include "KoXmlReaderForward.h" class QDomElement; class QStringList; /// The main namespace namespace KPlato { class Appointment; class DateTime; class Duration; class Node; class Project; class Task; class ScheduleManager; class XMLLoaderObject; class SchedulerPlugin; class KPlatoXmlLoaderBase; /// Caches effortcost data (bcws, bcwp, acwp) class EffortCostCache { public: EffortCostCache() : cached( false ) {} bool cached; EffortCostMap effortcostmap; }; /** * The Schedule class holds data calculated during project * calculation and scheduling, eg start- and end-times and * appointments. * There is one Schedule per node (tasks and project ) and one per resource. * Schedule is subclassed into: * MainSchedule Used by the main project. * NodeSchedule Used by all other nodes (tasks). * ResourceSchedule Used by resources. */ class PLANKERNEL_EXPORT Schedule { public: //NOTE: Must match Effort::Use atm. enum Type { Expected = 0 //Effort::Use_Expected }; Schedule(); explicit Schedule(Schedule *parent); Schedule( const QString& name, Type type, long id ); virtual ~Schedule(); QString name() const { return m_name; } void setName( const QString& name ) { m_name = name; } Type type() const { return m_type; } void setType( Type type ) { m_type = type; } void setType( const QString& type ); QString typeToString( bool translate = false ) const; long id() const { return m_id; } void setId( long id ) { m_id = id; } void setParent( Schedule *parent ); Schedule *parent() const { return m_parent; } virtual bool isDeleted() const; virtual void setDeleted( bool on ); virtual bool recalculate() const { return m_parent == 0 ? false : m_parent->recalculate(); } virtual DateTime recalculateFrom() const { return m_parent == 0 ? DateTime() : m_parent->recalculateFrom(); } virtual long parentScheduleId() const { return m_parent == 0 ? NOTSCHEDULED : m_parent->parentScheduleId(); } virtual Resource *resource() const { return 0; } virtual Node *node() const { return 0; } virtual bool isBaselined() const; virtual bool usePert() const; enum OBState { OBS_Parent, OBS_Allow, OBS_Deny }; /// Sets whether overbooking resources is allowed locally for this schedule /// If @p state is OBS_Parent, the parent is checked when allowOverbooking() is called virtual void setAllowOverbookingState( OBState state ); OBState allowOverbookingState() const; virtual bool allowOverbooking() const; virtual bool checkExternalAppointments() const; bool isCritical() const { return positiveFloat == Duration::zeroDuration; } virtual bool loadXML( const KoXmlElement &element, XMLLoaderObject &status ); virtual void saveXML( QDomElement &element ) const; void saveCommonXML( QDomElement &element ) const; void saveAppointments( QDomElement &element ) const; /// Return the effort available in the @p interval virtual Duration effort( const DateTimeInterval &interval ) const; virtual DateTimeInterval available( const DateTimeInterval &interval ) const; enum CalculationMode { Scheduling, CalculateForward, CalculateBackward }; /// Set calculation mode void setCalculationMode( int mode ) { m_calculationMode = mode; } /// Return calculation mode int calculationMode() const { return m_calculationMode; } /// Return the list of appointments QList appointments() const { return m_appointments; } /// Return true if the @p which list is not empty bool hasAppointments( int which ) const; /// Return the list of appointments /// @param which specifies which list is returned QList appointments(int which) const; /// Adds appointment to this schedule only virtual bool add( Appointment *appointment ); /// Adds appointment to both this resource schedule and node schedule virtual void addAppointment( Schedule * /*other*/, const DateTime & /*start*/, const DateTime & /*end*/, double /*load*/ = 100 ) {} /// Removes appointment without deleting it. virtual void takeAppointment( Appointment *appointment, int type = Scheduling ); Appointment *findAppointment( Schedule *resource, Schedule *node, int type = Scheduling ); /// Attach the appointment to appropriate list (appointment->calculationMode() specifies list) bool attach( Appointment *appointment ); DateTime appointmentStartTime() const; DateTime appointmentEndTime() const; virtual Appointment appointmentIntervals( int which = Scheduling, const DateTimeInterval &interval = DateTimeInterval() ) const; void copyAppointments( CalculationMode from, CalculationMode to ); virtual bool isOverbooked() const { return false; } virtual bool isOverbooked( const DateTime & /*start*/, const DateTime & /*end*/ ) const { return false; } virtual QStringList overbookedResources() const; /// Returns the first booked interval to @p node that intersects @p interval (limited to @p interval) virtual DateTimeInterval firstBookedInterval( const DateTimeInterval &interval, const Schedule *node ) const; /// Return the resources that has appointments to this schedule virtual QList resources() const; /// Return the resource names that has appointments to this schedule virtual QStringList resourceNameList() const; virtual EffortCostMap bcwsPrDay( EffortCostCalculationType type = ECCT_All ); virtual EffortCostMap bcwsPrDay( EffortCostCalculationType type = ECCT_All ) const; virtual EffortCostMap plannedEffortCostPrDay( const QDate &start, const QDate &end, EffortCostCalculationType type = ECCT_All ) const; virtual EffortCostMap plannedEffortCostPrDay( const Resource *resource, const QDate &start, const QDate &end, EffortCostCalculationType type = ECCT_All ) const; /// Returns the total planned effort for @p resource this schedule virtual Duration plannedEffort( const Resource *resource, EffortCostCalculationType type = ECCT_All) const; /// Returns the total planned effort for this schedule virtual Duration plannedEffort( EffortCostCalculationType type = ECCT_All) const; /// Returns the total planned effort for this schedule on date virtual Duration plannedEffort( const QDate &date, EffortCostCalculationType type = ECCT_All ) const; /// Returns the planned effort for @p resource on the @p date date virtual Duration plannedEffort( const Resource *resource, const QDate &date, EffortCostCalculationType type = ECCT_All ) const; /// Returns the planned effort up to and including date virtual Duration plannedEffortTo( const QDate &date, EffortCostCalculationType type = ECCT_All ) const; /// Returns the planned effort for @p resource up to and including date virtual Duration plannedEffortTo( const Resource *resource, const QDate &date, EffortCostCalculationType type = ECCT_All ) const; /** * Planned cost is the sum total of all resources and other costs * planned for this node. */ virtual EffortCost plannedCost( EffortCostCalculationType type = ECCT_All ) const; /// Planned cost on date virtual double plannedCost( const QDate &date, EffortCostCalculationType type = ECCT_All ) const; /** * Planned cost from start of activity up to and including date * is the sum of all resource costs and other costs planned for this schedule. */ virtual double plannedCostTo( const QDate &date, EffortCostCalculationType type = ECCT_All ) const; virtual double normalRatePrHour() const { return 0.0; } void setEarliestStart( DateTime &dt ) { earlyStart = dt; } void setLatestFinish( DateTime &dt ) { lateFinish = dt; } virtual void initiateCalculation(); virtual void calcResourceOverbooked(); virtual void insertHardConstraint( Node * ) {} virtual void insertSoftConstraint( Node * ) {} virtual void insertForwardNode( Node *node ); virtual void insertBackwardNode( Node *node ); virtual void insertStartNode( Node * ) {} virtual void insertEndNode( Node * ) {} virtual void insertSummaryTask( Node * ) {} void setScheduled( bool on ); bool isScheduled() const { return !notScheduled; } DateTime start() const { return startTime; } DateTime end() const { return endTime; } QStringList state() const; void setResourceError( bool on ) { resourceError = on; } void setResourceOverbooked( bool on ) { resourceOverbooked = on; } void setResourceNotAvailable( bool on ) { resourceNotAvailable = on; } void setConstraintError( bool on ) { constraintError = on; } void setNotScheduled( bool on ) { notScheduled = on; } void setSchedulingError( bool on ) { schedulingError = on; } void setPositiveFloat( KPlato::Duration f ) { positiveFloat = f; } void setNegativeFloat( KPlato::Duration f ) { negativeFloat = f; } void setFreeFloat( KPlato::Duration f ) { freeFloat = f; } void setInCriticalPath( bool on = true ) { inCriticalPath = on; } virtual ScheduleManager *manager() const { return 0; } class PLANKERNEL_EXPORT Log { public: enum Type { Type_Debug = 0, Type_Info, Type_Warning, Type_Error }; Log() : node( 0 ), resource( 0 ), severity( 0 ), phase( -1 ) {} Log( const Node *n, int sev, const QString &msg, int ph = -1 ); Log( const Node *n, const Resource *r, int sev, const QString &msg, int ph = -1 ); Log( const Log &other ); Log &operator=( const Log &other ); const Node *node; const Resource *resource; QString message; int severity; int phase; QString formatMsg() const; }; virtual void addLog( const Log &log ); virtual void clearLogs() {}; virtual void logError( const QString &, int = -1 ) {} virtual void logWarning( const QString &, int = -1 ) {} virtual void logInfo( const QString &, int = -1 ) {} virtual void logDebug( const QString &, int = -1 ) {} virtual void incProgress() { if ( m_parent ) m_parent->incProgress(); } void clearPerformanceCache(); protected: virtual void changed( Schedule * /*sch*/ ) {} protected: QString m_name; Type m_type; long m_id; bool m_deleted; Schedule *m_parent; OBState m_obstate; int m_calculationMode; QList m_appointments; QList m_forward; QList m_backward; friend class Node; friend class Task; friend class Project; friend class Resource; friend class RecalculateProjectCmd; friend class ScheduleManager; friend class KPlatoXmlLoaderBase; /** * earlyStart is calculated by PERT/CPM. * A task may be scheduled to start later because of constraints * or resource availability etc. */ DateTime earlyStart; /** * lateStart is calculated by PERT/CPM. * A task may not be scheduled to start later. */ DateTime lateStart; /** * earlyFinish is calculated by PERT/CPM. * A task may not be scheduled to finish earlier. */ DateTime earlyFinish; /** * lateFinish is calculated by PERT/CPM. * A task may be scheduled to finish earlier because of constraints * or resource availability etc. */ DateTime lateFinish; /** startTime is the scheduled start time. * It depends on constraints (i.e. ASAP/ALAP) and resource availability. * It will always be later or equal to earliestStart */ DateTime startTime; /** * m_endTime is the scheduled finish time. * It depends on constraints (i.e. ASAP/ALAP) and resource availability. * It will always be earlier or equal to latestFinish */ DateTime endTime; /** * duration is the scheduled duration which depends on * e.g. estimated effort, allocated resources and risk */ Duration duration; /// Set if EffortType == Effort, but no resource is requested bool resourceError; /// Set if the assigned resource is overbooked bool resourceOverbooked; /// Set if the requested resource is not available bool resourceNotAvailable; /// Set if the task cannot be scheduled to fulfil all the constraints bool constraintError; /// Set if the node has not been scheduled bool notScheduled; /// Set if the assigned resource cannot deliver the required estimated effort bool effortNotMet; /// Set if some other scheduling error occurs bool schedulingError; DateTime workStartTime; DateTime workEndTime; bool inCriticalPath; Duration positiveFloat; Duration negativeFloat; Duration freeFloat; EffortCostCache &bcwsPrDayCache( int type ) { return m_bcwsPrDay[ type ]; } EffortCostCache &bcwpPrDayCache( int type ) { return m_bcwpPrDay[ type ]; } EffortCostCache &acwpCache( int type ) { return m_acwp[ type ]; } QMap m_bcwsPrDay; QMap m_bcwpPrDay; QMap m_acwp; }; /** * NodeSchedule holds scheduling information for a node (task). * */ class PLANKERNEL_EXPORT NodeSchedule : public Schedule { public: NodeSchedule(); NodeSchedule( Node *node, const QString& name, Schedule::Type type, long id ); NodeSchedule( Schedule *parent, Node *node ); virtual ~NodeSchedule(); virtual bool isDeleted() const { return m_parent == 0 ? true : m_parent->isDeleted(); } void setDeleted( bool on ); virtual bool loadXML( const KoXmlElement &element, XMLLoaderObject &status ); virtual void saveXML( QDomElement &element ) const; // tasks------------> virtual void addAppointment( Schedule *resource, const DateTime &start, const DateTime &end, double load = 100 ); virtual void takeAppointment( Appointment *appointment, int type = Schedule::Scheduling ); virtual Node *node() const { return m_node; } virtual void setNode( Node *n ) { m_node = n; } /// Return the resources that has appointments to this schedule virtual QList resources() const; /// Return the resource names that has appointments to this schedule virtual QStringList resourceNameList() const; virtual void logError( const QString &msg, int phase = -1 ); virtual void logWarning( const QString &msg, int phase = -1 ); virtual void logInfo( const QString &msg, int phase = -1 ); virtual void logDebug( const QString &, int = -1 ); protected: void init(); private: Node *m_node; }; /** * ResourceSchedule holds scheduling information for a resource. * */ class PLANKERNEL_EXPORT ResourceSchedule : public Schedule { public: ResourceSchedule(); ResourceSchedule( Resource *Resource, const QString& name, Schedule::Type type, long id ); ResourceSchedule( Schedule *parent, Resource *Resource ); virtual ~ResourceSchedule(); virtual bool isDeleted() const { return m_parent == 0 ? true : m_parent->isDeleted(); } virtual void addAppointment( Schedule *node, const DateTime &start, const DateTime &end, double load = 100 ); virtual void takeAppointment( Appointment *appointment, int type = Scheduling ); virtual bool isOverbooked() const; virtual bool isOverbooked( const DateTime &start, const DateTime &end ) const; virtual Resource *resource() const { return m_resource; } virtual double normalRatePrHour() const; /// Return the effort available in the @p interval virtual Duration effort( const DateTimeInterval &interval ) const; virtual DateTimeInterval available( const DateTimeInterval &interval ) const; virtual void logError( const QString &msg, int phase = -1 ); virtual void logWarning( const QString &msg, int phase = -1 ); virtual void logInfo( const QString &msg, int phase = -1 ); virtual void logDebug( const QString &, int = -1 ); void setNodeSchedule( const Schedule *sch ) { m_nodeSchedule = sch; } private: Resource *m_resource; Schedule *m_parent; const Schedule *m_nodeSchedule; // used during scheduling }; /** * MainSchedule holds scheduling information for the main project node. * */ class PLANKERNEL_EXPORT MainSchedule : public NodeSchedule { public: MainSchedule(); MainSchedule( Node *node, const QString& name, Schedule::Type type, long id ); ~MainSchedule(); virtual bool isDeleted() const { return m_deleted; } virtual bool isBaselined() const; virtual bool allowOverbooking() const; virtual bool checkExternalAppointments() const; virtual bool usePert() const; virtual bool loadXML( const KoXmlElement &element, XMLLoaderObject &status ); virtual void saveXML( QDomElement &element ) const; void setManager( ScheduleManager *sm ) { m_manager = sm; } ScheduleManager *manager() const { return m_manager; } virtual bool recalculate() const; virtual DateTime recalculateFrom() const; virtual long parentScheduleId() const; DateTime calculateForward( int use ); DateTime calculateBackward( int use ); DateTime scheduleForward( const DateTime &earliest, int use ); DateTime scheduleBackward( const DateTime &latest, int use ); void clearNodes() { m_hardconstraints.clear(); m_softconstraints.clear(); m_forwardnodes.clear(); m_backwardnodes.clear(); m_startNodes.clear(); m_endNodes.clear(); m_summarytasks.clear(); } virtual void insertHardConstraint( Node *node ) { m_hardconstraints.append( node ); } QList hardConstraints() const { return m_hardconstraints; } virtual void insertSoftConstraint( Node *node ) { m_softconstraints.append( node ); } QList softConstraints() const { return m_softconstraints; } QList forwardNodes() const { return m_forwardnodes; } virtual void insertForwardNode( Node *node ) { m_forwardnodes.append( node ); } QList backwardNodes() const { return m_backwardnodes; } virtual void insertBackwardNode( Node *node ) { m_backwardnodes.append( node ); } virtual void insertStartNode( Node *node ) { m_startNodes.append( node ); } QList startNodes() const { return m_startNodes; } virtual void insertEndNode( Node *node ) { m_endNodes.append( node ); } QList endNodes() const { return m_endNodes; } virtual void insertSummaryTask( Node *node ) { m_summarytasks.append( node ); } QList summaryTasks() const { return m_summarytasks; } void clearCriticalPathList(); QList *currentCriticalPath() const; void addCriticalPath( QList *lst = 0 ); const QList< QList > *criticalPathList() const { return &(m_pathlists); } QList criticalPath( int index = 0 ) { QList lst; return m_pathlists.count() <= index ? lst : m_pathlists[ index ]; } void addCriticalPathNode( Node *node ); QVector logs() const; void setLog( const QVector &log ) { m_log = log; } virtual void addLog( const Schedule::Log &log ); virtual void clearLogs() { m_log.clear(); m_logPhase.clear(); } void setPhaseName( int phase, const QString &name ) { m_logPhase[ phase ] = name; } QString logPhase( int phase ) const { return m_logPhase.value( phase ); } static QString logSeverity( int severity ); QMap phaseNames() const { return m_logPhase; } void setPhaseNames( const QMap &pn ) { m_logPhase = pn; } virtual void incProgress(); QStringList logMessages() const; QList< QList > m_pathlists; bool criticalPathListCached; protected: virtual void changed( Schedule *sch ); private: friend class Project; ScheduleManager *m_manager; QList m_hardconstraints; QList m_softconstraints; QList m_forwardnodes; QList m_backwardnodes; QList m_startNodes; QList m_endNodes; QList m_summarytasks; QList *m_currentCriticalPath; QVector m_log; QMap m_logPhase; }; /** * ScheduleManager is used by the Project class to manage the schedules. * The ScheduleManager is the bases for the user interface to scheduling. * A ScheduleManager can have child manager(s). */ class PLANKERNEL_EXPORT ScheduleManager : public QObject { Q_OBJECT public: enum CalculationResult { CalculationRunning = 0, CalculationDone, CalculationStopped, CalculationCanceled, CalculationError }; explicit ScheduleManager( Project &project, const QString name = QString() ); ~ScheduleManager(); void setName( const QString& name ); QString name() const { return m_name; } void setManagerId( const QString &id ) { m_id = id; } QString managerId() const { return m_id; } Project &project() const { return m_project; } void setParentManager( ScheduleManager *sm, int index = -1 ); ScheduleManager *parentManager() const { return m_parent; } long scheduleId() const { return m_expected == 0 ? NOTSCHEDULED : m_expected->id(); } int removeChild( const ScheduleManager *sm ); void insertChild( ScheduleManager *sm, int index = -1 ); QList children() const { return m_children; } int childCount() const { return m_children.count(); } ScheduleManager *childAt( int index ) const { return m_children.value( index ); } /// Return list of all child managers (also childrens children) QList allChildren() const; int indexOf( const ScheduleManager* child ) const; bool isParentOf( const ScheduleManager *sm ) const; ScheduleManager *findManager( const QString &name ) const; /// This sub-schedule will be re-calculated based on the parents completion data bool recalculate() const { return m_recalculate; } /// Set re-calculate to @p on. void setRecalculate( bool on ) { m_recalculate = on; } /// The datetime this schedule will be calculated from DateTime recalculateFrom() const { return m_recalculateFrom; } /// Set the datetime this schedule will be calculated from to @p dt void setRecalculateFrom( const DateTime &dt ) { m_recalculateFrom = dt; } long parentScheduleId() const { return m_parent == 0 ? NOTSCHEDULED : m_parent->scheduleId(); } void createSchedules(); void setDeleted( bool on ); bool isScheduled() const { return m_expected == 0 ? false : m_expected->isScheduled(); } void setExpected( MainSchedule *sch ); MainSchedule *expected() const { return m_expected; } QStringList state() const; void setBaselined( bool on ); bool isBaselined() const { return m_baselined; } bool isChildBaselined() const; void setAllowOverbooking( bool on ); bool allowOverbooking() const; void setCheckExternalAppointments( bool on ); bool checkExternalAppointments() const; void setUsePert( bool on ); bool usePert() const { return m_usePert; } void setSchedulingDirection( bool on ); bool schedulingDirection() const { return m_schedulingDirection; } void setScheduling( bool on ); bool scheduling() const { return m_scheduling; } bool loadXML( KoXmlElement &element, XMLLoaderObject &status ); void saveXML( QDomElement &element ) const; /// Save a workpackage document void saveWorkPackageXML( QDomElement &element, const Node &node ) const; void scheduleChanged( MainSchedule *sch ); const QList schedulerPlugins() const; QString schedulerPluginId() const; void setSchedulerPluginId( const QString &id ); SchedulerPlugin *schedulerPlugin() const; QStringList schedulerPluginNames() const; int schedulerPluginIndex() const; void setSchedulerPlugin( int index ); /// Stop calculation. Use result if possible. void stopCalculation(); /// Terminate calculation. Forget any results. void haltCalculation(); void calculateSchedule(); int calculationResult() const { return m_calculationresult; } void setCalculationResult( int r ) { m_calculationresult = r; } /// Increments progress in the project void incProgress(); /// Returns current progress int progress() const { return m_progress; } /// Returns maximum progress value int maxProgress() const { return m_maxprogress; } /// Log added by MainSchedule /// Emits sigLogAdded() to enable synchronization between schedules void logAdded( const Schedule::Log &log ); /// Create and load a MainSchedule MainSchedule *loadMainSchedule( KoXmlElement &element, XMLLoaderObject &status ); /// Load an existing MainSchedule bool loadMainSchedule( MainSchedule *schedule, KoXmlElement &element, XMLLoaderObject &status ); QMap< int, QString > phaseNames() const; /// Return a list of the supported granularities of the current scheduler QList supportedGranularities() const; /// Return current index of supported granularities of the selected scheduler int granularity() const; /// Set current index of supported granularities of the selected scheduler void setGranularity( int duration ); public Q_SLOTS: /// Set maximum progress. Emits signal maxProgressChanged void setMaxProgress( int value ); /// Set progress. Emits signal progressChanged void setProgress( int value ); /// Add the lis of logs @p log to expected() void slotAddLog( const QVector &log ); void setPhaseNames( const QMap &phasenames ); Q_SIGNALS: void maxProgressChanged( int ); void progressChanged( int ); /// Emitted by logAdded() when new log entries are added - void logInserted( MainSchedule*, int firstrow, int lastrow ); + void logInserted(KPlato::MainSchedule*, int firstrow, int lastrow); /// Emitted by logAdded() /// Used by scheduling thread - void sigLogAdded( const Schedule::Log &log ); + void sigLogAdded(const KPlato::Schedule::Log &log); protected: Project &m_project; ScheduleManager *m_parent; QString m_name; QString m_id; bool m_baselined; bool m_allowOverbooking; bool m_checkExternalAppointments; bool m_usePert; bool m_recalculate; DateTime m_recalculateFrom; bool m_schedulingDirection; bool m_scheduling; int m_progress; int m_maxprogress; MainSchedule *m_expected; QList m_children; QString m_schedulerPluginId; int m_calculationresult; }; } //namespace KPlato Q_DECLARE_TYPEINFO(KPlato::Schedule::Log, Q_MOVABLE_TYPE); PLANKERNEL_EXPORT QDebug operator<<( QDebug dbg, const KPlato::Schedule *s ); PLANKERNEL_EXPORT QDebug operator<<( QDebug dbg, const KPlato::Schedule &s ); PLANKERNEL_EXPORT QDebug operator<<( QDebug dbg, const KPlato::Schedule::Log &log ); #endif diff --git a/src/libs/kernel/kptschedulerplugin.h b/src/libs/kernel/kptschedulerplugin.h index 7471b7a3..52b67a21 100644 --- a/src/libs/kernel/kptschedulerplugin.h +++ b/src/libs/kernel/kptschedulerplugin.h @@ -1,256 +1,256 @@ /* This file is part of the KDE project Copyright (C) 2009, 2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KPTSCHEDULERPLUGIN_H #define KPTSCHEDULERPLUGIN_H #include "plankernel_export.h" #include "kptschedule.h" #include #include #include #include #include #include #include namespace KPlato { class SchedulerThread; class Project; class ScheduleManager; class Node; class XMLLoaderObject; /** SchedulerPlugin is the base class for project calculation plugins. Sub-class SchedulerThread to do the actual calculation, then re-implement calculate() to calculate the project, and slotFinished() to fetch the result into your project. There is two ways to show progress:

  • Connect the SchedulerThread::maxProgressChanged() to ScheduleManager::setMaxProgress() and and SchedulerThread::progressChanged() to ScheduleManager::setProgress(). Note that too many progress signals too often may choke the ui thread.
  • Start the m_synctimer. This will fetch progress and log messages every 500 ms (by default).
When the thread has finished scheduling, data can be fetched from its temporary project into the real project by calling the updateProject() method. */ class PLANKERNEL_EXPORT SchedulerPlugin : public QObject { Q_OBJECT public: explicit SchedulerPlugin(QObject *parent); virtual ~SchedulerPlugin(); /// Localized name QString name() const; /// Name is normally set by the plugin loader, from Name in the desktop file void setName( const QString &name ); /// Localized comment QString comment() const; /// Comment is normally set by the plugin loader, from Comment in the desktop file void setComment( const QString &name ); /// A more elaborate description suitable for use in what's this virtual QString description() const { return QString(); } /// The schedulers capabilities enum Capabilities { AvoidOverbooking = 1, AllowOverbooking = 2, ScheduleForward = 4, ScheduleBackward = 8 }; /// Return the schedulers capabilities. /// By default returns all capabilities virtual int capabilities() const; /// Stop calculation of the schedule @p sm. Current result may be used. void stopCalculation( ScheduleManager *sm ); /// Terminate calculation of the schedule @p sm. No results will be available. void haltCalculation( ScheduleManager *sm ); /// Stop calculation of the scheduling @p job. Current result may be used. virtual void stopCalculation( SchedulerThread *job ); /// Terminate calculation of the scheduling @p job. No results will be available. virtual void haltCalculation( SchedulerThread *job ); /// Calculate the project virtual void calculate( Project &project, ScheduleManager *sm, bool nothread = false ) = 0; /// Return the list of supported granularities /// An empty list means granularity is not supported (the default) QList granularities() const; /// Return current index of supported granularities int granularity() const; /// Set current index of supported granularities void setGranularity( int index ); protected Q_SLOTS: virtual void slotSyncData(); protected: void updateProject( const Project *tp, const ScheduleManager *tm, Project *mp, ScheduleManager *sm ) const; void updateNode( const Node *tn, Node *mn, long sid, XMLLoaderObject &status ) const; void updateResource( const KPlato::Resource *tr, Resource *r, XMLLoaderObject &status ) const; void updateAppointments( const Project *tp, const ScheduleManager *tm, Project *mp, ScheduleManager *sm, XMLLoaderObject &status ) const; void updateProgress(); void updateLog(); void updateLog( SchedulerThread *job ); private: class Private; Private *d; protected: QTimer m_synctimer; QList m_jobs; int m_granularity; QList m_granularities; }; /** SchedulerThread is a basic class used to implement project calculation in a separate thread. The scheduling thread is meant to run on a private copy of the project to avoid that the ui thread changes the data while calculations are going on. The constructor creates a KoXmlDocument m_pdoc of the project that can be used to create a private project. This should be done in the reimplemented run() method. When the calculations are done the signal jobFinished() is emitted. This can be used to fetch data from the private calculated project into the actual project. To track progress, the progress() method should be called from the ui thread with an appropriate interval to avoid overload of the ui thread. The progressChanged() signal may also be used but note that async signal handling are very slow so it may affect the ui threads performance too much. */ class PLANKERNEL_EXPORT SchedulerThread : public QThread { Q_OBJECT public: SchedulerThread( Project *project, ScheduleManager *manager, QObject *parent ); ~SchedulerThread(); Project *mainProject() const { return m_mainproject; } ScheduleManager *mainManager() const { return m_mainmanager; } Project *project() const; ScheduleManager *manager() const; /// Run with no thread void doRun(); /// The scheduling is stopping bool isStopped() const { return m_stopScheduling; } /// The scheduling is halting bool isHalted() const { return m_haltScheduling; } int maxProgress() const; int progress() const; QVector takeLog(); QMap phaseNames() const; /// Save the @p project into @p document static void saveProject( Project *project, QDomDocument &document ); /// Load the @p project from @p document static bool loadProject( Project *project, const KoXmlDocument &document ); ///Add a scheduling error log message void logError( Node *n, Resource *r, const QString &msg, int phase = -1 ); ///Add a scheduling warning log message void logWarning( Node *n, Resource *r, const QString &msg, int phase = -1 ); ///Add a scheduling information log message void logInfo( Node *n, Resource *r, const QString &msg, int phase = -1 ); ///Add a scheduling debug log message void logDebug( Node *n, Resource *r, const QString &msg, int phase = -1 ); Q_SIGNALS: /// Job has started - void jobStarted( SchedulerThread *job ); + void jobStarted(KPlato::SchedulerThread *job); /// Job is finished - void jobFinished( SchedulerThread *job ); + void jobFinished(KPlato::SchedulerThread *job); /// Maximum progress value has changed - void maxProgressChanged( int value, ScheduleManager *sm = 0 ); + void maxProgressChanged(int value, KPlato::ScheduleManager *sm = 0); /// Progress has changed - void progressChanged( int value, ScheduleManager *sm = 0 ); + void progressChanged(int value, KPlato::ScheduleManager *sm = 0); public Q_SLOTS: /// Stop scheduling. Result may still be used. virtual void stopScheduling(); /// Halt scheduling. Discard result. virtual void haltScheduling(); protected Q_SLOTS: virtual void slotStarted(); virtual void slotFinished(); void setMaxProgress( int ); void setProgress( int ); void slotAddLog( const Schedule::Log &log ); protected: /// Re-implement to do the job virtual void run() {} protected: /// The actual project to be calculated. Not accessed outside constructor. Project *m_mainproject; /// The actual schedule manager to be calculated. Not accessed outside constructor. ScheduleManager *m_mainmanager; /// The schedule manager identity QString m_mainmanagerId; /// The temporary project Project *m_project; mutable QMutex m_projectMutex; /// The temporary schedule manager ScheduleManager *m_manager; mutable QMutex m_managerMutex; bool m_stopScheduling; /// Stop asap, preliminary result may be used bool m_haltScheduling; /// Stop and discrad result. Delete yourself. KoXmlDocument m_pdoc; int m_maxprogress; mutable QMutex m_maxprogressMutex; int m_progress; mutable QMutex m_progressMutex; QVector m_logs; mutable QMutex m_logMutex; QEventLoopLocker m_eventLoopLocker; /// to keep locale around, TODO: check if still needed with QLocale }; } //namespace KPlato #endif diff --git a/src/libs/kernel/kpttask.h b/src/libs/kernel/kpttask.h index e393b57e..45a617fe 100644 --- a/src/libs/kernel/kpttask.h +++ b/src/libs/kernel/kpttask.h @@ -1,761 +1,761 @@ /* This file is part of the KDE project Copyright (C) 2001 Thomas Zander zander@kde.org Copyright (C) 2004 - 2007 Dag Andersen Copyright (C) 2007 Florian Piquemal Copyright (C) 2007 Alexis Ménard This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTTASK_H #define KPTTASK_H #include "plankernel_export.h" #include "kptnode.h" #include "kptglobal.h" #include "kptdatetime.h" #include "kptduration.h" #include "kptresource.h" #include #include #include /// The main namespace. namespace KPlato { class Completion; /** * The Completion class holds information about the tasks progress. */ class PLANKERNEL_EXPORT Completion { public: class PLANKERNEL_EXPORT UsedEffort { public: class PLANKERNEL_EXPORT ActualEffort : public std::pair { public: explicit ActualEffort( KPlato::Duration ne = Duration::zeroDuration, KPlato::Duration oe = Duration::zeroDuration ) : std::pair( ne, oe ) {} ActualEffort( const ActualEffort &e ) : std::pair( e.first, e.second ) {} ~ActualEffort() {} Duration normalEffort() const { return first; } void setNormalEffort( KPlato::Duration e ) { first = e; } Duration overtimeEffort() const { return second; } void setOvertimeEffort( KPlato::Duration e ) { second = e; } /// Returns the sum of normalEffort + overtimeEffort Duration effort() const { return first + second; } void setEffort( KPlato::Duration ne, KPlato::Duration oe = Duration::zeroDuration ) { first = ne; second = oe; } }; UsedEffort(); UsedEffort( const UsedEffort &e ); ~UsedEffort(); bool operator==( const UsedEffort &e ) const; bool operator!=( const UsedEffort &e ) const { return !operator==( e ); } void mergeEffort( const UsedEffort &value ); void setEffort( QDate date, const ActualEffort &value ); /// Returns the total effort up to @p date Duration effortTo( QDate date ) const; /// Returns the total effort on @p date ActualEffort effort( QDate date ) const { return m_actual.value( date ); } ActualEffort takeEffort( QDate date ) { return m_actual.take( date ); } /// Returns the total effort for all registered dates Duration effort() const; QMap actualEffortMap() const { return m_actual; } /// Load from document bool loadXML(KoXmlElement &element, XMLLoaderObject &status ); /// Save to document void saveXML(QDomElement &element) const; bool contains( QDate date ) const { return m_actual.contains( date ); } private: QMap m_actual; }; typedef QMap DateUsedEffortMap; class PLANKERNEL_EXPORT Entry { public: Entry() : percentFinished( 0 ), remainingEffort( Duration::zeroDuration ), totalPerformed( Duration::zeroDuration ) {} Entry( int percent, Duration remaining, Duration performed ) : percentFinished( percent ), remainingEffort( remaining ), totalPerformed( performed ) {} Entry( const Entry &e ) { copy( e ); } bool operator==( const Entry &e ) const { return percentFinished == e.percentFinished && remainingEffort == e.remainingEffort && totalPerformed == e.totalPerformed && note == e.note; } bool operator!=( const Entry &e ) const { return ! operator==( e ); } Entry &operator=(const Entry &e ) { copy( e ); return *this; } int percentFinished; Duration remainingEffort; Duration totalPerformed; QString note; protected: void copy( const Entry &e ) { percentFinished = e.percentFinished; remainingEffort = e.remainingEffort; totalPerformed = e.totalPerformed; note = e.note; } }; typedef QMap EntryList; typedef QMap ResourceUsedEffortMap; explicit Completion( Node *node = 0 ); // review * or &, or at all? Completion( const Completion © ); virtual ~Completion(); bool operator==(const Completion &p); bool operator!=(Completion &p) { return !(*this == p); } Completion &operator=(const Completion &p); /// Load from document bool loadXML(KoXmlElement &element, XMLLoaderObject &status ); /// Save to document void saveXML(QDomElement &element) const; bool startIsValid() const { return m_started && m_startTime.isValid(); } bool isStarted() const { return m_started; } void setStarted( bool on ); bool finishIsValid() const { return m_finished && m_finishTime.isValid(); } bool isFinished() const { return m_finished; } void setFinished( bool on ); DateTime startTime() const { return m_startTime; } void setStartTime( const DateTime &dt ); DateTime finishTime() const { return m_finishTime; } void setFinishTime( const DateTime &dt ); void setPercentFinished( QDate date, int value ); void setRemainingEffort( QDate date, Duration value ); void setActualEffort( QDate date, Duration value ); /// Return a list of the resource that has done any work on this task QList resources() { return m_usedEffort.keys(); } const EntryList &entries() const { return m_entries; } void addEntry( QDate date, Entry *entry ); Entry *takeEntry( QDate date ) { return m_entries.take( date ); changed(); } Entry *entry( QDate date ) const { return m_entries[ date ]; } /// Returns the date of the latest entry QDate entryDate() const; /// Returns the percentFinished of the latest entry int percentFinished() const; /// Returns the percentFinished on @p date int percentFinished( QDate date ) const; /// Returns the estimated remaining effort Duration remainingEffort() const; /// Returns the estimated remaining effort on @p date Duration remainingEffort( QDate date ) const; /// Returns the total actual effort Duration actualEffort() const; /// Returns the total actual effort on @p date Duration actualEffort( QDate date ) const; /// Returns the total actual effort upto and including @p date Duration actualEffortTo( QDate date ) const; /// Returns the actual effort for @p resource on @p date Duration actualEffort( const Resource *resource, QDate date ) const; /// TODO QString note() const; /// TODO void setNote( const QString &str ); /// Returns the total actual cost double actualCost() const; /// Returns the actual cost for @p resource double actualCost( const Resource *resource ) const; /// Returns the actual cost on @p date double actualCost( QDate date ) const; /// Returns the total actual cost for @p resource on @p date double actualCost( const Resource *resource, QDate date ) const; /// Returns the total actual effort and cost upto and including @p date EffortCost actualCostTo( long int id, QDate date ) const; /** * Returns a map of all actual effort and cost entered */ virtual EffortCostMap actualEffortCost( long id, EffortCostCalculationType type = ECCT_All ) const; void addUsedEffort( const Resource *resource, UsedEffort *value = 0 ); UsedEffort *takeUsedEffort( const Resource *r ) { return m_usedEffort.take( const_cast( r ) ); changed(); } UsedEffort *usedEffort( const Resource *r ) const { return m_usedEffort.value( const_cast( r ) ); } const ResourceUsedEffortMap &usedEffortMap() const { return m_usedEffort; } void changed( int property = -1 ); Node *node() const { return m_node; } void setNode( Node *node ) { m_node = node; } enum Entrymode { FollowPlan, EnterCompleted, EnterEffortPerTask, EnterEffortPerResource }; void setEntrymode( Entrymode mode ) { m_entrymode = mode; } Entrymode entrymode() const { return m_entrymode; } void setEntrymode( const QString &mode ); QString entryModeToString() const; QStringList entrymodeList() const; EffortCostMap effortCostPrDay(QDate start, QDate end, long id = -1 ) const; /// Returns the actual effort and cost pr day used by @p resource EffortCostMap effortCostPrDay(const Resource *resource, QDate start, QDate end, long id = CURRENTSCHEDULE ) const; protected: void copy( const Completion ©); double averageCostPrHour( QDate date, long id ) const; std::pair actualStartEndDates() const; private: Node *m_node; bool m_started, m_finished; DateTime m_startTime, m_finishTime; EntryList m_entries; ResourceUsedEffortMap m_usedEffort; Entrymode m_entrymode; #ifndef NDEBUG public: void printDebug( const QByteArray &ident ) const; #endif }; /** * The WorkPackage class controls work flow for a task */ class PLANKERNEL_EXPORT WorkPackage { public: /// @enum WPTransmitionStatus describes if this package was sent or received enum WPTransmitionStatus { TS_None, /// Not sent nor received TS_Send, /// Package was sent to resource TS_Receive /// Package was received from resource }; explicit WorkPackage( Task *task = 0 ); explicit WorkPackage( const WorkPackage &wp ); virtual ~WorkPackage(); Task *parentTask() const { return m_task; } void setParentTask( Task *task ) { m_task = task; } /// Returns the transmission status of this package WPTransmitionStatus transmitionStatus() const { return m_transmitionStatus; } void setTransmitionStatus( WPTransmitionStatus sts ) { m_transmitionStatus = sts; } static QString transmitionStatusToString( WPTransmitionStatus sts, bool trans = false ); static WPTransmitionStatus transmitionStatusFromString( const QString &sts ); /// Load from document virtual bool loadXML(KoXmlElement &element, XMLLoaderObject &status ); /// Save the full workpackage virtual void saveXML(QDomElement &element) const; /// Load from document virtual bool loadLoggedXML(KoXmlElement &element, XMLLoaderObject &status ); /// Save the full workpackage virtual void saveLoggedXML(QDomElement &element) const; /// Set schedule manager void setScheduleManager( ScheduleManager *sm ); /// Return schedule manager ScheduleManager *scheduleManager() const { return m_manager; } /// Return the schedule id, or NOTSCHEDULED if no schedule manager is set long id() const { return m_manager ? m_manager->scheduleId() : NOTSCHEDULED; } Completion &completion(); const Completion &completion() const; void addLogEntry( DateTime &dt, const QString &str ); QMap log() const; QStringList log(); /// Return a list of resources fetched from the appointments or requests /// merged with resources added to completion QList fetchResources(); /// Return a list of resources fetched from the appointments or requests /// merged with resources added to completion QList fetchResources( long id ); /// Returns id of the resource that owns this package. If empty, task leader owns it. QString ownerId() const { return m_ownerId; } /// Set the resource that owns this package to @p owner. If empty, task leader owns it. void setOwnerId( const QString &id ) { m_ownerId = id; } /// Returns the name of the resource that owns this package. QString ownerName() const { return m_ownerName; } /// Set the name of the resource that owns this package. void setOwnerName( const QString &name ) { m_ownerName = name; } DateTime transmitionTime() const { return m_transmitionTime; } void setTransmitionTime( const DateTime &dt ) { m_transmitionTime = dt; } /// Clear workpackage data void clear(); private: Task *m_task; ScheduleManager *m_manager; Completion m_completion; QString m_ownerName; QString m_ownerId; WPTransmitionStatus m_transmitionStatus; DateTime m_transmitionTime; QMap m_log; }; class PLANKERNEL_EXPORT WorkPackageSettings { public: WorkPackageSettings(); bool loadXML( const KoXmlElement &element ); void saveXML( QDomElement &element) const; bool operator==( WorkPackageSettings settings ) const; bool operator!=( WorkPackageSettings settings ) const; bool usedEffort; bool progress; bool documents; }; /** * A task in the scheduling software is represented by this class. A task * can be anything from 'build house' to 'drill hole' It will always mean * an activity. */ class PLANKERNEL_EXPORT Task : public Node { Q_OBJECT public: explicit Task(Node *parent = 0); explicit Task(const Task &task, Node *parent = 0); ~Task(); /// Return task type. Can be Type_Task, Type_Summarytask ot Type_Milestone. virtual int type() const; /** * Instead of using the expected duration, generate a random value using * the Distribution of each Task. This can be used for Monte-Carlo * estimation of Project duration. */ Duration *getRandomDuration(); /** * Return the resource request made to group * (There should be only one) */ ResourceGroupRequest *resourceGroupRequest(const ResourceGroup *group) const; void clearResourceRequests(); void addRequest(ResourceGroup *group, int numResources); void addRequest(ResourceGroupRequest *request); void takeRequest(ResourceGroupRequest *request); void makeAppointments(); virtual QStringList requestNameList() const; virtual QList requestedResources() const; virtual bool containsRequest( const QString &/*identity*/ ) const; virtual ResourceRequest *resourceRequest( const QString &/*name*/ ) const; /// Return the list of resources assigned to this task virtual QStringList assignedNameList( long id = CURRENTSCHEDULE ) const; /** * Calculates if the assigned resource is overbooked * within the duration of this task */ void calcResourceOverbooked(); /// Load from document virtual bool load(KoXmlElement &element, XMLLoaderObject &status ); /// Save to document virtual void save(QDomElement &element) const; /// Save appointments for schedule with id virtual void saveAppointments(QDomElement &element, long id) const; /// Save a workpackage document with schedule identity @p id void saveWorkPackageXML( QDomElement &element, long id ) const; /** * Returns a list of planned effort and cost for this task * for the interval start, end inclusive */ virtual EffortCostMap plannedEffortCostPrDay(QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /** * Returns a list of planned effort and cost for the @p resource * for the interval @p start, @p end inclusive, useng schedule with identity @p id */ virtual EffortCostMap plannedEffortCostPrDay(const Resource *resource, QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the total planned effort for @p resource on this task (or subtasks) virtual Duration plannedEffort( const Resource *resource, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the total planned effort for this task (or subtasks) virtual Duration plannedEffort( long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the total planned effort for this task (or subtasks) on date virtual Duration plannedEffort(QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the total planned effort for @p resource on this task (or subtasks) on date virtual Duration plannedEffort( const Resource *resource, QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the planned effort up to and including date virtual Duration plannedEffortTo(QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the planned effort for @p resource up to and including date virtual Duration plannedEffortTo( const Resource *resource, QDate date, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the total actual effort for this task (or subtasks) virtual Duration actualEffort() const; /// Returns the total actual effort for this task (or subtasks) on date virtual Duration actualEffort(QDate date ) const; /// Returns the actual effort up to and including date virtual Duration actualEffortTo(QDate date ) const; /** * Returns the total planned cost for this task (or subtasks) */ virtual EffortCost plannedCost( long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Planned cost up to and including date virtual double plannedCostTo(QDate /*date*/, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns actual effort and cost up to and including @p date virtual EffortCost actualCostTo( long int id, QDate date ) const; /** * Returns a list of actual effort and cost for this task * for the interval start, end inclusive */ virtual EffortCostMap actualEffortCostPrDay( QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the actual effort and cost pr day used by @p resource virtual EffortCostMap actualEffortCostPrDay( const Resource *resource, QDate start, QDate end, long id = CURRENTSCHEDULE, EffortCostCalculationType = ECCT_All ) const; /// Returns the effort planned to be used to reach the actual percent finished virtual Duration budgetedWorkPerformed( QDate date, long id = CURRENTSCHEDULE ) const; /// Returns the cost planned to be used to reach the actual percent finished virtual double budgetedCostPerformed( QDate date, long id = CURRENTSCHEDULE ) const; using Node::bcwsPrDay; /// Return map of Budgeted Cost of Work Scheduled pr day virtual EffortCostMap bcwsPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ); /// Budgeted Cost of Work Scheduled virtual double bcws( QDate date, long id = CURRENTSCHEDULE ) const; using Node::bcwpPrDay; /// Return map of Budgeted Cost of Work Performed pr day (also includes bcwsPrDay) virtual EffortCostMap bcwpPrDay( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ); /// Budgeted Cost of Work Performed virtual double bcwp( long id = CURRENTSCHEDULE ) const; /// Budgeted Cost of Work Performed ( up to @p date ) virtual double bcwp( QDate date, long id = CURRENTSCHEDULE ) const; using Node::acwp; /// Map of Actual Cost of Work Performed virtual EffortCostMap acwp( long id = CURRENTSCHEDULE, EffortCostCalculationType type = ECCT_All ); /// Actual Cost of Work Performed up to dat virtual EffortCost acwp( QDate date, long id = CURRENTSCHEDULE ) const; /// Effort based performance index virtual double effortPerformanceIndex( QDate date, long id = CURRENTSCHEDULE ) const; /// Schedule performance index virtual double schedulePerformanceIndex( QDate date, long id = CURRENTSCHEDULE ) const; /// Cost performance index virtual double costPerformanceIndex( long int id, QDate date, bool *error=0 ) const; /** * Return the duration that an activity's start can be delayed * without affecting the project completion date. * An activity with positive float is not on the critical path. * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule. */ Duration positiveFloat( long id = CURRENTSCHEDULE ) const; void setPositiveFloat( Duration fl, long id = CURRENTSCHEDULE ) const; /** * Return the duration by which the duration of an activity or path * has to be reduced in order to fulfil a timing- or dependency constraint. * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule. */ Duration negativeFloat( long id = CURRENTSCHEDULE ) const; void setNegativeFloat( Duration fl, long id = CURRENTSCHEDULE ) const; /** * Return the duration by which an activity can be delayed or extended * without affecting the start of any succeeding activity. * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule. */ Duration freeFloat( long id = CURRENTSCHEDULE ) const; void setFreeFloat( Duration fl, long id = CURRENTSCHEDULE ) const; /** * Return the duration from Early Start to Late Start. * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule. */ Duration startFloat( long id = CURRENTSCHEDULE ) const; /** * Return the duration from Early Finish to Late Finish. * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule. */ Duration finishFloat( long id = CURRENTSCHEDULE ) const; /** * A task is critical if positive float equals 0 * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule. */ virtual bool isCritical( long id = CURRENTSCHEDULE ) const; /** * Set current schedule to schedule with identity id, for me and my children. * @param id Schedule identity */ virtual void setCurrentSchedule(long id); /** * The assigned resources can not fulfil the estimated effort. * @param id Schedule identity. If id is CURRENTSCHEDULE, use current schedule. */ virtual bool effortMetError( long id = CURRENTSCHEDULE ) const; Completion &completion() { return m_workPackage.completion(); } const Completion &completion() const { return m_workPackage.completion(); } WorkPackage &workPackage() { return m_workPackage; } const WorkPackage &workPackage() const { return m_workPackage; } int workPackageLogCount() const { return m_packageLog.count(); } QList workPackageLog() const { return m_packageLog; } void addWorkPackage( WorkPackage *wp ); void removeWorkPackage( WorkPackage *wp ); WorkPackage *workPackageAt( int index ) const; QString wpOwnerName() const; WorkPackage::WPTransmitionStatus wpTransmitionStatus() const; DateTime wpTransmitionTime() const; /** * Returns the state of the task * @param id The identity of the schedule used when calculating the state */ virtual uint state( long id = CURRENTSCHEDULE ) const; /// Check if this node has any dependent child nodes virtual bool isEndNode() const; /// Check if this node has any dependent parent nodes virtual bool isStartNode() const; QList parentProxyRelations() const { return m_parentProxyRelations; } QList childProxyRelations() const { return m_childProxyRelations; } /** * Calculates and returns the duration of the node. * Uses the correct expected-, optimistic- or pessimistic effort * dependent on @p use. * @param time Where to start calculation. * @param use Calculate using expected-, optimistic- or pessimistic estimate. * @param backward If true, time specifies when the task should end. */ virtual Duration duration(const DateTime &time, int use, bool backward); /** * Return the duration calculated on bases of the estimates calendar */ Duration length(const DateTime &time, Duration duration, bool backward); Duration length(const DateTime &time, Duration uration, Schedule *sch, bool backward); /// Copy info from parent schedule void copySchedule(); /// Copy intervals from parent schedule void copyAppointments(); /// Copy intervals from parent schedule in the range @p start, @p end void copyAppointments( const DateTime &start, const DateTime &end = DateTime() ); Q_SIGNALS: - void workPackageToBeAdded( Node *node, int row ); - void workPackageAdded( Node *node ); - void workPackageToBeRemoved( Node *node, int row ); - void workPackageRemoved( Node *node ); + void workPackageToBeAdded(KPlato::Node *node, int row); + void workPackageAdded(KPlato::Node *node); + void workPackageToBeRemoved(KPlato::Node *node, int row); + void workPackageRemoved(KPlato::Node *node); public: virtual void initiateCalculation(MainSchedule &sch); /** * Sets up the lists used for calculation. * This includes adding summarytasks relations to subtasks * and lists for start- and endnodes. */ virtual void initiateCalculationLists(MainSchedule &sch); /** * Calculates early start and early finish, first for all predeccessors, * then for this task. * @param use Calculate using expected-, optimistic- or pessimistic estimate. */ virtual DateTime calculateForward(int use); /** * Calculates ref m_durationForward from ref earliestStart and * returns the resulting end time (early finish), * which will be used as the successors ref earliestStart. * * @param use Calculate using expected-, optimistic- or pessimistic estimate. */ virtual DateTime calculateEarlyFinish(int use); /** * Calculates late start and late finish, first for all successors, * then for this task. * @param use Calculate using expected-, optimistic- or pessimistic estimate. */ virtual DateTime calculateBackward(int use); /** * Calculates ref m_durationBackward from ref latestFinish and * returns the resulting start time (late start), * which will be used as the predecessors ref latestFinish. * * @param use Calculate using expected-, optimistic- or pessimistic estimate. */ virtual DateTime calculateLateStart(int use); /** * Schedules the task within the limits of earliestStart and latestFinish. * Calculates ref m_startTime, ref m_endTime and ref m_duration, * Assumes ref calculateForward() and ref calculateBackward() has been run. * * @param earliest The task is not scheduled to start earlier than this * @param use Calculate using expected-, optimistic- or pessimistic estimate. * @return The tasks endtime which can be used for scheduling the successor. */ virtual DateTime scheduleForward(const DateTime &earliest, int use); /** * Schedules the task within the limits of start time and latestFinish, * Calculates end time and duration. * Assumes ref calculateForward() and ref calculateBackward() has been run. * * @param use Calculate using expected-, optimistic- or pessimistic estimate. * @return The tasks endtime which can be used for scheduling the successor. */ virtual DateTime scheduleFromStartTime(int use); /** * Schedules the task within the limits of earliestStart and latestFinish. * Calculates ref m_startTime, ref m_endTime and ref m_duration, * Assumes ref calculateForward() and ref calculateBackward() has been run. * * @param latest The task is not scheduled to end later than this * @param use Calculate using expected-, optimistic- or pessimistic estimate. * @return The tasks starttime which can be used for scheduling the predeccessor. */ virtual DateTime scheduleBackward(const DateTime &latest, int use); /** * Schedules the task within the limits of end time and latestFinish. * Calculates endTime and duration. * Assumes ref calculateForward() and ref calculateBackward() has been run. * * @param latest The task is not scheduled to end later than this * @param use Calculate using expected-, optimistic- or pessimistic estimate. * @return The tasks starttime which can be used for scheduling the predeccessor. */ virtual DateTime scheduleFromEndTime(int use); /** * Summarytasks (with milestones) need special treatment because * milestones are always 'glued' to their predecessors. */ virtual void adjustSummarytask(); /// Calculate the critical path virtual bool calcCriticalPath(bool fromEnd); virtual void calcFreeFloat(); // Proxy relations are relations to/from summarytasks. // These relations are distributed to the child tasks before calculation. virtual void clearProxyRelations(); virtual void addParentProxyRelations( const QList & ); virtual void addChildProxyRelations( const QList & ); virtual void addParentProxyRelation(Node *, const Relation *); virtual void addChildProxyRelation(Node *, const Relation *); public: DateTime earlyStartDate(); void setEarlyStartDate(DateTime value); DateTime earlyFinishDate(); void setEarlyFinishDate(DateTime value); DateTime lateStartDate(); void setLateStartDate(DateTime value); DateTime lateFinishDate(); void setLateFinishDate(DateTime value); int activitySlack(); void setActivitySlack(int value); int activityFreeMargin(); void setActivityFreeMargin(int value); protected: /** * Return the duration calculated on bases of the requested resources */ Duration calcDuration(const DateTime &time, Duration effort, bool backward); private: DateTime calculateSuccessors(const QList &list, int use); DateTime calculatePredeccessors(const QList &list, int use); DateTime scheduleSuccessors(const QList &list, int use); DateTime schedulePredeccessors(const QList &list, int use); /// Fixed duration: Returns @p dt /// Duration with calendar: Returns first available after @p dt /// Has working resource(s) allocated: Returns the earliest time a resource can start work after @p dt, and checks appointments if @p sch is not null. DateTime workTimeAfter(const DateTime &dt, Schedule *sch = 0) const; /// Fixed duration: Returns @p dt /// Duration with calendar: Returns first available before @p dt /// Has working resource(s) allocated: Returns the latest time a resource can finish work, and checks appointments if @p sch is not null. DateTime workTimeBefore(const DateTime &dt, Schedule *sch = 0) const; private: QList m_resource; QList m_parentProxyRelations; QList m_childProxyRelations; // This list store pointers to linked task QList m_requiredTasks; WorkPackage m_workPackage; QList m_packageLog; bool m_calculateForwardRun; bool m_calculateBackwardRun; bool m_scheduleForwardRun; bool m_scheduleBackwardRun; }; } //KPlato namespace Q_DECLARE_METATYPE( KPlato::Completion::UsedEffort::ActualEffort ) #ifndef QT_NO_DEBUG_STREAM PLANKERNEL_EXPORT QDebug operator<<( QDebug dbg, const KPlato::Completion::UsedEffort::ActualEffort &ae ); #endif #endif diff --git a/src/libs/models/kptaccountsmodel.cpp b/src/libs/models/kptaccountsmodel.cpp index bd6fd9fd..8451c20c 100644 --- a/src/libs/models/kptaccountsmodel.cpp +++ b/src/libs/models/kptaccountsmodel.cpp @@ -1,1155 +1,1155 @@ /* This file is part of the KDE project Copyright (C) 2007, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptaccountsmodel.h" #include "kptglobal.h" #include "kptlocale.h" #include "kptcommonstrings.h" #include "kptcommand.h" #include "kptduration.h" #include "kptnode.h" #include "kptproject.h" #include "kpttask.h" #include "kptaccount.h" #include "kptdatetime.h" #include "kptschedule.h" #include "kptdebug.h" #include #include namespace KPlato { //-------------------------------------- AccountModel::AccountModel() : QObject(), m_project( 0 ) { } const QMetaEnum AccountModel::columnMap() const { return metaObject()->enumerator( metaObject()->indexOfEnumerator("Properties") ); } int AccountModel::propertyCount() const { return columnMap().keyCount(); } QVariant AccountModel::data( const Account *a, int property, int role ) const { QVariant result; if ( a == 0 ) { return QVariant(); } switch ( property ) { case AccountModel::Name: result = name( a, role ); break; case AccountModel::Description: result = description( a, role ); break; default: debugPlan<<"data: invalid display value column"<name()<<","<name(); case Qt::ToolTipRole: if ( a->isDefaultAccount() ) { return xi18nc( "1=account name", "%1 (Default account)", a->name() ); } return a->name(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Qt::CheckStateRole: if ( a->isDefaultAccount() ) { return m_project && m_project->isBaselined() ? Qt::PartiallyChecked : Qt::Checked; } return m_project && m_project->isBaselined() ? QVariant() : Qt::Unchecked; case Qt::DecorationRole: if ( a->isBaselined() ) { return koIcon("view-time-schedule-baselined"); } break; } return QVariant(); } QVariant AccountModel::description( const Account *a, int role ) const { //debugPlan<name()<<","<description(); break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant AccountModel::headerData( int property, int role ) const { if ( role == Qt::DisplayRole ) { switch ( property ) { case AccountModel::Name: return i18n( "Name" ); case AccountModel::Description: return i18n( "Description" ); default: return QVariant(); } } if ( role == Qt::TextAlignmentRole ) { return QVariant(); } if ( role == Qt::ToolTipRole ) { switch ( property ) { case AccountModel::Name: return ToolTip::accountName(); case AccountModel::Description: return ToolTip::accountDescription(); default: return QVariant(); } } return QVariant(); } //---------------------------------------- AccountItemModel::AccountItemModel( QObject *parent ) : ItemModelBase( parent ), m_account( 0 ) { } AccountItemModel::~AccountItemModel() { } const QMetaEnum AccountItemModel::columnMap() const { return m_model.columnMap(); } void AccountItemModel::slotAccountToBeInserted( const Account *parent, int row ) { //debugPlan<name(); Q_ASSERT( m_account == 0 ); m_account = const_cast(parent); beginInsertRows( index( parent ), row, row ); } void AccountItemModel::slotAccountInserted( const Account *account ) { //debugPlan<name(); Q_ASSERT( account->parent() == m_account ); Q_UNUSED( account ); endInsertRows(); m_account = 0; } void AccountItemModel::slotAccountToBeRemoved( const Account *account ) { //debugPlan<name(); Q_ASSERT( m_account == 0 ); m_account = const_cast(account); int row = index( account ).row(); beginRemoveRows( index( account->parent() ), row, row ); } void AccountItemModel::slotAccountRemoved( const Account *account ) { //debugPlan<name(); Q_ASSERT( account == m_account ); Q_UNUSED( account ); endRemoveRows(); m_account = 0; } void AccountItemModel::setProject( Project *project ) { if ( m_project ) { Accounts *acc = &( m_project->accounts() ); - disconnect( acc , SIGNAL(changed(Account*)), this, SLOT(slotAccountChanged(Account*)) ); + disconnect( acc , SIGNAL(changed(KPlato::Account*)), this, SLOT(slotAccountChanged(KPlato::Account*)) ); - disconnect( acc, SIGNAL(accountAdded(const Account*)), this, SLOT(slotAccountInserted(const Account*)) ); - disconnect( acc, SIGNAL(accountToBeAdded(const Account*,int)), this, SLOT(slotAccountToBeInserted(const Account*,int)) ); + disconnect( acc, SIGNAL(accountAdded(const KPlato::Account*)), this, SLOT(slotAccountInserted(const KPlato::Account*)) ); + disconnect( acc, SIGNAL(accountToBeAdded(const KPlato::Account*,int)), this, SLOT(slotAccountToBeInserted(const KPlato::Account*,int)) ); - disconnect( acc, SIGNAL(accountRemoved(const Account*)), this, SLOT(slotAccountRemoved(const Account*)) ); - disconnect( acc, SIGNAL(accountToBeRemoved(const Account*)), this, SLOT(slotAccountToBeRemoved(const Account*)) ); + disconnect( acc, SIGNAL(accountRemoved(const KPlato::Account*)), this, SLOT(slotAccountRemoved(const KPlato::Account*)) ); + disconnect( acc, SIGNAL(accountToBeRemoved(const KPlato::Account*)), this, SLOT(slotAccountToBeRemoved(const KPlato::Account*)) ); } m_project = project; m_model.m_project = project; if ( project ) { Accounts *acc = &( project->accounts() ); debugPlan<isBaselined() ) { flags |= Qt::ItemIsEditable; flags |= Qt::ItemIsUserCheckable; } break; } default: flags |= Qt::ItemIsEditable; break; } } return flags; } QModelIndex AccountItemModel::parent( const QModelIndex &index ) const { if ( !index.isValid() || m_project == 0 ) { return QModelIndex(); } //debugPlan<parent(); if ( par ) { a = par->parent(); int row = -1; if ( a ) { row = a->accountList().indexOf( par ); } else { row = m_project->accounts().accountList().indexOf( par ); } //debugPlan<name()<<":"<= columnCount() || row < 0 ) { return QModelIndex(); } Account *par = account( parent ); if ( par == 0 ) { if ( row < m_project->accounts().accountList().count() ) { return createIndex( row, column, m_project->accounts().accountList().at( row ) ); } } else if ( row < par->accountList().count() ) { return createIndex( row, column, par->accountList().at( row ) ); } return QModelIndex(); } QModelIndex AccountItemModel::index( const Account *account, int column ) const { Account *a = const_cast(account); if ( m_project == 0 || account == 0 ) { return QModelIndex(); } int row = -1; Account *par = a->parent(); if ( par == 0 ) { row = m_project->accounts().accountList().indexOf( a ); } else { row = par->accountList().indexOf( a ); } if ( row == -1 ) { return QModelIndex(); } return createIndex( row, column, a ); } int AccountItemModel::columnCount( const QModelIndex & ) const { return m_model.propertyCount(); } int AccountItemModel::rowCount( const QModelIndex &parent ) const { if ( m_project == 0 ) { return 0; } Account *par = account( parent ); if ( par == 0 ) { return m_project->accounts().accountList().count(); } return par->accountList().count(); } bool AccountItemModel::setName( Account *a, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toString() != a->name() ) { emit executeCommand( new RenameAccountCmd( a, value.toString(), kundo2_i18n( "Modify account name" ) ) ); } return true; case Qt::CheckStateRole: { switch ( value.toInt() ) { case Qt::Unchecked: if ( a->isDefaultAccount() ) { emit executeCommand( new ModifyDefaultAccountCmd( m_project->accounts(), a, 0, kundo2_i18n( "De-select as default account" ) ) ); return true; } break; case Qt::Checked: if ( ! a->isDefaultAccount() ) { emit executeCommand( new ModifyDefaultAccountCmd( m_project->accounts(), m_project->accounts().defaultAccount(), a, kundo2_i18n( "Select as default account" ) ) ); return true; } break; default: break; } } default: break; } return false; } bool AccountItemModel::setDescription( Account *a, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toString() != a->description() ) { emit executeCommand( new ModifyAccountDescriptionCmd( a, value.toString(), kundo2_i18n( "Modify account description" ) ) ); } return true; } return false; } QVariant AccountItemModel::data( const QModelIndex &index, int role ) const { QVariant result; Account *a = account( index ); if ( a == 0 ) { return QVariant(); } result = m_model.data( a, index.column(), role ); return result; } bool AccountItemModel::setData( const QModelIndex &index, const QVariant &value, int role ) { if ( ! index.isValid() ) { return ItemModelBase::setData( index, value, role ); } if ( ( flags( index ) &( Qt::ItemIsEditable | Qt::CheckStateRole ) ) == 0 ) { Q_ASSERT( true ); return false; } Account *a = account( index ); debugPlan<name()<( index.internalPointer() ); } void AccountItemModel::slotAccountChanged( Account *account ) { Account *par = account->parent(); if ( par ) { int row = par->accountList().indexOf( account ); emit dataChanged( createIndex( row, 0, account ), createIndex( row, columnCount() - 1, account ) ); } else { int row = m_project->accounts().accountList().indexOf( account ); emit dataChanged( createIndex( row, 0, account ), createIndex( row, columnCount() - 1, account ) ); } } QModelIndex AccountItemModel::insertAccount( Account *account, Account *parent, int index ) { debugPlan; if ( account->name().isEmpty() || m_project->accounts().findAccount( account->name() ) ) { QString s = parent == 0 ? account->name() : parent->name(); account->setName( m_project->accounts().uniqueId( s ) ); //m_project->accounts().insertId( account ); } emit executeCommand( new AddAccountCmd( *m_project, account, parent, index, kundo2_i18n( "Add account" ) ) ); int row = -1; if ( parent ) { row = parent->accountList().indexOf( account ); } else { row = m_project->accounts().accountList().indexOf( account ); } if ( row != -1 ) { //debugPlan<<"Inserted:"<name(); return createIndex( row, 0, account ); } debugPlan<<"Can't find"<name(); return QModelIndex(); } void AccountItemModel::removeAccounts( QList lst ) { MacroCommand *cmd = 0; KUndo2MagicString c = kundo2_i18np( "Delete Account", "Delete %1 Accounts", lst.count() ); while ( ! lst.isEmpty() ) { bool del = true; Account *acc = lst.takeFirst(); foreach ( Account *a, lst ) { if ( acc->isChildOf( a ) ) { del = false; // acc will be deleted when a is deleted break; } } if ( del ) { if ( cmd == 0 ) cmd = new MacroCommand( c ); cmd->addCommand( new RemoveAccountCmd( *m_project, acc ) ); } } if ( cmd ) emit executeCommand( cmd ); } //---------------------------------------- CostBreakdownItemModel::CostBreakdownItemModel( QObject *parent ) : ItemModelBase( parent ), m_manager( 0 ), m_cumulative( false ), m_periodtype( Period_Day ), m_startmode( StartMode_Project ), m_endmode( EndMode_Project ), m_showmode( ShowMode_Both ) { m_format = QString( "%1 [%2]" ); } CostBreakdownItemModel::~CostBreakdownItemModel() { } const QMetaEnum CostBreakdownItemModel::columnMap() const { return metaObject()->enumerator( metaObject()->indexOfEnumerator("Properties") ); } int CostBreakdownItemModel::propertyCount() const { return columnMap().keyCount(); } void CostBreakdownItemModel::slotAccountToBeInserted( const Account *parent, int row ) { //debugPlan<name(); beginInsertRows( index( parent ), row, row ); } void CostBreakdownItemModel::slotAccountInserted( const Account *account ) { Q_UNUSED(account); //debugPlan<name(); endInsertRows(); } void CostBreakdownItemModel::slotAccountToBeRemoved( const Account *account ) { //debugPlan<name(); int row = index( account ).row(); beginRemoveRows( index( account->parent() ), row, row ); } void CostBreakdownItemModel::slotAccountRemoved( const Account *account ) { Q_UNUSED(account); //debugPlan<name(); endRemoveRows(); } void CostBreakdownItemModel::slotDataChanged() { fetchData(); foreach ( Account *a, m_plannedCostMap.keys() ) { QModelIndex idx1 = index( a ); QModelIndex idx2 = index( idx1.row(), columnCount() - 1, parent( idx1 ) ); //debugPlan<name()<accounts() ); - disconnect( acc , SIGNAL(changed(Account*)), this, SLOT(slotAccountChanged(Account*)) ); + disconnect( acc , SIGNAL(changed(KPlato::Account*)), this, SLOT(slotAccountChanged(KPlato::Account*)) ); - disconnect( acc, SIGNAL(accountAdded(const Account*)), this, SLOT(slotAccountInserted(const Account*)) ); - disconnect( acc, SIGNAL(accountToBeAdded(const Account*,int)), this, SLOT(slotAccountToBeInserted(const Account*,int)) ); + disconnect( acc, SIGNAL(accountAdded(const KPlato::Account*)), this, SLOT(slotAccountInserted(const KPlato::Account*)) ); + disconnect( acc, SIGNAL(accountToBeAdded(const KPlato::Account*,int)), this, SLOT(slotAccountToBeInserted(const KPlato::Account*,int)) ); - disconnect( acc, SIGNAL(accountRemoved(const Account*)), this, SLOT(slotAccountRemoved(const Account*)) ); - disconnect( acc, SIGNAL(accountToBeRemoved(const Account*)), this, SLOT(slotAccountToBeRemoved(const Account*)) ); + disconnect( acc, SIGNAL(accountRemoved(const KPlato::Account*)), this, SLOT(slotAccountRemoved(const KPlato::Account*)) ); + disconnect( acc, SIGNAL(accountToBeRemoved(const KPlato::Account*)), this, SLOT(slotAccountToBeRemoved(const KPlato::Account*)) ); disconnect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - disconnect( m_project , SIGNAL(nodeChanged(Node*)), this, SLOT(slotDataChanged()) ); - disconnect( m_project , SIGNAL(nodeAdded(Node*)), this, SLOT(slotDataChanged()) ); - disconnect( m_project , SIGNAL(nodeRemoved(Node*)), this, SLOT(slotDataChanged()) ); + disconnect( m_project , SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotDataChanged()) ); + disconnect( m_project , SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotDataChanged()) ); + disconnect( m_project , SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotDataChanged()) ); - disconnect( m_project , SIGNAL(resourceChanged(Resource*)), this, SLOT(slotDataChanged()) ); - disconnect( m_project , SIGNAL(resourceAdded(const Resource*)), this, SLOT(slotDataChanged()) ); - disconnect( m_project , SIGNAL(resourceRemoved(const Resource*)), this, SLOT(slotDataChanged()) ); + disconnect( m_project , SIGNAL(resourceChanged(KPlato::Resource*)), this, SLOT(slotDataChanged()) ); + disconnect( m_project , SIGNAL(resourceAdded(const KPlato::Resource*)), this, SLOT(slotDataChanged()) ); + disconnect( m_project , SIGNAL(resourceRemoved(const KPlato::Resource*)), this, SLOT(slotDataChanged()) ); } m_project = project; if ( project ) { Accounts *acc = &( project->accounts() ); debugPlan<scheduleId(); } EffortCostMap CostBreakdownItemModel::fetchPlannedCost( Account *account ) { EffortCostMap ec; ec = account->plannedCost( id() ); m_plannedCostMap.insert( account, ec ); QDate s = ec.startDate(); if ( ! m_plannedStart.isValid() || s < m_plannedStart ) { m_plannedStart = s; } QDate e = ec.endDate(); if ( ! m_plannedEnd.isValid() || e > m_plannedEnd ) { m_plannedEnd = e; } return ec; } EffortCostMap CostBreakdownItemModel::fetchActualCost( Account *account ) { debugPlan<name(); EffortCostMap ec; ec = account->actualCost( id() ); m_actualCostMap.insert( account, ec ); QDate s = ec.startDate(); if ( ! m_actualStart.isValid() || s < m_actualStart ) { m_actualStart = s; } QDate e = ec.endDate(); if ( ! m_actualEnd.isValid() || e > m_actualEnd ) { m_actualEnd = e; } debugPlan<name()<accounts().allAccounts() ) { fetchPlannedCost( a ); fetchActualCost( a ); } } QModelIndex CostBreakdownItemModel::parent( const QModelIndex &index ) const { if ( !index.isValid() || m_project == 0 ) { return QModelIndex(); } //debugPlan<parent(); if ( par ) { a = par->parent(); int row = -1; if ( a ) { row = a->accountList().indexOf( par ); } else { row = m_project->accounts().accountList().indexOf( par ); } //debugPlan<name()<<":"<= columnCount() || row < 0 ) { return QModelIndex(); } Account *par = account( parent ); if ( par == 0 ) { if ( row < m_project->accounts().accountList().count() ) { return createIndex( row, column, m_project->accounts().accountList().at( row ) ); } } else if ( row < par->accountList().count() ) { return createIndex( row, column, par->accountList().at( row ) ); } return QModelIndex(); } QModelIndex CostBreakdownItemModel::index( const Account *account ) const { Account *a = const_cast(account); if ( m_project == 0 || account == 0 ) { return QModelIndex(); } int row = -1; Account *par = a->parent(); if ( par == 0 ) { row = m_project->accounts().accountList().indexOf( a ); } else { row = par->accountList().indexOf( a ); } if ( row == -1 ) { return QModelIndex(); } return createIndex( row, 0, a ); } int CostBreakdownItemModel::columnCount( const QModelIndex & ) const { int c = propertyCount(); if ( startDate().isValid() && endDate().isValid() ) { switch ( m_periodtype ) { case Period_Day: { c += startDate().daysTo( endDate()) + 1; break; } case Period_Week: { int days = QLocale().firstDayOfWeek() - startDate().dayOfWeek(); if ( days > 0 ) { days -= 7; } QDate start = startDate().addDays( days ); c += (start.daysTo( endDate() ) / 7) + 1; break; } case Period_Month: { int days = startDate().daysInMonth() - startDate().day() + 1; for ( QDate d = startDate(); d < endDate(); d = d.addDays( days ) ) { ++c; days = qMin( d.daysTo( endDate() ), static_cast(d.daysInMonth()) ); } break; } } } return c; } int CostBreakdownItemModel::rowCount( const QModelIndex &parent ) const { if ( m_project == 0 ) { return 0; } Account *par = account( parent ); if ( par == 0 ) { return m_project->accounts().accountList().count(); } return par->accountList().count(); } QString CostBreakdownItemModel::formatMoney( double cost1, double cost2 ) const { if ( m_showmode == ShowMode_Planned ) { return m_project->locale()->formatMoney( cost1, "", 0 ); } if ( m_showmode == ShowMode_Actual ) { return m_project->locale()->formatMoney( cost2, "", 0 ); } if ( m_showmode == ShowMode_Both ) { return QString(m_format).arg( m_project->locale()->formatMoney( cost2, "", 0 ) ).arg( m_project->locale()->formatMoney( cost1, "", 0 ) ); } if ( m_showmode == ShowMode_Deviation ) { return m_project->locale()->formatMoney( cost1 - cost2, "", 0 ); } return ""; } QVariant CostBreakdownItemModel::data( const QModelIndex &index, int role ) const { QVariant result; Account *a = account( index ); if ( a == 0 ) { return QVariant(); } if ( role == Qt::DisplayRole ) { switch ( index.column() ) { case Name: return a->name(); case Description: return a->description(); case Total: { return formatMoney( m_plannedCostMap.value( a ).totalCost(), m_actualCostMap.value( a ).totalCost() ); } case Planned: return m_project->locale()->formatMoney( m_plannedCostMap.value( a ).totalCost(), "", 0 ); case Actual: return m_project->locale()->formatMoney( m_actualCostMap.value( a ).totalCost(), "", 0 ); default: { int col = index.column() - propertyCount(); EffortCostMap pc = m_plannedCostMap.value( a ); EffortCostMap ac = m_actualCostMap.value( a ); switch ( m_periodtype ) { case Period_Day: { double planned = 0.0; if ( m_cumulative ) { planned = pc.costTo( startDate().addDays( col ) ); } else { planned = pc.costOnDate( startDate().addDays( col ) ); } double actual = 0.0; if ( m_cumulative ) { actual = ac.costTo( startDate().addDays( col ) ); } else { actual = ac.costOnDate( startDate().addDays( col ) ); } return formatMoney( planned, actual ); } case Period_Week: { int days = QLocale().firstDayOfWeek() - startDate().dayOfWeek(); if ( days > 0 ) { days -= 7; ; } QDate start = startDate().addDays( days ); int week = col; double planned = 0.0; if ( m_cumulative ) { planned = pc.costTo( start.addDays( ++week * 7 ) ); } else { planned = week == 0 ? pc.cost( startDate(), startDate().daysTo( start.addDays( 7 ) ) ) : pc.cost( start.addDays( week * 7 ) ); } double actual = 0.0; if ( m_cumulative ) { actual = ac.costTo( start.addDays( ++week * 7 ) ); } else { actual = week == 0 ? ac.cost( startDate(), startDate().daysTo( start.addDays( 7 ) ) ) : ac.cost( start.addDays( week * 7 ) ); } return formatMoney( planned, actual ); } case Period_Month: { int days = startDate().daysInMonth() - startDate().day() + 1; QDate start = startDate(); for ( int i = 0; i < col; ++i ) { start = start.addDays( days ); days = start.daysInMonth(); } int planned = 0.0; if ( m_cumulative ) { planned = pc.costTo( start.addDays( start.daysInMonth() - start.day() + 1 ) ); } else { planned = pc.cost( start, start.daysInMonth() - start.day() + 1); } int actual = 0.0; if ( m_cumulative ) { actual = ac.costTo( start.addDays( start.daysInMonth() - start.day() + 1 ) ); } else { actual = ac.cost( start, start.daysInMonth() - start.day() + 1); } return formatMoney( planned, actual ); } default: return 0.0; break; } } } } else if ( role == Qt::ToolTipRole ) { switch ( index.column() ) { case Name: return a->name(); case Description: return a->description(); case Total: { double act = m_actualCostMap.value( a ).totalCost(); double pl = m_plannedCostMap.value( a ).totalCost(); return i18n( "Actual total cost: %1, planned total cost: %2", m_project->locale()->formatMoney( act, "", 0 ), m_project->locale()->formatMoney( pl, "", 0 ) ); } case Planned: case Actual: default: break; } } else if ( role == Qt::TextAlignmentRole ) { return headerData( index.column(), Qt::Horizontal, role ); } else { switch ( index.column() ) { case Name: case Description: case Planned: case Actual: return QVariant(); default: { return cost( a, index.column() - propertyCount(), role ); } } } return QVariant(); } QVariant CostBreakdownItemModel::cost( const Account *a, int offset, int role ) const { EffortCostMap costmap; if ( role == Role::Planned ) { costmap = m_plannedCostMap.value( const_cast( a ) ); } else if ( role == Role::Actual ) { costmap = m_actualCostMap.value( const_cast( a ) ); } else { return QVariant(); } double cost = 0.0; switch ( m_periodtype ) { case Period_Day: { if ( m_cumulative ) { cost = costmap.costTo( startDate().addDays( offset ) ); } else { cost = costmap.costOnDate( startDate().addDays( offset ) ); } break; } case Period_Week: { int days = QLocale().firstDayOfWeek() - startDate().dayOfWeek(); if ( days > 0 ) { days -= 7; ; } QDate start = startDate().addDays( days ); int week = offset; if ( m_cumulative ) { cost = costmap.costTo( start.addDays( ++week * 7 ) ); } else { cost = week == 0 ? costmap.cost( startDate(), startDate().daysTo( start.addDays( 7 ) ) ) : costmap.cost( start.addDays( week * 7 ) ); } break; } case Period_Month: { int days = startDate().daysInMonth() - startDate().day() + 1; QDate start = startDate(); for ( int i = 0; i < offset; ++i ) { start = start.addDays( days ); days = start.daysInMonth(); } if ( m_cumulative ) { cost = costmap.costTo( start.addDays( start.daysInMonth() - start.day() + 1 ) ); } else { cost = costmap.cost( start, start.daysInMonth() - start.day() + 1); } break; } default: break; } return cost; } int CostBreakdownItemModel::periodType() const { return m_periodtype; } void CostBreakdownItemModel::setPeriodType( int period ) { if ( m_periodtype != period ) { beginResetModel(); m_periodtype = period; endResetModel(); } } int CostBreakdownItemModel::startMode() const { return m_startmode; } void CostBreakdownItemModel::setStartMode( int mode ) { beginResetModel(); m_startmode = mode; endResetModel(); } int CostBreakdownItemModel::endMode() const { return m_endmode; } void CostBreakdownItemModel::setEndMode( int mode ) { beginResetModel(); m_endmode = mode; endResetModel(); } QDate CostBreakdownItemModel::startDate() const { if ( m_project == 0 || m_manager == 0 ) { return m_start; } switch ( m_startmode ) { case StartMode_Project: { QDate d = m_project->startTime( id() ).date(); if ( m_plannedStart.isValid() && m_plannedStart < d ) { d = m_plannedStart; } if ( m_actualStart.isValid() && m_actualStart < d ) { d = m_actualStart; } return d; } default: break; } return m_start; } void CostBreakdownItemModel::setStartDate( const QDate &date ) { beginResetModel(); m_start = date; endResetModel(); } QDate CostBreakdownItemModel::endDate() const { if ( m_project == 0 || m_manager == 0 ) { return m_end; } switch ( m_endmode ) { case EndMode_Project: { QDate d = m_project->endTime( id() ).date(); if ( m_plannedEnd.isValid() && m_plannedEnd > d ) { d = m_plannedEnd; } if ( m_actualEnd.isValid() && m_actualEnd > d ) { d = m_actualEnd; } return d; } case EndMode_CurrentDate: return QDate::currentDate(); default: break; } return m_end; } void CostBreakdownItemModel::setEndDate( const QDate &date ) { beginResetModel(); m_end = date; endResetModel(); } bool CostBreakdownItemModel::cumulative() const { return m_cumulative; } void CostBreakdownItemModel::setCumulative( bool on ) { beginResetModel(); m_cumulative = on; endResetModel(); } int CostBreakdownItemModel::showMode() const { return m_showmode; } void CostBreakdownItemModel::setShowMode( int show ) { m_showmode = show; } QVariant CostBreakdownItemModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( orientation == Qt::Horizontal ) { if ( role == Qt::DisplayRole ) { switch (section) { case Name: return i18n( "Name" ); case Description: return i18n( "Description" ); case Total: return i18n( "Total" ); case Planned: return i18n("Planned"); case Actual: return i18n("Actual"); default: break; } int col = section - propertyCount(); switch ( m_periodtype ) { case Period_Day: { return startDate().addDays( col ).toString( Qt::ISODate ); } case Period_Week: { return startDate().addDays( ( col ) * 7 ).weekNumber(); } case Period_Month: { int days = startDate().daysInMonth() - startDate().day() + 1; QDate start = startDate(); for ( int i = 0; i < col; ++i ) { start = start.addDays( days ); days = start.daysInMonth(); } return QDate::shortMonthName( start.month() ); } default: return section; break; } return QVariant(); } if ( role == Qt::EditRole ) { switch (section) { case Name: return QStringLiteral( "Name" ); case Description: return QStringLiteral( "Description" ); case Total: return QStringLiteral( "Total" ); case Planned: return QStringLiteral("Planned"); case Actual: return QStringLiteral("Actual"); default: break; } int col = section - propertyCount(); switch ( m_periodtype ) { case Period_Day: { return startDate().addDays( col ); } case Period_Week: { return startDate().addDays( ( col ) * 7 ).weekNumber(); } case Period_Month: { int days = startDate().daysInMonth() - startDate().day() + 1; QDate start = startDate(); for ( int i = 0; i < col; ++i ) { start = start.addDays( days ); days = start.daysInMonth(); } return start.month(); } default: return section; break; } return QVariant(); } if ( role == Qt::ToolTipRole ) { switch ( section ) { case Name: return ToolTip::accountName(); case Description: return ToolTip::accountDescription(); case Total: return i18n( "The total cost for the account shown as: Actual cost [ Planned cost ]" ); case Planned: case Actual: default: return QVariant(); } } if ( role == Qt::TextAlignmentRole ) { switch ( section ) { case Name: return QVariant(); case Description: return QVariant(); default: return (int)(Qt::AlignRight|Qt::AlignVCenter); } return QVariant(); } } return ItemModelBase::headerData(section, orientation, role); } Account *CostBreakdownItemModel::account( const QModelIndex &index ) const { return static_cast( index.internalPointer() ); } void CostBreakdownItemModel::slotAccountChanged( Account *account ) { Q_UNUSED(account); fetchData(); foreach ( Account *a, m_plannedCostMap.keys() ) { QModelIndex idx1 = index( a ); QModelIndex idx2 = index( idx1.row(), columnCount() - 1, parent( idx1 ) ); //debugPlan<name()< Copyright (C) 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTACCOUNTSMODEL_H #define KPTACCOUNTSMODEL_H #include "planmodels_export.h" #include #include "kpteffortcostmap.h" namespace KPlato { class Project; class Account; class ScheduleManager; class AccountItemModel; class PLANMODELS_EXPORT AccountModel : public QObject { Q_OBJECT Q_ENUMS( Properties ) public: AccountModel(); ~AccountModel() {} enum Properties { Name = 0, Description }; const QMetaEnum columnMap() const; int propertyCount() const; virtual QVariant data( const Account *a, int property, int role = Qt::DisplayRole ) const; virtual QVariant headerData( int property, int role = Qt::DisplayRole ) const; protected: QVariant name( const Account *account, int role ) const; QVariant description( const Account *account, int role ) const; private: friend class AccountItemModel; Project *m_project; }; class PLANMODELS_EXPORT AccountItemModel : public ItemModelBase { Q_OBJECT public: explicit AccountItemModel( QObject *parent = 0 ); ~AccountItemModel(); const QMetaEnum columnMap() const; virtual void setProject( Project *project ); virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; QModelIndex index( const Account* account, int column = 0 ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; Account *account( const QModelIndex &index ) const; QModelIndex insertAccount( Account *account, Account *parent = 0, int index = -1 ); void removeAccounts( QList lst ); protected Q_SLOTS: - void slotAccountChanged( Account* ); - void slotAccountToBeInserted( const Account *parent, int row ); - void slotAccountInserted( const Account *account ); - void slotAccountToBeRemoved( const Account *account ); - void slotAccountRemoved( const Account *account ); + void slotAccountChanged(KPlato::Account*); + void slotAccountToBeInserted(const KPlato::Account *parent, int row); + void slotAccountInserted(const KPlato::Account *account); + void slotAccountToBeRemoved(const KPlato::Account *account); + void slotAccountRemoved(const KPlato::Account *account); protected: bool setName( Account *account, const QVariant &value, int role ); bool setDescription( Account *account, const QVariant &value, int role ); private: AccountModel m_model; Account *m_account; // test for sane operation }; //--------------- class PLANMODELS_EXPORT CostBreakdownItemModel : public ItemModelBase { Q_OBJECT Q_ENUMS( Properties ) public: enum PeriodType { Period_Day = 0, Period_Week = 1, Period_Month = 2 }; enum StartMode { StartMode_Project = 0, StartMode_Date = 1 }; enum EndMode { EndMode_Project = 0, EndMode_Date = 1, EndMode_CurrentDate = 2 }; enum ShowMode { ShowMode_Actual = 0, ShowMode_Planned = 1, ShowMode_Both = 2, ShowMode_Deviation = 3 }; explicit CostBreakdownItemModel( QObject *parent = 0 ); ~CostBreakdownItemModel(); enum Properties { Name = 0, Description, Total, Planned, Actual }; const QMetaEnum columnMap() const; int propertyCount() const; virtual void setProject( Project *project ); virtual void setScheduleManager( ScheduleManager *sm ); long id() const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; QModelIndex index( const Account* account ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; Account *account( const QModelIndex &index ) const; bool cumulative() const; void setCumulative( bool on ); int periodType() const; void setPeriodType( int period ); int startMode() const; void setStartMode( int mode ); int endMode() const; void setEndMode( int mode ); QDate startDate() const; void setStartDate( const QDate &date ); QDate endDate() const; void setEndDate( const QDate &date ); int showMode() const; void setShowMode( int show ); QString formatMoney( double plannedCost, double actualCost ) const; QString format() const { return m_format; } void setFormat( const QString &f ) { m_format = f; } protected: void fetchData(); EffortCostMap fetchPlannedCost( Account *account ); EffortCostMap fetchActualCost( Account *account ); QVariant cost( const Account *a, int offset, int role ) const; protected Q_SLOTS: - void slotAccountChanged( Account* ); - void slotAccountToBeInserted( const Account *parent, int row ); - void slotAccountInserted( const Account *account ); - void slotAccountToBeRemoved( const Account *account ); - void slotAccountRemoved( const Account *account ); + void slotAccountChanged(KPlato::Account*); + void slotAccountToBeInserted(const KPlato::Account *parent, int row); + void slotAccountInserted(const KPlato::Account *account); + void slotAccountToBeRemoved(const KPlato::Account *account); + void slotAccountRemoved(const KPlato::Account *account); void slotDataChanged(); private: ScheduleManager *m_manager; bool m_cumulative; int m_periodtype; int m_startmode; int m_endmode; QDate m_start; QDate m_end; int m_showmode; QMap m_plannedCostMap; QDate m_plannedStart, m_plannedEnd; QMap m_actualCostMap; QDate m_actualStart, m_actualEnd; QString m_format; }; } //KPlato namespace #endif diff --git a/src/libs/models/kptcalendarmodel.cpp b/src/libs/models/kptcalendarmodel.cpp index 7f5600cb..541a7084 100644 --- a/src/libs/models/kptcalendarmodel.cpp +++ b/src/libs/models/kptcalendarmodel.cpp @@ -1,1477 +1,1477 @@ /* This file is part of the KDE project * Copyright (C) 2007, 2012 Dag Andersen * Copyright (C) 2017 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. */ #include "kptcalendarmodel.h" #include "kptglobal.h" #include "kptcommonstrings.h" #include "kptcommand.h" #include "kptitemmodelbase.h" #include "kptcalendar.h" #include "kptduration.h" #include "kptnode.h" #include "kptproject.h" #include "kpttask.h" #include "kptdatetime.h" #include "kcalendar/kdatetable.h" #include "kptdebug.h" #include #include #include #include #include #ifdef HAVE_KHOLIDAYS #include #endif namespace KPlato { //----------------------------------------- CalendarDayItemModelBase::CalendarDayItemModelBase( QObject *parent ) : ItemModelBase( parent ), m_calendar( 0 ) { } CalendarDayItemModelBase::~CalendarDayItemModelBase() { } void CalendarDayItemModelBase::slotCalendarToBeRemoved( const Calendar *calendar ) { if ( calendar && calendar == m_calendar ) { setCalendar( 0 ); } } void CalendarDayItemModelBase::setCalendar( Calendar *calendar ) { m_calendar = calendar; } void CalendarDayItemModelBase::setProject( Project *project ) { beginResetModel(); setCalendar( 0 ); if ( m_project ) { disconnect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - disconnect( m_project, SIGNAL(calendarToBeRemoved(const Calendar*)), this, SLOT(slotCalendarToBeRemoved(const Calendar*)) ); + disconnect( m_project, SIGNAL(calendarToBeRemoved(const KPlato::Calendar*)), this, SLOT(slotCalendarToBeRemoved(const KPlato::Calendar*))); } m_project = project; if ( project ) { connect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - connect( m_project, SIGNAL(calendarToBeRemoved(const Calendar*)), this, SLOT(slotCalendarToBeRemoved(const Calendar*)) ); + connect( m_project, SIGNAL(calendarToBeRemoved(const KPlato::Calendar*)), this, SLOT(slotCalendarToBeRemoved(const KPlato::Calendar*))); } endResetModel(); } //------------------------------------- CalendarItemModel::CalendarItemModel( QObject *parent ) : ItemModelBase( parent ), m_calendar( 0 ) { } CalendarItemModel::~CalendarItemModel() { } const QMetaEnum CalendarItemModel::columnMap() const { return metaObject()->enumerator( metaObject()->indexOfEnumerator("Properties") ); } void CalendarItemModel::slotCalendarToBeInserted( const Calendar *parent, int row ) { //debugPlan<<(parent?parent->name():"Top level")<<","<(parent); beginInsertRows( index( parent ), row, row ); } void CalendarItemModel::slotCalendarInserted( const Calendar *calendar ) { //debugPlan<name(); Q_ASSERT( calendar->parentCal() == m_calendar ); #ifdef NDEBUG Q_UNUSED(calendar) #endif endInsertRows(); m_calendar = 0; } void CalendarItemModel::slotCalendarToBeRemoved( const Calendar *calendar ) { //debugPlan<name(); int row = index( calendar ).row(); beginRemoveRows( index( calendar->parentCal() ), row, row ); } void CalendarItemModel::slotCalendarRemoved( const Calendar * ) { //debugPlan<name(); endRemoveRows(); } void CalendarItemModel::setProject( Project *project ) { beginResetModel(); if ( m_project ) { disconnect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - disconnect( m_project , SIGNAL(calendarChanged(Calendar*)), this, SLOT(slotCalendarChanged(Calendar*)) ); + disconnect( m_project , SIGNAL(calendarChanged(KPlato::Calendar*)), this, SLOT(slotCalendarChanged(KPlato::Calendar*))); - disconnect( m_project, SIGNAL(calendarAdded(const Calendar*)), this, SLOT(slotCalendarInserted(const Calendar*)) ); - disconnect( m_project, SIGNAL(calendarToBeAdded(const Calendar*,int)), this, SLOT(slotCalendarToBeInserted(const Calendar*,int)) ); + disconnect( m_project, SIGNAL(calendarAdded(const KPlato::Calendar*)), this, SLOT(slotCalendarInserted(const KPlato::Calendar*))); + disconnect( m_project, SIGNAL(calendarToBeAdded(const KPlato::Calendar*,int)), this, SLOT(slotCalendarToBeInserted(const KPlato::Calendar*,int))); - disconnect( m_project, SIGNAL(calendarRemoved(const Calendar*)), this, SLOT(slotCalendarRemoved(const Calendar*)) ); - disconnect( m_project, SIGNAL(calendarToBeRemoved(const Calendar*)), this, SLOT(slotCalendarToBeRemoved(const Calendar*)) ); + disconnect( m_project, SIGNAL(calendarRemoved(const KPlato::Calendar*)), this, SLOT(slotCalendarRemoved(const KPlato::Calendar*))); + disconnect( m_project, SIGNAL(calendarToBeRemoved(const KPlato::Calendar*)), this, SLOT(slotCalendarToBeRemoved(const KPlato::Calendar*))); } m_project = project; if ( project ) { connect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - connect( m_project, SIGNAL(calendarChanged(Calendar*)), this, SLOT(slotCalendarChanged(Calendar*)) ); + connect( m_project, SIGNAL(calendarChanged(KPlato::Calendar*)), this, SLOT(slotCalendarChanged(KPlato::Calendar*))); - connect( m_project, SIGNAL(calendarAdded(const Calendar*)), this, SLOT(slotCalendarInserted(const Calendar*)) ); - connect( m_project, SIGNAL(calendarToBeAdded(const Calendar*,int)), this, SLOT(slotCalendarToBeInserted(const Calendar*,int)) ); + connect( m_project, SIGNAL(calendarAdded(const KPlato::Calendar*)), this, SLOT(slotCalendarInserted(const KPlato::Calendar*))); + connect( m_project, SIGNAL(calendarToBeAdded(const KPlato::Calendar*,int)), this, SLOT(slotCalendarToBeInserted(const KPlato::Calendar*,int))); - connect( m_project, SIGNAL(calendarRemoved(const Calendar*)), this, SLOT(slotCalendarRemoved(const Calendar*)) ); - connect( m_project, SIGNAL(calendarToBeRemoved(const Calendar*)), this, SLOT(slotCalendarToBeRemoved(const Calendar*)) ); + connect( m_project, SIGNAL(calendarRemoved(const KPlato::Calendar*)), this, SLOT(slotCalendarRemoved(const KPlato::Calendar*))); + connect( m_project, SIGNAL(calendarToBeRemoved(const KPlato::Calendar*)), this, SLOT(slotCalendarToBeRemoved(const KPlato::Calendar*))); } endResetModel(); } Qt::ItemFlags CalendarItemModel::flags( const QModelIndex &index ) const { Qt::ItemFlags flags = ItemModelBase::flags( index ); if ( !m_readWrite ) { return flags &= ~Qt::ItemIsEditable; } flags |= Qt::ItemIsDropEnabled; if ( !index.isValid() ) { return flags; } Calendar *c = calendar(index); if (!c || c->isShared()) { if (index.column() == Name) { flags |= Qt::ItemIsUserCheckable; } return flags; } flags |= Qt::ItemIsDragEnabled; if ( calendar ( index ) ) { switch ( index.column() ) { case Name: flags |= ( Qt::ItemIsEditable | Qt::ItemIsUserCheckable ); break; case Scope: flags &= ~Qt::ItemIsEditable; break; case TimeZone: if ( parent( index ).isValid() ) { flags &= ~Qt::ItemIsEditable; } else { flags |= Qt::ItemIsEditable; } break; #ifdef HAVE_KHOLIDAYS case HolidayRegion: flags |= Qt::ItemIsEditable; break; #endif default: flags |= Qt::ItemIsEditable; break; } } return flags; } QModelIndex CalendarItemModel::parent( const QModelIndex &index ) const { if ( !index.isValid() || m_project == 0 ) { return QModelIndex(); } //debugPlan<parentCal(); if ( par ) { a = par->parentCal(); int row = -1; if ( a ) { row = a->indexOf( par ); } else { row = m_project->indexOf( par ); } //debugPlan<name()<<":"<= columnCount() || row < 0 ) { return QModelIndex(); } Calendar *par = calendar( parent ); if ( par == 0 ) { if ( row < m_project->calendars().count() ) { return createIndex( row, column, m_project->calendars().at( row ) ); } } else if ( row < par->calendars().count() ) { return createIndex( row, column, par->calendars().at( row ) ); } return QModelIndex(); } QModelIndex CalendarItemModel::index( const Calendar *calendar, int column ) const { if ( m_project == 0 || calendar == 0 ) { return QModelIndex(); } Calendar *a = const_cast(calendar); int row = -1; Calendar *par = a->parentCal(); if ( par == 0 ) { row = m_project->calendars().indexOf( a ); } else { row = par->indexOf( a ); } if ( row == -1 ) { return QModelIndex(); } return createIndex( row, column, a ); } int CalendarItemModel::columnCount( const QModelIndex & ) const { return columnMap().keyCount(); } int CalendarItemModel::rowCount( const QModelIndex &parent ) const { if ( m_project == 0 ) { return 0; } Calendar *par = calendar( parent ); if ( par == 0 ) { return m_project->calendars().count(); } return par->calendars().count(); } QVariant CalendarItemModel::name( const Calendar *a, int role ) const { //debugPlan<name()<<","<name(); case Qt::ToolTipRole: if ( a->isDefault() ) { return xi18nc( "1=calendar name", "%1 (Default calendar)", a->name() ); } return a->name(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Qt::CheckStateRole: return a->isDefault() ? Qt::Checked : Qt::Unchecked; } return QVariant(); } QVariant CalendarItemModel::scope( const Calendar *a, int role ) const { //debugPlan<name()<<","<isShared() ? i18n("Shared") : i18n("Local"); case Qt::EditRole: return a->isShared() ? "Shared" : "Local"; case Qt::ToolTipRole: if ( !a->isShared() ) { return xi18nc( "@info:tooltip 1=calendar name", "%1 is a Local calendar", a->name() ); } return xi18nc( "@info:tooltip 1=calendar name", "%1 is a Shared calendar", a->name() ); case Role::EnumList: return QStringList() << i18n("Shared") << i18n("Local"); case Role::EnumListValue: return a->isShared() ? 0 : 1; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } bool CalendarItemModel::setName( Calendar *a, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toString() != a->name() ) { emit executeCommand( new CalendarModifyNameCmd( a, value.toString(), kundo2_i18n( "Modify calendar name" ) ) ); return true; } break; case Qt::CheckStateRole: { switch ( value.toInt() ) { case Qt::Unchecked: if ( a->isDefault() ) { emit executeCommand( new ProjectModifyDefaultCalendarCmd( m_project, 0, kundo2_i18n( "De-select as default calendar" ) ) ); return true; } break; case Qt::Checked: if ( ! a->isDefault() ) { emit executeCommand( new ProjectModifyDefaultCalendarCmd( m_project, a, kundo2_i18n( "Select as default calendar" ) ) ); return true; } break; default: break; } } default: break; } return false; } QVariant CalendarItemModel::timeZone( const Calendar *a, int role ) const { //debugPlan<name()<<","<timeZone().id() ); case Role::EnumList: { QStringList lst; foreach ( const QByteArray &id, QTimeZone::availableTimeZoneIds() ) { lst << i18n( id ); } lst.sort(); return lst; } case Role::EnumListValue: { QStringList lst = timeZone( a, Role::EnumList ).toStringList(); return lst.indexOf( i18n ( a->timeZone().id() ) ); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } bool CalendarItemModel::setTimeZone( Calendar *a, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { if ( timeZone( a, Role::EnumListValue ) == value.toInt() ) { return false; } QStringList lst = timeZone( a, Role::EnumList ).toStringList(); QString name = lst.value( value.toInt() ); QTimeZone tz; foreach ( const QByteArray &id, QTimeZone::availableTimeZoneIds() ) { if ( name == i18n( id ) ) { tz = QTimeZone( id ); break; } } if ( !tz.isValid() ) { return false; } emit executeCommand( new CalendarModifyTimeZoneCmd( a, tz, kundo2_i18n( "Modify calendar timezone" ) ) ); return true; } } return false; } #ifdef HAVE_KHOLIDAYS QVariant CalendarItemModel::holidayRegion( const Calendar *a, int role ) const { //debugPlan<name()<<","<holidayRegionCode().isEmpty() || !a->holidayRegion()->isValid()) { return i18n("None"); } if (a->holidayRegionCode() == "Default") { return i18n("Default"); } return a->holidayRegion()->name(); case Qt::EditRole: if (a->holidayRegionCode().isEmpty()) { return "None"; } return a->holidayRegionCode(); case Qt::ToolTipRole: if (!a->holidayRegion()->isValid()) { return xi18nc("@info:tooltip", "No holidays"); } else if (a->holidayRegionCode() == "Default") { return xi18nc("@info:tooltip", "Default region: %1", a->holidayRegion()->name()); } return a->holidayRegion()->description(); case Role::EnumList: { QStringList lst; lst << i18n("None") << i18n("Default"); for (const QString &code : a->holidayRegionCodes()) { lst << KHolidays::HolidayRegion::name(code); } return lst; } case Role::EnumListValue: { if (!a->holidayRegion()->isValid()) { return 0; // None } if (a->holidayRegionCode() == "Default") { return 1; } return a->holidayRegionCodes().indexOf(a->holidayRegionCode()) + 2; } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } bool CalendarItemModel::setHolidayRegion( Calendar *a, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { QString code = "None"; if (value.toInt() == 1) { code = "Default"; } else if (value.toInt() > 1) { code = a->holidayRegionCodes().value(value.toInt() - 2); } if (a->holidayRegionCode() == code || (code == "None" && a->holidayRegionCode().isEmpty())) { return false; } emit executeCommand(new CalendarModifyHolidayRegionCmd(a, code, kundo2_i18n("Modify calendar holiday region"))); return true; } } return false; } #endif QVariant CalendarItemModel::data( const QModelIndex &index, int role ) const { QVariant result; Calendar *a = calendar( index ); if ( a == 0 ) { return QVariant(); } switch ( index.column() ) { case Name: result = name( a, role ); break; case Scope: result = scope( a, role ); break; case TimeZone: result = timeZone( a, role ); break; #ifdef HAVE_KHOLIDAYS case HolidayRegion: result = holidayRegion( a, role ); break; #endif default: debugPlan<<"data: invalid display value column"<( index.internalPointer() ); } void CalendarItemModel::slotCalendarChanged( Calendar *calendar ) { Calendar *par = calendar->parentCal(); if ( par ) { int row = par->indexOf( calendar ); emit dataChanged( createIndex( row, 0, calendar ), createIndex( row, columnCount() - 1, calendar ) ); } else { int row = m_project->indexOf( calendar ); emit dataChanged( createIndex( row, 0, calendar ), createIndex( row, columnCount() - 1, calendar ) ); } } Qt::DropActions CalendarItemModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } QStringList CalendarItemModel::mimeTypes() const { return QStringList() << "application/x-vnd.kde.plan.calendarid.internal"; } QMimeData *CalendarItemModel::mimeData( const QModelIndexList & indexes ) const { QMimeData *m = new QMimeData(); QByteArray encodedData; QDataStream stream(&encodedData, QIODevice::WriteOnly); QList rows; foreach (const QModelIndex &index, indexes) { if ( index.isValid() && !rows.contains( index.row() ) ) { debugPlan<id(); } } } m->setData("application/x-vnd.kde.plan.calendarid.internal", encodedData); return m; } bool CalendarItemModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int /*column*/, const QModelIndex &parent ) { debugPlan<hasFormat( "application/x-vnd.kde.plan.calendarid.internal" ) ) { return false; } if ( action == Qt::MoveAction ) { debugPlan<<"MoveAction"; QByteArray encodedData = data->data( "application/x-vnd.kde.plan.calendarid.internal" ); QDataStream stream(&encodedData, QIODevice::ReadOnly); Calendar *par = 0; if ( parent.isValid() ) { par = calendar( parent ); } MacroCommand *cmd = 0; QList lst = calendarList( stream ); foreach ( Calendar *c, lst ) { if ( c->parentCal() != par ) { if ( cmd == 0 ) cmd = new MacroCommand( kundo2_i18n( "Re-parent calendar" ) ); cmd->addCommand( new CalendarModifyParentCmd( m_project, c, par ) ); } else { if ( cmd == 0 ) cmd = new MacroCommand( kundo2_i18n( "Move calendar" ) ); cmd->addCommand( new CalendarMoveCmd( m_project, c, row, par ) ); } } if ( cmd ) { emit executeCommand( cmd ); return true; } //debugPlan<name(); } return false; } QList CalendarItemModel::calendarList( QDataStream &stream ) const { QList lst; while (!stream.atEnd()) { QString id; stream >> id; Calendar *c = m_project->findCalendar( id ); if ( c ) { lst << c; } } return lst; } bool CalendarItemModel::dropAllowed( Calendar *on, const QMimeData *data ) { debugPlan<hasFormat("application/x-vnd.kde.plan.calendarid.internal"); if ( !data->hasFormat("application/x-vnd.kde.plan.calendarid.internal") ) { return false; } if ( on == 0 && ! ( flags( QModelIndex() ) & (int)Qt::ItemIsDropEnabled ) ) { return false; } QByteArray encodedData = data->data( "application/x-vnd.kde.plan.calendarid.internal" ); QDataStream stream(&encodedData, QIODevice::ReadOnly); QList lst = calendarList( stream ); foreach ( Calendar *c, lst ) { if ( (flags( index( c ) ) & (int)Qt::ItemIsDropEnabled) == 0 ) { return false; } if ( on != 0 && on == c->parentCal() ) { return false; } if ( on != 0 && ( on == c || on->isChildOf( c ) ) ) { return false; } } return true; } QModelIndex CalendarItemModel::insertCalendar ( Calendar *calendar, int pos, Calendar *parent ) { //debugPlan<indexOf( calendar ); } else { row = m_project->indexOf( calendar ); } if ( row != -1 ) { //debugPlan<<"Inserted:"<name()<<"row="< /*lst*/ ) { } void CalendarItemModel::removeCalendar( Calendar *calendar ) { if ( calendar == 0 ) { return; } emit executeCommand( new CalendarRemoveCmd( m_project, calendar, kundo2_i18n( "Delete calendar" ) ) ); } //------------------------------------------ CalendarDayItemModel::CalendarDayItemModel( QObject *parent ) : CalendarDayItemModelBase( parent ) { } CalendarDayItemModel::~CalendarDayItemModel() { } void CalendarDayItemModel::slotWorkIntervalAdded( CalendarDay *day, TimeInterval *ti ) { Q_UNUSED(ti); //debugPlan<indexOfWeekday( day ); if ( c == -1 ) { return; } dataChanged( createIndex( 0, c, day ), createIndex( 0, c, day ) ); } void CalendarDayItemModel::slotWorkIntervalRemoved( CalendarDay *day, TimeInterval *ti ) { Q_UNUSED(ti); int c = m_calendar->indexOfWeekday( day ); if ( c == -1 ) { return; } dataChanged( createIndex( 0, c, day ), createIndex( 0, c, day ) ); } void CalendarDayItemModel::slotDayChanged( CalendarDay *day ) { int c = m_calendar->indexOfWeekday( day ); if ( c == -1 ) { return; } debugPlan<indexOf( ti ); emit dataChanged( createIndex( row, 0, ti ), createIndex( row, columnCount() - 1, ti ) );*/ } void CalendarDayItemModel::setCalendar( Calendar *calendar ) { beginResetModel(); //debugPlan<"<weekday( column + 1 ); // weekdays are 1..7 if ( d == 0 ) { return QModelIndex(); } return createIndex( row, column, d ); } QModelIndex CalendarDayItemModel::index( const CalendarDay *d) const { if ( m_project == 0 || m_calendar == 0 ) { return QModelIndex(); } int col = m_calendar->indexOfWeekday( d ); if ( col == -1 ) { return QModelIndex(); } return createIndex( 0, col, const_cast( d ) ); } int CalendarDayItemModel::columnCount( const QModelIndex &/*parent*/ ) const { return 7; } int CalendarDayItemModel::rowCount( const QModelIndex &parent ) const { if ( m_project == 0 || m_calendar == 0 || parent.isValid() ) { return 0; } return 1; } QVariant CalendarDayItemModel::name( int weekday, int role ) const { //debugPlan<name()<<","<= 1 && weekday <= 7 ) { return QLocale().dayName( weekday, QLocale::ShortFormat ); } break; case Qt::ToolTipRole: if ( weekday >= 1 && weekday <= 7 ) { return QLocale().dayName( weekday, QLocale::LongFormat ); } break; case Qt::EditRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant CalendarDayItemModel::dayState( const CalendarDay *d, int role ) const { switch ( role ) { case Qt::DisplayRole: switch ( d->state() ) { case CalendarDay::Undefined: return i18nc( "Undefined", "U" ); case CalendarDay::NonWorking: return i18nc( "NonWorking", "NW" ); case CalendarDay::Working: return i18nc( "Working", "W" ); } break; case Qt::ToolTipRole: return CalendarDay::stateToString( d->state(), true ); case Role::EnumList: { QStringList lst = CalendarDay::stateList( true ); return lst; } case Qt::EditRole: case Role::EnumListValue: { return d->state(); } case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::EditorType: return Delegate::EnumEditor; } return QVariant(); } bool CalendarDayItemModel::setDayState( CalendarDay *d, const QVariant &value, int role ) { //debugPlan; switch ( role ) { case Qt::EditRole: int v = value.toInt(); emit executeCommand( new CalendarModifyStateCmd( m_calendar, d, static_cast( v ), kundo2_i18n( "Modify calendar state" ) ) ); return true; } return false; } QVariant CalendarDayItemModel::workDuration( const CalendarDay *day, int role ) const { //debugPlan<date()<<","<state() == CalendarDay::Working ) { return QLocale().toString( day->workDuration().toDouble( Duration::Unit_h ), 'f', 1 ); } return QVariant(); } case Qt::ToolTipRole: { if ( day->state() == CalendarDay::Working ) { QLocale locale; QStringList tip; foreach ( TimeInterval *i, day->timeIntervals() ) { tip << i18nc( "1=time 2=The number of hours of work duration (non integer)", "%1, %2 hours", locale.toString( i->startTime(), QLocale::ShortFormat ), locale.toString( i->hours(), 'f', 2 ) ); } return tip.join( "\n" ); } return QVariant(); } case Qt::EditRole: break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Qt::TextAlignmentRole: return Qt::AlignCenter; } return QVariant(); } QVariant CalendarDayItemModel::data( const QModelIndex &index, int role ) const { QVariant result; if ( ! index.isValid() ) { return result; } CalendarDay *d = day( index ); if ( d == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: { switch ( d->state() ) { case CalendarDay::Working: result = workDuration( d, role ); break; case CalendarDay::NonWorking: result = dayState( d, role ); break; default: { // Return parent value (if any) for ( Calendar *c = m_calendar->parentCal(); c != 0; c = c->parentCal() ) { d = c->weekday( index.column() + 1 ); Q_ASSERT( d ); if ( d->state() == CalendarDay::Working ) { return workDuration( d, role ); } if ( d->state() == CalendarDay::NonWorking ) { return dayState( d, role ); } } break; } } break; } case Qt::ToolTipRole: { if ( d->state() == CalendarDay::Undefined ) { return xi18nc( "@info:tooltip", "Undefined" ); } if ( d->state() == CalendarDay::NonWorking ) { return xi18nc( "@info:tooltip", "Non-working" ); } QLocale locale; KFormat format(locale); QStringList tip; foreach ( TimeInterval *i, d->timeIntervals() ) { tip << xi18nc( "@info:tooltip 1=time 2=The work duration (non integer)", "%1, %2", locale.toString( i->startTime(), QLocale::ShortFormat ), format.formatDuration( i->second ) ); } return tip.join( "" ); } case Qt::FontRole: { if ( d->state() != CalendarDay::Undefined ) { return QVariant(); } // If defined in parent, return italic for ( Calendar *c = m_calendar->parentCal(); c != 0; c = c->parentCal() ) { d = c->weekday( index.column() + 1 ); Q_ASSERT( d ); if ( d->state() != CalendarDay::Undefined ) { QFont f; f.setItalic( true ); return f; } } break; } } return result; } bool CalendarDayItemModel::setData( const QModelIndex &index, const QVariant &value, int role ) { return ItemModelBase::setData( index, value, role ); } QVariant CalendarDayItemModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( orientation == Qt::Horizontal ) { if ( role == Qt::DisplayRole ) { switch ( section ) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: return name( section + 1, role ); default: return QVariant(); } } else if ( role == Qt::TextAlignmentRole ) { switch (section) { default: return Qt::AlignCenter; } } } if ( role == Qt::ToolTipRole ) { switch ( section ) { /* case 0: return ToolTip::Calendar Name;*/ default: return QVariant(); } } return ItemModelBase::headerData(section, orientation, role); } CalendarDay *CalendarDayItemModel::day( const QModelIndex &index ) const { return static_cast( index.internalPointer() ); } QAbstractItemDelegate *CalendarDayItemModel::createDelegate( int column, QWidget *parent ) const { Q_UNUSED(parent); switch ( column ) { default: return 0; } return 0; } //----------------------- DateTableDataModel::DateTableDataModel( QObject *parent ) : KDateTableDataModel( parent ), m_calendar( 0 ) { } void DateTableDataModel::setCalendar( Calendar *calendar ) { if ( m_calendar ) { - disconnect( m_calendar, SIGNAL(dayAdded(CalendarDay*)), this, SIGNAL(reset()) ); - disconnect( m_calendar, SIGNAL(dayRemoved(CalendarDay*)), this, SIGNAL(reset()) ); - disconnect( m_calendar, SIGNAL(changed(CalendarDay*)), this, SIGNAL(reset()) ); + disconnect( m_calendar, SIGNAL(dayAdded(KPlato::CalendarDay*)), this, SIGNAL(reset())); + disconnect( m_calendar, SIGNAL(dayRemoved(KPlato::CalendarDay*)), this, SIGNAL(reset())); + disconnect( m_calendar, SIGNAL(changed(KPlato::CalendarDay*)), this, SIGNAL(reset())); } m_calendar = calendar; if ( m_calendar ) { - connect( m_calendar, SIGNAL(dayAdded(CalendarDay*)), this, SIGNAL(reset()) ); - connect( m_calendar, SIGNAL(dayRemoved(CalendarDay*)), this, SIGNAL(reset()) ); - connect( m_calendar, SIGNAL(changed(CalendarDay*)), this, SIGNAL(reset()) ); + connect( m_calendar, SIGNAL(dayAdded(KPlato::CalendarDay*)), this, SIGNAL(reset())); + connect( m_calendar, SIGNAL(dayRemoved(KPlato::CalendarDay*)), this, SIGNAL(reset())); + connect( m_calendar, SIGNAL(changed(KPlato::CalendarDay*)), this, SIGNAL(reset())); } emit reset(); } QVariant DateTableDataModel::data( const Calendar &cal, const QDate &date, int role ) const { switch ( role ) { case Qt::DisplayRole: { CalendarDay *day = cal.findDay( date ); if ( day == 0 || day->state() == CalendarDay::Undefined ) { #ifdef HAVE_KHOLIDAYS if (cal.isHoliday(date)) { return i18nc( "NonWorking", "NW" ); } #endif if ( cal.parentCal() ) { return data( *( cal.parentCal() ), date, role ); } return ""; } if ( day->state() == CalendarDay::NonWorking ) { return i18nc( "NonWorking", "NW" ); } double v; v = day->workDuration().toDouble( Duration::Unit_h ); return QLocale().toString( v, 'f', 1 ); } case Qt::TextAlignmentRole: return (uint)( Qt::AlignHCenter | Qt::AlignBottom ); case Qt::FontRole: { CalendarDay *day = cal.findDay( date ); if ( day && day->state() != CalendarDay::Undefined ) { if ( &cal != m_calendar ) { QFont f; f.setItalic( true ); return f; } return QVariant(); } if ( cal.parentCal() ) { return data( *( cal.parentCal() ), date, role ); } break; } default: break; } return QVariant(); } QVariant DateTableDataModel::data( const QDate &date, int role, int dataType ) const { //debugPlan<findDay( date ); if ( day == 0 || day->state() == CalendarDay::Undefined ) { #ifdef HAVE_KHOLIDAYS if (m_calendar->isHoliday(date)) { return xi18nc( "@info:tooltip", "Holiday" ); } #endif return xi18nc( "@info:tooltip", "Undefined" ); } if ( day->state() == CalendarDay::NonWorking ) { return xi18nc( "@info:tooltip", "Non-working" ); } QLocale locale; KFormat format(locale); QStringList tip; foreach ( TimeInterval *i, day->timeIntervals() ) { tip << xi18nc( "@info:tooltip 1=time 2=The work duration (non integer)", "%1, %2", locale.toString( i->startTime(), QLocale::ShortFormat ), format.formatDuration( i->second ) ); } return tip.join( "\n" ); } switch ( dataType ) { case -1: { //default (date) switch ( role ) { case Qt::DisplayRole: { return QVariant(); } case Qt::TextAlignmentRole: return (uint)Qt::AlignLeft | Qt::AlignTop; case Qt::FontRole: break;//return QFont( "Helvetica", 6 ); case Qt::BackgroundRole: break;//return QColor( "red" ); default: break; } break; } case 0: { if ( m_calendar == 0 ) { return ""; } return data( *m_calendar, date, role ); } default: break; } return QVariant(); } QVariant DateTableDataModel::weekDayData( int day, int role ) const { Q_UNUSED(day); Q_UNUSED(role); return QVariant(); } QVariant DateTableDataModel::weekNumberData( int week, int role ) const { Q_UNUSED(week); Q_UNUSED(role); return QVariant(); } //------------- DateTableDateDelegate::DateTableDateDelegate( QObject *parent ) : KDateTableDateDelegate( parent ) { } QRectF DateTableDateDelegate::paint( QPainter *painter, const StyleOptionViewItem &option, const QDate &date, KDateTableDataModel *model ) { //debugPlan<save(); painter->translate( r.width(), 0.0 ); QRectF rect( 1, 1, option.rectF.right() - r.width(), option.rectF.bottom() ); //debugPlan<<" rects: "<data( date, Qt::DisplayRole, 0 ).toString(); int align = model->data( date, Qt::TextAlignmentRole, 0 ).toInt(); QFont f = option.font; QVariant v = model->data( date, Qt::FontRole, 0 ); if ( v.isValid() ) { f = v.value(); } painter->setFont( f ); if ( option.state & QStyle::State_Selected ) { painter->setPen( option.palette.highlightedText().color() ); } else { painter->setPen( option.palette.color( QPalette::Text ) ); } painter->drawText(rect, align, text, &r); painter->restore(); return r; } //------------------------------------- CalendarExtendedItemModel::CalendarExtendedItemModel( QObject *parent ) : CalendarItemModel( parent ) { } Qt::ItemFlags CalendarExtendedItemModel::flags( const QModelIndex &index ) const { Qt::ItemFlags flags = CalendarItemModel::flags( index ); if ( ! m_readWrite || ! index.isValid() || calendar( index ) == 0 ) { return flags; } return flags |= Qt::ItemIsEditable; } QModelIndex CalendarExtendedItemModel::index( int row, int column, const QModelIndex &parent ) const { if ( m_project == 0 || column < 0 || column >= columnCount() || row < 0 ) { return QModelIndex(); } Calendar *par = calendar( parent ); if ( par == 0 ) { if ( row < m_project->calendars().count() ) { return createIndex( row, column, m_project->calendars().at( row ) ); } } else if ( row < par->calendars().count() ) { return createIndex( row, column, par->calendars().at( row ) ); } return QModelIndex(); } int CalendarExtendedItemModel::columnCount( const QModelIndex & ) const { return CalendarItemModel::columnCount() + 2; // weekdays + date } QVariant CalendarExtendedItemModel::data( const QModelIndex &index, int role ) const { QVariant result; Calendar *a = calendar( index ); if ( a == 0 ) { return QVariant(); } int col = index.column() - CalendarItemModel::columnCount( index ); if ( col < 0 ) { return CalendarItemModel::data( index, role ); } switch ( col ) { default: debugPlan<<"Fetching data from weekdays and date is not supported"; break; } return result; } bool CalendarExtendedItemModel::setData( const QModelIndex &index, const QVariant &value, int role ) { int col = index.column() - CalendarItemModel::columnCount( index ); if ( col < 0 ) { return CalendarItemModel::setData( index, value, role ); } if ( ( flags( index ) &( Qt::ItemIsEditable ) ) == 0 ) { return false; } Calendar *cal = calendar( index ); if ( cal == 0 || col > 2 ) { return false; } switch ( col ) { case 0: { // weekday if ( value.type() != QVariant::List ) { return false; } QVariantList lst = value.toList(); if ( lst.count() < 2 ) { return false; } int wd = CalendarWeekdays::dayOfWeek( lst.at( 0 ).toString() ); if ( wd < 1 || wd > 7 ) { return false; } CalendarDay *day = new CalendarDay(); if ( lst.count() == 2 ) { QString state = lst.at( 1 ).toString(); if ( state == "NonWorking" ) { day->setState( CalendarDay::NonWorking ); } else if ( state == "Undefined" ) { day->setState( CalendarDay::Undefined ); } else { delete day; return false; } CalendarModifyWeekdayCmd *cmd = new CalendarModifyWeekdayCmd( cal, wd, day, kundo2_i18n( "Modify calendar weekday" ) ); emit executeCommand( cmd ); return true; } if ( lst.count() % 2 == 0 ) { delete day; return false; } day->setState( CalendarDay::Working ); for ( int i = 1; i < lst.count(); i = i + 2 ) { QTime t1 = lst.at( i ).toTime(); QTime t2 = lst.at( i + 1 ).toTime(); int length = t1.msecsTo( t2 ); if ( t1 == QTime( 0, 0, 0 ) && t2 == t1 ) { length = 24 * 60 * 60 *1000; } else if ( length < 0 && t2 == QTime( 0, 0, 0 ) ) { length += 24 * 60 * 60 *1000; } else if ( length == 0 || ( length < 0 && t2 != QTime( 0, 0, 0 ) ) ) { delete day; return false; } length = qAbs( length ); day->addInterval( t1, length ); } CalendarModifyWeekdayCmd *cmd = new CalendarModifyWeekdayCmd( cal, wd, day, kundo2_i18n( "Modify calendar weekday" ) ); emit executeCommand( cmd ); return true; } case 1: { // day if ( value.type() != QVariant::List ) { return false; } CalendarDay *day = new CalendarDay(); QVariantList lst = value.toList(); if ( lst.count() < 2 ) { return false; } day->setDate( lst.at( 0 ).toDate() ); if ( ! day->date().isValid() ) { delete day; return false; } if ( lst.count() == 2 ) { QString state = lst.at( 1 ).toString(); if ( state == "NonWorking" ) { day->setState( CalendarDay::NonWorking ); } else if ( state == "Undefined" ) { day->setState( CalendarDay::Undefined ); } else { delete day; return false; } CalendarModifyDayCmd *cmd = new CalendarModifyDayCmd( cal, day, kundo2_i18n( "Modify calendar date" ) ); emit executeCommand( cmd ); return true; } if ( lst.count() % 2 == 0 ) { delete day; return false; } day->setState( CalendarDay::Working ); for ( int i = 1; i < lst.count(); i = i + 2 ) { QTime t1 = lst.at( i ).toTime(); QTime t2 = lst.at( i + 1 ).toTime(); int length = t1.msecsTo( t2 ); if ( t1 == QTime( 0, 0, 0 ) && t2 == t1 ) { length = 24 * 60 * 60 *1000; } else if ( length < 0 && t2 == QTime( 0, 0, 0 ) ) { length += 24 * 60 * 60 *1000; } else if ( length == 0 || ( length < 0 && t2 != QTime( 0, 0, 0 ) ) ) { delete day; return false; } length = qAbs( length ); day->addInterval( t1, length ); } CalendarModifyDayCmd *cmd = new CalendarModifyDayCmd( cal, day, kundo2_i18n( "Modify calendar date" ) ); emit executeCommand( cmd ); return true; } } return false; } QVariant CalendarExtendedItemModel::headerData( int section, Qt::Orientation orientation, int role ) const { int col = section - CalendarItemModel::columnCount(); if ( col < 0 ) { return CalendarItemModel::headerData( section, orientation, role ); } if ( orientation == Qt::Horizontal ) { if ( role == Qt::DisplayRole ) { switch ( col ) { case 0: return xi18nc( "@title:column", "Weekday" ); case 1: return xi18nc( "@title:column", "Date" ); default: return QVariant(); } } else if ( role == Qt::TextAlignmentRole ) { switch ( col ) { default: return QVariant(); } } } if ( role == Qt::ToolTipRole ) { switch ( section ) { default: return QVariant(); } } return QVariant(); } int CalendarExtendedItemModel::columnNumber(const QString& name) const { QStringList lst; lst << "Weekday" << "Date"; if ( lst.contains( name ) ) { return lst.indexOf( name ) + CalendarItemModel::columnCount(); } return CalendarItemModel::columnMap().keyToValue( name.toUtf8() ); } } // namespace KPlato diff --git a/src/libs/models/kptcalendarmodel.h b/src/libs/models/kptcalendarmodel.h index 971f91b1..eb644020 100644 --- a/src/libs/models/kptcalendarmodel.h +++ b/src/libs/models/kptcalendarmodel.h @@ -1,273 +1,273 @@ /* This file is part of the KDE project * Copyright (C) 2007 Dag Andersen * Copyright (C) 2017 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 KPTCALENDARMODEL_H #define KPTCALENDARMODEL_H #include "planmodels_export.h" #include "kptitemmodelbase.h" #include "kptcalendar.h" #include "kptcalendarmodel.h" #include "kcalendar/kdatetable.h" class QPainter; namespace KPlato { class View; class Project; class Calendar; class CalendarDay; class PLANMODELS_EXPORT CalendarDayItemModelBase : public ItemModelBase { Q_OBJECT public: explicit CalendarDayItemModelBase( QObject *parent = 0 ); ~CalendarDayItemModelBase(); virtual void setCalendar( Calendar *calendar ); virtual Calendar *calendar() const { return m_calendar; } virtual void setProject( Project *project ); CalendarDay *day( const QModelIndex &index ) const; // TimeInterval *interval( const QModelIndex &index ) const; // QModelIndex insertInterval ( TimeInterval *ti, CalendarDay *day ); // void removeInterval( TimeInterval *ti ); // CalendarDay *parentDay( const TimeInterval *ti ) const { return m_days.value( const_cast( ti ) ); } protected Q_SLOTS: - void slotCalendarToBeRemoved( const Calendar *calendar ); + void slotCalendarToBeRemoved(const KPlato::Calendar *calendar); protected: Calendar *m_calendar; // current calendar // QMap m_days; }; class PLANMODELS_EXPORT CalendarItemModel : public ItemModelBase { Q_OBJECT Q_ENUMS( Properties ) public: explicit CalendarItemModel( QObject *parent = 0 ); ~CalendarItemModel(); enum Properties { Name = 0, Scope, TimeZone #ifdef HAVE_KHOLIDAYS , HolidayRegion #endif }; const QMetaEnum columnMap() const; virtual void setProject( Project *project ); virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; QModelIndex index( const Calendar *calendar, int column = 0 ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; virtual QMimeData * mimeData( const QModelIndexList & indexes ) const; virtual QStringList mimeTypes () const; virtual Qt::DropActions supportedDropActions() const; virtual bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ); using ItemModelBase::dropAllowed; bool dropAllowed( Calendar *on, const QMimeData *data ); Calendar *calendar( const QModelIndex &index ) const; QModelIndex insertCalendar( Calendar *calendar, int pos, Calendar *parent = 0 ); void removeCalendar( QList lst ); void removeCalendar( Calendar *calendar ); protected Q_SLOTS: - void slotCalendarChanged( Calendar* ); - void slotCalendarToBeInserted( const Calendar *parent, int row ); - void slotCalendarInserted( const Calendar *calendar ); - void slotCalendarToBeRemoved( const Calendar *calendar ); - void slotCalendarRemoved( const Calendar *calendar ); + void slotCalendarChanged(KPlato::Calendar*); + void slotCalendarToBeInserted(const KPlato::Calendar *parent, int row); + void slotCalendarInserted(const KPlato::Calendar *calendar); + void slotCalendarToBeRemoved(const KPlato::Calendar *calendar); + void slotCalendarRemoved(const KPlato::Calendar *calendar); protected: QVariant name( const Calendar *calendar, int role ) const; bool setName( Calendar *calendar, const QVariant &value, int role ); QVariant scope( const Calendar *calendar, int role ) const; QVariant timeZone( const Calendar *calendar, int role ) const; bool setTimeZone( Calendar *calendar, const QVariant &value, int role ); #ifdef HAVE_KHOLIDAYS QVariant holidayRegion( const Calendar *calendar, int role ) const; bool setHolidayRegion( Calendar *calendar, const QVariant &value, int role ); #endif QList calendarList( QDataStream &stream ) const; private: Calendar *m_calendar; // test for sane operation }; class PLANMODELS_EXPORT CalendarDayItemModel : public CalendarDayItemModelBase { Q_OBJECT public: explicit CalendarDayItemModel( QObject *parent = 0 ); ~CalendarDayItemModel(); virtual void setCalendar( Calendar *calendar ); virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual bool hasChildren( const QModelIndex & parent = QModelIndex() ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; QModelIndex index( const CalendarDay* day ) const; QModelIndex index( const TimeInterval* ti ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; CalendarDay *day( const QModelIndex &index ) const; TimeInterval *interval( const QModelIndex &index ) const; QAbstractItemDelegate *createDelegate( int column, QWidget *parent ) const; QModelIndex insertInterval ( TimeInterval *ti, CalendarDay *day ); void removeInterval( TimeInterval *ti ); QModelIndex insertDay ( CalendarDay *day ); void removeDay ( CalendarDay *day ); bool isDate( const CalendarDay *day ) const; bool isWeekday( const CalendarDay *day ) const; protected Q_SLOTS: - void slotDayChanged( CalendarDay *day ); - void slotTimeIntervalChanged( TimeInterval *ti ); - -/* void slotDayToBeAdded( CalendarDay *day, int row ); - void slotDayAdded( CalendarDay *day ); - void slotDayToBeRemoved( CalendarDay *day ); - void slotDayRemoved( CalendarDay *day );*/ + void slotDayChanged(KPlato::CalendarDay *day); + void slotTimeIntervalChanged(KPlato::TimeInterval *ti); + +/* void slotDayToBeAdded(KPlato::CalendarDay *day, int row); + void slotDayAdded(KPlato::*CalendarDay *day); + void slotDayToBeRemoved(KPlato::CalendarDay *day); + void slotDayRemoved(KPlato::CalendarDay *day);*/ -// void slotWorkIntervalToBeAdded( CalendarDay *day, TimeInterval *ti, int row ); - void slotWorkIntervalAdded( CalendarDay *day, TimeInterval *ti ); -// void slotWorkIntervalToBeRemoved( CalendarDay *day, TimeInterval *ti ); - void slotWorkIntervalRemoved( CalendarDay *day, TimeInterval *ti ); +// void slotWorkIntervalToBeAdded(KPlato::CalendarDay *day, TimeInterval *ti, int row); + void slotWorkIntervalAdded(KPlato::CalendarDay *day, KPlato::TimeInterval *ti); +// void slotWorkIntervalToBeRemoved(KPlato::CalendarDay *day, TimeInterval *ti); + void slotWorkIntervalRemoved(KPlato::CalendarDay *day, KPlato::TimeInterval *ti); protected: /* QVariant date( const CalendarDay *day, int role ) const; bool setDate( CalendarDay *day, const QVariant &value, int role );*/ QVariant name( int weekday, int role ) const; QVariant dayState( const CalendarDay *day, int role ) const; bool setDayState( CalendarDay *day, const QVariant &value, int role ); /* QVariant intervalStart( const TimeInterval *ti, int role ) const; bool setIntervalStart( TimeInterval *ti, const QVariant &value, int role ); QVariant intervalEnd( const TimeInterval *ti, int role ) const; bool setIntervalEnd( TimeInterval *ti, const QVariant &value, int role );*/ QVariant workDuration( const CalendarDay *day, int role ) const; // QVariant intervalDuration( const TimeInterval *ti, int role ) const; void addIntervals( CalendarDay *day ); void removeIntervals( CalendarDay *day ); }; //-----> class PLANMODELS_EXPORT DateTableDataModel : public KDateTableDataModel { Q_OBJECT public: explicit DateTableDataModel(QObject *parent); /// Fetch data for @p date, @p dataType specifies the type of data virtual QVariant data( const QDate &date, int role = Qt::DisplayRole, int dataType = -1 ) const; virtual QVariant weekDayData( int day, int role = Qt::DisplayRole ) const; virtual QVariant weekNumberData( int week, int role = Qt::DisplayRole ) const; public Q_SLOTS: - void setCalendar( Calendar *calendar ); + void setCalendar(KPlato::Calendar *calendar); Q_SIGNALS: void reset(); void dataChanged( const QDate &start, const QDate &end ); protected: QVariant data( const Calendar &cal, const QDate &date, int role ) const; private: Calendar *m_calendar; }; //------- class PLANMODELS_EXPORT DateTableDateDelegate : public KDateTableDateDelegate { Q_OBJECT public: explicit DateTableDateDelegate(QObject *parent = 0); ~DateTableDateDelegate() {} virtual QRectF paint( QPainter *painter, const StyleOptionViewItem &option, const QDate &date, KDateTableDataModel *model ); }; class PLANMODELS_EXPORT CalendarExtendedItemModel : public CalendarItemModel { Q_OBJECT public: explicit CalendarExtendedItemModel( QObject *parent = 0 ); virtual Qt::ItemFlags flags( const QModelIndex & index ) const; using CalendarItemModel::index; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; int columnNumber( const QString &name ) const; }; } //KPlato namespace #endif diff --git a/src/libs/models/kptdocumentmodel.h b/src/libs/models/kptdocumentmodel.h index 86cf73cc..2067c7de 100644 --- a/src/libs/models/kptdocumentmodel.h +++ b/src/libs/models/kptdocumentmodel.h @@ -1,126 +1,126 @@ /* This file is part of the KDE project Copyright (C) 2007 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 KPTDOCUMENTMODEL_H #define KPTDOCUMENTMODEL_H #include "kptitemmodelbase.h" namespace KPlato { class Document; class Documents; class PLANMODELS_EXPORT DocumentModel : public QObject { Q_OBJECT public: enum Properties { Property_Url = 0, Property_Name, Property_Type, Property_SendAs, Property_Status }; DocumentModel() : QObject() {} ~DocumentModel() {} QVariant data( const Document *doc, int property, int role = Qt::DisplayRole ) const; static bool setData( Document *doc, int property, const QVariant & value, int role = Qt::EditRole ); static QVariant headerData( int section, int role = Qt::DisplayRole ); static int propertyCount(); QVariant url( const Document *doc, int role ) const; QVariant name( const Document *doc, int role ) const; bool setName( Document *doc, const QVariant &value, int role ); QVariant type( const Document *doc, int role ) const; bool setType( Document *doc, const QVariant &value, int role ); QVariant status( const Document *doc, int role ) const; QVariant sendAs( const Document *doc, int role ) const; bool setSendAs( Document *doc, const QVariant &value, int role ); }; class PLANMODELS_EXPORT DocumentItemModel : public ItemModelBase { Q_OBJECT public: explicit DocumentItemModel( QObject *parent = 0 ); ~DocumentItemModel(); virtual void setDocuments( Documents *docs ); Documents *documents() const; virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; virtual QModelIndex index( const Document *doc ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; virtual QMimeData * mimeData( const QModelIndexList & indexes ) const; virtual QStringList mimeTypes () const; virtual Qt::DropActions supportedDropActions() const; virtual bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ); Document *document( const QModelIndex &index ) const; QAbstractItemDelegate *createDelegate( int column, QWidget *parent ) const; QModelIndex insertDocument( Document *doc, Document *after ); bool dropAllowed( Document *on, const QMimeData *data ); virtual bool dropAllowed( const QModelIndex &index, int dropIndicatorPosition, const QMimeData *data ); protected Q_SLOTS: - void slotDocumentChanged( Document* ); - void slotDocumentToBeInserted( Documents*, int row ); - void slotDocumentInserted( Document* ); - void slotDocumentToBeRemoved( Document* ); - void slotDocumentRemoved( Document* ); + void slotDocumentChanged(KPlato::Document*); + void slotDocumentToBeInserted(KPlato::Documents*, int row); + void slotDocumentInserted(KPlato::Document*); + void slotDocumentToBeRemoved(KPlato::Document*); + void slotDocumentRemoved(KPlato::Document*); protected: bool setUrl( Document *doc, const QVariant &value, int role ); bool setName( Document *doc, const QVariant &value, int role ); bool setType( Document *doc, const QVariant &value, int role ); bool setSendAs( Document *doc, const QVariant &value, int role ); private: Documents *m_documents; DocumentModel m_model; }; } //namespace KPlato #endif diff --git a/src/libs/models/kptitemmodelbase.h b/src/libs/models/kptitemmodelbase.h index 38c19bc0..0c760e1e 100644 --- a/src/libs/models/kptitemmodelbase.h +++ b/src/libs/models/kptitemmodelbase.h @@ -1,323 +1,323 @@ /* This file is part of the KDE project Copyright (C) 2006 - 2009 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 KPTITEMMODELBASE_H #define KPTITEMMODELBASE_H #include "planmodels_export.h" #include "kptglobal.h" #include "kpttreecombobox.h" #include #include #include #include class KUndo2Command; /// The main namespace namespace KPlato { class Project; class ScheduleManager; /// Namespace for item delegate specific enums namespace Delegate { /// For selector delegate enum EditorType { EnumEditor, TimeEditor }; /// Controls action when editor is closed. See QAbstractItemDelegate::EndEditHint. enum EndEditHint { NoHint = QAbstractItemDelegate::NoHint, EditNextItem = QAbstractItemDelegate::EditNextItem, EditPreviousItem = QAbstractItemDelegate::EditPreviousItem, SubmitModelCache = QAbstractItemDelegate::SubmitModelCache, RevertModelCache = QAbstractItemDelegate::RevertModelCache, EditLeftItem = 100, EditRightItem = 101, EditDownItem = 102, EditUpItem = 103 }; } /// ItemDelegate implements improved control over closeEditor class PLANMODELS_EXPORT ItemDelegate : public QStyledItemDelegate { Q_OBJECT public: /// Constructor explicit ItemDelegate(QObject *parent = 0) : QStyledItemDelegate( parent ), m_lastHint( Delegate::NoHint ) {} /// Extend EndEditHint for movement from edited item to next item to edit Delegate::EndEditHint endEditHint() const { return m_lastHint; } /// Increase the sizehint height a little to give room for editors QSize sizeHint( const QStyleOptionViewItem & option, const QModelIndex & index ) const; protected: /// Implements arrow key navigation bool eventFilter(QObject *object, QEvent *event); /// Draw custom focus // virtual void drawFocus(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect ) const; private: Delegate::EndEditHint m_lastHint; }; class PLANMODELS_EXPORT CheckStateItemDelegate : public ItemDelegate { Q_OBJECT public: explicit CheckStateItemDelegate(QObject *parent = 0); protected: bool editorEvent( QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index ); }; class PLANMODELS_EXPORT DateTimeCalendarDelegate : public ItemDelegate { Q_OBJECT public: explicit DateTimeCalendarDelegate(QObject *parent = 0); QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const; void setEditorData( QWidget *editor, const QModelIndex &index ) const; void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const; void updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const; }; class PLANMODELS_EXPORT ProgressBarDelegate : public ItemDelegate { Q_OBJECT public: explicit ProgressBarDelegate(QObject *parent = 0); ~ProgressBarDelegate(); void paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const; QSize sizeHint( const QStyleOptionViewItem &option, const QModelIndex &index ) const; QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const; void setEditorData( QWidget *editor, const QModelIndex &index ) const; void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const; void updateEditorGeometry( QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index ) const; protected: void initStyleOptionProgressBar( QStyleOptionProgressBar *option, const QModelIndex &index ) const; }; class Slider : public QSlider { Q_OBJECT public: explicit Slider( QWidget *parent ); private Q_SLOTS: void updateTip( int value ); }; class PLANMODELS_EXPORT SelectorDelegate : public ItemDelegate { Q_OBJECT public: explicit SelectorDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; class PLANMODELS_EXPORT EnumDelegate : public ItemDelegate { Q_OBJECT public: explicit EnumDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; //------------------------------------ class PLANMODELS_EXPORT RequieredResourceDelegate : public ItemDelegate { Q_OBJECT public: explicit RequieredResourceDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; class PLANMODELS_EXPORT DurationSpinBoxDelegate : public ItemDelegate { Q_OBJECT public: explicit DurationSpinBoxDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; class PLANMODELS_EXPORT SpinBoxDelegate : public ItemDelegate { Q_OBJECT public: explicit SpinBoxDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; class PLANMODELS_EXPORT DoubleSpinBoxDelegate : public ItemDelegate { Q_OBJECT public: explicit DoubleSpinBoxDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; class PLANMODELS_EXPORT MoneyDelegate : public ItemDelegate { Q_OBJECT public: explicit MoneyDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; class PLANMODELS_EXPORT TimeDelegate : public ItemDelegate { Q_OBJECT public: explicit TimeDelegate(QObject *parent = 0); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const; void setEditorData(QWidget *editor, const QModelIndex &index) const; void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const; void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; class PLANMODELS_EXPORT ItemModelBase : public QAbstractItemModel { Q_OBJECT public: // FIXME: Refactor, This is a copy from protected enum in QAbstractItemView enum DropIndicatorPosition { OnItem, /*QAbstractItemView::OnItem*/ /// The item will be dropped on the index. AboveItem, /*QAbstractItemView::AboveItem*/ /// The item will be dropped above the index. BelowItem, /*QAbstractItemView::BelowItem*/ /// The item will be dropped below the index. OnViewport /*QAbstractItemView::OnViewport*/ /// The item will be dropped onto a region of the viewport with no items if acceptDropsOnView is set. }; explicit ItemModelBase( QObject *parent = 0 ); virtual ~ItemModelBase(); virtual const QMetaEnum columnMap() const { return QMetaEnum(); } Project *project() const { return m_project; } ScheduleManager *scheduleManager() const { return m_manager; } bool isReadWrite() { return m_readWrite; } void setReadOnly( int column, bool ro ) { m_columnROMap[ column ] = ro; } /// Returns true if @p column has been set to ReadOnly. bool isColumnReadOnly( int column ) const { return m_columnROMap.contains( column ) && m_columnROMap[ column ]; } /** * Check if the @p data is allowed to be dropped on @p index, * @p dropIndicatorPosition indicates position relative @p index. * * Base implementation checks flags and mimetypes. */ virtual bool dropAllowed( const QModelIndex &index, int dropIndicatorPosition, const QMimeData *data ); /// Create the correct delegate for @p column. @p parent is the delegates parent widget. /// If default should be used, return 0. virtual QAbstractItemDelegate *createDelegate( int column, QWidget *parent ) const { Q_UNUSED(column); Q_UNUSED(parent); return 0; } QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; bool setData( const QModelIndex &index, const QVariant &value, int role ); QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; /// Return the sortorder to be used for @p column virtual int sortRole( int /*column*/ ) const { return Qt::DisplayRole; } Q_SIGNALS: /// Connect to this signal if your model modifies data using undo commands. void executeCommand( KUndo2Command* ); public Q_SLOTS: - virtual void setProject( Project *project ); - virtual void setScheduleManager( ScheduleManager *sm ); + virtual void setProject(KPlato::Project *project); + virtual void setScheduleManager(KPlato::ScheduleManager *sm); virtual void setReadWrite( bool rw ) { m_readWrite = rw; } /// Reimplement if your model can be refreshed virtual void refresh() {} protected Q_SLOTS: virtual void slotLayoutToBeChanged(); virtual void slotLayoutChanged(); void projectDeleted(); protected: Project *m_project; ScheduleManager *m_manager; bool m_readWrite; QMap m_columnROMap; }; } // namespace KPlato #endif diff --git a/src/libs/models/kptnodechartmodel.cpp b/src/libs/models/kptnodechartmodel.cpp index 38c5d4ea..a75bb764 100644 --- a/src/libs/models/kptnodechartmodel.cpp +++ b/src/libs/models/kptnodechartmodel.cpp @@ -1,549 +1,549 @@ /* This file is part of the Calligra project * Copyright (c) 2008, 2012 Dag Andersen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptnodechartmodel.h" #include "kptlocale.h" #include "kptnode.h" #include "kptproject.h" #include "kptschedule.h" #include "kptresource.h" #include "kptdebug.h" #include #include #include #include #include namespace KPlato { ChartItemModel::ChartItemModel( QObject *parent ) : ItemModelBase( parent ), m_localizeValues( false ) { } QModelIndex ChartItemModel::parent( const QModelIndex &index ) const { Q_UNUSED(index); return QModelIndex(); } const QMetaEnum ChartItemModel::columnMap() const { return metaObject()->enumerator( metaObject()->indexOfEnumerator("Properties") ); } int ChartItemModel::columnCount( const QModelIndex &/*parent*/ ) const { return columnMap().keyCount(); } int ChartItemModel::rowCount( const QModelIndex &parent ) const { return parent.isValid() ? 0 : startDate().daysTo( endDate() ) + 1; } QModelIndex ChartItemModel::index( int row, int column, const QModelIndex &parent ) const { if ( m_project == 0 || row < 0 || column < 0 ) { //debugPlan<<"No project"< m_bcws.endDate() ) { res = m_bcws.bcwpEffort( date ); } return res; } double ChartItemModel::acwpEffort( int day ) const { return m_acwp.hoursTo( startDate().addDays( day ) ); } double ChartItemModel::bcwsCost( int day ) const { return m_bcws.costTo( startDate().addDays( day ) ); } double ChartItemModel::bcwpCost( int day ) const { double res = 0.0; QDate date = startDate().addDays( day ); if ( m_bcws.days().contains( date ) ) { res = m_bcws.bcwpCost( date ); } else if ( date > m_bcws.endDate() ) { res = m_bcws.bcwpCost( m_bcws.endDate() ); } return res; } double ChartItemModel::acwpCost( int day ) const { return m_acwp.costTo( startDate().addDays( day ) ); } double ChartItemModel::spiEffort( int day ) const { double p = bcwpEffort( day ); double s = bcwsEffort( day ); return s == 0.0 ? 0.0 : p / s; } double ChartItemModel::spiCost( int day ) const { double p = bcwpCost( day ); double s = bcwsCost( day ); return s == 0.0 ? 0.0 : p / s; } double ChartItemModel::cpiEffort( int day ) const { double p = bcwpEffort( day ); double a = acwpEffort( day ); return a == 0.0 ? 0.0 : p / a; } double ChartItemModel::cpiCost( int day ) const { double p = bcwpCost( day ); double a = acwpCost( day ); return a == 0.0 ? 0.0 : p / a; } QVariant ChartItemModel::data( const QModelIndex &index, int role ) const { QVariant result; if ( role == Qt::DisplayRole ) { if ( ! m_localizeValues ) { return data( index, Qt::EditRole ); } else { QLocale locale; // TODO: temporary workaround while KLocale/money logic still used Locale *planLocale; Locale *tmpPlanLocale = 0; if (project()) { planLocale = project()->locale(); } else { tmpPlanLocale = new Locale(); planLocale = tmpPlanLocale; } switch ( index.column() ) { case BCWSCost: result = planLocale->formatMoney( bcwsCost( index.row() ), QString(), 0 ); break; case BCWPCost: result = planLocale->formatMoney( bcwpCost( index.row() ), QString(), 0 ); break; case ACWPCost: result = planLocale->formatMoney( acwpCost( index.row() ), QString(), 0 ); break; case BCWSEffort: result = locale.toString( bcwsEffort( index.row() ), 'f', 0 ); break; case BCWPEffort: result = locale.toString( bcwpEffort( index.row() ), 'f', 0 ); break; case ACWPEffort: result = locale.toString( acwpEffort( index.row() ), 'f', 0 ); break; case SPICost: result = locale.toString( spiCost( index.row() ), 'f', 2 ); break; case CPICost: result = locale.toString( cpiCost( index.row() ), 'f', 2 ); break; case SPIEffort: result = locale.toString( spiEffort( index.row() ), 'f', 2 ); break; case CPIEffort: result = locale.toString( cpiEffort( index.row() ), 'f', 2 ); break; default: break; } delete tmpPlanLocale; } //debugPlan< 0.0 && v < 1.0 ) { result = QBrush( Qt::red ); } return result; } else if ( role == KChart::DatasetBrushRole ) { return headerData( index.column(), Qt::Horizontal, role ); } else if ( role == KChart::DatasetPenRole ) { return headerData( index.column(), Qt::Horizontal, role ); } //debugPlan<() ); result = p; //debugPlan< &nodes ) { beginResetModel(); debugPlan<isChildOf( n ) ) { beginResetModel(); calculate(); endResetModel(); return; } } } void ChartItemModel::slotResourceChanged( Resource* ) { beginResetModel(); calculate(); endResetModel(); } void ChartItemModel::slotResourceChanged( const Resource* ) { beginResetModel(); calculate(); endResetModel(); } QDate ChartItemModel::startDate() const { QDate d = m_bcws.startDate(); if ( m_acwp.startDate().isValid() ) { if ( ! d.isValid() || d > m_acwp.startDate() ) { d = m_acwp.startDate(); } } return d; } QDate ChartItemModel::endDate() const { return qMax( m_bcws.endDate(), m_acwp.endDate() ); } void ChartItemModel::calculate() { //debugPlan<isChildOf( p ) ) { skip = true; break; } } if ( ! skip ) { m_bcws += n->bcwpPrDay( m_manager->scheduleId(), ECCT_EffortWork ); m_acwp += n->acwp( m_manager->scheduleId() ); } } } } //debugPlan<<"bcwp"< * * 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 KPTNODECHARTMODEL_H #define KPTNODECHARTMODEL_H #include "planmodels_export.h" #include "kptitemmodelbase.h" #include "kpteffortcostmap.h" #include #include "kptdebug.h" #include namespace KPlato { class Resource; class Project; class ScheduleManager; class Node; class PLANMODELS_EXPORT ChartProxyModel : public QSortFilterProxyModel { Q_OBJECT public: explicit ChartProxyModel(QObject *parent = 0) : QSortFilterProxyModel( parent ) {} QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const { //if ( role == Qt::DisplayRole && orientation == Qt::Vertical ) debugPlan<<"fetch:"< &columns ) { m_rejects = columns; invalidateFilter(); } QList rejectColumns() const { return m_rejects; } void setZeroColumns( const QList &columns ) { m_zerocolumns = columns; } QList zeroColumns() const { return m_zerocolumns; } void reset() { beginResetModel(); endResetModel(); } protected: bool filterAcceptsColumn ( int source_column, const QModelIndex &/*source_parent */) const { //debugPlan< m_rejects; QList m_zerocolumns; }; class PLANMODELS_EXPORT ChartItemModel : public ItemModelBase { Q_OBJECT Q_ENUMS( Properties ) public: enum Properties { BCWSCost, BCWPCost, ACWPCost, BCWSEffort, BCWPEffort, ACWPEffort, SPICost, CPICost, SPIEffort, CPIEffort }; const QMetaEnum columnMap() const; explicit ChartItemModel(QObject *parent = 0); // virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; const EffortCostMap &bcwp() const { return m_bcws; } const EffortCostMap &acwp() const { return m_acwp; } void setProject( Project *project ); void setNodes( const QList &nodes ); void addNode( Node *node ); void clearNodes(); QDate startDate() const; QDate endDate() const; void calculate(); void setLocalizeValues( bool on ); public Q_SLOTS: - void setScheduleManager( ScheduleManager *sm ); - void slotNodeRemoved( Node *node ); - void slotNodeChanged( Node *node ); - void slotResourceChanged( Resource *resource ); - void slotResourceChanged( const Resource *resource ); + void setScheduleManager(KPlato::ScheduleManager *sm); + void slotNodeRemoved(KPlato::Node *node); + void slotNodeChanged(KPlato::Node *node); + void slotResourceChanged(KPlato::Resource *resource); + void slotResourceChanged(const KPlato::Resource *resource); protected: double bcwsEffort( int day ) const; double bcwpEffort( int day ) const; double acwpEffort( int day ) const; double bcwsCost( int day ) const; double bcwpCost( int day ) const; double acwpCost( int day ) const; double spiEffort( int day ) const; double cpiEffort( int day ) const; double spiCost( int day ) const; double cpiCost( int day ) const; protected: QList m_nodes; EffortCostMap m_bcws; EffortCostMap m_acwp; bool m_localizeValues; }; class PLANMODELS_EXPORT PerformanceDataCurrentDateModel : public ChartItemModel { Q_OBJECT public: explicit PerformanceDataCurrentDateModel(QObject *parent); int rowCount( const QModelIndex &parent = QModelIndex() ) const; int columnCount( const QModelIndex &parent = QModelIndex() ) const; QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const; QVariant data( const QModelIndex &proxyIndex, int role = Qt::DisplayRole ) const; QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; QModelIndex mapIndex( const QModelIndex &idx ) const; }; } //namespace KPlato #endif diff --git a/src/libs/models/kptnodeitemmodel.cpp b/src/libs/models/kptnodeitemmodel.cpp index 185de255..b67a3b87 100644 --- a/src/libs/models/kptnodeitemmodel.cpp +++ b/src/libs/models/kptnodeitemmodel.cpp @@ -1,5209 +1,5209 @@ /* This file is part of the KDE project Copyright (C) 2007 - 2009, 2012 Dag Andersen Copyright (C) 2016 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptnodeitemmodel.h" #include "kptglobal.h" #include "kptlocale.h" #include "kptcommonstrings.h" #include "kptcommand.h" #include "kptduration.h" #include "kptproject.h" #include "kptnode.h" #include "kpttaskcompletedelegate.h" #include "kptxmlloaderobject.h" #include "kptdebug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace KPlato { //-------------------------------------- NodeModel::NodeModel() : QObject(), m_project( 0 ), m_manager( 0 ), m_now( QDate::currentDate() ), m_prec( 1 ) { } const QMetaEnum NodeModel::columnMap() const { return metaObject()->enumerator( metaObject()->indexOfEnumerator("Properties") ); } void NodeModel::setProject( Project *project ) { debugPlan<"<"<name(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Qt::DecorationRole: if ( node->isBaselined() ) { return koIcon("view-time-schedule-baselined"); } break; case Role::Foreground: { if ( ! m_project ) { break; } switch ( node->type() ) { case Node::Type_Task: return static_cast( node )->completion().isFinished() ? m_project->config().taskFinishedColor() : m_project->config().taskNormalColor(); case Node::Type_Milestone: return static_cast( node )->completion().isFinished() ? m_project->config().milestoneFinishedColor() : m_project->config().milestoneNormalColor(); case Node::Type_Summarytask: return m_project->config().summaryTaskLevelColor( node->level() ); default: break; } break; } } return QVariant(); } QVariant NodeModel::leader( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return node->leader(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::allocation( const Node *node, int role ) const { if ( node->type() == Node::Type_Task ) { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return node->requests().requestNameList().join( "," ); case Qt::ToolTipRole: { QMap lst; foreach ( ResourceRequest *rr, node->requests().resourceRequests( false ) ) { QStringList sl; foreach( Resource *r, rr->requiredResources() ) { sl << r->name(); } lst.insert( rr->resource()->name(), sl ); } if ( lst.isEmpty() ) { return xi18nc( "@info:tooltip", "No resources has been allocated" ); } QStringList sl; for ( QMap::ConstIterator it = lst.constBegin(); it != lst.constEnd(); ++it ) { if ( it.value().isEmpty() ) { sl << it.key(); } else { sl << xi18nc( "@info:tooltip 1=resource name, 2=list of required resources", "%1 (%2)", it.key(), it.value().join(", ") ); } } if ( sl.count() == 1 ) { return xi18nc( "@info:tooltip 1=resource name", "Allocated resource:%1", sl.first() ); } KLocalizedString ks = kxi18nc( "@info:tooltip 1=list of resources", "Allocated resources:%1"); // Hack to get around ks escaping '<' and '>' QString s = ks.subs(sl.join("#¤#")).toString(); return s.replace("#¤#", "
"); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } } return QVariant(); } QVariant NodeModel::description( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: { KRichTextWidget w( node->description(), 0 ); w.switchToPlainText(); QString s = w.textOrHtml(); int i = s.indexOf( '\n' ); s = s.left( i ); if ( i > 0 ) { s += "..."; } return s; } case Qt::ToolTipRole: { KRichTextWidget w( node->description(), 0 ); w.switchToPlainText(); if ( w.textOrHtml().isEmpty() ) { return QVariant(); } return node->description(); } case Qt::EditRole: return node->description(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::type( const Node *node, int role ) const { //debugPlan<name()<<", "<typeToString( true ); case Qt::EditRole: return node->type(); case Qt::TextAlignmentRole: return (int)(Qt::AlignLeft|Qt::AlignVCenter); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::constraint( const Node *node, int role ) const { if ( node->type() == Node::Type_Project ) { switch ( role ) { case Qt::DisplayRole: return i18n( "Target times" ); case Qt::ToolTipRole: return xi18nc( "@info:tooltip", "Earliest start and latest finish" ); case Role::EnumList: case Qt::EditRole: case Role::EnumListValue: return QVariant(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } } else if ( node->type() != Node::Type_Summarytask ) { switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: return node->constraintToString( true ); case Role::EnumList: return Node::constraintList( true ); case Qt::EditRole: return node->constraint(); case Role::EnumListValue: return (int)node->constraint(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } } return QVariant(); } QVariant NodeModel::constraintStartTime( const Node *node, int role ) const { if ( node->type() == Node::Type_Project ) { switch ( role ) { case Qt::DisplayRole: { return QLocale().toString( node->constraintStartTime(), QLocale::ShortFormat ); } case Qt::ToolTipRole: { return QLocale().toString( node->constraintStartTime(), QLocale::LongFormat ); } case Qt::EditRole: return node->constraintStartTime(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } else if ( node->type() != Node::Type_Summarytask ) { switch ( role ) { case Qt::DisplayRole: { QString s = QLocale().toString( node->constraintStartTime(), QLocale::ShortFormat ); switch ( node->constraint() ) { case Node::StartNotEarlier: case Node::MustStartOn: case Node::FixedInterval: return s; default: break; } return QString( "(%1)" ).arg( s ); } case Qt::ToolTipRole: { int c = node->constraint(); if ( c == Node::MustStartOn || c == Node::StartNotEarlier || c == Node::FixedInterval ) { return QLocale().toString( node->constraintStartTime(), QLocale::LongFormat ); } break; } case Qt::EditRole: return node->constraintStartTime(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } } return QVariant(); } QVariant NodeModel::constraintEndTime( const Node *node, int role ) const { if ( node->type() == Node::Type_Project ) { switch ( role ) { case Qt::DisplayRole: { return QLocale().toString( node->constraintEndTime(), QLocale::ShortFormat ); } case Qt::ToolTipRole: { return QLocale().toString( node->constraintEndTime(), QLocale::LongFormat ); } case Qt::EditRole: return node->constraintEndTime(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } else if ( node->type() != Node::Type_Summarytask ) { switch ( role ) { case Qt::DisplayRole: { QString s = QLocale().toString( node->constraintEndTime(), QLocale::ShortFormat ); switch ( node->constraint() ) { case Node::FinishNotLater: case Node::MustFinishOn: case Node::FixedInterval: return s; default: break; } return QString( "(%1)" ).arg( s ); } case Qt::ToolTipRole: { int c = node->constraint(); if ( c == Node::FinishNotLater || c == Node::MustFinishOn || c == Node::FixedInterval ) { return QLocale().toString( node->constraintEndTime(), QLocale::LongFormat ); } break; } case Qt::EditRole: return node->constraintEndTime(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } } return QVariant(); } QVariant NodeModel::estimateType( const Node *node, int role ) const { if ( node->estimate() == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: if ( node->type() == Node::Type_Task ) { return node->estimate()->typeToString( true ); } return QString(); case Role::EnumList: return Estimate::typeToStringList( true ); case Qt::EditRole: if ( node->type() == Node::Type_Task ) { return node->estimate()->typeToString(); } return QString(); case Role::EnumListValue: return (int)node->estimate()->type(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::estimateCalendar( const Node *node, int role ) const { if ( node->estimate() == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: if ( node->type() == Node::Type_Task ) { if ( node->estimate()->calendar() ) { return node->estimate()->calendar()->name(); } return i18n( "None" ); } return QString(); case Qt::ToolTipRole: if ( node->type() == Node::Type_Task ) { if ( node->estimate()->type() == Estimate::Type_Effort ) { return xi18nc( "@info:tooltip", "Not applicable, estimate type is Effort" ); } if ( node->estimate()->calendar() ) { return node->estimate()->calendar()->name(); } return QVariant(); } return QString(); case Role::EnumList: { QStringList lst; lst << i18n( "None" ); const Node *n = const_cast( node )->projectNode(); if ( n ) { lst += static_cast( n )->calendarNames(); } return lst; } case Qt::EditRole: if ( node->type() == Node::Type_Task ) { if ( node->estimate()->calendar() == 0 ) { return i18n( "None" ); } return node->estimate()->calendar()->name(); } return QString(); case Role::EnumListValue: { if ( node->estimate()->calendar() == 0 ) { return 0; } QStringList lst; const Node *n = const_cast( node )->projectNode(); if ( n ) { lst = static_cast( n )->calendarNames(); } return lst.indexOf( node->estimate()->calendar()->name() ) + 1; } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::estimate( const Node *node, int role ) const { if ( node->estimate() == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { Duration::Unit unit = node->estimate()->unit(); QString s = QLocale().toString( node->estimate()->expectedEstimate(), 'f', m_prec ) + Duration::unitToString( unit, true ); if ( node->constraint() == Node::FixedInterval && node->estimate()->type() == Estimate::Type_Duration ) { s = '(' + s + ')'; } return s; } break; case Qt::ToolTipRole: if ( node->type() == Node::Type_Task ) { Duration::Unit unit = node->estimate()->unit(); QString s = QLocale().toString( node->estimate()->expectedEstimate(), 'f', m_prec ) + Duration::unitToString( unit, true ); Estimate::Type t = node->estimate()->type(); if ( node->constraint() == Node::FixedInterval && t == Estimate::Type_Duration ) { s = xi18nc( "@info:tooltip", "Not applicable, constraint is Fixed Interval" ); } else if ( t == Estimate::Type_Effort ) { s = xi18nc( "@info:tooltip", "Estimated effort: %1", s ); } else { s = xi18nc( "@info:tooltip", "Estimated duration: %1", s ); } return s; } break; case Qt::EditRole: return node->estimate()->expectedEstimate(); case Role::DurationUnit: return static_cast( node->estimate()->unit() ); case Role::Minimum: return m_project->config().minimumDurationUnit(); case Role::Maximum: return m_project->config().maximumDurationUnit(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::optimisticRatio( const Node *node, int role ) const { if ( node->estimate() == 0 || node->type() == Node::Type_Summarytask || node->type() == Node::Type_Milestone ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: if ( node->type() == Node::Type_Task && node->constraint() == Node::FixedInterval && node->estimate()->type() == Estimate::Type_Duration ) { QString s = QString::number( node->estimate()->optimisticRatio() ); s = '(' + s + ')'; return s; } if ( node->estimate() ) { return node->estimate()->optimisticRatio(); } break; case Qt::EditRole: if ( node->estimate() ) { return node->estimate()->optimisticRatio(); } break; case Qt::ToolTipRole: if ( node->type() == Node::Type_Task ) { Duration::Unit unit = node->estimate()->unit(); QString s = QLocale().toString( node->estimate()->optimisticEstimate(), 'f', m_prec ) + Duration::unitToString( unit, true ); Estimate::Type t = node->estimate()->type(); if ( node->constraint() == Node::FixedInterval && t == Estimate::Type_Duration ) { s = xi18nc( "@info:tooltip", "Not applicable, constraint is Fixed Interval" ); } else if ( t == Estimate::Type_Effort ) { s = xi18nc( "@info:tooltip", "Optimistic effort: %1", s ); } else { s = xi18nc( "@info:tooltip", "Optimistic duration: %1", s ); } return s; } break; case Role::Minimum: return -99; case Role::Maximum: return 0; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::pessimisticRatio( const Node *node, int role ) const { if ( node->estimate() == 0 || node->type() == Node::Type_Summarytask || node->type() == Node::Type_Milestone ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: if ( node->type() == Node::Type_Task && node->constraint() == Node::FixedInterval && node->estimate()->type() == Estimate::Type_Duration ) { QString s = QString::number( node->estimate()->pessimisticRatio() ); s = '(' + s + ')'; return s; } if ( node->estimate() ) { return node->estimate()->pessimisticRatio(); } break; case Qt::EditRole: if ( node->estimate() ) { return node->estimate()->pessimisticRatio(); } break; case Qt::ToolTipRole: if ( node->type() == Node::Type_Task ) { Duration::Unit unit = node->estimate()->unit(); QString s = QLocale().toString( node->estimate()->pessimisticEstimate(), 'f', m_prec ) + Duration::unitToString( unit, true ); Estimate::Type t = node->estimate()->type(); if ( node->constraint() == Node::FixedInterval && t == Estimate::Type_Duration ) { s = xi18nc( "@info:tooltip", "Not applicable, constraint is Fixed Interval" ); } else if ( t == Estimate::Type_Effort ) { s = xi18nc( "@info:tooltip", "Pessimistic effort: %1", s ); } else { s = xi18nc( "@info:tooltip", "Pessimistic duration: %1", s ); } return s; } break; case Role::Minimum: return 0; case Role::Maximum: return INT_MAX; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::riskType( const Node *node, int role ) const { if ( node->estimate() == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: if ( node->type() == Node::Type_Task ) { return node->estimate()->risktypeToString( true ); } return QString(); case Role::EnumList: return Estimate::risktypeToStringList( true ); case Qt::EditRole: if ( node->type() == Node::Type_Task ) { return node->estimate()->risktypeToString(); } return QString(); case Role::EnumListValue: return (int)node->estimate()->risktype(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::runningAccount( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( node->type() == Node::Type_Task ) { Account *a = node->runningAccount(); return a == 0 ? i18n( "None" ) : a->name(); } break; case Qt::ToolTipRole: if ( node->type() == Node::Type_Task ) { Account *a = node->runningAccount(); return a ? xi18nc( "@info:tooltip", "Account for resource cost: %1", a->name() ) : xi18nc( "@info:tooltip", "Account for resource cost" ); } break; case Role::EnumListValue: case Qt::EditRole: { Account *a = node->runningAccount(); return a == 0 ? 0 : ( m_project->accounts().costElements().indexOf( a->name() ) + 1 ); } case Role::EnumList: { QStringList lst; lst << i18n("None"); lst += m_project->accounts().costElements(); return lst; } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::startupAccount( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { Account *a = node->startupAccount(); //debugPlan<name()<<": "<name(); } break; case Qt::ToolTipRole: if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { Account *a = node->startupAccount(); //debugPlan<name()<<": "<name() ) : xi18nc( "@info:tooltip", "Account for task startup cost" ); } break; case Role::EnumListValue: case Qt::EditRole: { Account *a = node->startupAccount(); return a == 0 ? 0 : ( m_project->accounts().costElements().indexOf( a->name() ) + 1 ); } case Role::EnumList: { QStringList lst; lst << i18n("None"); lst += m_project->accounts().costElements(); return lst; } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::startupCost( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { return m_project->locale()->formatMoney( node->startupCost() ); } break; case Qt::EditRole: return node->startupCost(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::shutdownAccount( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { Account *a = node->shutdownAccount(); return a == 0 ? i18n( "None" ) : a->name(); } break; case Qt::ToolTipRole: if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { Account *a = node->shutdownAccount(); return a ? xi18nc( "@info:tooltip", "Account for task shutdown cost: %1", a->name() ) : xi18nc( "@info:tooltip", "Account for task shutdown cost" ); } break; case Role::EnumListValue: case Qt::EditRole: { Account *a = node->shutdownAccount(); return a == 0 ? 0 : ( m_project->accounts().costElements().indexOf( a->name() ) + 1 ); } case Role::EnumList: { QStringList lst; lst << i18n("None"); lst += m_project->accounts().costElements(); return lst; } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::shutdownCost( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: if ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) { return m_project->locale()->formatMoney( node->shutdownCost() ); } break; case Qt::EditRole: return node->shutdownCost(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::startTime( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return QLocale().toString( node->startTime( id() ), QLocale::ShortFormat ); case Qt::ToolTipRole: //debugPlan<name()<<", "<startTime( id() ), QLocale::LongFormat ) ); case Qt::EditRole: return node->startTime( id() ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::endTime( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return QLocale().toString( node->endTime( id() ), QLocale::ShortFormat ); case Qt::ToolTipRole: //debugPlan<name()<<", "<endTime( id() ), QLocale::LongFormat ) ); case Qt::EditRole: return node->endTime( id() ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::duration( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( node->type() == Node::Type_Task ) { Duration::Unit unit = node->estimate()->unit(); double v = node->duration( id() ).toDouble( unit ); return QVariant(QLocale().toString( v, 'f', m_prec ) + Duration::unitToString( unit, true )); } else if ( node->type() == Node::Type_Project ) { Duration::Unit unit = Duration::Unit_d; double v = node->duration( id() ).toDouble( unit ); return QVariant(QLocale().toString( v, 'f', m_prec ) + Duration::unitToString( unit, true )); } break; case Qt::ToolTipRole: if ( node->type() == Node::Type_Task ) { Duration::Unit unit = node->estimate()->unit(); double v = node->duration( id() ).toDouble( unit ); return xi18nc( "@info:tooltip", "Scheduled duration: %1", QLocale().toString( v, 'f', m_prec ) + Duration::unitToString( unit, true ) ); } else if ( node->type() == Node::Type_Project ) { Duration::Unit unit = Duration::Unit_d; double v = node->duration( id() ).toDouble( unit ); return xi18nc( "@info:tooltip", "Scheduled duration: %1", QLocale().toString( v, 'f', m_prec ) + Duration::unitToString( unit, true ) ); } break; case Qt::EditRole: { return node->duration( id() ).toDouble( Duration::Unit_h ); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::varianceDuration( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( node->type() == Node::Type_Task ) { Duration::Unit unit = node->estimate()->unit(); double v = node->variance( id(), unit ); return QLocale().toString( v, 'f', 2 ); } break; case Qt::EditRole: if ( node->type() == Node::Type_Task ) { Duration::Unit unit = node->estimate()->unit(); return node->variance( id(), unit ); } return 0.0; case Qt::ToolTipRole: if ( node->type() == Node::Type_Task ) { Duration::Unit unit = node->estimate()->unit(); double v = node->variance( id(), unit ); return xi18nc( "@info:tooltip", "PERT duration variance: %1", QLocale().toString( v ,'f', 2 ) ); } break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::varianceEstimate( const Estimate *est, int role ) const { switch ( role ) { case Qt::DisplayRole: { if ( est == 0 ) { return QVariant(); } Duration::Unit unit = est->unit(); double v = est->variance( unit ); //debugPlan<name()<<": "<variance( est->unit() ); } case Qt::ToolTipRole: { if ( est == 0 ) { return QVariant(); } Duration::Unit unit = est->unit(); double v = est->variance( unit ); return xi18nc( "@info:tooltip", "PERT estimate variance: %1", QLocale().toString( v, 'f', 2 ) + Duration::unitToString( unit, true ) ); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::optimisticDuration( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: { if ( node->type() != Node::Type_Task ) { return QVariant(); } Duration d = node->duration( id() ); d = ( d * ( 100 + node->estimate()->optimisticRatio() ) ) / 100; Duration::Unit unit = node->estimate()->unit(); double v = d.toDouble( unit ); //debugPlan<name()<<": "<type() != Node::Type_Task ) { return 0.0; } Duration d = node->duration( id() ); d = ( d * ( 100 + node->estimate()->optimisticRatio() ) ) / 100; Duration::Unit unit = node->estimate()->unit(); return d.toDouble( unit ); } case Qt::ToolTipRole: { if ( node->type() != Node::Type_Task ) { return QVariant(); } Duration d = node->duration( id() ); d = ( d * ( 100 + node->estimate()->optimisticRatio() ) ) / 100; Duration::Unit unit = node->estimate()->unit(); double v = d.toDouble( unit ); //debugPlan<name()<<": "<unit(); return QVariant(QLocale().toString( est->optimisticEstimate(), 'f', m_prec ) + Duration::unitToString( unit, true )); break; } case Qt::EditRole: { if ( est == 0 ) { return 0.0; } return est->optimisticEstimate(); } case Qt::ToolTipRole: { if ( est == 0 ) { return QVariant(); } Duration::Unit unit = est->unit(); return xi18nc( "@info:tooltip", "Optimistic estimate: %1", QLocale().toString( est->optimisticEstimate(), 'f', m_prec ) + Duration::unitToString( unit, true ) ); break; } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::pertExpected( const Estimate *est, int role ) const { switch ( role ) { case Qt::DisplayRole: { if ( est == 0 ) { return QVariant(); } Duration::Unit unit = est->unit(); double v = Estimate::scale( est->pertExpected(), unit, est->scales() ); return QVariant(QLocale().toString( v, 'f', m_prec ) + Duration::unitToString( unit, true )); } case Qt::EditRole: { if ( est == 0 ) { return 0.0; } return Estimate::scale( est->pertExpected(), est->unit(), est->scales() ); } case Qt::ToolTipRole: { if ( est == 0 ) { return QVariant(); } Duration::Unit unit = est->unit(); double v = Estimate::scale( est->pertExpected(), unit, est->scales() ); return xi18nc( "@info:tooltip", "PERT expected estimate: %1", QLocale().toString( v, 'f', m_prec ) + Duration::unitToString( unit, true ) ); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::pessimisticDuration( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: { if ( node->type() != Node::Type_Task ) { return QVariant(); } Duration d = node->duration( id() ); d = ( d * ( 100 + node->estimate()->pessimisticRatio() ) ) / 100; Duration::Unit unit = node->estimate()->unit(); double v = d.toDouble( unit ); //debugPlan<name()<<": "<type() != Node::Type_Task ) { return 0.0; } Duration d = node->duration( id() ); d = ( d * ( 100 + node->estimate()->pessimisticRatio() ) ) / 100; return d.toDouble( node->estimate()->unit() ); } case Qt::ToolTipRole: { if ( node->type() != Node::Type_Task ) { return QVariant(); } Duration d = node->duration( id() ); d = ( d * ( 100 + node->estimate()->pessimisticRatio() ) ) / 100; Duration::Unit unit = node->estimate()->unit(); double v = d.toDouble( unit ); //debugPlan<name()<<": "<unit(); return QVariant(QLocale().toString( est->pessimisticEstimate(), 'f', m_prec ) + Duration::unitToString( unit, true )); break; } case Qt::EditRole: { if ( est == 0 ) { return 0.0; } return est->pessimisticEstimate(); } case Qt::ToolTipRole: { if ( est == 0 ) { return QVariant(); } Duration::Unit unit = est->unit(); return xi18nc( "@info:tooltip", "Pessimistic estimate: %1", QLocale().toString( est->pessimisticEstimate(), 'f', m_prec ) + Duration::unitToString( unit, true ) ); break; } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::earlyStart( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: return QLocale().toString( t->earlyStart( id() ), QLocale::ShortFormat ); case Qt::ToolTipRole: return QLocale().toString( t->earlyStart( id() ).date(), QLocale::ShortFormat ); case Qt::EditRole: return t->earlyStart( id() ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::earlyFinish( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: return QLocale().toString( t->earlyFinish( id() ), QLocale::ShortFormat ); case Qt::ToolTipRole: return QLocale().toString( t->earlyFinish( id() ).date(), QLocale::ShortFormat ); case Qt::EditRole: return t->earlyFinish( id() ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::lateStart( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: return QLocale().toString( t->lateStart( id() ), QLocale::ShortFormat ); case Qt::ToolTipRole: return QLocale().toString( t->lateStart( id() ).date(), QLocale::ShortFormat ); case Qt::EditRole: return t->lateStart( id() ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::lateFinish( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: return QLocale().toString( t->lateFinish( id() ), QLocale::ShortFormat ); case Qt::ToolTipRole: return QLocale().toString( t->lateFinish( id() ).date(), QLocale::ShortFormat ); case Qt::EditRole: return t->lateFinish( id() ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::positiveFloat( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: return t->positiveFloat( id() ).toString( Duration::Format_i18nHourFraction ); case Qt::ToolTipRole: return t->positiveFloat( id() ).toString( Duration::Format_i18nDayTime ); case Qt::EditRole: return t->positiveFloat( id() ).toDouble( Duration::Unit_h ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::freeFloat( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: return t->freeFloat( id() ).toString( Duration::Format_i18nHourFraction ); case Qt::ToolTipRole: return t->freeFloat( id() ).toString( Duration::Format_i18nDayTime ); case Qt::EditRole: return t->freeFloat( id() ).toDouble( Duration::Unit_h ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::negativeFloat( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: return t->negativeFloat( id() ).toString( Duration::Format_i18nHourFraction ); case Qt::ToolTipRole: return t->negativeFloat( id() ).toString( Duration::Format_i18nDayTime ); case Qt::EditRole: return t->negativeFloat( id() ).toDouble( Duration::Unit_h ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::startFloat( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: return t->startFloat( id() ).toString( Duration::Format_i18nHourFraction ); case Qt::ToolTipRole: return t->startFloat( id() ).toString( Duration::Format_i18nDayTime ); case Qt::EditRole: return t->startFloat( id() ).toDouble( Duration::Unit_h ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::finishFloat( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: return t->finishFloat( id() ).toString( Duration::Format_i18nHourFraction ); case Qt::ToolTipRole: return t->finishFloat( id() ).toString( Duration::Format_i18nDayTime ); case Qt::EditRole: return t->finishFloat( id() ).toDouble( Duration::Unit_h ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::assignedResources( const Node *node, int role ) const { if ( node->type() != Node::Type_Task ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return node->assignedNameList( id() ).join(","); case Qt::ToolTipRole: { QStringList lst = node->assignedNameList( id() ); if ( ! lst.isEmpty() ) { return xi18nc( "@info:tooltip 1=list of resources", "Assigned resources:%1", node->assignedNameList( id() ).join("") ); } break; } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::completed( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: return t->completion().percentFinished(); case Qt::EditRole: return t->completion().percentFinished(); case Qt::ToolTipRole: return xi18nc( "@info:tooltip", "Task is %1% completed", t->completion().percentFinished() ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::status( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: { int st = t->state( id() ); if ( st & Node::State_NotScheduled ) { return SchedulingState::notScheduled(); } if ( st & Node::State_Finished ) { if ( st & Node::State_FinishedLate ) { return i18n( "Finished late" ); } if ( st & Node::State_FinishedEarly ) { return i18n( "Finished early" ); } return i18n( "Finished" ); } if ( st & Node::State_Running ) { if ( st & Node::State_Late ) { return i18n( "Running late" ); } return i18n( "Running" ); } if ( st & Node::State_Started ) { if ( st & Node::State_StartedLate ) { return i18n( "Started late" ); } if ( st & Node::State_StartedEarly ) { return i18n( "Started early" ); } if ( st & Node::State_Late ) { return i18n( "Running late" ); } return i18n( "Started" ); } if ( st & Node::State_ReadyToStart ) { if ( st & Node::State_Late ) { return i18n( "Not started" ); } return i18n( "Can start" ); } if ( st & Node::State_NotReadyToStart ) { if ( st & Node::State_Late ) { return i18n( "Delayed" ); } return i18n( "Cannot start" ); } return i18n( "Not started" ); break; } case Qt::ToolTipRole: { int st = t->state( id() ); if ( st & Node::State_NotScheduled ) { return SchedulingState::notScheduled(); } if ( st & Node::State_Finished ) { if ( st & Node::State_FinishedLate ) { Duration d = t->completion().finishTime() - t->endTime( id() ); return xi18nc( "@info:tooltip", "Finished %1 late", d.toString( Duration::Format_i18nDay ) ); } if ( st & Node::State_FinishedEarly ) { Duration d = t->endTime( id() ) - t->completion().finishTime(); return xi18nc( "@info:tooltip", "Finished %1 early", d.toString( Duration::Format_i18nDay ) ); } return xi18nc( "@info:tooltip", "Finished" ); } if ( st & Node::State_Started ) { if ( st & Node::State_StartedLate ) { Duration d = t->completion().startTime() - t->startTime( id() ); return xi18nc( "@info:tooltip", "Started %1 late", d.toString( Duration::Format_i18nDay ) ); } if ( st & Node::State_StartedEarly ) { Duration d = t->startTime( id() ) - t->completion().startTime(); return xi18nc( "@info:tooltip", "Started %1 early", d.toString( Duration::Format_i18nDay ) ); } return xi18nc( "@info:tooltip", "Started" ); } if ( st & Node::State_Running ) { return xi18nc( "@info:tooltip", "Running" ); } if ( st & Node::State_ReadyToStart ) { return xi18nc( "@info:tooltip", "Can start" ); } if ( st & Node::State_NotReadyToStart ) { QStringList names; // TODO: proxy relations foreach ( Relation *r, node->dependParentNodes() ) { switch ( r->type() ) { case Relation::FinishFinish: case Relation::FinishStart: if ( ! static_cast( r->parent() )->completion().isFinished() ) { if ( ! names.contains( r->parent()->name() ) ) { names << r->parent()->name(); } } break; case Relation::StartStart: if ( ! static_cast( r->parent() )->completion().isStarted() ) { if ( ! names.contains( r->parent()->name() ) ) { names << r->parent()->name(); } } break; } } return names.isEmpty() ? xi18nc( "@info:tooltip", "Cannot start" ) : xi18nc( "@info:tooltip 1=list of task names", "Cannot start, waiting for:%1", names.join( "" ) ); } return xi18nc( "@info:tooltip", "Not started" ); break; } case Qt::EditRole: return t->state( id() ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::startedTime( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: if ( t->completion().isStarted() ) { return QLocale().toString( t->completion().startTime(), QLocale::ShortFormat ); } break; case Qt::ToolTipRole: if ( t->completion().isStarted() ) { return xi18nc( "@info:tooltip", "Actual start: %1", QLocale().toString( t->completion().startTime().date(), QLocale::LongFormat ) ); } break; case Qt::EditRole: if ( t->completion().isStarted() ) { return t->completion().startTime(); } return QDateTime::currentDateTime(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::isStarted( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return t->completion().isStarted(); case Qt::ToolTipRole: if ( t->completion().isStarted() ) { return xi18nc( "@info:tooltip", "The task started at: %1", QLocale().toString( t->completion().startTime().date(), QLocale::LongFormat ) ); } return xi18nc( "@info:tooltip", "The task is not started" ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::finishedTime( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: if ( t->completion().isFinished() ) { return QLocale().toString( t->completion().finishTime(), QLocale::ShortFormat ); } break; case Qt::ToolTipRole: if ( t->completion().isFinished() ) { return xi18nc( "@info:tooltip", "Actual finish: %1", QLocale().toString( t->completion().finishTime(), QLocale::LongFormat ) ); } break; case Qt::EditRole: if ( t->completion().isFinished() ) { return t->completion().finishTime(); } break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::isFinished( const Node *node, int role ) const { if ( ! ( node->type() == Node::Type_Task || node->type() == Node::Type_Milestone ) ) { return QVariant(); } const Task *t = static_cast( node ); switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return t->completion().isFinished(); case Qt::ToolTipRole: if ( t->completion().isFinished() ) { return xi18nc( "@info:tooltip", "The task finished at: %1", QLocale().toString( t->completion().finishTime().date(), QLocale::LongFormat ) ); } return xi18nc( "@info:tooltip", "The task is not finished" ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::plannedEffortTo( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return node->plannedEffortTo( m_now, id() ).format(); case Qt::ToolTipRole: return xi18nc( "@info:tooltip", "Planned effort until %1: %2", QLocale().toString( m_now, QLocale::ShortFormat ), node->plannedEffortTo( m_now, id() ).toString( Duration::Format_i18nHour ) ); case Qt::EditRole: return node->plannedEffortTo( m_now, id() ).toDouble( Duration::Unit_h ); case Role::DurationUnit: return static_cast( Duration::Unit_h ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::actualEffortTo( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return node->actualEffortTo( m_now ).format(); case Qt::ToolTipRole: //debugPlan<actualEffortTo( m_now ).toString( Duration::Format_i18nHour ) ); case Qt::EditRole: return node->actualEffortTo( m_now ).toDouble( Duration::Unit_h ); case Role::DurationUnit: return static_cast( Duration::Unit_h ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::remainingEffort( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: { const Task *t = dynamic_cast( node ); if ( t ) { return t->completion().remainingEffort().format(); } break; } case Qt::ToolTipRole: { const Task *t = dynamic_cast( node ); if ( t ) { return xi18nc( "@info:tooltip", "Remaining effort: %1", t->completion().remainingEffort().toString( Duration::Format_i18nHour ) ); } break; } case Qt::EditRole: { const Task *t = dynamic_cast( node ); if ( t == 0 ) { return QVariant(); } return t->completion().remainingEffort().toDouble( Duration::Unit_h ); } case Role::DurationUnit: return static_cast( Duration::Unit_h ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::plannedCostTo( const Node *node, int role ) const { Locale *l = m_project->locale(); switch ( role ) { case Qt::DisplayRole: return l->formatMoney( node->plannedCostTo( m_now, id() ) ); case Qt::ToolTipRole: return xi18nc( "@info:tooltip", "Planned cost until %1: %2", QLocale().toString( m_now, QLocale::ShortFormat ), l->formatMoney( node->plannedCostTo( m_now, id() ) ) ); case Qt::EditRole: return node->plannedCostTo( m_now ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::actualCostTo( const Node *node, int role ) const { Locale *l = m_project->locale(); switch ( role ) { case Qt::DisplayRole: return l->formatMoney( node->actualCostTo( id(), m_now ).cost() ); case Qt::ToolTipRole: return xi18nc( "@info:tooltip", "Actual cost until %1: %2", QLocale().toString( m_now, QLocale::ShortFormat ), l->formatMoney( node->actualCostTo( id(), m_now ).cost() ) ); case Qt::EditRole: return node->actualCostTo( id(), m_now ).cost(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::note( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: if ( node->type() == Node::Type_Task ) { Node *n = const_cast( node ); return static_cast( n )->completion().note(); } break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::nodeSchedulingStatus( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return node->schedulingStatus( id(), true ).value( 0 ); case Qt::EditRole: return node->schedulingStatus( id(), false ).value( 0 ); case Qt::ToolTipRole: return node->schedulingStatus( id(), true ).join( "\n" ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::resourceIsMissing( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( node->resourceError( id() ) ) { return i18n( "Error" ); } break; case Qt::EditRole: return node->resourceError( id() ); case Qt::ToolTipRole: if ( node->resourceError( id() ) ) { return xi18nc( "@info:tooltip", "Resource allocation is expected when the task estimate type is Effort" ); } break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::Foreground: { if ( ! m_project ) { break; } switch ( node->type() ) { case Node::Type_Task: return m_project->config().taskErrorColor(); case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); default: break; } } } return QVariant(); } QVariant NodeModel::resourceIsOverbooked( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( node->resourceOverbooked( id() ) ) { return i18n( "Error" ); } break; case Qt::EditRole: return node->resourceOverbooked( id() ); case Qt::ToolTipRole: if ( node->resourceOverbooked( id() ) ) { return xi18nc( "@info:tooltip", "A resource has been overbooked" ); } break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::Foreground: { if ( ! m_project ) { break; } switch ( node->type() ) { case Node::Type_Task: return m_project->config().taskErrorColor(); case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); default: break; } } } return QVariant(); } QVariant NodeModel::resourceIsNotAvailable( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( node->resourceNotAvailable( id() ) ) { return i18n( "Error" ); } break; case Qt::EditRole: return node->resourceNotAvailable( id() ); case Qt::ToolTipRole: if ( node->resourceNotAvailable( id() ) ) { return xi18nc( "@info:tooltip", "No resource is available for this task" ); } break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::Foreground: { if ( ! m_project ) { break; } switch ( node->type() ) { case Node::Type_Task: return m_project->config().taskErrorColor(); case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); default: break; } } } return QVariant(); } QVariant NodeModel::schedulingConstraintsError( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( node->constraintError( id() ) ) { return i18n( "Error" ); } break; case Qt::EditRole: return node->constraintError( id() ); case Qt::ToolTipRole: if ( node->constraintError( id() ) ) { return xi18nc( "@info:tooltip", "Failed to comply with a timing constraint" ); } break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::Foreground: { if ( ! m_project ) { break; } switch ( node->type() ) { case Node::Type_Task: return m_project->config().taskErrorColor(); case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); default: break; } } } return QVariant(); } QVariant NodeModel::nodeIsNotScheduled( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( node->notScheduled( id() ) ) { return i18n( "Error" ); } break; case Qt::EditRole: return node->notScheduled( id() ); case Qt::ToolTipRole: if ( node->notScheduled( id() ) ) { return xi18nc( "@info:tooltip", "This task has not been scheduled" ); } break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::Foreground: { if ( ! m_project ) { break; } switch ( node->type() ) { case Node::Type_Task: return m_project->config().taskErrorColor(); case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); default: break; } } } return QVariant(); } QVariant NodeModel::effortNotMet( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( node->effortMetError( id() ) ) { return i18n( "Error" ); } break; case Qt::EditRole: return node->effortMetError( id() ); case Qt::ToolTipRole: if ( node->effortMetError( id() ) ) { return xi18nc( "@info:tooltip", "The assigned resources cannot deliver the required estimated effort" ); } break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::Foreground: { if ( ! m_project ) { break; } switch ( node->type() ) { case Node::Type_Task: return m_project->config().taskErrorColor(); case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); default: break; } } } return QVariant(); } QVariant NodeModel::schedulingError( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( node->schedulingError( id() ) ) { return i18n( "Error" ); } break; case Qt::EditRole: return node->schedulingError( id() ); case Qt::ToolTipRole: if ( node->schedulingError( id() ) ) { return xi18nc( "@info:tooltip", "Scheduling error" ); } break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::Foreground: { if ( ! m_project ) { break; } switch ( node->type() ) { case Node::Type_Task: return m_project->config().taskErrorColor(); case Node::Type_Milestone: return m_project->config().milestoneErrorColor(); default: break; } } } return QVariant(); } QVariant NodeModel::wbsCode( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return node->wbsCode(); case Qt::ToolTipRole: return xi18nc( "@info:tooltip", "Work breakdown structure code: %1", node->wbsCode() ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case SortableRole: return node->wbsCode(true); } return QVariant(); } QVariant NodeModel::nodeLevel( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return node->level(); case Qt::ToolTipRole: return xi18nc( "@info:tooltip", "Task level: %1", node->level() ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::nodeBCWS( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return m_project->locale()->formatMoney( node->bcws( m_now, id() ), QString(), 0 ); case Qt::EditRole: return node->bcws( m_now, id() ); case Qt::ToolTipRole: return xi18nc( "@info:tooltip", "Budgeted Cost of Work Scheduled at %1: %2", QLocale().toString( m_now, QLocale::ShortFormat ), m_project->locale()->formatMoney( node->bcws( m_now, id() ), QString(), 0 ) ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::nodeBCWP( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return m_project->locale()->formatMoney( node->bcwp( id() ), QString(), 0 ); case Qt::EditRole: return node->bcwp( id() ); case Qt::ToolTipRole: return xi18nc( "@info:tooltip", "Budgeted Cost of Work Performed at %1: %2", QLocale().toString( m_now, QLocale::ShortFormat ), m_project->locale()->formatMoney( node->bcwp( id() ), QString(), 0 ) ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::nodeACWP( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return m_project->locale()->formatMoney( node->acwp( m_now, id() ).cost(), QString(), 0 ); case Qt::EditRole: return node->acwp( m_now, id() ).cost(); case Qt::ToolTipRole: return xi18nc( "@info:tooltip", "Actual Cost of Work Performed at %1: %2", QLocale().toString( m_now, QLocale::ShortFormat ), m_project->locale()->formatMoney( node->acwp( m_now, id() ).cost() ) ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::nodePerformanceIndex( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return QLocale().toString( node->schedulePerformanceIndex( m_now, id() ), 'f', 2 ); case Qt::EditRole: return node->schedulePerformanceIndex( m_now, id() ); case Qt::ToolTipRole: return xi18nc( "@info:tooltip", "Schedule Performance Index at %1: %2", m_now.toString(), QLocale().toString( node->schedulePerformanceIndex( m_now, id() ), 'f', 2 ) ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Qt::ForegroundRole: return QColor(node->schedulePerformanceIndex( m_now, id() ) < 1.0 ? Qt::red : Qt::black); } return QVariant(); } QVariant NodeModel::nodeIsCritical( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return node->isCritical( id() ); case Qt::ToolTipRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::Foreground: { if ( ! m_project ) { break; } switch ( node->type() ) { case Node::Type_Task: return m_project->config().taskNormalColor(); case Node::Type_Milestone: return m_project->config().milestoneNormalColor(); default: break; } } } return QVariant(); } QVariant NodeModel::nodeInCriticalPath( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return node->inCriticalPath( id() ); case Qt::ToolTipRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::Foreground: { if ( ! m_project ) { break; } switch ( node->type() ) { case Node::Type_Task: return m_project->config().taskNormalColor(); case Node::Type_Milestone: return m_project->config().milestoneNormalColor(); default: break; } } } return QVariant(); } QVariant NodeModel::wpOwnerName( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: { const Task *t = dynamic_cast( node ); if ( t == 0 ) { return QVariant(); } if ( t->wpTransmitionStatus() == WorkPackage::TS_None ) { return xi18nc( "Not available", "NA" ); } return t->wpOwnerName(); } case Qt::ToolTipRole: { const Task *task = dynamic_cast( node ); if ( task == 0 ) { return QVariant(); } int sts = task->wpTransmitionStatus(); QString t = wpTransmitionTime( node, Qt::DisplayRole ).toString(); if ( sts == WorkPackage::TS_Send ) { return xi18nc( "@info:tooltip", "Latest work package sent to %1 at %2", static_cast( node )->wpOwnerName(), t ); } if ( sts == WorkPackage::TS_Receive ) { return xi18nc( "@info:tooltip", "Latest work package received from %1 at %2", static_cast( node )->wpOwnerName(), t ); } return xi18nc( "@info:tooltip", "Not available" ); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::wpTransmitionStatus( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: { const Task *t = dynamic_cast( node ); if ( t == 0 ) { return QVariant(); } if ( t->wpTransmitionStatus() == WorkPackage::TS_None ) { return xi18nc( "Not available", "NA" ); } return WorkPackage::transmitionStatusToString( t->wpTransmitionStatus(), true ); } case Qt::EditRole: { const Task *t = dynamic_cast( node ); if ( t == 0 ) { return QVariant(); } return WorkPackage::transmitionStatusToString( t->wpTransmitionStatus(), false ); } case Qt::ToolTipRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::wpTransmitionTime( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: { const Task *t = dynamic_cast( node ); if ( t == 0 ) { return QVariant(); } if ( t->wpTransmitionStatus() == WorkPackage::TS_None ) { return xi18nc( "Not available", "NA" ); } return QLocale().toString( t->wpTransmitionTime(), QLocale::ShortFormat ); } case Qt::ToolTipRole: { const Task *task = dynamic_cast( node ); if ( task == 0 ) { return QVariant(); } int sts = task->wpTransmitionStatus(); QString t = wpTransmitionTime( node, Qt::DisplayRole ).toString(); if ( sts == WorkPackage::TS_Send ) { return xi18nc( "@info:tooltip", "Latest work package sent: %1", t ); } if ( sts == WorkPackage::TS_Receive ) { return xi18nc( "@info:tooltip", "Latest work package received: %1", t ); } return xi18nc( "@info:tooltip", "Not available" ); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant NodeModel::data( const Node *n, int property, int role ) const { QVariant result; switch ( property ) { // Edited by user case NodeName: result = name( n, role ); break; case NodeType: result = type( n, role ); break; case NodeResponsible: result = leader( n, role ); break; case NodeAllocation: result = allocation( n, role ); break; case NodeEstimateType: result = estimateType( n, role ); break; case NodeEstimateCalendar: result = estimateCalendar( n, role ); break; case NodeEstimate: result = estimate( n, role ); break; case NodeOptimisticRatio: result = optimisticRatio( n, role ); break; case NodePessimisticRatio: result = pessimisticRatio( n, role ); break; case NodeRisk: result = riskType( n, role ); break; case NodeConstraint: result = constraint( n, role ); break; case NodeConstraintStart: result = constraintStartTime( n, role ); break; case NodeConstraintEnd: result = constraintEndTime( n, role ); break; case NodeRunningAccount: result = runningAccount( n, role ); break; case NodeStartupAccount: result = startupAccount( n, role ); break; case NodeStartupCost: result = startupCost( n, role ); break; case NodeShutdownAccount: result = shutdownAccount( n, role ); break; case NodeShutdownCost: result = shutdownCost( n, role ); break; case NodeDescription: result = description( n, role ); break; // Based on edited values case NodeExpected: result = pertExpected( n->estimate(), role ); break; case NodeVarianceEstimate: result = varianceEstimate( n->estimate(), role ); break; case NodeOptimistic: result = optimisticEstimate( n->estimate(), role ); break; case NodePessimistic: result = pessimisticEstimate( n->estimate(), role ); break; // After scheduling case NodeStartTime: result = startTime( n, role ); break; case NodeEndTime: result = endTime( n, role ); break; case NodeEarlyStart: result = earlyStart( n, role ); break; case NodeEarlyFinish: result = earlyFinish( n, role ); break; case NodeLateStart: result = lateStart( n, role ); break; case NodeLateFinish: result = lateFinish( n, role ); break; case NodePositiveFloat: result = positiveFloat( n, role ); break; case NodeFreeFloat: result = freeFloat( n, role ); break; case NodeNegativeFloat: result = negativeFloat( n, role ); break; case NodeStartFloat: result = startFloat( n, role ); break; case NodeFinishFloat: result = finishFloat( n, role ); break; case NodeAssignments: result = assignedResources( n, role ); break; // Based on scheduled values case NodeDuration: result = duration( n, role ); break; case NodeVarianceDuration: result = varianceDuration( n, role ); break; case NodeOptimisticDuration: result = optimisticDuration( n, role ); break; case NodePessimisticDuration: result = pessimisticDuration( n, role ); break; // Completion case NodeStatus: result = status( n, role ); break; case NodeCompleted: result = completed( n, role ); break; case NodePlannedEffort: result = plannedEffortTo( n, role ); break; case NodeActualEffort: result = actualEffortTo( n, role ); break; case NodeRemainingEffort: result = remainingEffort( n, role ); break; case NodePlannedCost: result = plannedCostTo( n, role ); break; case NodeActualCost: result = actualCostTo( n, role ); break; case NodeActualStart: result = startedTime( n, role ); break; case NodeStarted: result = isStarted( n, role ); break; case NodeActualFinish: result = finishedTime( n, role ); break; case NodeFinished: result = isFinished( n, role ); break; case NodeStatusNote: result = note( n, role ); break; // Scheduling errors case NodeSchedulingStatus: result = nodeSchedulingStatus( n, role ); break; case NodeNotScheduled: result = nodeIsNotScheduled( n, role ); break; case NodeAssignmentMissing: result = resourceIsMissing( n, role ); break; case NodeResourceOverbooked: result = resourceIsOverbooked( n, role ); break; case NodeResourceUnavailable: result = resourceIsNotAvailable( n, role ); break; case NodeConstraintsError: result = schedulingConstraintsError( n, role ); break; case NodeEffortNotMet: result = effortNotMet( n, role ); break; case NodeSchedulingError: result = schedulingError( n, role ); break; case NodeWBSCode: result = wbsCode( n, role ); break; case NodeLevel: result = nodeLevel( n, role ); break; // Performance case NodeBCWS: result = nodeBCWS( n, role ); break; case NodeBCWP: result = nodeBCWP( n, role ); break; case NodeACWP: result = nodeACWP( n, role ); break; case NodePerformanceIndex: result = nodePerformanceIndex( n, role ); break; case NodeCritical: result = nodeIsCritical( n, role ); break; case NodeCriticalPath: result = nodeInCriticalPath( n, role ); break; case WPOwnerName: result = wpOwnerName( n, role ); break; case WPTransmitionStatus: result = wpTransmitionStatus( n, role ); break; case WPTransmitionTime: result = wpTransmitionTime( n, role ); break; default: //debugPlan<<"Invalid property number: "<name() ) { return 0; } KUndo2MagicString s = kundo2_i18n( "Modify name" ); switch ( node->type() ) { case Node::Type_Task: s = kundo2_i18n( "Modify task name" ); break; case Node::Type_Milestone: s = kundo2_i18n( "Modify milestone name" ); break; case Node::Type_Summarytask: s = kundo2_i18n( "Modify summarytask name" ); break; case Node::Type_Project: s = kundo2_i18n( "Modify project name" ); break; } return new NodeModifyNameCmd( *node, value.toString(), s ); } } return 0; } KUndo2Command *NodeModel::setLeader( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { if ( value.toString() != node->leader() ) { return new NodeModifyLeaderCmd( *node, value.toString(), kundo2_i18n( "Modify responsible" ) ); } break; } default: break; } return 0; } KUndo2Command *NodeModel::setAllocation( Node */*node*/, const QVariant &/*value*/, int /*role*/ ) { return 0; } KUndo2Command *NodeModel::setDescription( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toString() == node->description() ) { return 0; } return new NodeModifyDescriptionCmd( *node, value.toString(), kundo2_i18n( "Modify task description" ) ); } return 0; } KUndo2Command *NodeModel::setType( Node *, const QVariant &, int ) { return 0; } KUndo2Command *NodeModel::setConstraint( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { Node::ConstraintType v; QStringList lst = node->constraintList( false ); if ( lst.contains( value.toString() ) ) { v = Node::ConstraintType( lst.indexOf( value.toString() ) ); } else { v = Node::ConstraintType( value.toInt() ); } //debugPlan<constraint() ) { return new NodeModifyConstraintCmd( *node, v, kundo2_i18n( "Modify constraint type" ) ); } break; } default: break; } return 0; } KUndo2Command *NodeModel::setConstraintStartTime( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { QDateTime dt = value.toDateTime(); dt.setTime( QTime( dt.time().hour(), dt.time().minute(), 0 ) ); // reset possible secs/msecs if ( dt != node->constraintStartTime() ) { return new NodeModifyConstraintStartTimeCmd( *node, dt, kundo2_i18n( "Modify constraint start time" ) ); } break; } default: break; } return 0; } KUndo2Command *NodeModel::setConstraintEndTime( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { QDateTime dt = value.toDateTime(); dt.setTime( QTime( dt.time().hour(), dt.time().minute(), 0 ) ); // reset possible secs/msecs if ( dt != node->constraintEndTime() ) { return new NodeModifyConstraintEndTimeCmd( *node, dt, kundo2_i18n( "Modify constraint end time" ) ); } break; } default: break; } return 0; } KUndo2Command *NodeModel::setEstimateType( Node *node, const QVariant &value, int role ) { if ( node->estimate() == 0 ) { return 0; } switch ( role ) { case Qt::EditRole: { Estimate::Type v; QStringList lst = node->estimate()->typeToStringList( false ); if ( lst.contains( value.toString() ) ) { v = Estimate::Type( lst.indexOf( value.toString() ) ); } else { v = Estimate::Type( value.toInt() ); } if ( v != node->estimate()->type() ) { return new ModifyEstimateTypeCmd( *node, node->estimate()->type(), v, kundo2_i18n( "Modify estimate type" ) ); } break; } default: break; } return 0; } KUndo2Command *NodeModel::setEstimateCalendar( Node *node, const QVariant &value, int role ) { if ( node->estimate() == 0 ) { return 0; } switch ( role ) { case Qt::EditRole: { Calendar *c = 0; Calendar *old = node->estimate()->calendar(); if ( value.toInt() > 0 ) { QStringList lst = estimateCalendar( node, Role::EnumList ).toStringList(); if ( value.toInt() < lst.count() ) { c = m_project->calendarByName( lst.at( value.toInt() ) ); } } if ( c != old ) { return new ModifyEstimateCalendarCmd( *node, old, c, kundo2_i18n( "Modify estimate calendar" ) ); } break; } default: break; } return 0; } KUndo2Command *NodeModel::setEstimate( Node *node, const QVariant &value, int role ) { if ( node->estimate() == 0 ) { return 0; } switch ( role ) { case Qt::EditRole: { double d; Duration::Unit unit; if ( value.toList().count() == 2 ) { d = value.toList()[0].toDouble(); unit = static_cast( value.toList()[1].toInt() ); } else if ( value.canConvert() ) { bool ok = Duration::valueFromString( value.toString(), d, unit ); if ( ! ok ) { return 0; } } else { return 0; } //debugPlan<"<estimate()->expectedEstimate() ) { if ( cmd == 0 ) cmd = new MacroCommand( kundo2_i18n( "Modify estimate" ) ); cmd->addCommand( new ModifyEstimateCmd( *node, node->estimate()->expectedEstimate(), d ) ); } if ( unit != node->estimate()->unit() ) { if ( cmd == 0 ) cmd = new MacroCommand( kundo2_i18n( "Modify estimate" ) ); cmd->addCommand( new ModifyEstimateUnitCmd( *node, node->estimate()->unit(), unit ) ); } if ( cmd ) { return cmd; } break; } default: break; } return 0; } KUndo2Command *NodeModel::setOptimisticRatio( Node *node, const QVariant &value, int role ) { if ( node->estimate() == 0 ) { return 0; } switch ( role ) { case Qt::EditRole: if ( value.toInt() != node->estimate()->optimisticRatio() ) { return new EstimateModifyOptimisticRatioCmd( *node, node->estimate()->optimisticRatio(), value.toInt(), kundo2_i18n( "Modify optimistic estimate" ) ); } break; default: break; } return 0; } KUndo2Command *NodeModel::setPessimisticRatio( Node *node, const QVariant &value, int role ) { if ( node->estimate() == 0 ) { return 0; } switch ( role ) { case Qt::EditRole: if ( value.toInt() != node->estimate()->pessimisticRatio() ) { return new EstimateModifyPessimisticRatioCmd( *node, node->estimate()->pessimisticRatio(), value.toInt(), kundo2_i18n( "Modify pessimistic estimate" ) ); } default: break; } return 0; } KUndo2Command *NodeModel::setRiskType( Node *node, const QVariant &value, int role ) { if ( node->estimate() == 0 ) { return 0; } switch ( role ) { case Qt::EditRole: { int val = 0; QStringList lst = node->estimate()->risktypeToStringList( false ); if ( lst.contains( value.toString() ) ) { val = lst.indexOf( value.toString() ); } else { val = value.toInt(); } if ( val != node->estimate()->risktype() ) { Estimate::Risktype v = Estimate::Risktype( val ); return new EstimateModifyRiskCmd( *node, node->estimate()->risktype(), v, kundo2_i18n( "Modify risk type" ) ); } break; } default: break; } return 0; } KUndo2Command *NodeModel::setRunningAccount( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { //debugPlan<name(); QStringList lst = runningAccount( node, Role::EnumList ).toStringList(); if ( value.toInt() < lst.count() ) { Account *a = m_project->accounts().findAccount( lst.at( value.toInt() ) ); Account *old = node->runningAccount(); if ( old != a ) { return new NodeModifyRunningAccountCmd( *node, old, a, kundo2_i18n( "Modify running account" ) ); } } break; } default: break; } return 0; } KUndo2Command *NodeModel::setStartupAccount( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { //debugPlan<name(); QStringList lst = startupAccount( node, Role::EnumList ).toStringList(); if ( value.toInt() < lst.count() ) { Account *a = m_project->accounts().findAccount( lst.at( value.toInt() ) ); Account *old = node->startupAccount(); //debugPlan<<(value.toInt())<<";"<<(lst.at( value.toInt()))<<":"<startupCost() ) { return new NodeModifyStartupCostCmd( *node, v, kundo2_i18n( "Modify startup cost" ) ); } break; } default: break; } return 0; } KUndo2Command *NodeModel::setShutdownAccount( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { //debugPlan<name(); QStringList lst = shutdownAccount( node, Role::EnumList ).toStringList(); if ( value.toInt() < lst.count() ) { Account *a = m_project->accounts().findAccount( lst.at( value.toInt() ) ); Account *old = node->shutdownAccount(); if ( old != a ) { return new NodeModifyShutdownAccountCmd( *node, old, a, kundo2_i18n( "Modify shutdown account" ) ); } } break; } default: break; } return 0; } KUndo2Command *NodeModel::setShutdownCost( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { double v = value.toDouble(); if ( v != node->shutdownCost() ) { return new NodeModifyShutdownCostCmd( *node, v, kundo2_i18n( "Modify shutdown cost" ) ); } break; } default: break; } return 0; } KUndo2Command *NodeModel::setCompletion( Node */*node*/, const QVariant &/*value*/, int /*role*/ ) { return 0; } KUndo2Command *NodeModel::setRemainingEffort( Node *node, const QVariant &value, int role ) { if ( role == Qt::EditRole && node->type() == Node::Type_Task ) { Task *t = static_cast( node ); double d( value.toList()[0].toDouble() ); Duration::Unit unit = static_cast( value.toList()[1].toInt() ); Duration dur( d, unit ); return new ModifyCompletionRemainingEffortCmd( t->completion(), QDate::currentDate(), dur, kundo2_i18n( "Modify remaining effort" ) ); } return 0; } KUndo2Command *NodeModel::setActualEffort( Node *node, const QVariant &value, int role ) { if ( role == Qt::EditRole && node->type() == Node::Type_Task ) { Task *t = static_cast( node ); double d( value.toList()[0].toDouble() ); Duration::Unit unit = static_cast( value.toList()[1].toInt() ); Duration dur( d, unit ); return new ModifyCompletionActualEffortCmd( t->completion(), QDate::currentDate(), dur, kundo2_i18n( "Modify actual effort" ) ); } return 0; } KUndo2Command *NodeModel::setStartedTime( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { Task *t = qobject_cast( node ); if ( t == 0 ) { return 0; } MacroCommand *m = new MacroCommand( kundo2_i18n( "Modify actual start time" ) ); if ( ! t->completion().isStarted() ) { m->addCommand( new ModifyCompletionStartedCmd( t->completion(), true ) ); } m->addCommand( new ModifyCompletionStartTimeCmd( t->completion(), value.toDateTime() ) ); if ( t->type() == Node::Type_Milestone ) { m->addCommand( new ModifyCompletionFinishedCmd( t->completion(), true ) ); m->addCommand( new ModifyCompletionFinishTimeCmd( t->completion(), value.toDateTime() ) ); if ( t->completion().percentFinished() < 100 ) { Completion::Entry *e = new Completion::Entry( 100, Duration::zeroDuration, Duration::zeroDuration ); m->addCommand( new AddCompletionEntryCmd( t->completion(), value.toDate(), e ) ); } } return m; } default: break; } return 0; } KUndo2Command *NodeModel::setFinishedTime( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { Task *t = qobject_cast( node ); if ( t == 0 ) { return 0; } MacroCommand *m = new MacroCommand( kundo2_i18n( "Modify actual finish time" ) ); if ( ! t->completion().isFinished() ) { m->addCommand( new ModifyCompletionFinishedCmd( t->completion(), true ) ); if ( t->completion().percentFinished() < 100 ) { Completion::Entry *e = new Completion::Entry( 100, Duration::zeroDuration, Duration::zeroDuration ); m->addCommand( new AddCompletionEntryCmd( t->completion(), value.toDate(), e ) ); } } m->addCommand( new ModifyCompletionFinishTimeCmd( t->completion(), value.toDateTime() ) ); if ( t->type() == Node::Type_Milestone ) { m->addCommand( new ModifyCompletionStartedCmd( t->completion(), true ) ); m->addCommand( new ModifyCompletionStartTimeCmd( t->completion(), value.toDateTime() ) ); } return m; } default: break; } return 0; } //---------------------------- NodeItemModel::NodeItemModel( QObject *parent ) : ItemModelBase( parent ), m_node( 0 ), m_projectshown( false ) { setReadOnly( NodeModel::NodeDescription, true ); } NodeItemModel::~NodeItemModel() { } void NodeItemModel::setShowProject( bool on ) { beginResetModel(); m_projectshown = on; endResetModel(); emit projectShownChanged( on ); } void NodeItemModel::slotNodeToBeInserted( Node *parent, int row ) { //debugPlan<name()<<"; "<parentNode()->name()<<"-->"<name(); Q_ASSERT( node->parentNode() == m_node ); endInsertRows(); m_node = 0; emit nodeInserted( node ); } void NodeItemModel::slotNodeToBeRemoved( Node *node ) { //debugPlan<name(); Q_ASSERT( m_node == 0 ); m_node = node; int row = index( node ).row(); beginRemoveRows( index( node->parentNode() ), row, row ); } void NodeItemModel::slotNodeRemoved( Node *node ) { //debugPlan<name(); Q_ASSERT( node == m_node ); #ifdef NDEBUG Q_UNUSED(node) #endif endRemoveRows(); m_node = 0; } void NodeItemModel::slotNodeToBeMoved( Node *node, int pos, Node *newParent, int newPos ) { //debugPlan<parentNode()->name()<name()<parentNode() ), pos, pos, index( newParent ), newPos ); } void NodeItemModel::slotNodeMoved( Node *node ) { Q_UNUSED( node ); //debugPlan<parentNode()->name()<parentNode()->indexOf( node ); endMoveRows(); } void NodeItemModel::slotLayoutChanged() { //debugPlan<name(); emit layoutAboutToBeChanged(); emit layoutChanged(); } void NodeItemModel::slotProjectCalculated(ScheduleManager *sm) { debugPlan<allNodes() ) { int row = n->parentNode()->indexOf( n ); QModelIndex idx = createIndex( row, NodeModel::NodeWBSCode, n ); emit dataChanged( idx, idx ); } } void NodeItemModel::setProject( Project *project ) { beginResetModel(); if ( m_project ) { disconnect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - disconnect( m_project, SIGNAL(localeChanged()), this, SLOT(slotLayoutChanged()) ); - disconnect( m_project, SIGNAL(wbsDefinitionChanged()), this, SLOT(slotWbsDefinitionChanged()) ); - disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - disconnect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); - disconnect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); + disconnect( m_project, SIGNAL(localeChanged()), this, SLOT(slotLayoutChanged())); + disconnect( m_project, SIGNAL(wbsDefinitionChanged()), this, SLOT(slotWbsDefinitionChanged())); + disconnect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*))); + disconnect( m_project, SIGNAL(nodeToBeAdded(KPlato::Node*,int)), this, SLOT(slotNodeToBeInserted(KPlato::Node*,int))); + disconnect( m_project, SIGNAL(nodeToBeRemoved(KPlato::Node*)), this, SLOT(slotNodeToBeRemoved(KPlato::Node*))); - disconnect( m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotNodeToBeMoved(Node*,int,Node*,int)) ); - disconnect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotNodeMoved(Node*)) ); + disconnect( m_project, SIGNAL(nodeToBeMoved(KPlato::Node*,int,KPlato::Node*,int)), this, SLOT(slotNodeToBeMoved(KPlato::Node*,int,KPlato::Node*,int))); + disconnect( m_project, SIGNAL(nodeMoved(KPlato::Node*)), this, SLOT(slotNodeMoved(KPlato::Node*))); - disconnect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); - disconnect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); - disconnect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*))); + disconnect( m_project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeInserted(KPlato::Node*))); + disconnect( m_project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*))); + disconnect( m_project, SIGNAL(projectCalculated(KPlato::ScheduleManager*)), this, SLOT(slotProjectCalculated(KPlato::ScheduleManager*))); } m_project = project; debugPlan<"<isBaselined(); flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; switch ( index.column() ) { case NodeModel::NodeName: // name flags |= Qt::ItemIsEditable; break; case NodeModel::NodeType: break; // Node type case NodeModel::NodeResponsible: // Responsible flags |= Qt::ItemIsEditable; break; case NodeModel::NodeAllocation: // allocation if ( n->type() == Node::Type_Task ) { flags |= Qt::ItemIsEditable; } break; case NodeModel::NodeEstimateType: // estimateType { if ( ! baselined && ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { flags |= Qt::ItemIsEditable; } break; } case NodeModel::NodeEstimate: // estimate { if ( ! baselined && ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { flags |= Qt::ItemIsEditable; } break; } case NodeModel::NodeOptimisticRatio: // optimisticRatio case NodeModel::NodePessimisticRatio: // pessimisticRatio { if ( ! baselined && n->type() == Node::Type_Task ) { flags |= Qt::ItemIsEditable; } break; } case NodeModel::NodeEstimateCalendar: { if ( ! baselined && n->type() == Node::Type_Task ) { flags |= Qt::ItemIsEditable; } break; } case NodeModel::NodeRisk: // risktype { if ( ! baselined && n->type() == Node::Type_Task ) { flags |= Qt::ItemIsEditable; } break; } case NodeModel::NodeConstraint: // constraint type if ( ! baselined && ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { flags |= Qt::ItemIsEditable; } break; case NodeModel::NodeConstraintStart: { // constraint start if ( ! baselined && n->type() == Node::Type_Project ) { flags |= Qt::ItemIsEditable; break; } if ( ! baselined && ! ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { break; } flags |= Qt::ItemIsEditable; break; } case NodeModel::NodeConstraintEnd: { // constraint end if ( ! baselined && n->type() == Node::Type_Project ) { flags |= Qt::ItemIsEditable; break; } if ( ! baselined && ! ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { break; } flags |= Qt::ItemIsEditable; break; } case NodeModel::NodeRunningAccount: // running account if ( ! baselined && n->type() == Node::Type_Task ) { flags |= Qt::ItemIsEditable; } break; case NodeModel::NodeStartupAccount: // startup account case NodeModel::NodeStartupCost: // startup cost case NodeModel::NodeShutdownAccount: // shutdown account case NodeModel::NodeShutdownCost: { // shutdown cost if ( ! baselined && ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { flags |= Qt::ItemIsEditable; } break; } case NodeModel::NodeDescription: // description flags |= Qt::ItemIsEditable; break; default: break; } Task *t = static_cast( n ); if ( manager() && t->isScheduled( id() ) ) { if ( ! t->completion().isStarted() ) { switch ( index.column() ) { case NodeModel::NodeActualStart: flags |= Qt::ItemIsEditable; break; case NodeModel::NodeActualFinish: if ( t->type() == Node::Type_Milestone ) { flags |= Qt::ItemIsEditable; } break; case NodeModel::NodeCompleted: if ( t->state() & Node::State_ReadyToStart ) { flags |= Qt::ItemIsEditable; } break; default: break; } } else if ( ! t->completion().isFinished() ) { switch ( index.column() ) { case NodeModel::NodeActualFinish: case NodeModel::NodeCompleted: case NodeModel::NodeRemainingEffort: flags |= Qt::ItemIsEditable; break; case NodeModel::NodeActualEffort: if ( t->completion().entrymode() == Completion::EnterEffortPerTask || t->completion().entrymode() == Completion::EnterEffortPerResource ) { flags |= Qt::ItemIsEditable; } break; default: break; } } } } return flags; } QModelIndex NodeItemModel::parent( const QModelIndex &index ) const { if ( ! index.isValid() ) { return QModelIndex(); } Node *n = node( index ); if ( n == 0 || n == m_project ) { return QModelIndex(); } Node *p = n->parentNode(); if ( p == m_project ) { return m_projectshown ? createIndex( 0, 0, p ) : QModelIndex(); } int row = p->parentNode()->indexOf( p ); if ( row == -1 ) { return QModelIndex(); } return createIndex( row, 0, p ); } QModelIndex NodeItemModel::index( int row, int column, const QModelIndex &parent ) const { if ( parent.isValid() ) { Q_ASSERT( parent.model() == this ); } //debugPlan<= columnCount() || row < 0 ) { //debugPlan<= p->numChildren() ) { errorPlan<name()<<" row too high"<childNode( row ); QModelIndex idx = createIndex(row, column, n); //debugPlan<parentNode(); if ( par ) { //debugPlan<"<indexOf( node ), column, const_cast(node) ); } if ( m_projectshown && node == m_project ) { return createIndex( 0, column, m_project ); } //debugPlan<( node ); if ( task == 0 ) { return false; } switch ( role ) { case Qt::EditRole: { MacroCommand *cmd = 0; QStringList res = m_project->resourceNameList(); QStringList req = node->requestNameList(); QStringList alloc; foreach ( const QString &s, value.toString().split( QRegExp(" *, *"), QString::SkipEmptyParts ) ) { alloc << s.trimmed(); } // first add all new resources (to "default" group) ResourceGroup *pargr = m_project->groupByName( i18n( "Resources" ) ); foreach ( const QString &s, alloc ) { Resource *r = m_project->resourceByName( s.trimmed() ); if ( r != 0 ) { continue; } if ( cmd == 0 ) cmd = new MacroCommand( kundo2_i18n( "Add resource" ) ); if ( pargr == 0 ) { pargr = new ResourceGroup(); pargr->setName( i18n( "Resources" ) ); cmd->addCommand( new AddResourceGroupCmd( m_project, pargr ) ); //debugPlan<<"add group:"<name(); } r = new Resource(); r->setName( s.trimmed() ); cmd->addCommand( new AddResourceCmd( pargr, r ) ); //debugPlan<<"add resource:"<name(); emit executeCommand( cmd ); cmd = 0; } KUndo2MagicString c = kundo2_i18n( "Modify resource allocations" ); // Handle deleted requests foreach ( const QString &s, req ) { // if a request is not in alloc, it must have been be removed by the user if ( alloc.indexOf( s ) == -1 ) { // remove removed resource request ResourceRequest *r = node->resourceRequest( s ); if ( r ) { if ( cmd == 0 ) cmd = new MacroCommand( c ); //debugPlan<<"delete request:"<resource()->name()<<" group:"<parent()->group()->name(); cmd->addCommand( new RemoveResourceRequestCmd( r->parent(), r ) ); } } } // Handle new requests QMap groupmap; foreach ( const QString &s, alloc ) { // if an allocation is not in req, it must be added if ( req.indexOf( s ) == -1 ) { ResourceGroup *pargr = 0; Resource *r = m_project->resourceByName( s ); if ( r == 0 ) { // Handle request to non existing resource pargr = m_project->groupByName( i18n( "Resources" ) ); if ( pargr == 0 ) { pargr = new ResourceGroup(); pargr->setName( i18n( "Resources" ) ); cmd->addCommand( new AddResourceGroupCmd( m_project, pargr ) ); //debugPlan<<"add group:"<name(); } r = new Resource(); r->setName( s ); cmd->addCommand( new AddResourceCmd( pargr, r ) ); //debugPlan<<"add resource:"<name(); emit executeCommand( cmd ); cmd = 0; } else { pargr = r->parentGroup(); //debugPlan<<"add '"<name()<<"' to group:"<resourceGroupRequest( pargr ); if ( g == 0 ) { g = groupmap.value( pargr ); } if ( g == 0 ) { // create a group request if ( cmd == 0 ) cmd = new MacroCommand( c ); g = new ResourceGroupRequest( pargr ); cmd->addCommand( new AddResourceGroupRequestCmd( *task, g ) ); groupmap.insert( pargr, g ); //debugPlan<<"add group request:"<addCommand( new AddResourceRequestCmd( g, new ResourceRequest( r, r->units() ) ) ); //debugPlan<<"add request:"<name()<<" group:"<name()<type() == Node::Type_Task ) { Completion &c = static_cast( node )->completion(); QDateTime dt = QDateTime::currentDateTime(); QDate date = dt.date(); MacroCommand *m = new MacroCommand( kundo2_i18n( "Modify completion" ) ); if ( ! c.isStarted() ) { m->addCommand( new ModifyCompletionStartTimeCmd( c, dt ) ); m->addCommand( new ModifyCompletionStartedCmd( c, true ) ); } m->addCommand( new ModifyCompletionPercentFinishedCmd( c, date, value.toInt() ) ); if ( value.toInt() == 100 ) { m->addCommand( new ModifyCompletionFinishTimeCmd( c, dt ) ); m->addCommand( new ModifyCompletionFinishedCmd( c, true ) ); } emit executeCommand( m ); // also adds a new entry if necessary if ( c.entrymode() == Completion::EnterCompleted ) { Duration planned = static_cast( node )->plannedEffort( m_nodemodel.id() ); Duration actual = ( planned * value.toInt() ) / 100; debugPlan<execute(); m->addCommand( cmd ); cmd = new ModifyCompletionRemainingEffortCmd( c, date, planned - actual ); cmd->execute(); m->addCommand( cmd ); } return true; } if ( node->type() == Node::Type_Milestone ) { Completion &c = static_cast( node )->completion(); if ( value.toInt() > 0 ) { QDateTime dt = QDateTime::currentDateTime(); QDate date = dt.date(); MacroCommand *m = new MacroCommand( kundo2_i18n( "Set finished" ) ); m->addCommand( new ModifyCompletionStartTimeCmd( c, dt ) ); m->addCommand( new ModifyCompletionStartedCmd( c, true ) ); m->addCommand( new ModifyCompletionFinishTimeCmd( c, dt ) ); m->addCommand( new ModifyCompletionFinishedCmd( c, true ) ); m->addCommand( new ModifyCompletionPercentFinishedCmd( c, date, 100 ) ); emit executeCommand( m ); // also adds a new entry if necessary return true; } return false; } return false; } QVariant NodeItemModel::data( const QModelIndex &index, int role ) const { if ( role == Qt::TextAlignmentRole ) { return headerData( index.column(), Qt::Horizontal, role ); } Node *n = node( index ); if ( role == Role::Object ) { return n ? QVariant::fromValue( static_cast( n ) ) : QVariant(); } QVariant result; if ( n != 0 ) { result = m_nodemodel.data( n, index.column(), role ); //debugPlan<name()<<": "<numChildren(); } Qt::DropActions NodeItemModel::supportedDropActions() const { return Qt::CopyAction | Qt::MoveAction; } QStringList NodeItemModel::mimeTypes() const { return QStringList() << "application/x-vnd.kde.plan.nodeitemmodel.internal" << "application/x-vnd.kde.plan.resourceitemmodel.internal" << "application/x-vnd.kde.plan.project" << "text/uri-list"; } QMimeData *NodeItemModel::mimeData( const QModelIndexList & indexes ) const { QMimeData *m = new QMimeData(); QByteArray encodedData; QDataStream stream(&encodedData, QIODevice::WriteOnly); QList rows; foreach (const QModelIndex &index, indexes) { if ( index.isValid() && !rows.contains( index.row() ) ) { //debugPlan<id(); } } } m->setData("application/x-vnd.kde.plan.nodeitemmodel.internal", encodedData); return m; } bool NodeItemModel::dropAllowed( const QModelIndex &index, int dropIndicatorPosition, const QMimeData *data ) { debugPlan; if ( m_projectshown && ! index.isValid() ) { return false; } Node *dn = node( index ); // returns project if ! index.isValid() if ( dn == 0 ) { errorPlan<<"no node (or project) to drop on!"; return false; // hmmm } if ( data->hasFormat("application/x-vnd.kde.plan.resourceitemmodel.internal") ) { switch ( dropIndicatorPosition ) { case ItemModelBase::OnItem: if ( index.column() == NodeModel::NodeAllocation ) { debugPlan<<"resource:"<type() == Node::Type_Task); return dn->type() == Node::Type_Task; } else if ( index.column() == NodeModel::NodeResponsible ) { debugPlan<<"resource:"<hasFormat( "application/x-vnd.kde.plan.nodeitemmodel.internal") || data->hasFormat( "application/x-vnd.kde.plan.project" ) || data->hasUrls() ) { switch ( dropIndicatorPosition ) { case ItemModelBase::AboveItem: case ItemModelBase::BelowItem: // dn == sibling, if not project if ( dn == m_project ) { return dropAllowed( dn, data ); } return dropAllowed( dn->parentNode(), data ); case ItemModelBase::OnItem: // dn == new parent return dropAllowed( dn, data ); default: break; } } else { debugPlan<<"Unknown mimetype"; } return false; } QList NodeItemModel::resourceList( QDataStream &stream ) { QList lst; while (!stream.atEnd()) { QString id; stream >> id; debugPlan<<"id"<findResource( id ); if ( r ) { lst << r; } } debugPlan<isBaselined() && on->type() != Node::Type_Summarytask ) { return false; } if ( data->hasFormat( "application/x-vnd.kde.plan.nodeitemmodel.internal" ) ) { QByteArray encodedData = data->data( "application/x-vnd.kde.plan.nodeitemmodel.internal" ); QDataStream stream(&encodedData, QIODevice::ReadOnly); QList lst = nodeList( stream ); foreach ( Node *n, lst ) { if ( n->type() == Node::Type_Project || on == n || on->isChildOf( n ) ) { return false; } } lst = removeChildNodes( lst ); foreach ( Node *n, lst ) { if ( ! m_project->canMoveTask( n, on ) ) { return false; } } } return true; } QList NodeItemModel::nodeList( QDataStream &stream ) { QList lst; while (!stream.atEnd()) { QString id; stream >> id; Node *node = m_project->findNode( id ); if ( node ) { lst << node; } } return lst; } QList NodeItemModel::removeChildNodes( const QList &nodes ) { QList lst; foreach ( Node *node, nodes ) { bool ins = true; foreach ( Node *n, lst ) { if ( node->isChildOf( n ) ) { //debugPlan<name()<<" is child of"<name(); ins = false; break; } } if ( ins ) { //debugPlan<<" insert"<name(); lst << node; } } QList nl = lst; QList nlst = lst; foreach ( Node *node, nl ) { foreach ( Node *n, nlst ) { if ( n->isChildOf( node ) ) { //debugPlan<name()<<" is child of"<name(); int i = nodes.indexOf( n ); lst.removeAt( i ); } } } return lst; } bool NodeItemModel::dropResourceMimeData( const QMimeData *data, Qt::DropAction action, int /*row*/, int /*column*/, const QModelIndex &parent ) { QByteArray encodedData = data->data( "application/x-vnd.kde.plan.resourceitemmodel.internal" ); QDataStream stream(&encodedData, QIODevice::ReadOnly); Node *n = node( parent ); debugPlan<name(); if ( parent.column() == NodeModel::NodeResponsible ) { QString s; foreach ( Resource *r, resourceList( stream ) ) { s += r->name(); } if ( ! s.isEmpty() ) { if ( action == Qt::CopyAction && ! n->leader().isEmpty() ) { s += ',' + n->leader(); } KUndo2Command *cmd = m_nodemodel.setLeader( n, s, Qt::EditRole ); if ( cmd ) { emit executeCommand( cmd ); } debugPlan<type() == Node::Type_Task ) { QList lst = resourceList( stream ); if ( action == Qt::CopyAction ) { lst += static_cast( n )->requestedResources(); } KUndo2Command *cmd = createAllocationCommand( static_cast( *n ), lst ); if ( cmd ) { emit executeCommand( cmd ); } return true; } return true; } bool NodeItemModel::dropProjectMimeData( const QMimeData *data, Qt::DropAction action, int row, int /*column*/, const QModelIndex &parent ) { Node *n = node( parent ); if ( n == 0 ) { n = m_project; } debugPlan<data( "application/x-vnd.kde.plan.project" ) ); KoXmlElement element = doc.documentElement().namedItem( "project" ).toElement(); Project project; XMLLoaderObject status; status.setVersion( doc.documentElement().attribute( "version", PLAN_FILE_SYNTAX_VERSION ) ); status.setProject( &project ); if ( ! project.load( element, status ) ) { debugPlan<<"Failed to load project"; return false; } project.generateUniqueNodeIds(); KUndo2Command *cmd = new InsertProjectCmd( project, n, n->childNode( row - 1 ), kundo2_i18nc("1=project or task name", "Insert %1", project.name() ) ); emit executeCommand( cmd ); return true; } bool NodeItemModel::dropUrlMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) { if ( data->hasUrls() ) { QList urls = data->urls(); debugPlan<bad() ) { // d->lastErrorMessage = i18n( "Not a valid Calligra file: %1", file ); debugPlan<<"bad store"<open( "root" ) ) { // maindoc.xml debugPlan<<"No root"<device() ); KoXmlElement element = doc.documentElement().namedItem( "project" ).toElement(); Project project; XMLLoaderObject status; status.setVersion( doc.documentElement().attribute( "version", PLAN_FILE_SYNTAX_VERSION ) ); status.setProject( &project ); if ( ! project.load( element, status ) ) { debugPlan<<"Failed to load project from:"<childNode( row - 1 ), kundo2_i18n( "Insert %1", url.fileName() ) ); emit executeCommand( cmd ); return true; } KUndo2Command *NodeItemModel::createAllocationCommand( Task &task, const QList &lst ) { MacroCommand *cmd = new MacroCommand( kundo2_i18n( "Modify resource allocations" ) ); QMap groups; foreach ( Resource *r, lst ) { if ( ! groups.contains( r->parentGroup() ) && task.resourceGroupRequest( r->parentGroup() ) == 0 ) { ResourceGroupRequest *gr = new ResourceGroupRequest( r->parentGroup() ); groups[ r->parentGroup() ] = gr; cmd->addCommand( new AddResourceGroupRequestCmd( task, gr ) ); } } QList resources = task.requestedResources(); foreach ( Resource *r, lst ) { if ( resources.contains( r ) ) { continue; } ResourceGroupRequest *gr = groups.value( r->parentGroup() ); if ( gr == 0 ) { gr = task.resourceGroupRequest( r->parentGroup() ); } if ( gr == 0 ) { errorPlan<<"No group request found, cannot add resource request:"<name(); continue; } cmd->addCommand( new AddResourceRequestCmd( gr, new ResourceRequest( r, 100 ) ) ); } foreach ( Resource *r, resources ) { if ( ! lst.contains( r ) ) { ResourceGroupRequest *gr = task.resourceGroupRequest( r->parentGroup() ); ResourceRequest *rr = task.requests().find( r ); if ( gr && rr ) { cmd->addCommand( new RemoveResourceRequestCmd( gr, rr ) ); } } } if ( cmd->isEmpty() ) { delete cmd; return 0; } return cmd; } bool NodeItemModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) { debugPlan<hasFormat( "application/x-vnd.kde.plan.resourceitemmodel.internal" ) ) { return dropResourceMimeData( data, action, row, column, parent ); } if ( data->hasFormat( "application/x-vnd.kde.plan.nodeitemmodel.internal" ) ) { if ( action == Qt::MoveAction ) { //debugPlan<<"MoveAction"; QByteArray encodedData = data->data( "application/x-vnd.kde.plan.nodeitemmodel.internal" ); QDataStream stream(&encodedData, QIODevice::ReadOnly); Node *par = 0; if ( parent.isValid() ) { par = node( parent ); } else { par = m_project; } QList lst = nodeList( stream ); QList nodes = removeChildNodes( lst ); // children goes with their parent foreach ( Node *n, nodes ) { if ( ! m_project->canMoveTask( n, par ) ) { //debugPlan<<"Can't move task:"<name(); return false; } } int offset = 0; MacroCommand *cmd = 0; foreach ( Node *n, nodes ) { if ( cmd == 0 ) cmd = new MacroCommand( kundo2_i18n( "Move tasks" ) ); // append nodes if dropped *on* another node, insert if dropped *after* int pos = row == -1 ? -1 : row + offset; if ( pos >= 0 && n->parentNode() == par && par->indexOf( n ) < pos ) { --pos; } if ( n->parentNode() == par ) { // avoid drop into the same position, QAbstractItemModel does not like it int crow = par->indexOf( n ); if ( ( ( pos == -1 ) && ( crow == par->numChildren() - 1 ) ) || ( pos == crow ) ) { delete cmd; cmd = 0; continue; } } cmd->addCommand( new NodeMoveCmd( m_project, n, par, pos ) ); offset++; } if ( cmd ) { emit executeCommand( cmd ); } //debugPlan<name(); return true; } } if ( data->hasFormat( "application/x-vnd.kde.plan.project" ) ) { debugPlan; return dropProjectMimeData( data, action, row, column, parent ); } if ( data->hasUrls() ) { return dropUrlMimeData( data, action, row, column, parent ); } return false; } Node *NodeItemModel::node( const QModelIndex &index ) const { Node *n = m_project; if ( index.isValid() ) { //debugPlan<( index.internalPointer() ); Q_ASSERT( n ); } return n; } void NodeItemModel::slotNodeChanged( Node *node ) { if ( node == 0 || ( ! m_projectshown && node->type() == Node::Type_Project ) ) { return; } if ( node->type() == Node::Type_Project ) { emit dataChanged( createIndex( 0, 0, node ), createIndex( 0, columnCount()-1, node ) ); return; } int row = node->parentNode()->findChildNode( node ); Q_ASSERT( row >= 0 ); emit dataChanged( createIndex( row, 0, node ), createIndex( row, columnCount()-1, node ) ); } QModelIndex NodeItemModel::insertTask( Node *node, Node *after ) { MacroCommand *cmd = new MacroCommand( kundo2_i18n( "Add task" ) ); cmd->addCommand( new TaskAddCmd( m_project, node, after ) ); if ( m_project && node->type() == Node::Type_Task ) { QMap groups; foreach ( Resource *r, m_project->autoAllocateResources() ) { if ( ! groups.contains( r->parentGroup() ) ) { ResourceGroupRequest *gr = new ResourceGroupRequest( r->parentGroup() ); cmd->addCommand( new AddResourceGroupRequestCmd( static_cast(*node), gr ) ); groups[ r->parentGroup() ] = gr; } ResourceRequest *rr = new ResourceRequest( r, 100 ); cmd->addCommand( new AddResourceRequestCmd( groups[ r->parentGroup() ], rr ) ); } } emit executeCommand( cmd ); int row = -1; if ( node->parentNode() ) { row = node->parentNode()->indexOf( node ); } if ( row != -1 ) { //debugPlan<<"Inserted: "<name()<<"; "<name(); return QModelIndex(); } QModelIndex NodeItemModel::insertSubtask( Node *node, Node *parent ) { emit executeCommand( new SubtaskAddCmd( m_project, node, parent, kundo2_i18n( "Add sub-task" ) ) ); int row = -1; if ( node->parentNode() ) { row = node->parentNode()->indexOf( node ); } if ( row != -1 ) { //debugPlan<parentNode()<<" inserted: "<name()<<"; "<name(); return QModelIndex(); } int NodeItemModel::sortRole( int column ) const { int v = Qt::DisplayRole; switch ( column ) { case NodeModel::NodeStartTime: case NodeModel::NodeEndTime: case NodeModel::NodeActualStart: case NodeModel::NodeActualFinish: case NodeModel::NodeEarlyStart: case NodeModel::NodeEarlyFinish: case NodeModel::NodeLateStart: case NodeModel::NodeLateFinish: case NodeModel::NodeConstraintStart: case NodeModel::NodeConstraintEnd: v = Qt::EditRole; break; case NodeModel::NodeWBSCode: v = NodeModel::SortableRole; break; default: break; } debugPlan< lst = parentmap.values(); while ( ! lst.isEmpty() ) delete (int*)(lst.takeFirst()); } int GanttItemModel::rowCount( const QModelIndex &parent ) const { if ( m_showSpecial ) { if ( parentmap.values().contains( parent.internalPointer() ) ) { return 0; } Node *n = node( parent ); if ( n && n->type() == Node::Type_Task ) { return 5; // the task + early start + late finish ++ } } return NodeItemModel::rowCount( parent ); } QModelIndex GanttItemModel::index( int row, int column, const QModelIndex &parent ) const { if ( m_showSpecial && parent.isValid() ) { Node *p = node( parent ); if ( p->type() == Node::Type_Task ) { void *v = 0; foreach ( void *i, parentmap.values( p ) ) { if ( *( (int*)( i ) ) == row ) { v = i; break; } } if ( v == 0 ) { v = new int( row ); const_cast( this )->parentmap.insertMulti( p, v ); } return createIndex( row, column, v ); } } return NodeItemModel::index( row, column, parent ); } QModelIndex GanttItemModel::parent( const QModelIndex &idx ) const { if ( m_showSpecial ) { QList lst = parentmap.keys( idx.internalPointer() ); if ( ! lst.isEmpty() ) { Q_ASSERT( lst.count() == 1 ); return index( lst.first() ); } } return NodeItemModel::parent( idx ); } QVariant GanttItemModel::data( const QModelIndex &index, int role ) const { if ( ! index.isValid() ) { return QVariant(); } if ( role == Qt::TextAlignmentRole ) { return headerData( index.column(), Qt::Horizontal, role ); } QModelIndex idx = index; QList lst; if ( m_showSpecial ) { lst = parentmap.keys( idx.internalPointer() ); } if ( ! lst.isEmpty() ) { Q_ASSERT( lst.count() == 1 ); int row = *((int*)(idx.internalPointer())); Node *n = lst.first(); if ( role == SpecialItemTypeRole ) { return row; // 0=task, 1=early start, 2=late finish... } switch ( row ) { case 0: // the task if ( idx.column() == NodeModel::NodeType && role == KGantt::ItemTypeRole ) { switch ( n->type() ) { case Node::Type_Task: return KGantt::TypeTask; default: break; } } break; case 1: { // early start if ( role != Qt::DisplayRole && role != Qt::EditRole && role != KGantt::ItemTypeRole ) { return QVariant(); } switch ( idx.column() ) { case NodeModel::NodeName: return "Early Start"; case NodeModel::NodeType: return KGantt::TypeEvent; case NodeModel::NodeStartTime: case NodeModel::NodeEndTime: return n->earlyStart( id() ); default: break; } } case 2: { // late finish if ( role != Qt::DisplayRole && role != Qt::EditRole && role != KGantt::ItemTypeRole ) { return QVariant(); } switch ( idx.column() ) { case NodeModel::NodeName: return "Late Finish"; case NodeModel::NodeType: return KGantt::TypeEvent; case NodeModel::NodeStartTime: case NodeModel::NodeEndTime: return n->lateFinish( id() ); default: break; } } case 3: { // late start if ( role != Qt::DisplayRole && role != Qt::EditRole && role != KGantt::ItemTypeRole ) { return QVariant(); } switch ( idx.column() ) { case NodeModel::NodeName: return "Late Start"; case NodeModel::NodeType: return KGantt::TypeEvent; case NodeModel::NodeStartTime: case NodeModel::NodeEndTime: return n->lateStart( id() ); default: break; } } case 4: { // early finish if ( role != Qt::DisplayRole && role != Qt::EditRole && role != KGantt::ItemTypeRole ) { return QVariant(); } switch ( idx.column() ) { case NodeModel::NodeName: return "Early Finish"; case NodeModel::NodeType: return KGantt::TypeEvent; case NodeModel::NodeStartTime: case NodeModel::NodeEndTime: return n->earlyFinish( id() ); default: break; } } default: return QVariant(); } idx = createIndex( idx.row(), idx.column(), n ); } else { if ( role == SpecialItemTypeRole ) { return 0; // task of some type } if ( idx.column() == NodeModel::NodeType && role == KGantt::ItemTypeRole ) { QModelIndex notScheduled = idx.sibling(idx.row(), NodeModel::NodeNotScheduled); if (notScheduled.data(Qt::EditRole).toBool()) { return QVariant(); } QVariant result = NodeItemModel::data( idx, Qt::EditRole ); switch ( result.toInt() ) { case Node::Type_Project: return KGantt::TypeSummary; case Node::Type_Summarytask: return KGantt::TypeSummary; case Node::Type_Milestone: return KGantt::TypeEvent; default: return m_showSpecial ? KGantt::TypeMulti : KGantt::TypeTask; } } } return NodeItemModel::data( idx, role ); } //---------------------------- MilestoneItemModel::MilestoneItemModel( QObject *parent ) : ItemModelBase( parent ) { } MilestoneItemModel::~MilestoneItemModel() { } QList MilestoneItemModel::mileStones() const { QList lst; foreach( Node* n, m_nodemap ) { if ( n->type() == Node::Type_Milestone ) { lst << n; } } return lst; } void MilestoneItemModel::slotNodeToBeInserted( Node *parent, int row ) { Q_UNUSED(parent); Q_UNUSED(row); } void MilestoneItemModel::slotNodeInserted( Node *node ) { Q_UNUSED(node); resetModel(); } void MilestoneItemModel::slotNodeToBeRemoved( Node *node ) { Q_UNUSED(node); //debugPlan<name(); /* int row = m_nodemap.values().indexOf( node ); if ( row != -1 ) { Q_ASSERT( m_nodemap.contains( node->wbsCode() ) ); Q_ASSERT( m_nodemap.keys().indexOf( node->wbsCode() ) == row ); beginRemoveRows( QModelIndex(), row, row ); m_nodemap.remove( node->wbsCode() ); endRemoveRows(); }*/ } void MilestoneItemModel::slotNodeRemoved( Node *node ) { Q_UNUSED(node); resetModel(); //endRemoveRows(); } void MilestoneItemModel::slotLayoutChanged() { //debugPlan<name(); emit layoutAboutToBeChanged(); emit layoutChanged(); } void MilestoneItemModel::slotNodeToBeMoved( Node *node, int pos, Node *newParent, int newPos ) { Q_UNUSED( node ); Q_UNUSED( pos ); Q_UNUSED( newParent ); Q_UNUSED( newPos ); } void MilestoneItemModel::slotNodeMoved( Node *node ) { Q_UNUSED( node ); resetModel(); } void MilestoneItemModel::setProject( Project *project ) { if ( m_project ) { disconnect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - disconnect( m_project, SIGNAL(localeChanged()), this, SLOT(slotLayoutChanged()) ); - disconnect( m_project, SIGNAL(wbsDefinitionChanged()), this, SLOT(slotWbsDefinitionChanged()) ); - disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - disconnect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); - disconnect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); + disconnect( m_project, SIGNAL(localeChanged()), this, SLOT(slotLayoutChanged())); + disconnect( m_project, SIGNAL(wbsDefinitionChanged()), this, SLOT(slotWbsDefinitionChanged())); + disconnect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*))); + disconnect( m_project, SIGNAL(nodeToBeAdded(KPlato::Node*,int)), this, SLOT(slotNodeToBeInserted(KPlato::Node*,int))); + disconnect( m_project, SIGNAL(nodeToBeRemoved(KPlato::Node*)), this, SLOT(slotNodeToBeRemoved(KPlato::Node*))); - disconnect(m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotNodeToBeMoved(Node*,int,Node*,int))); - disconnect(m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotNodeMoved(Node*))); + disconnect(m_project, SIGNAL(nodeToBeMoved(KPlato::Node*,int,KPlato::Node*,int)), this, SLOT(slotNodeToBeMoved(KPlato::Node*,int,KPlato::Node*,int))); + disconnect(m_project, SIGNAL(nodeMoved(KPlato::Node*)), this, SLOT(slotNodeMoved(KPlato::Node*))); - disconnect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); - disconnect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); + disconnect( m_project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeInserted(KPlato::Node*))); + disconnect( m_project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*))); } m_project = project; //debugPlan<"<allNodes() ) { m_nodemap.insert( n->wbsCode(true), n ); } } return cnt != m_nodemap.count(); } void MilestoneItemModel::resetModel() { beginResetModel(); resetData(); endResetModel(); } Qt::ItemFlags MilestoneItemModel::flags( const QModelIndex &index ) const { Qt::ItemFlags flags = QAbstractItemModel::flags( index ); if ( !index.isValid() ) { if ( m_readWrite ) { flags |= Qt::ItemIsDropEnabled; } return flags; } if ( m_readWrite ) { flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; switch ( index.column() ) { case NodeModel::NodeName: // name flags |= Qt::ItemIsEditable; break; case NodeModel::NodeType: break; // Node type case NodeModel::NodeResponsible: // Responsible flags |= Qt::ItemIsEditable; break; case NodeModel::NodeConstraint: // constraint type flags |= Qt::ItemIsEditable; break; case NodeModel::NodeConstraintStart: { // constraint start Node *n = node( index ); if ( n == 0 ) break; int c = n->constraint(); if ( c == Node::MustStartOn || c == Node::StartNotEarlier || c == Node::FixedInterval ) { flags |= Qt::ItemIsEditable; } break; } case NodeModel::NodeConstraintEnd: { // constraint end Node *n = node( index ); if ( n == 0 ) break; int c = n->constraint(); if ( c == Node::MustFinishOn || c == Node::FinishNotLater || c == Node::FixedInterval ) { flags |= Qt::ItemIsEditable; } break; } case NodeModel::NodeStartupAccount: // startup account case NodeModel::NodeStartupCost: // startup cost case NodeModel::NodeShutdownAccount: // shutdown account case NodeModel::NodeShutdownCost: { // shutdown cost Node *n = node( index ); if ( n && (n->type() == Node::Type_Task || n->type() == Node::Type_Milestone) ) { flags |= Qt::ItemIsEditable; } break; } case NodeModel::NodeDescription: // description break; default: flags &= ~Qt::ItemIsEditable; } } return flags; } QModelIndex MilestoneItemModel::parent( const QModelIndex &index ) const { Q_UNUSED(index); return QModelIndex(); } QModelIndex MilestoneItemModel::index( int row, int column, const QModelIndex &parent ) const { //debugPlan<= m_nodemap.count() ) { //debugPlan<<"No index for"<( node ) ), 0, const_cast(node) ); } QVariant MilestoneItemModel::data( const QModelIndex &index, int role ) const { QVariant result; if ( role == Qt::TextAlignmentRole ) { return headerData( index.column(), Qt::Horizontal, role ); } Node *n = node( index ); if ( n != 0 ) { if ( index.column() == NodeModel::NodeType && role == KGantt::ItemTypeRole ) { result = m_nodemodel.data( n, index.column(), Qt::EditRole ); switch ( result.toInt() ) { case Node::Type_Summarytask: return KGantt::TypeSummary; case Node::Type_Milestone: return KGantt::TypeEvent; default: return KGantt::TypeTask; } return result; } } result = m_nodemodel.data( n, index.column(), role ); return result; } bool MilestoneItemModel::setData( const QModelIndex &index, const QVariant &/*value*/, int role ) { if ( ( flags(index) &Qt::ItemIsEditable ) == 0 || role != Qt::EditRole ) { return false; } // Node *n = node( index ); switch (index.column()) { default: qWarning("data: invalid display value column %d", index.column()); return false; } return false; } QVariant MilestoneItemModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( orientation == Qt::Horizontal ) { if (role == Qt::DisplayRole || role == Qt::TextAlignmentRole || role == Qt::EditRole) { return m_nodemodel.headerData(section, role); } } if ( role == Qt::ToolTipRole ) { return NodeModel::headerData( section, role ); } return ItemModelBase::headerData(section, orientation, role); } QAbstractItemDelegate *MilestoneItemModel::createDelegate( int column, QWidget *parent ) const { switch ( column ) { case NodeModel::NodeEstimateType: return new EnumDelegate( parent ); case NodeModel::NodeEstimateCalendar: return new EnumDelegate( parent ); case NodeModel::NodeEstimate: return new DurationSpinBoxDelegate( parent ); case NodeModel::NodeOptimisticRatio: return new SpinBoxDelegate( parent ); case NodeModel::NodePessimisticRatio: return new SpinBoxDelegate( parent ); case NodeModel::NodeRisk: return new EnumDelegate( parent ); case NodeModel::NodeConstraint: return new EnumDelegate( parent ); case NodeModel::NodeRunningAccount: return new EnumDelegate( parent ); case NodeModel::NodeStartupAccount: return new EnumDelegate( parent ); case NodeModel::NodeStartupCost: return new MoneyDelegate( parent ); case NodeModel::NodeShutdownAccount: return new EnumDelegate( parent ); case NodeModel::NodeShutdownCost: return new MoneyDelegate( parent ); case NodeModel::NodeCompleted: return new TaskCompleteDelegate( parent ); case NodeModel::NodeRemainingEffort: return new DurationSpinBoxDelegate( parent ); case NodeModel::NodeActualEffort: return new DurationSpinBoxDelegate( parent ); default: return 0; } return 0; } int MilestoneItemModel::columnCount( const QModelIndex &/*parent*/ ) const { return m_nodemodel.propertyCount(); } int MilestoneItemModel::rowCount( const QModelIndex &parent ) const { //debugPlan< rows; foreach (const QModelIndex &index, indexes) { if ( index.isValid() && !rows.contains( index.row() ) ) { //debugPlan<id(); } } } m->setData("application/x-vnd.kde.plan.nodeitemmodel.internal", encodedData); return m; } bool MilestoneItemModel::dropAllowed( const QModelIndex &index, int dropIndicatorPosition, const QMimeData *data ) { //debugPlan; Node *dn = node( index ); if ( dn == 0 ) { errorPlan<<"no node to drop on!"; return false; // hmmm } switch ( dropIndicatorPosition ) { case ItemModelBase::AboveItem: case ItemModelBase::BelowItem: // dn == sibling return dropAllowed( dn->parentNode(), data ); case ItemModelBase::OnItem: // dn == new parent return dropAllowed( dn, data ); default: break; } return false; } bool MilestoneItemModel::dropAllowed( Node *on, const QMimeData *data ) { if ( !data->hasFormat("application/x-vnd.kde.plan.nodeitemmodel.internal") ) { return false; } if ( on == m_project ) { return true; } QByteArray encodedData = data->data( "application/x-vnd.kde.plan.nodeitemmodel.internal" ); QDataStream stream(&encodedData, QIODevice::ReadOnly); QList lst = nodeList( stream ); foreach ( Node *n, lst ) { if ( on == n || on->isChildOf( n ) ) { return false; } } lst = removeChildNodes( lst ); foreach ( Node *n, lst ) { if ( ! m_project->canMoveTask( n, on ) ) { return false; } } return true; } QList MilestoneItemModel::nodeList( QDataStream &stream ) { QList lst; while (!stream.atEnd()) { QString id; stream >> id; Node *node = m_project->findNode( id ); if ( node ) { lst << node; } } return lst; } QList MilestoneItemModel::removeChildNodes( const QList &nodes ) { QList lst; foreach ( Node *node, nodes ) { bool ins = true; foreach ( Node *n, lst ) { if ( node->isChildOf( n ) ) { //debugPlan<name()<<" is child of"<name(); ins = false; break; } } if ( ins ) { //debugPlan<<" insert"<name(); lst << node; } } QList nl = lst; QList nlst = lst; foreach ( Node *node, nl ) { foreach ( Node *n, nlst ) { if ( n->isChildOf( node ) ) { //debugPlan<name()<<" is child of"<name(); int i = nodes.indexOf( n ); lst.removeAt( i ); } } } return lst; } bool MilestoneItemModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int /*column*/, const QModelIndex &parent ) { //debugPlan<hasFormat( "application/x-vnd.kde.plan.nodeitemmodel.internal" ) ) { return false; } if ( action == Qt::MoveAction ) { //debugPlan<<"MoveAction"; QByteArray encodedData = data->data( "application/x-vnd.kde.plan.nodeitemmodel.internal" ); QDataStream stream(&encodedData, QIODevice::ReadOnly); Node *par = 0; if ( parent.isValid() ) { par = node( parent ); } else { par = m_project; } QList lst = nodeList( stream ); QList nodes = removeChildNodes( lst ); // children goes with their parent foreach ( Node *n, nodes ) { if ( ! m_project->canMoveTask( n, par ) ) { //debugPlan<<"Can't move task:"<name(); return false; } } int offset = 0; MacroCommand *cmd = 0; foreach ( Node *n, nodes ) { if ( cmd == 0 ) cmd = new MacroCommand( kundo2_i18n( "Move tasks" ) ); // append nodes if dropped *on* another node, insert if dropped *after* int pos = row == -1 ? -1 : row + offset; cmd->addCommand( new NodeMoveCmd( m_project, n, par, pos ) ); offset++; } if ( cmd ) { emit executeCommand( cmd ); } //debugPlan<name(); return true; } return false; } Node *MilestoneItemModel::node( const QModelIndex &index ) const { Node *n = 0; if ( index.isValid() ) { //debugPlan<( index.internalPointer() ); } return n; } void MilestoneItemModel::slotNodeChanged( Node *node ) { //debugPlan<name(); if ( node == 0 ) { return; } beginResetModel(); resetData(); endResetModel(); } void MilestoneItemModel::slotWbsDefinitionChanged() { //debugPlan; if ( m_project == 0 ) { return; } if ( ! m_nodemap.isEmpty() ) { beginResetModel(); resetData(); endResetModel(); } } int MilestoneItemModel::sortRole( int column ) const { int v = Qt::DisplayRole; switch ( column ) { case NodeModel::NodeStartTime: case NodeModel::NodeEndTime: case NodeModel::NodeActualStart: case NodeModel::NodeActualFinish: case NodeModel::NodeEarlyStart: case NodeModel::NodeEarlyFinish: case NodeModel::NodeLateStart: case NodeModel::NodeLateFinish: case NodeModel::NodeConstraintStart: case NodeModel::NodeConstraintEnd: v = Qt::EditRole; break; case NodeModel::NodeWBSCode: v = NodeModel::SortableRole; break; default: break; } return v; } //-------------- NodeSortFilterProxyModel::NodeSortFilterProxyModel( ItemModelBase* model, QObject *parent, bool filterUnscheduled ) : QSortFilterProxyModel( parent ), m_filterUnscheduled( filterUnscheduled ) { setSourceModel( model ); setDynamicSortFilter( true ); } ItemModelBase *NodeSortFilterProxyModel::itemModel() const { return static_cast( sourceModel() ); } void NodeSortFilterProxyModel::setFilterUnscheduled( bool on ) { m_filterUnscheduled = on; invalidateFilter(); } bool NodeSortFilterProxyModel::filterAcceptsRow ( int row, const QModelIndex & parent ) const { //debugPlan<project() == 0 ) { //debugPlan<project(); return false; } if ( m_filterUnscheduled ) { QString s = sourceModel()->data( sourceModel()->index( row, NodeModel::NodeNotScheduled, parent ), Qt::EditRole ).toString(); if ( s == "true" ) { //debugPlan<<"Filtered unscheduled:"<index( row, 0, parent ); return false; } } bool accepted = QSortFilterProxyModel::filterAcceptsRow( row, parent ); //debugPlan<index( row, 0, parent )<<"accepted ="<sortRole(column)); QSortFilterProxyModel::sort(column, order); } //------------------ TaskModuleModel::TaskModuleModel( QObject *parent ) : QAbstractItemModel( parent ) { } void TaskModuleModel::addTaskModule( Project *project, const QUrl &url ) { beginInsertRows( QModelIndex(), m_modules.count(), m_modules.count() ); m_modules << project; m_urls << url; endInsertRows(); } Qt::ItemFlags TaskModuleModel::flags( const QModelIndex &idx ) const { Qt::ItemFlags f = QAbstractItemModel::flags( idx ) | Qt::ItemIsDropEnabled; if ( idx.isValid() ) { f |= Qt::ItemIsDragEnabled; } return f; } int TaskModuleModel::columnCount (const QModelIndex &/*idx*/ ) const { return 1; } int TaskModuleModel::rowCount( const QModelIndex &idx ) const { return idx.isValid() ? 0 : m_modules.count(); } QVariant TaskModuleModel::data( const QModelIndex& idx, int role ) const { if (!idx.isValid() || idx.row() >= m_modules.count()) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: return m_modules.value( idx.row() )->name(); case Qt::ToolTipRole: return m_modules.value( idx.row() )->description(); case Qt::WhatsThisRole: return m_modules.value( idx.row() )->description(); case Qt::UserRole: return m_urls.value(idx.row()); default: break; } return QVariant(); } QVariant TaskModuleModel::headerData( int /*section*/, Qt::Orientation orientation , int role ) const { if ( orientation == Qt::Horizontal ) { switch ( role ) { case Qt::DisplayRole: return xi18nc( "@title:column", "Name" ); default: break; } } return QVariant(); } QModelIndex TaskModuleModel::parent( const QModelIndex& /*idx*/ ) const { return QModelIndex(); } QModelIndex TaskModuleModel::index( int row, int column, const QModelIndex &parent ) const { if ( parent.isValid() ) { return QModelIndex(); } return createIndex( row, column, m_modules.value( row ) ); } QStringList TaskModuleModel::mimeTypes() const { return QStringList() << "application/x-vnd.kde.plan" << "text/uri-list"; } bool TaskModuleModel::dropMimeData( const QMimeData *data, Qt::DropAction /*action*/, int /*row*/, int /*column*/, const QModelIndex &/*parent*/ ) { if ( data->hasUrls() ) { QList urls = data->urls(); debugPlan<bad() ) { // d->lastErrorMessage = i18n( "Not a valid Calligra file: %1", file ); debugPlan<<"bad store"<open( "root" ) ) { // maindoc.xml debugPlan<<"No root"<device() ); KoXmlElement element = doc.documentElement().namedItem( "project" ).toElement(); Project *project = new Project(); XMLLoaderObject status; status.setVersion( doc.documentElement().attribute( "version", PLAN_FILE_SYNTAX_VERSION ) ); status.setProject( project ); if ( project->load( element, status ) ) { stripProject( project ); addTaskModule( project, url ); if ( emitsignal ) { // FIXME: save destroys the project, so give it a copy (see kptview.cpp) Project p; status.setProject( &p ); p.load( element, status ); emit saveTaskModule( url, &p ); } } else { debugPlan<<"Failed to load project from:"<save( doc ); mime->setData( "application/x-vnd.kde.plan.project", document.toByteArray() ); } } return mime; } void TaskModuleModel::stripProject( Project *project ) const { foreach ( ScheduleManager *sm, project->scheduleManagers() ) { DeleteScheduleManagerCmd c( *project, sm ); } } void TaskModuleModel::loadTaskModules( const QStringList &files ) { debugPlan< 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 NODEITEMMODEL_H #define NODEITEMMODEL_H #include "kptitemmodelbase.h" #include "kptschedule.h" #include "kptworkpackagemodel.h" #include #include #include #include class QMimeData; class KUndo2Command; class KoXmlWriter; class KoStore; class KoOdfWriteStore; namespace KPlato { class Project; class Node; class Estimate; class PLANMODELS_EXPORT NodeModel : public QObject { Q_OBJECT Q_ENUMS( Properties ) public: NodeModel(); ~NodeModel() {} enum SpecialRoles { SortableRole = Qt::UserRole + 5024 // unlikely high number }; enum Properties { NodeName = 0, NodeType, NodeResponsible, NodeAllocation, NodeEstimateType, NodeEstimateCalendar, NodeEstimate, NodeOptimisticRatio, NodePessimisticRatio, NodeRisk, NodeConstraint, NodeConstraintStart, NodeConstraintEnd, NodeRunningAccount, NodeStartupAccount, NodeStartupCost, NodeShutdownAccount, NodeShutdownCost, NodeDescription, // Based on edited values NodeExpected, NodeVarianceEstimate, NodeOptimistic, NodePessimistic, // After scheduling NodeStartTime, NodeEndTime, NodeEarlyStart, NodeEarlyFinish, NodeLateStart, NodeLateFinish, NodePositiveFloat, NodeFreeFloat, NodeNegativeFloat, NodeStartFloat, NodeFinishFloat, NodeAssignments, // Based on scheduled values NodeDuration, NodeVarianceDuration, NodeOptimisticDuration, NodePessimisticDuration, // Completion NodeStatus, NodeCompleted, NodePlannedEffort, NodeActualEffort, NodeRemainingEffort, NodePlannedCost, NodeActualCost, NodeActualStart, NodeStarted, NodeActualFinish, NodeFinished, NodeStatusNote, // Scheduling errors NodeSchedulingStatus, NodeNotScheduled, NodeAssignmentMissing, NodeResourceOverbooked, NodeResourceUnavailable, NodeConstraintsError, NodeEffortNotMet, NodeSchedulingError, NodeWBSCode, NodeLevel, // Performance NodeBCWS, NodeBCWP, NodeACWP, NodePerformanceIndex, // NodeCritical, NodeCriticalPath, // Info from latest work package transmission WPOwnerName, WPTransmitionStatus, WPTransmitionTime }; const QMetaEnum columnMap() const; void setProject( Project *project ); void setManager( ScheduleManager *sm ); Project *project() const { return m_project; } ScheduleManager *manager() const { return m_manager; } long id() const { return m_manager == 0 ? -1 : m_manager->scheduleId(); } QVariant data( const Node *node, int property, int role = Qt::DisplayRole ) const; KUndo2Command *setData( Node *node, int property, const QVariant & value, int role = Qt::EditRole ); static QVariant headerData( int section, int role = Qt::DisplayRole ); int propertyCount() const; void setNow( const QDate &now ) { m_now = now; } QDate now() const { return m_now; } QVariant name( const Node *node, int role ) const; QVariant leader( const Node *node, int role ) const; QVariant allocation( const Node *node, int role ) const; QVariant description( const Node *node, int role ) const; QVariant type( const Node *node, int role ) const; QVariant constraint( const Node *node, int role ) const; QVariant constraintStartTime( const Node *node, int role ) const; QVariant constraintEndTime( const Node *node, int role ) const; QVariant estimateType( const Node *node, int role ) const; QVariant estimateCalendar( const Node *node, int role ) const; QVariant estimate( const Node *node, int role ) const; QVariant optimisticRatio( const Node *node, int role ) const; QVariant pessimisticRatio( const Node *node, int role ) const; QVariant riskType( const Node *node, int role ) const; QVariant runningAccount( const Node *node, int role ) const; QVariant startupAccount( const Node *node, int role ) const; QVariant startupCost( const Node *node, int role ) const; QVariant shutdownAccount( const Node *node, int role ) const; QVariant shutdownCost( const Node *node, int role ) const; QVariant startTime( const Node *node, int role ) const; QVariant endTime( const Node *node, int role ) const; QVariant duration( const Node *node, int role ) const; QVariant varianceDuration( const Node *node, int role ) const; QVariant varianceEstimate( const Estimate *est, int role ) const; QVariant optimisticDuration( const Node *node, int role ) const; QVariant optimisticEstimate( const Estimate *est, int role ) const; QVariant pertExpected( const Estimate *est, int role ) const; QVariant pessimisticDuration( const Node *node, int role ) const; QVariant pessimisticEstimate( const Estimate *est, int role ) const; QVariant earlyStart( const Node *node, int role ) const; QVariant earlyFinish( const Node *node, int role ) const; QVariant lateStart( const Node *node, int role ) const; QVariant lateFinish( const Node *node, int role ) const; QVariant positiveFloat( const Node *node, int role ) const; QVariant freeFloat( const Node *node, int role ) const; QVariant negativeFloat( const Node *node, int role ) const; QVariant startFloat( const Node *node, int role ) const; QVariant finishFloat( const Node *node, int role ) const; QVariant assignedResources( const Node *node, int role ) const; QVariant status( const Node *node, int role ) const; QVariant completed( const Node *node, int role ) const; QVariant startedTime( const Node *node, int role ) const; QVariant isStarted( const Node *node, int role ) const; QVariant finishedTime( const Node *node, int role ) const; QVariant isFinished( const Node *node, int role ) const; QVariant plannedEffortTo( const Node *node, int role ) const; QVariant actualEffortTo( const Node *node, int role ) const; QVariant remainingEffort( const Node *node, int role ) const; QVariant plannedCostTo( const Node *node, int role ) const; QVariant actualCostTo( const Node *node, int role ) const; QVariant note( const Node *node, int role ) const; /// The nodes scheduling status QVariant nodeSchedulingStatus( const Node *node, int role ) const; /// Set if the node has not been scheduled QVariant nodeIsNotScheduled( const Node *node, int role ) const; /// Set if EffortType == Effort, but no resource is requested QVariant resourceIsMissing( const Node *node, int role ) const; /// Set if the assigned resource is overbooked QVariant resourceIsOverbooked( const Node *node, int role ) const; /// Set if the requested resource is not available QVariant resourceIsNotAvailable( const Node *node, int role ) const; /// Set if the task cannot be scheduled to fulfil all the constraints QVariant schedulingConstraintsError( const Node *node, int role ) const; /// Resources could not fulfil estimate QVariant effortNotMet( const Node *node, int role ) const; /// Other scheduling error occurred QVariant schedulingError( const Node *node, int role ) const; QVariant wbsCode( const Node *node, int role ) const; QVariant nodeLevel( const Node *node, int role ) const; QVariant nodeBCWS( const Node *node, int role ) const; QVariant nodeBCWP( const Node *node, int role ) const; QVariant nodeACWP( const Node *node, int role ) const; QVariant nodePerformanceIndex( const Node *node, int role ) const; QVariant nodeIsCritical( const Node *node, int role ) const; QVariant nodeInCriticalPath( const Node *node, int role ) const; QVariant wpOwnerName( const Node *node, int role ) const; QVariant wpTransmitionStatus( const Node *node, int role ) const; QVariant wpTransmitionTime( const Node *node, int role ) const; KUndo2Command *setName( Node *node, const QVariant &value, int role ); KUndo2Command *setLeader( Node *node, const QVariant &value, int role ); KUndo2Command *setAllocation( Node *node, const QVariant &value, int role ); KUndo2Command *setDescription( Node *node, const QVariant &value, int role ); KUndo2Command *setType( Node *node, const QVariant &value, int role ); KUndo2Command *setConstraint( Node *node, const QVariant &value, int role ); KUndo2Command *setConstraintStartTime( Node *node, const QVariant &value, int role ); KUndo2Command *setConstraintEndTime( Node *node, const QVariant &value, int role ); KUndo2Command *setEstimateType( Node *node, const QVariant &value, int role ); KUndo2Command *setEstimateCalendar( Node *node, const QVariant &value, int role ); KUndo2Command *setEstimate( Node *node, const QVariant &value, int role ); KUndo2Command *setOptimisticRatio( Node *node, const QVariant &value, int role ); KUndo2Command *setPessimisticRatio( Node *node, const QVariant &value, int role ); KUndo2Command *setRiskType( Node *node, const QVariant &value, int role ); KUndo2Command *setRunningAccount( Node *node, const QVariant &value, int role ); KUndo2Command *setStartupAccount( Node *node, const QVariant &value, int role ); KUndo2Command *setStartupCost( Node *node, const QVariant &value, int role ); KUndo2Command *setShutdownAccount( Node *node, const QVariant &value, int role ); KUndo2Command *setShutdownCost( Node *node, const QVariant &value, int role ); KUndo2Command *setCompletion( Node *node, const QVariant &value, int role ); KUndo2Command *setActualEffort( Node *node, const QVariant &value, int role ); KUndo2Command *setRemainingEffort( Node *node, const QVariant &value, int role ); KUndo2Command *setStartedTime( Node *node, const QVariant &value, int role ); KUndo2Command *setFinishedTime( Node *node, const QVariant &value, int role ); private: Project *m_project; ScheduleManager *m_manager; QDate m_now; int m_prec; }; class PLANMODELS_EXPORT NodeItemModel : public ItemModelBase { Q_OBJECT public: explicit NodeItemModel( QObject *parent = 0 ); ~NodeItemModel(); /// Returns a column number/- name map for this model virtual const QMetaEnum columnMap() const { return m_nodemodel.columnMap(); } ScheduleManager *manager() const { return m_nodemodel.manager(); } long id() const { return m_nodemodel.id(); } virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; virtual QModelIndex index( const Node *node, int column = 0 ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; virtual QMimeData * mimeData( const QModelIndexList & indexes ) const; virtual QStringList mimeTypes () const; virtual Qt::DropActions supportedDropActions() const; virtual bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ); Node *node( const QModelIndex &index ) const; QAbstractItemDelegate *createDelegate( int column, QWidget *parent ) const; QModelIndex insertTask( Node *node, Node *after ); QModelIndex insertSubtask( Node *node, Node *parent ); QList nodeList( QDataStream &stream ); QList resourceList( QDataStream &stream ); static QList removeChildNodes( const QList &nodes ); bool dropAllowed( Node *on, const QMimeData *data ); virtual bool dropAllowed( const QModelIndex &index, int dropIndicatorPosition, const QMimeData *data ); bool projectShown() const { return m_projectshown; } /// Return the sortorder to be used for @p column virtual int sortRole( int column ) const; Q_SIGNALS: - void nodeInserted( Node *node ); + void nodeInserted(KPlato::Node *node); void projectShownChanged( bool ); public Q_SLOTS: - virtual void setProject( Project *project ); - virtual void setScheduleManager( ScheduleManager *sm ); + virtual void setProject(KPlato::Project *project); + virtual void setScheduleManager(KPlato::ScheduleManager *sm); void setShowProject( bool on ); protected Q_SLOTS: virtual void slotWbsDefinitionChanged(); - virtual void slotNodeChanged( Node* ); - virtual void slotNodeToBeInserted( Node *node, int row ); - virtual void slotNodeInserted( Node *node ); - virtual void slotNodeToBeRemoved( Node *node ); - virtual void slotNodeRemoved( Node *node ); + virtual void slotNodeChanged(KPlato::Node* ); + virtual void slotNodeToBeInserted(KPlato::Node *node, int row ); + virtual void slotNodeInserted(KPlato::Node *node ); + virtual void slotNodeToBeRemoved(KPlato::Node *node ); + virtual void slotNodeRemoved(KPlato::Node *node ); - virtual void slotNodeToBeMoved( Node *node, int pos, Node *newParent, int newPos ); - virtual void slotNodeMoved( Node *node ); + virtual void slotNodeToBeMoved(KPlato::Node *node, int pos, KPlato::Node *newParent, int newPos ); + virtual void slotNodeMoved(KPlato::Node *node ); virtual void slotLayoutChanged(); - virtual void slotProjectCalculated( ScheduleManager *sm ); + virtual void slotProjectCalculated(KPlato::ScheduleManager *sm); protected: virtual bool setType( Node *node, const QVariant &value, int role ); bool setCompletion( Node *node, const QVariant &value, int role ); bool setAllocation( Node *node, const QVariant &value, int role ); bool dropResourceMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ); bool dropProjectMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ); KUndo2Command *createAllocationCommand( Task &task, const QList &lst ); bool dropUrlMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ); bool importProjectFile( const QUrl &url, Qt::DropAction action, int row, int column, const QModelIndex &parent ); protected: Node *m_node; // for sanity check NodeModel m_nodemodel; bool m_projectshown; }; //-------------------------------------- class PLANMODELS_EXPORT GanttItemModel : public NodeItemModel { Q_OBJECT public: enum GanttModelRoles { SpecialItemTypeRole = Qt::UserRole + 123 }; //FIXME explicit GanttItemModel(QObject *parent = 0); ~GanttItemModel(); virtual int rowCount( const QModelIndex &parent ) const; using NodeItemModel::index; virtual QModelIndex index( int row, int column, const QModelIndex &parent ) const; QModelIndex parent( const QModelIndex &idx ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; void setShowSpecial( bool on ) { m_showSpecial = on; } bool showSpecial() const { return m_showSpecial; } private: bool m_showSpecial; QMap parentmap; }; // TODO: Rename, this is now a flat node item model class PLANMODELS_EXPORT MilestoneItemModel : public ItemModelBase { Q_OBJECT public: explicit MilestoneItemModel( QObject *parent = 0 ); ~MilestoneItemModel(); /// Returns a column number/- name map for this model virtual const QMetaEnum columnMap() const { return m_nodemodel.columnMap(); } ScheduleManager *manager() const { return m_nodemodel.manager(); } long id() const { return m_nodemodel.id(); } virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; virtual QModelIndex index( const Node *node ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; virtual QMimeData * mimeData( const QModelIndexList & indexes ) const; virtual QStringList mimeTypes () const; virtual Qt::DropActions supportedDropActions() const; virtual bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ); Node *node( const QModelIndex &index ) const; virtual QAbstractItemDelegate *createDelegate( int column, QWidget *parent ) const; QModelIndex insertTask( Node *node, Node *after ); QModelIndex insertSubtask( Node *node, Node *parent ); QList nodeList( QDataStream &stream ); static QList removeChildNodes( const QList &nodes ); bool dropAllowed( Node *on, const QMimeData *data ); virtual bool dropAllowed( const QModelIndex &index, int dropIndicatorPosition, const QMimeData *data ); QList mileStones() const; int sortRole(int column) const; public Q_SLOTS: - virtual void setProject( Project *project ); - virtual void setScheduleManager( ScheduleManager *sm ); + virtual void setProject(KPlato::Project *project); + virtual void setScheduleManager(KPlato::ScheduleManager *sm); protected Q_SLOTS: - void slotNodeChanged( Node* ); - void slotNodeToBeInserted( Node *node, int row ); - void slotNodeInserted( Node *node ); - void slotNodeToBeRemoved( Node *node ); - void slotNodeRemoved( Node *node ); - void slotNodeToBeMoved( Node *node, int pos, Node *newParent, int newPos ); - void slotNodeMoved( Node *node ); + void slotNodeChanged(KPlato::Node*); + void slotNodeToBeInserted(KPlato::Node *node, int row); + void slotNodeInserted(KPlato::Node *node); + void slotNodeToBeRemoved(KPlato::Node *node); + void slotNodeRemoved(KPlato::Node *node); + void slotNodeToBeMoved(KPlato::Node *node, int pos,KPlato::Node *newParent, int newPos); + void slotNodeMoved(KPlato::Node *node); void slotLayoutChanged(); void slotWbsDefinitionChanged(); protected: bool resetData(); void resetModel(); private: NodeModel m_nodemodel; QMap m_nodemap; }; class PLANMODELS_EXPORT NodeSortFilterProxyModel : public QSortFilterProxyModel { Q_OBJECT public: NodeSortFilterProxyModel( ItemModelBase* model, QObject *parent, bool filterUnscheduled = true ); ItemModelBase *itemModel() const; void setFilterUnscheduled( bool on ); bool filterUnscheduled() const { return m_filterUnscheduled; } void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); protected: bool filterAcceptsRow ( int source_row, const QModelIndex & source_parent ) const; private: NodeItemModel *m_model; bool m_filterUnscheduled; }; class PLANMODELS_EXPORT TaskModuleModel : public QAbstractItemModel { Q_OBJECT public: explicit TaskModuleModel(QObject *parent = 0); void addTaskModule(Project *project , const QUrl &url); Qt::ItemFlags flags( const QModelIndex &idx ) const; int columnCount( const QModelIndex &idx = QModelIndex() ) const; int rowCount( const QModelIndex &idx = QModelIndex() ) const; QVariant data( const QModelIndex &idx, int role = Qt::DisplayRole ) const; QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; QModelIndex parent( const QModelIndex &idx ) const; QModelIndex index( int row, int column, const QModelIndex &parent ) const; QStringList mimeTypes() const; bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ); QMimeData *mimeData( const QModelIndexList &idx ) const; bool importProject( const QUrl &url, bool emitsignal = true ); public Q_SLOTS: void loadTaskModules( const QStringList &files ); Q_SIGNALS: void executeCommand( KUndo2Command *cmd ); - void saveTaskModule( const QUrl &url, Project *project ); + void saveTaskModule( const QUrl &url, KPlato::Project *project ); void removeTaskModule( const QUrl &url ); protected: void stripProject( Project *project ) const; private: QList m_modules; QList m_urls; }; } //namespace KPlato #endif //NODEITEMMODEL_H diff --git a/src/libs/models/kptpertcpmmodel.cpp b/src/libs/models/kptpertcpmmodel.cpp index 0a9fccd4..c1ee9811 100644 --- a/src/libs/models/kptpertcpmmodel.cpp +++ b/src/libs/models/kptpertcpmmodel.cpp @@ -1,880 +1,880 @@ /* This file is part of the KDE project Copyright (C) 2007, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptpertcpmmodel.h" #include "kptglobal.h" #include "kptcommonstrings.h" #include "kptproject.h" #include "kpttask.h" #include "kptnode.h" #include "kptschedule.h" #include "kptdebug.h" #include #include #include #include namespace KPlato { class Project; class Node; class Task; typedef QList NodeList; // TODO: find some better values static const quintptr ListItemId = static_cast(-1); static const quintptr ProjectItemId = static_cast(-2); CriticalPathItemModel::CriticalPathItemModel( QObject *parent ) : ItemModelBase( parent ), m_manager( 0 ) { /* connect( this, SIGNAL(modelAboutToBeReset()), SLOT(slotAboutToBeReset()) ); connect( this, SIGNAL(modelReset()), SLOT(slotReset()) );*/ } CriticalPathItemModel::~CriticalPathItemModel() { } void CriticalPathItemModel::slotNodeToBeInserted( Node *, int ) { //debugPlan<name(); } void CriticalPathItemModel::slotNodeInserted( Node * /*node*/ ) { //debugPlan<getParent->name()<<"-->"<name(); } void CriticalPathItemModel::slotNodeToBeRemoved( Node *node ) { Q_UNUSED(node); //debugPlan<name(); /* if ( m_path.contains( node ) ) { }*/ } void CriticalPathItemModel::slotNodeRemoved( Node *node ) { Q_UNUSED(node); //debugPlan<name(); } void CriticalPathItemModel::setProject( Project *project ) { beginResetModel(); if ( m_project ) { disconnect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - disconnect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); - disconnect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); - disconnect( m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotLayoutToBeChanged()) ); + disconnect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeToBeAdded(KPlato::Node*,int)), this, SLOT(slotNodeToBeInserted(KPlato::Node*,int)) ); + disconnect( m_project, SIGNAL(nodeToBeRemoved(KPlato::Node*)), this, SLOT(slotNodeToBeRemoved(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeToBeMoved(KPlato::Node*,int,KPlato::Node*,int)), this, SLOT(slotLayoutToBeChanged()) ); - disconnect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); - disconnect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); - disconnect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotLayoutChanged()) ); + disconnect( m_project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeInserted(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeMoved(KPlato::Node*)), this, SLOT(slotLayoutChanged()) ); } m_project = project; m_nodemodel.setProject( project ); if ( project ) { connect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - connect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - connect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); - connect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); - connect( m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotLayoutToBeChanged()) ); + connect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeToBeAdded(KPlato::Node*,int)), this, SLOT(slotNodeToBeInserted(KPlato::Node*,int)) ); + connect( m_project, SIGNAL(nodeToBeRemoved(KPlato::Node*)), this, SLOT(slotNodeToBeRemoved(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeToBeMoved(KPlato::Node*,int,KPlato::Node*,int)), this, SLOT(slotLayoutToBeChanged()) ); - connect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); - connect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); - connect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotLayoutChanged()) ); + connect( m_project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeInserted(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeMoved(KPlato::Node*)), this, SLOT(slotLayoutChanged()) ); } endResetModel(); } void CriticalPathItemModel::setManager( ScheduleManager *sm ) { beginResetModel(); debugPlan<criticalPath( m_manager->scheduleId(), 0 ); } debugPlan<= columnCount() || row < 0 ) { return QModelIndex(); } if ( parent.isValid() ) { return QModelIndex(); } Node *n = m_path.value( row ); QModelIndex i = createIndex(row, column, n ); return i; } Duration::Unit CriticalPathItemModel::presentationUnit( const Duration &dur ) const { if ( dur.toDouble( Duration::Unit_d ) < 1.0 ) { return Duration::Unit_h; } return Duration::Unit_d; } QVariant CriticalPathItemModel::name( int role ) const { switch ( role ) { case Qt::DisplayRole: return i18n( "Path" ); case Qt::ToolTipRole: case Qt::EditRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant CriticalPathItemModel::duration( int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: { Duration v = m_project->duration( m_manager->scheduleId() ); return QVariant(QLocale().toString( v.toDouble( presentationUnit( v ) ), 'f', 1 ) + Duration::unitToString( presentationUnit( v ) )); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant CriticalPathItemModel::variance( int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: { double v = 0.0; foreach ( Node *n, m_path ) { long id = m_manager->scheduleId(); v += n->variance( id, presentationUnit( m_project->duration( id ) ) ); } return QLocale().toString( v, 'f', 1 ); break; } case Qt::EditRole: { double v = 0.0; foreach ( Node *n, m_path ) { v += n->variance( m_manager->scheduleId() ); } return v; } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant CriticalPathItemModel::notUsed( int role ) const { switch ( role ) { case Qt::DisplayRole: return ""; default: return QVariant(); } return QVariant(); } QVariant CriticalPathItemModel::data( const QModelIndex &index, int role ) const { QVariant result; if ( ! index.isValid() ) { return result; } if ( role == Qt::TextAlignmentRole ) { return alignment( index.column() ); } Node *n = node( index ); if ( n == 0 ) { switch ( index.column() ) { case NodeModel::NodeName: result = name( role ); break; case NodeModel::NodeDuration: result = duration( role ); break; case NodeModel::NodeVarianceDuration: result = variance( role ); break; default: result = notUsed( role ); break; } } else { result = m_nodemodel.data( n, index.column(), role ); } if ( result.isValid() ) { if ( role == Qt::DisplayRole && result.type() == QVariant::String && result.toString().isEmpty()) { // HACK to show focus in empty cells result = ' '; } return result; } return result; } QVariant CriticalPathItemModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( orientation == Qt::Horizontal ) { if ( role == Qt::DisplayRole ) { return m_nodemodel.headerData( section, role ); } else if ( role == Qt::TextAlignmentRole ) { return alignment( section ); } } if ( role == Qt::ToolTipRole ) { return m_nodemodel.headerData( section, role ); } else if ( role == Qt::WhatsThisRole ) { return m_nodemodel.headerData( section, role ); } return ItemModelBase::headerData(section, orientation, role); } QVariant CriticalPathItemModel::alignment( int column ) const { return m_nodemodel.headerData( column, Qt::TextAlignmentRole ); } int CriticalPathItemModel::columnCount( const QModelIndex & ) const { return m_nodemodel.propertyCount(); } int CriticalPathItemModel::rowCount( const QModelIndex &parent ) const { if ( parent.isValid() ) { return 0; } if ( m_manager && m_manager->expected() && m_manager->expected()->criticalPathList() ) { return m_path.count() + 1; } return 0; } Node *CriticalPathItemModel::node( const QModelIndex &index ) const { if ( ! index.isValid() ) { return 0; } return m_path.value( index.row() ); } void CriticalPathItemModel::slotNodeChanged( Node *node ) { debugPlan; if ( node == 0 || node->type() == Node::Type_Project || ! m_path.contains( node ) ) { return; } int row = m_path.indexOf( node ); emit dataChanged( createIndex( row, 0, node ), createIndex( row, columnCount() - 1, node ) ); } //----------------------------- PertResultItemModel::PertResultItemModel( QObject *parent ) : ItemModelBase( parent ), m_manager( 0 ) { /* connect( this, SIGNAL(modelAboutToBeReset()), SLOT(slotAboutToBeReset()) ); connect( this, SIGNAL(modelReset()), SLOT(slotReset()) );*/ } PertResultItemModel::~PertResultItemModel() { } void PertResultItemModel::slotAboutToBeReset() { debugPlan; clear(); } void PertResultItemModel::slotReset() { debugPlan; refresh(); } void PertResultItemModel::slotNodeToBeInserted( Node *, int ) { //debugPlan<name(); clear(); } void PertResultItemModel::slotNodeInserted( Node * /*node*/ ) { //debugPlan<getParent->name()<<"-->"<name(); refresh(); } void PertResultItemModel::slotNodeToBeRemoved( Node * /*node*/ ) { //debugPlan<name(); clear(); } void PertResultItemModel::slotNodeRemoved( Node * /*node*/ ) { //debugPlan<name(); refresh(); } void PertResultItemModel::setProject( Project *project ) { clear(); if ( m_project ) { disconnect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - disconnect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); - disconnect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); - disconnect( m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotLayoutToBeChanged()) ); + disconnect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeToBeAdded(KPlato::Node*,int)), this, SLOT(slotNodeToBeInserted(KPlato::Node*,int)) ); + disconnect( m_project, SIGNAL(nodeToBeRemoved(KPlato::Node*)), this, SLOT(slotNodeToBeRemoved(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeToBeMoved(KPlato::Node*,int,KPlato::Node*,int)), this, SLOT(slotLayoutToBeChanged()) ); - disconnect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); - disconnect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); - disconnect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotLayoutChanged()) ); + disconnect( m_project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeInserted(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeMoved(KPlato::Node*)), this, SLOT(slotLayoutChanged()) ); } m_project = project; m_nodemodel.setProject( project ); if ( project ) { connect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - connect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - connect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); - connect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); - connect( m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotLayoutToBeChanged()) ); - - connect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); - connect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); - connect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotLayoutChanged()) ); + connect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeToBeAdded(KPlato::Node*,int)), this, SLOT(slotNodeToBeInserted(KPlato::Node*,int)) ); + connect( m_project, SIGNAL(nodeToBeRemoved(KPlato::Node*)), this, SLOT(slotNodeToBeRemoved(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeToBeMoved(KPlato::Node*,int,KPlato::Node*,int)), this, SLOT(slotLayoutToBeChanged()) ); + + connect( m_project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeInserted(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeMoved(KPlato::Node*)), this, SLOT(slotLayoutChanged()) ); } refresh(); } void PertResultItemModel::setManager( ScheduleManager *sm ) { m_manager = sm; m_nodemodel.setManager( sm ); refresh(); } void PertResultItemModel::clear() { debugPlan<count(); if ( c > 0 ) { // FIXME: gives error msg: // Can't select indexes from different model or with different parents QModelIndex i = index( l ); debugPlan<scheduleId(); debugPlan< *lst = m_project->criticalPathList( id ); if ( lst ) { for ( int i = 0; i < lst->count(); ++i ) { m_topNames << i18n( "Critical Path" ); m_top.append( const_cast( &( lst->at( i ) ) ) ); debugPlan<at( i ); } if ( lst->isEmpty() ) debugPlan<<"No critical path"; } foreach( Node* n, m_project->allNodes() ) { if ( n->type() != Node::Type_Task && n->type() != Node::Type_Milestone ) { continue; } Task *t = static_cast( n ); if ( t->inCriticalPath( id ) ) { continue; } else if ( t->isCritical( id ) ) { m_critical.append( t ); } else { m_noncritical.append( t ); } } if ( ! m_critical.isEmpty() ) { m_topNames << i18n( "Critical" ); m_top.append(&m_critical ); } if ( ! m_noncritical.isEmpty() ) { m_topNames << i18n( "Non-critical" ); m_top.append(&m_noncritical ); } if ( ! m_top.isEmpty() ) { debugPlan<count(); if ( c > 0 ) { beginInsertRows( index( l ), 0, c-1 ); endInsertRows(); } } } } Qt::ItemFlags PertResultItemModel::flags( const QModelIndex &index ) const { Qt::ItemFlags flags = QAbstractItemModel::flags( index ); flags &= ~( Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled ); return flags; } QModelIndex PertResultItemModel::parent( const QModelIndex &index ) const { if ( !index.isValid() ) { return QModelIndex(); } //debugPlan<= columnCount() || row < 0 ) { return QModelIndex(); } if ( ! parent.isValid() ) { if ( row == 0 ) { QModelIndex idx = createIndex(row, column, ProjectItemId ); // project return idx; } if ( row >= m_top.count() ) { return QModelIndex(); // shouldn't happened } QModelIndex idx = createIndex(row, column, ListItemId ); //debugPlan<indexOf( const_cast( node ) ); // if ( row != -1 ) { // return createIndex( row, 0, const_cast( node ) ); // } // } // return QModelIndex(); // } QModelIndex PertResultItemModel::index( const NodeList *lst ) const { if ( m_project == 0 || lst == 0 ) { return QModelIndex(); } NodeList *l = const_cast( lst ); int row = m_top.indexOf( l ); if ( row <= 0 ) { return QModelIndex(); } return createIndex( row, 0, ListItemId ); } QVariant PertResultItemModel::name( int row, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return m_topNames.value( row ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant PertResultItemModel::name( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return node->name(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant PertResultItemModel::earlyStart( const Task *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return node->earlyStart( m_manager->scheduleId() ); case Qt::ToolTipRole: return QLocale().toString( node->earlyStart( m_manager->scheduleId() ).date(), QLocale::ShortFormat ); case Qt::EditRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant PertResultItemModel::earlyFinish( const Task *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return node->earlyFinish( m_manager->scheduleId() ); case Qt::ToolTipRole: return QLocale().toString( node->earlyFinish( m_manager->scheduleId() ).date(), QLocale::ShortFormat ); case Qt::EditRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant PertResultItemModel::lateStart( const Task *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return node->lateStart( m_manager->scheduleId() ); case Qt::ToolTipRole: return QLocale().toString( node->lateStart( m_manager->scheduleId() ).date(), QLocale::ShortFormat ); case Qt::EditRole: break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant PertResultItemModel::lateFinish( const Task *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return node->lateFinish( m_manager->scheduleId() ); case Qt::ToolTipRole: return QLocale().toString( node->lateFinish( m_manager->scheduleId() ).date(), QLocale::ShortFormat ); case Qt::EditRole: break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant PertResultItemModel::positiveFloat( const Task *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return node->positiveFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nHourFraction ); case Qt::ToolTipRole: return node->positiveFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nDayTime ); case Qt::EditRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant PertResultItemModel::freeFloat( const Task *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return node->freeFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nHourFraction ); case Qt::ToolTipRole: return node->freeFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nDayTime ); case Qt::EditRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant PertResultItemModel::negativeFloat( const Task *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return node->negativeFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nHourFraction ); case Qt::ToolTipRole: return node->negativeFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nDayTime ); case Qt::EditRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant PertResultItemModel::startFloat( const Task *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return node->startFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nHourFraction ); case Qt::ToolTipRole: return node->startFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nDayTime ); case Qt::EditRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant PertResultItemModel::finishFloat( const Task *node, int role ) const { switch ( role ) { case Qt::DisplayRole: return node->finishFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nHourFraction ); case Qt::ToolTipRole: return node->finishFloat( m_manager->scheduleId() ).toString( Duration::Format_i18nDayTime ); case Qt::EditRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant PertResultItemModel::data( const QModelIndex &index, int role ) const { QVariant result; if ( ! index.isValid() ) { return result; } if ( role == Qt::TextAlignmentRole ) { return alignment( index.column() ); } Node *n = node( index ); if ( n == 0 ) { switch ( index.column() ) { case 0: return name( index.row(), role ); default: break; } return QVariant(); } if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) { result = m_nodemodel.data( n, index.column(), role ); } if ( n->type() == Node::Type_Project ) { //Project *p = static_cast( n ); switch ( index.column() ) { case NodeModel::NodeName: result = name( NodeModel::NodeName, role ); break; default: //debugPlan<<"data: invalid display value column "<count(); return l->count(); } //debugPlan<<"node "<value( index.row() ); } return 0; } void PertResultItemModel::slotNodeChanged( Node *) { debugPlan; refresh(); /* if ( node == 0 || node->type() == Node::Type_Project ) { return; } int row = node->getParent()->findChildNode( node ); emit dataChanged( createIndex( row, 0, node ), createIndex( row, columnCount() - 1, node ) );*/ } } // namespace KPlato diff --git a/src/libs/models/kptpertcpmmodel.h b/src/libs/models/kptpertcpmmodel.h index bac73a18..9a4c8678 100644 --- a/src/libs/models/kptpertcpmmodel.h +++ b/src/libs/models/kptpertcpmmodel.h @@ -1,179 +1,179 @@ /* This file is part of the KDE project Copyright (C) 2007 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 KPTPERTCPMMODEL_H #define KPTPERTCPMMODEL_H #include "planmodels_export.h" #include #include /// The main namespace namespace KPlato { class Duration; class Node; class Project; class ScheduleManager; class Task; typedef QList NodeList; class PLANMODELS_EXPORT CriticalPathItemModel : public ItemModelBase { Q_OBJECT public: explicit CriticalPathItemModel( QObject *parent = 0 ); ~CriticalPathItemModel(); const QMetaEnum columnMap() const { return m_nodemodel.columnMap(); } virtual void setProject( Project *project ); virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; Node *node( const QModelIndex &index ) const; void setManager( ScheduleManager *sm ); ScheduleManager *manager() const { return m_manager; } /// Select a proper unit for total path values, dependent on @p duration Duration::Unit presentationUnit( const Duration &duration ) const; protected Q_SLOTS: - void slotNodeChanged( Node* ); - void slotNodeToBeInserted( Node *node, int row ); - void slotNodeInserted( Node *node ); - void slotNodeToBeRemoved( Node *node ); - void slotNodeRemoved( Node *node ); + void slotNodeChanged(KPlato::Node*); + void slotNodeToBeInserted(KPlato::Node *node, int row); + void slotNodeInserted(KPlato::Node *node); + void slotNodeToBeRemoved(KPlato::Node *node); + void slotNodeRemoved(KPlato::Node *node); public: QVariant alignment( int column ) const; QVariant name( int role ) const; QVariant duration( int role ) const; QVariant variance( int role ) const; QVariant notUsed( int role ) const; private: ScheduleManager *m_manager; QList m_path; NodeModel m_nodemodel; }; //-------------------- /** This model displays results from project scheduling. */ class PLANMODELS_EXPORT PertResultItemModel : public ItemModelBase { Q_OBJECT public: explicit PertResultItemModel( QObject *parent = 0 ); ~PertResultItemModel(); const QMetaEnum columnMap() const { return m_nodemodel.columnMap(); } virtual void setProject( Project *project ); virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; // virtual QModelIndex index( const Node *node ) const; virtual QModelIndex index( const NodeList *lst ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; virtual QMimeData * mimeData( const QModelIndexList & indexes ) const; virtual QStringList mimeTypes () const; virtual Qt::DropActions supportedDropActions() const; virtual bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ); NodeList *list( const QModelIndex &index ) const; Node *node( const QModelIndex &index ) const; QAbstractItemDelegate *createDelegate( int column, QWidget *parent ) const; NodeList nodeList( QDataStream &stream ); using ItemModelBase::dropAllowed; bool dropAllowed( Node *on, const QMimeData *data ); void clear(); void refresh(); void setManager( ScheduleManager *sm ); ScheduleManager *manager() const { return m_manager; } protected Q_SLOTS: void slotAboutToBeReset(); void slotReset(); - void slotNodeChanged( Node* ); - void slotNodeToBeInserted( Node *node, int row ); - void slotNodeInserted( Node *node ); - void slotNodeToBeRemoved( Node *node ); - void slotNodeRemoved( Node *node ); + void slotNodeChanged(KPlato:: Node*); + void slotNodeToBeInserted(KPlato:: Node *node, int row); + void slotNodeInserted(KPlato:: Node *node); + void slotNodeToBeRemoved(KPlato:: Node *node); + void slotNodeRemoved(KPlato:: Node *node); protected: QVariant alignment( int column ) const; QVariant name( int row, int role ) const; QVariant name( const Node *node, int role ) const; QVariant earlyStart( const Task *node, int role ) const; QVariant earlyFinish( const Task *node, int role ) const; QVariant lateStart( const Task *node, int role ) const; QVariant lateFinish( const Task *node, int role ) const; QVariant positiveFloat( const Task *node, int role ) const; QVariant freeFloat( const Task *node, int role ) const; QVariant negativeFloat( const Task *node, int role ) const; QVariant startFloat( const Task *node, int role ) const; QVariant finishFloat( const Task *node, int role ) const; private: QStringList m_topNames; QList m_top; NodeList m_cp; NodeList m_critical; NodeList m_noncritical; NodeList m_dummyList; ScheduleManager *m_manager; NodeModel m_nodemodel; }; } //KPlato namespace #endif diff --git a/src/libs/models/kptrelationmodel.cpp b/src/libs/models/kptrelationmodel.cpp index 3ab2486e..491c7027 100644 --- a/src/libs/models/kptrelationmodel.cpp +++ b/src/libs/models/kptrelationmodel.cpp @@ -1,454 +1,454 @@ /* This file is part of the KDE project Copyright (C) 2007, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptrelationmodel.h" #include "kptglobal.h" #include "kptcommonstrings.h" #include "kptcommand.h" #include "kptduration.h" #include "kptproject.h" #include "kptnode.h" #include "kptrelation.h" #include "kptdebug.h" #include #include #include namespace KPlato { QVariant RelationModel::parentName( const Relation *r, int role ) const { //debugPlan<parent()->name(); case Qt::TextAlignmentRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant RelationModel::childName( const Relation *r, int role ) const { //debugPlan<child()->name(); case Qt::TextAlignmentRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant RelationModel::type( const Relation *r, int role ) const { //debugPlan<typeToString( true ); case Role::EnumList: return r->typeList( true ); case Qt::EditRole: case Role::EnumListValue: return (int)r->type(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant RelationModel::lag( const Relation *r, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: { Duration::Unit unit = Duration::Unit_h; return QVariant(QLocale().toString( r->lag().toDouble( unit ), 'f', 1 ) + Duration::unitToString( unit, true )); } case Qt::EditRole: return r->lag().toDouble( Duration::Unit_h ); case Role::DurationUnit: return static_cast( Duration::Unit_h ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant RelationModel::data( const Relation *r, int property, int role ) const { QVariant result; switch ( property ) { case 0: result = parentName( r, role ); break; case 1: result = childName( r, role ); break; case 2: result = type( r, role ); break; case 3: result = lag( r, role ); break; default: //debugPlan<<"Invalid property number: "<child() ) { return; } // relations always appended int row = rowCount(); beginInsertRows( QModelIndex(), row, row ); } void RelationItemModel::slotRelationAdded( Relation *relation ) { debugPlan; if ( m_node == 0 || m_node != relation->child() ) { return; } endInsertRows(); } void RelationItemModel::slotRelationToBeRemoved( Relation *relation ) { if ( m_node == 0 || ! m_node->dependParentNodes().contains( relation ) ) { return; } m_removedRelation = relation; int row = m_node->dependParentNodes().indexOf( relation ); debugPlan<dependParentNodes().contains( relation ) ) { return; } int row = m_node->dependParentNodes().indexOf( relation ); emit dataChanged( createIndex( row, 0 ), createIndex( row, columnCount()-1 ) ); } void RelationItemModel::slotNodeToBeRemoved( Node *node ) { if ( node != m_node ) { return; } setNode( 0 ); } void RelationItemModel::slotNodeRemoved( Node *node ) { Q_UNUSED(node); } void RelationItemModel::slotLayoutChanged() { //debugPlan<name()<type(); if ( v == r->type() ) { return false; } emit executeCommand( new ModifyRelationTypeCmd( r, v, kundo2_i18n("Modify relation type") ) ); return true; } return false; } bool RelationItemModel::setLag( Relation *r, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { Duration::Unit unit = static_cast( value.toList()[1].toInt() ); Duration d( value.toList()[0].toDouble(), unit ); debugPlan<"<lag() ) { return false; } emit executeCommand( new ModifyRelationLagCmd( r, d, kundo2_i18n( "Modify relation time lag" ) ) ); return true; } default: break; } return false; } QVariant RelationItemModel::data( const QModelIndex &index, int role ) const { if ( role == Qt::TextAlignmentRole ) { return headerData( index.column(), Qt::Horizontal, role ); } QVariant result; Relation *r = relation( index ); if ( r != 0 ) { result = m_relationmodel.data( r, index.column(), role ); } if ( result.isValid() ) { if ( role == Qt::DisplayRole && result.type() == QVariant::String && result.toString().isEmpty()) { // HACK to show focus in empty cells result = ' '; } return result; } return result; } bool RelationItemModel::setData( const QModelIndex &index, const QVariant &value, int role ) { if ( ! index.isValid() ) { return ItemModelBase::setData( index, value, role ); } if ( ( flags(index) & Qt::ItemIsEditable ) == 0 || role != Qt::EditRole ) { return false; } Relation *r = relation( index ); switch (index.column()) { case 0: return false; case 1: return false; case 2: return setType( r, value, role ); case 3: return setLag( r, value, role ); default: qWarning("data: invalid display value column %d", index.column()); return false; } return false; } QVariant RelationItemModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( orientation == Qt::Horizontal ) { if ( role == Qt::DisplayRole ) { return m_relationmodel.headerData( section, role ); } else if ( role == Qt::TextAlignmentRole ) { switch (section) { case 2: return Qt::AlignCenter; case 3: return Qt::AlignRight; default: return QVariant(); } } } if ( role == Qt::ToolTipRole ) { return RelationModel::headerData( section, role ); } return ItemModelBase::headerData(section, orientation, role); } QAbstractItemDelegate *RelationItemModel::createDelegate( int column, QWidget *parent ) const { switch ( column ) { case 2: return new EnumDelegate( parent ); case 3: return new DurationSpinBoxDelegate( parent ); default: return 0; } return 0; } int RelationItemModel::columnCount( const QModelIndex &/*parent*/ ) const { return m_relationmodel.propertyCount(); } int RelationItemModel::rowCount( const QModelIndex &parent ) const { if ( m_project == 0 || m_node == 0 || parent.isValid() ) { return 0; } return m_node->numDependParentNodes(); } Relation *RelationItemModel::relation( const QModelIndex &index ) const { if ( ! index.isValid() || m_node == 0 ) { return 0; } return m_node->dependParentNodes().value( index.row() ); } void RelationItemModel::slotNodeChanged( Node *node ) { Q_UNUSED(node); beginResetModel(); endResetModel(); } } //namespace KPlato diff --git a/src/libs/models/kptrelationmodel.h b/src/libs/models/kptrelationmodel.h index 098520ed..54c9cd62 100644 --- a/src/libs/models/kptrelationmodel.h +++ b/src/libs/models/kptrelationmodel.h @@ -1,114 +1,114 @@ /* This file is part of the KDE project Copyright (C) 2007 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 RELATIONMODEL_H #define RELATIONMODEL_H #include "kptitemmodelbase.h" #include "kptschedule.h" class QModelIndex; class KUndo2Command; namespace KPlato { class Project; class Node; class Relation; class PLANMODELS_EXPORT RelationModel : public QObject { Q_OBJECT public: RelationModel() : QObject() {} ~RelationModel() {} QVariant data( const Relation *relation, int property, int role = Qt::DisplayRole ) const; static QVariant headerData( int section, int role = Qt::DisplayRole ); static int propertyCount(); QVariant parentName( const Relation *r, int role ) const; QVariant childName( const Relation *r, int role ) const; QVariant type( const Relation *r, int role ) const; QVariant lag( const Relation *r, int role ) const; }; class PLANMODELS_EXPORT RelationItemModel : public ItemModelBase { Q_OBJECT public: explicit RelationItemModel( QObject *parent = 0 ); ~RelationItemModel(); virtual void setProject( Project *project ); virtual void setNode( Node *node ); virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; Relation *relation( const QModelIndex &index ) const; QAbstractItemDelegate *createDelegate( int column, QWidget *parent ) const; Q_SIGNALS: void executeCommand( KUndo2Command* ); - + protected Q_SLOTS: - void slotNodeChanged( Node* ); - void slotNodeToBeRemoved( Node *node ); - void slotNodeRemoved( Node *node ); - void slotRelationToBeRemoved( Relation *r ); - void slotRelationRemoved( Relation *r ); - void slotRelationToBeAdded( Relation *r, int, int ); - void slotRelationAdded( Relation *r ); - void slotRelationModified( Relation *r ); + void slotNodeChanged(KPlato::Node*); + void slotNodeToBeRemoved(KPlato::Node *node); + void slotNodeRemoved(KPlato::Node *node); + void slotRelationToBeRemoved(KPlato::Relation *r); + void slotRelationRemoved(KPlato::Relation *r); + void slotRelationToBeAdded(KPlato::Relation *r, int, int); + void slotRelationAdded(KPlato::Relation *r); + void slotRelationModified(KPlato::Relation *r); void slotLayoutChanged(); protected: bool setType( Relation *r, const QVariant &value, int role ); bool setLag( Relation *r, const QVariant &value, int role ); private: Node *m_node; RelationModel m_relationmodel; Relation *m_removedRelation; // to control endRemoveRows() }; } //namespace KPlato #endif diff --git a/src/libs/models/kptresourceallocationmodel.cpp b/src/libs/models/kptresourceallocationmodel.cpp index 6120ca96..e62ab36f 100644 --- a/src/libs/models/kptresourceallocationmodel.cpp +++ b/src/libs/models/kptresourceallocationmodel.cpp @@ -1,1076 +1,1076 @@ /* This file is part of the KDE project Copyright (C) 2009, 2012 Dag Andersen danders@get2net> 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. */ #include "kptresourceallocationmodel.h" #include "kptcommonstrings.h" #include "kptcommand.h" #include "kptitemmodelbase.h" #include "kptcalendar.h" #include "kptduration.h" #include "kptnode.h" #include "kptproject.h" #include "kpttask.h" #include "kptresource.h" #include "kptdatetime.h" #include "kptdebug.h" #include #include namespace KPlato { //-------------------------------------- ResourceAllocationModel::ResourceAllocationModel( QObject *parent ) : QObject( parent ), m_project( 0 ), m_task( 0 ) { } ResourceAllocationModel::~ResourceAllocationModel() { } const QMetaEnum ResourceAllocationModel::columnMap() const { return metaObject()->enumerator( metaObject()->indexOfEnumerator("Properties") ); } void ResourceAllocationModel::setProject( Project *project ) { m_project = project; } void ResourceAllocationModel::setTask( Task *task ) { m_task = task; } int ResourceAllocationModel::propertyCount() const { return columnMap().keyCount(); } QVariant ResourceAllocationModel::name( const Resource *res, int role ) const { //debugPlan<name()<<","<name(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceAllocationModel::name( const ResourceGroup *res, int role ) const { //debugPlan<name()<<","<name(); break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceAllocationModel::type( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return res->typeToString( true ); case Role::EnumList: return res->typeToStringList( true ); case Role::EnumListValue: return (int)res->type(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceAllocationModel::type( const ResourceGroup *res, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return res->typeToString( true ); case Role::EnumList: return res->typeToStringList( true ); case Role::EnumListValue: return (int)res->type(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceAllocationModel::allocation( const ResourceGroup *group, const Resource *res, int role ) const { if ( m_project == 0 || m_task == 0 ) { return QVariant(); } const ResourceGroupRequest *rg = m_task->requests().find( group ); const ResourceRequest *rr = 0; if ( rg ) { rr = rg->find( res ); } switch ( role ) { case Qt::DisplayRole: { int units = rr ? rr->units() : 0; // xgettext: no-c-format return i18nc( "%", "%1%", units ); } case Qt::EditRole: return rr ? rr->units() : 0; case Qt::ToolTipRole: { int units = rr ? rr->units() : 0; if ( units == 0 ) { return xi18nc( "@info:tooltip", "Not allocated" ); } // xgettext: no-c-format return xi18nc( "@info:tooltip", "Allocated units: %1%", units ); } case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::Minimum: return 0; case Role::Maximum: return 100; case Qt::CheckStateRole: return Qt::Unchecked; } return QVariant(); } QVariant ResourceAllocationModel::allocation( const ResourceGroup *res, int role ) const { if ( m_project == 0 || m_task == 0 ) { return QVariant(); } const ResourceGroupRequest *req = m_task->requests().find( res ); switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return req ? req->units() : 0; case Qt::ToolTipRole: return QVariant(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::Minimum: return 0; case Role::Maximum: return res->numResources(); } return QVariant(); } QVariant ResourceAllocationModel::maximum( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: // xgettext: no-c-format return i18nc( "%", "%1%", res->units() ); case Qt::EditRole: return res->units(); case Qt::ToolTipRole: // xgettext: no-c-format return i18n( "Maximum units available: %1%", res->units() ); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceAllocationModel::required( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: { QStringList lst; foreach ( Resource *r, res->requiredResources() ) { lst << r->name(); } return lst.join( "," ); } case Qt::EditRole: return QVariant();//Not used case Qt::ToolTipRole: return QVariant(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: return QVariant(); case Qt::WhatsThisRole: return xi18nc( "@info:whatsthis", "Required Resources" "A working resource can be assigned to one or more required resources." " A required resource is a material resource that the working resource depends on" " in order to do the work." "To be able to use a material resource as a required resource, the material resource" " must be part of a group of type Material." ); } return QVariant(); } QVariant ResourceAllocationModel::maximum( const ResourceGroup *res, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return res->numResources(); case Qt::ToolTipRole: return i18np( "There is %1 resource available in this group", "There are %1 resources available in this group", res->numResources() ); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceAllocationModel::data( const ResourceGroup *group, const Resource *resource, int property, int role ) const { QVariant result; if ( resource == 0 ) { return result; } switch ( property ) { case RequestName: result = name( resource, role ); break; case RequestType: result = type( resource, role ); break; case RequestAllocation: result = allocation( group, resource, role ); break; case RequestMaximum: result = maximum( resource, role ); break; case RequestRequired: result = required( resource, role ); break; default: debugPlan<<"data: invalid display value: property="<Required Resources" "A working resource can be assigned to one or more required resources." " A required resource is a material resource that the working resource depends on" " in order to do the work." "To be able to use a material resource as a required resource, the material resource" " must be part of a group of type Material." ); default: return QVariant(); } } return QVariant(); } //-------------------------------------- ResourceAllocationItemModel::ResourceAllocationItemModel( QObject *parent ) : ItemModelBase( parent ) { } ResourceAllocationItemModel::~ResourceAllocationItemModel() { } void ResourceAllocationItemModel::slotResourceToBeInserted( const ResourceGroup *group, int row ) { //debugPlan<name()<<","<name(); endInsertRows(); emit layoutChanged(); //HACK to make the right view react! Bug in qt? } void ResourceAllocationItemModel::slotResourceToBeRemoved( const Resource *resource ) { //debugPlan<name(); int row = index( resource ).row(); beginRemoveRows( index( resource->parentGroup() ), row, row ); } void ResourceAllocationItemModel::slotResourceRemoved( const Resource */*resource */) { //debugPlan<name(); endRemoveRows(); } void ResourceAllocationItemModel::slotResourceGroupToBeInserted( const ResourceGroup */*group*/, int row ) { //debugPlan<name(); beginInsertRows( QModelIndex(), row, row ); } void ResourceAllocationItemModel::slotResourceGroupInserted( const ResourceGroup */*group */) { //debugPlan<name(); endInsertRows(); } void ResourceAllocationItemModel::slotResourceGroupToBeRemoved( const ResourceGroup *group ) { //debugPlan<name(); int row = index( group ).row(); beginRemoveRows( QModelIndex(), row, row ); } void ResourceAllocationItemModel::slotResourceGroupRemoved( const ResourceGroup */*group */) { //debugPlan<name(); endRemoveRows(); } void ResourceAllocationItemModel::setProject( Project *project ) { if ( m_project ) { disconnect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - disconnect( m_project, SIGNAL(resourceChanged(Resource*)), this, SLOT(slotResourceChanged(Resource*)) ); - disconnect( m_project, SIGNAL(resourceGroupChanged(ResourceGroup*)), this, SLOT(slotResourceGroupChanged(ResourceGroup*)) ); + disconnect( m_project, SIGNAL(resourceChanged(KPlato::Resource*)), this, SLOT(slotResourceChanged(KPlato::Resource*)) ); + disconnect( m_project, SIGNAL(resourceGroupChanged(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupChanged(KPlato::ResourceGroup*)) ); - disconnect( m_project, SIGNAL(resourceGroupToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const ResourceGroup*,int)) ); + disconnect( m_project, SIGNAL(resourceGroupToBeAdded(const KPlato::ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const KPlato::ResourceGroup*,int)) ); - disconnect( m_project, SIGNAL(resourceGroupToBeRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const ResourceGroup*)) ); + disconnect( m_project, SIGNAL(resourceGroupToBeRemoved(const KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const KPlato::ResourceGroup*)) ); - disconnect( m_project, SIGNAL(resourceToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const ResourceGroup*,int)) ); + disconnect( m_project, SIGNAL(resourceToBeAdded(const KPlato::ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const KPlato::ResourceGroup*,int)) ); - disconnect( m_project, SIGNAL(resourceToBeRemoved(const Resource*)), this, SLOT(slotResourceToBeRemoved(const Resource*)) ); + disconnect( m_project, SIGNAL(resourceToBeRemoved(const KPlato::Resource*)), this, SLOT(slotResourceToBeRemoved(const KPlato::Resource*)) ); - disconnect( m_project, SIGNAL(resourceGroupAdded(const ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const ResourceGroup*)) ); + disconnect( m_project, SIGNAL(resourceGroupAdded(const KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const KPlato::ResourceGroup*)) ); - disconnect( m_project, SIGNAL(resourceGroupRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const ResourceGroup*)) ); + disconnect( m_project, SIGNAL(resourceGroupRemoved(const KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const KPlato::ResourceGroup*)) ); - disconnect( m_project, SIGNAL(resourceAdded(const Resource*)), this, SLOT(slotResourceInserted(const Resource*)) ); + disconnect( m_project, SIGNAL(resourceAdded(const KPlato::Resource*)), this, SLOT(slotResourceInserted(const KPlato::Resource*)) ); - disconnect( m_project, SIGNAL(resourceRemoved(const Resource*)), this, SLOT(slotResourceRemoved(const Resource*)) ); + disconnect( m_project, SIGNAL(resourceRemoved(const KPlato::Resource*)), this, SLOT(slotResourceRemoved(const KPlato::Resource*)) ); } m_project = project; if ( m_project ) { connect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - connect( m_project, SIGNAL(resourceChanged(Resource*)), this, SLOT(slotResourceChanged(Resource*)) ); - connect( m_project, SIGNAL(resourceGroupChanged(ResourceGroup*)), this, SLOT(slotResourceGroupChanged(ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceChanged(KPlato::Resource*)), this, SLOT(slotResourceChanged(KPlato::Resource*)) ); + connect( m_project, SIGNAL(resourceGroupChanged(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupChanged(KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceGroupToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const ResourceGroup*,int)) ); + connect( m_project, SIGNAL(resourceGroupToBeAdded(const KPlato::ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const KPlato::ResourceGroup*,int)) ); - connect( m_project, SIGNAL(resourceGroupToBeRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceGroupToBeRemoved(const KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const ResourceGroup*,int)) ); + connect( m_project, SIGNAL(resourceToBeAdded(const KPlato::ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const KPlato::ResourceGroup*,int)) ); - connect( m_project, SIGNAL(resourceToBeRemoved(const Resource*)), this, SLOT(slotResourceToBeRemoved(const Resource*)) ); + connect( m_project, SIGNAL(resourceToBeRemoved(const KPlato::Resource*)), this, SLOT(slotResourceToBeRemoved(const KPlato::Resource*)) ); - connect( m_project, SIGNAL(resourceGroupAdded(const ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceGroupAdded(const KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceGroupRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceGroupRemoved(const KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceAdded(const Resource*)), this, SLOT(slotResourceInserted(const Resource*)) ); + connect( m_project, SIGNAL(resourceAdded(const KPlato::Resource*)), this, SLOT(slotResourceInserted(const KPlato::Resource*)) ); - connect( m_project, SIGNAL(resourceRemoved(const Resource*)), this, SLOT(slotResourceRemoved(const Resource*)) ); + connect( m_project, SIGNAL(resourceRemoved(const KPlato::Resource*)), this, SLOT(slotResourceRemoved(const KPlato::Resource*)) ); } m_model.setProject( m_project ); } void ResourceAllocationItemModel::setTask( Task *task ) { if ( task == m_model.task() ) { return; } if ( m_model.task() == 0 ) { beginResetModel(); filldata( task ); m_model.setTask( task ); endResetModel(); return; } if ( task ) { emit layoutAboutToBeChanged(); filldata( task ); m_model.setTask( task ); emit layoutChanged(); } } void ResourceAllocationItemModel::filldata( Task *task ) { qDeleteAll( m_resourceCache ); m_resourceCache.clear(); qDeleteAll( m_groupCache ); m_groupCache.clear(); m_requiredChecked.clear(); if ( m_project && task ) { foreach ( const ResourceGroup *g, m_project->resourceGroups() ) { const ResourceGroupRequest *gr = task->requests().find( g ); if ( gr ) { m_groupCache[ g ] = new ResourceGroupRequest( *gr ); } } foreach ( const Resource *r, m_project->resourceList() ) { const ResourceRequest *rr = task->requests().find( r ); if ( rr ) { m_resourceCache[ r ] = new ResourceRequest( *rr ); if ( ! m_resourceCache[ r ]->requiredResources().isEmpty() ) { m_requiredChecked[ r ] = Qt::Checked; } } } } } bool ResourceAllocationItemModel::hasMaterialResources() const { if ( ! m_project ) { return false; } foreach ( const ResourceGroup *g, m_project->resourceGroups() ) { if ( g->type() == ResourceGroup::Type_Material ) { foreach ( const Resource *r, g->resources() ) { if ( r->type() == Resource::Type_Material ) { return true; } } } } return false; } Qt::ItemFlags ResourceAllocationItemModel::flags( const QModelIndex &index ) const { Qt::ItemFlags flags = ItemModelBase::flags( index ); if ( !m_readWrite ) { //debugPlan<<"read only"<type() != Resource::Type_Work ) { flags &= ~( Qt::ItemIsEditable | Qt::ItemIsUserCheckable ); } else if ( m_resourceCache.contains( r ) && m_resourceCache[ r ]->units() > 0 ) { flags |= ( Qt::ItemIsEditable | Qt::ItemIsUserCheckable ); if ( ! hasMaterialResources() ) { flags &= ~Qt::ItemIsEnabled; } } break; } default: flags &= ~Qt::ItemIsEditable; break; } return flags; } QModelIndex ResourceAllocationItemModel::parent( const QModelIndex &index ) const { if ( !index.isValid() || m_project == 0 ) { return QModelIndex(); } //debugPlan<( object( index ) ); if ( r && r->parentGroup() ) { // only resources have parent int row = m_project->indexOf( r->parentGroup() ); return createIndex( row, 0, r->parentGroup() ); } return QModelIndex(); } QModelIndex ResourceAllocationItemModel::index( int row, int column, const QModelIndex &parent ) const { if ( m_project == 0 || column < 0 || column >= columnCount() || row < 0 ) { return QModelIndex(); } if ( ! parent.isValid() ) { if ( row < m_project->numResourceGroups() ) { return createIndex( row, column, m_project->resourceGroupAt( row ) ); } return QModelIndex(); } QObject *p = object( parent ); ResourceGroup *g = qobject_cast( p ); if ( g ) { if ( row < g->numResources() ) { return createIndex( row, column, g->resourceAt( row ) ); } return QModelIndex(); } return QModelIndex(); } QModelIndex ResourceAllocationItemModel::index( const Resource *resource ) const { if ( m_project == 0 || resource == 0 ) { return QModelIndex(); } Resource *r = const_cast(resource); int row = -1; ResourceGroup *par = r->parentGroup(); if ( par ) { row = par->indexOf( r ); return createIndex( row, 0, r ); } return QModelIndex(); } QModelIndex ResourceAllocationItemModel::index( const ResourceGroup *group ) const { if ( m_project == 0 || group == 0 ) { return QModelIndex(); } ResourceGroup *g = const_cast(group); int row = m_project->indexOf( g ); return createIndex( row, 0, g ); } int ResourceAllocationItemModel::columnCount( const QModelIndex &/*parent*/ ) const { return m_model.propertyCount(); } int ResourceAllocationItemModel::rowCount( const QModelIndex &parent ) const { if ( m_project == 0 || m_model.task() == 0 ) { return 0; } if ( ! parent.isValid() ) { return m_project->numResourceGroups(); } QObject *p = object( parent ); ResourceGroup *g = qobject_cast( p ); if ( g ) { return g->numResources(); } return 0; } QVariant ResourceAllocationItemModel::allocation( const ResourceGroup *group, const Resource *res, int role ) const { if ( m_model.task() == 0 ) { return QVariant(); } if ( ! m_resourceCache.contains( res ) ) { if ( role == Qt::EditRole ) { ResourceRequest *req = m_model.task()->requests().find( res ); if ( req == 0 ) { req = new ResourceRequest( const_cast( res ), 0 ); } const_cast( this )->m_resourceCache.insert( res, req ); return req->units(); } return m_model.allocation( group, res, role ); } switch ( role ) { case Qt::DisplayRole: { // xgettext: no-c-format return i18nc( "%", "%1%", m_resourceCache[ res ]->units() ); } case Qt::EditRole: return m_resourceCache[ res ]->units(); case Qt::ToolTipRole: { if ( res->units() == 0 ) { return xi18nc( "@info:tooltip", "Not allocated" ); } return xi18nc( "@info:tooltip", "%1 allocated out of %2 available", allocation( group, res, Qt::DisplayRole ).toString(), m_model.maximum( res, Qt::DisplayRole ).toString() ); } case Qt::CheckStateRole: return m_resourceCache[ res ]->units() == 0 ? Qt::Unchecked : Qt::Checked; default: return m_model.allocation( group, res, role ); } return QVariant(); } int ResourceAllocationItemModel::requestedResources( const ResourceGroup *res ) const { int c = 0; foreach ( const Resource *r, res->resources() ) { if ( m_resourceCache.contains( r ) && m_resourceCache[ r ]->units() > 0 ) { ++c; } } return c; } QVariant ResourceAllocationItemModel::allocation( const ResourceGroup *res, int role ) const { if ( m_model.task() == 0 ) { return QVariant(); } if ( ! m_groupCache.contains( res ) ) { return m_model.allocation( res, role ); } switch ( role ) { case Qt::DisplayRole: return QString(" %1 (%2)" ) .arg( qMax( m_groupCache[ res ]->units(), allocation( res, Role::Minimum ).toInt() ) ) .arg(requestedResources( res ) ); case Qt::EditRole: return qMax( m_groupCache[ res ]->units(), allocation( res, Role::Minimum ).toInt() ); case Qt::ToolTipRole: { QString s1 = i18ncp( "@info:tooltip", "%1 resource requested for dynamic allocation", "%1 resources requested for dynamic allocation", allocation( res, Qt::EditRole ).toInt() ); QString s2 = i18ncp( "@info:tooltip", "%1 resource allocated", "%1 resources allocated", requestedResources( res ) ); return xi18nc( "@info:tooltip", "%1%2", s1, s2 ); } case Qt::WhatsThisRole: { return xi18nc( "@info:whatsthis", "Group allocations" "You can allocate a number of resources from a group and let" " the scheduler select from the available resources at the time of scheduling." " These dynamically allocated resources will be in addition to any resource you have allocated specifically." ); } case Role::Minimum: { return 0; } case Role::Maximum: { return res->numResources() - requestedResources( res ); } default: return m_model.allocation( res, role ); } return QVariant(); } bool ResourceAllocationItemModel::setAllocation( Resource *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { m_resourceCache[ res ]->setUnits( value.toInt() ); QModelIndex idx = index( res->parentGroup() ); emit dataChanged( index( idx.row(), 0, QModelIndex() ), index( idx.row(), columnCount() - 1, QModelIndex() ) ); return true; } case Qt::CheckStateRole: { if ( ! m_resourceCache.contains( res ) ) { m_resourceCache[ res ] = new ResourceRequest( res, 0 ); } if ( m_resourceCache[ res ]->units() == 0 ) { m_resourceCache[ res ]->setUnits( 100 ); ResourceGroup *g = res->parentGroup(); if ( m_groupCache.contains( g ) ) { ResourceGroupRequest *gr = m_groupCache[ g ]; if ( gr->units() + requestedResources( g ) > g->numResources() ) { gr->setUnits( gr->units() - 1 ); } } } else { m_resourceCache[ res ]->setUnits( 0 ); } QModelIndex idx = index( res->parentGroup() ); emit dataChanged( index( idx.row(), 0, QModelIndex() ), index( idx.row(), columnCount() - 1, QModelIndex() ) ); return true; } } return false; } bool ResourceAllocationItemModel::setAllocation( ResourceGroup *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( ! m_groupCache.contains( res ) ) { m_groupCache[ res ] = new ResourceGroupRequest( res, 0 ); } m_groupCache[ res ]->setUnits( value.toInt() ); emit dataChanged( index( res ), index( res ) ); return true; } return false; } QVariant ResourceAllocationItemModel::maximum( const ResourceGroup *res, int role ) const { switch ( role ) { case Qt::DisplayRole: { int c = res->numResources() - requestedResources( res ); if ( m_groupCache.contains( res ) ) { c -= m_groupCache[ res ]->units(); } return i18nc( "1: free resources, 2: number of resources", "%1 of %2", c, res->numResources() ); } case Qt::ToolTipRole: return xi18ncp( "@info:tooltip", "There is %1 resource available in this group", "There are %1 resources available in this group", res->numResources() ); default: return m_model.maximum( res, role ); } return QVariant(); } QVariant ResourceAllocationItemModel::required( const QModelIndex &idx, int role ) const { if ( m_model.task() == 0 ) { return QVariant(); } Resource *res = resource( idx ); if ( res == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: { if ( res->type() == Resource::Type_Work ) { QStringList lst; if ( m_requiredChecked[ res ] ) { foreach ( const Resource *r, required( idx ) ) { lst << r->name(); } } return lst.isEmpty() ? i18n( "None" ) : lst.join( "," ); } break; } case Qt::EditRole: break; case Qt::ToolTipRole: switch ( res->type() ) { case Resource::Type_Work: { if ( ! hasMaterialResources() ) { return xi18nc( "@info:tooltip", "No material resources available" ); } QStringList lst; if ( m_requiredChecked[ res ] ) { foreach ( const Resource *r, required( idx ) ) { lst << r->name(); } } return lst.isEmpty() ? xi18nc( "@info:tooltip", "No required resources" ) : lst.join( "\n" ); } case Resource::Type_Material: return xi18nc( "@info:tooltip", "Material resources cannot have required resources" ); case Resource::Type_Team: return xi18nc( "@info:tooltip", "Team resources cannot have required resources" ); } break; case Qt::CheckStateRole: if ( res->type() == Resource::Type_Work ) { return m_requiredChecked[ res ]; } break; default: return m_model.required( res, role ); } return QVariant(); } bool ResourceAllocationItemModel::setRequired( const QModelIndex &idx, const QVariant &value, int role ) { Resource *res = resource( idx ); if ( res == 0 ) { return false; } switch ( role ) { case Qt::CheckStateRole: m_requiredChecked[ res ] = value.toInt(); if ( value.toInt() == Qt::Unchecked ) { m_resourceCache[ res ]->setRequiredResources( QList() ); } emit dataChanged( idx, idx ); return true; } return false; } QVariant ResourceAllocationItemModel::notUsed( const ResourceGroup *, int role ) const { switch ( role ) { case Qt::DisplayRole: return QString(" "); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::EditRole: case Qt::ToolTipRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceAllocationItemModel::data( const QModelIndex &index, int role ) const { QVariant result; QObject *obj = object( index ); if ( obj == 0 ) { return QVariant(); } if ( role == Qt::TextAlignmentRole ) { // use same alignment as in header (headers always horizontal) return headerData( index.column(), Qt::Horizontal, role ); } Resource *r = qobject_cast( obj ); if ( r ) { if ( index.column() == ResourceAllocationModel::RequestAllocation ) { return allocation( r->parentGroup(), r, role ); } if ( index.column() == ResourceAllocationModel::RequestRequired ) { return required( index, role ); } result = m_model.data( r->parentGroup(), r, index.column(), role ); } else { ResourceGroup *g = qobject_cast( obj ); if ( g ) { switch ( index.column() ) { case ResourceAllocationModel::RequestAllocation: result = allocation( g, role ); break; case ResourceAllocationModel::RequestMaximum: result = maximum( g, role ); break; default: result = m_model.data( g, index.column(), role ); break; } } } if ( role == Qt::DisplayRole && ! result.isValid() ) { // HACK to show focus in empty cells result = ' '; } return result; } bool ResourceAllocationItemModel::setData( const QModelIndex &index, const QVariant &value, int role ) { if ( ! index.isValid() ) { return ItemModelBase::setData( index, value, role ); } if ( ( flags( index ) & Qt::ItemIsEditable ) == 0 ) { return false; } QObject *obj = object( index ); Resource *r = qobject_cast( obj ); if ( r ) { switch (index.column()) { case ResourceAllocationModel::RequestAllocation: if ( setAllocation( r, value, role ) ) { emit dataChanged( index, index ); QModelIndex idx = this->index( index.row(), ResourceAllocationModel::RequestAllocation, parent( parent( index ) ) ); emit dataChanged( idx, idx ); return true; } return false; case ResourceAllocationModel::RequestRequired: return setRequired( index, value, role ); default: //qWarning("data: invalid display value column %d", index.column()); return false; } } ResourceGroup *g = qobject_cast( obj ); if ( g ) { switch (index.column()) { case ResourceAllocationModel::RequestAllocation: if ( setAllocation( g, value, role ) ) { emit dataChanged( index, index ); return true; } return false; default: //qWarning("data: invalid display value column %d", index.column()); return false; } } return false; } QVariant ResourceAllocationItemModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( orientation == Qt::Horizontal ) { if ( role == Qt::DisplayRole ) { return m_model.headerData( section, role ); } if ( role == Qt::TextAlignmentRole ) { switch (section) { case 0: return QVariant(); default: return Qt::AlignCenter; } return Qt::AlignCenter; } } return m_model.headerData( section, role ); } QAbstractItemDelegate *ResourceAllocationItemModel::createDelegate( int col, QWidget *parent ) const { switch ( col ) { case ResourceAllocationModel::RequestAllocation: return new SpinBoxDelegate( parent ); case ResourceAllocationModel::RequestRequired: return new RequieredResourceDelegate( parent ); default: break; } return 0; } QObject *ResourceAllocationItemModel::object( const QModelIndex &index ) const { QObject *o = 0; if ( index.isValid() ) { o = static_cast( index.internalPointer() ); Q_ASSERT( o ); } return o; } void ResourceAllocationItemModel::slotResourceChanged( Resource *res ) { ResourceGroup *g = res->parentGroup(); if ( g ) { int row = g->indexOf( res ); emit dataChanged( createIndex( row, 0, res ), createIndex( row, columnCount() - 1, res ) ); return; } } void ResourceAllocationItemModel::slotResourceGroupChanged( ResourceGroup *res ) { Project *p = res->project(); if ( p ) { int row = p->resourceGroups().indexOf( res ); emit dataChanged( createIndex( row, 0, res ), createIndex( row, columnCount() - 1, res ) ); } } Resource *ResourceAllocationItemModel::resource( const QModelIndex &idx ) const { return qobject_cast( object( idx ) ); } void ResourceAllocationItemModel::setRequired( const QModelIndex &idx, const QList &lst ) { Resource *r = resource( idx ); Q_ASSERT( r ); if ( m_resourceCache.contains( r ) ) { m_resourceCache[ r ]->setRequiredResources( lst ); emit dataChanged( idx, idx ); } } QList ResourceAllocationItemModel::required( const QModelIndex &idx ) const { Resource *r = resource( idx ); Q_ASSERT( r ); if ( m_resourceCache.contains( r ) ) { ResourceRequest* request = m_resourceCache[ r ]; return request->requiredResources(); } return r->requiredResources(); } } // namespace KPlato diff --git a/src/libs/models/kptresourceallocationmodel.h b/src/libs/models/kptresourceallocationmodel.h index 53de0ce2..0702d439 100644 --- a/src/libs/models/kptresourceallocationmodel.h +++ b/src/libs/models/kptresourceallocationmodel.h @@ -1,176 +1,176 @@ /* This file is part of the KDE project Copyright (C) 2009 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 KPTRESOURCEALLOCATIONMODEL_H #define KPTRESOURCEALLOCATIONMODEL_H #include "planmodels_export.h" #include #include #include namespace KPlato { class Project; class Task; class Resource; class ResourceGroup; class ResourceRequest; class ResourceGroupRequest; /** The ResourceAllocationModel gives access to resource requests */ class PLANMODELS_EXPORT ResourceAllocationModel : public QObject { Q_OBJECT Q_ENUMS( Properties ) public: explicit ResourceAllocationModel( QObject *parent = 0 ); ~ResourceAllocationModel(); enum Properties { RequestName = 0, RequestType, RequestAllocation, RequestMaximum, RequestRequired }; const QMetaEnum columnMap() const; void setProject( Project *project ); Task *task() const { return m_task; } void setTask( Task *task ); int propertyCount() const; QVariant data( const ResourceGroup *group, const Resource *resource, int property, int role = Qt::DisplayRole ) const; QVariant data( const ResourceGroup *group, int property, int role = Qt::DisplayRole ) const; static QVariant headerData( int section, int role = Qt::DisplayRole ); QVariant name( const Resource *res, int role ) const; QVariant type( const Resource *res, int role ) const; QVariant allocation( const ResourceGroup *group, const Resource *res, int role ) const; QVariant maximum( const Resource *res, int role ) const; QVariant required( const Resource *res, int role ) const; QVariant name( const ResourceGroup *res, int role ) const; QVariant type( const ResourceGroup *res, int role ) const; QVariant allocation( const ResourceGroup *res, int role ) const; QVariant maximum( const ResourceGroup *res, int role ) const; private: Project *m_project; Task *m_task; }; /** The ResourceAllocationItemModel facilitates viewing and modifying resource allocations for a task. */ class PLANMODELS_EXPORT ResourceAllocationItemModel : public ItemModelBase { Q_OBJECT public: explicit ResourceAllocationItemModel( QObject *parent = 0 ); ~ResourceAllocationItemModel(); virtual const QMetaEnum columnMap() const { return m_model.columnMap(); } virtual void setProject( Project *project ); Task *task() const { return m_model.task(); } virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; QModelIndex index( const ResourceGroup *group ) const; QModelIndex index( const Resource *resource ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; QAbstractItemDelegate *createDelegate( int col, QWidget *parent ) const; QObject *object( const QModelIndex &index ) const; const QMap &resourceCache() const { return m_resourceCache; } const QMap &groupCache() const { return m_groupCache; } Resource *resource( const QModelIndex &idx ) const; void setRequired( const QModelIndex &idx, const QList &lst ); QList required( const QModelIndex &idx ) const; public Q_SLOTS: - void setTask( Task *task ); + void setTask(KPlato::Task *task); protected Q_SLOTS: - void slotResourceChanged( Resource* ); - void slotResourceGroupChanged( ResourceGroup * ); - void slotResourceGroupToBeInserted( const ResourceGroup *group, int row ); - void slotResourceGroupInserted( const ResourceGroup *group ); - void slotResourceGroupToBeRemoved( const ResourceGroup *group ); - void slotResourceGroupRemoved( const ResourceGroup *group ); - void slotResourceToBeInserted( const ResourceGroup *group, int row ); - void slotResourceInserted( const Resource *resource ); - void slotResourceToBeRemoved( const Resource *resource ); - void slotResourceRemoved( const Resource *resource ); + void slotResourceChanged(KPlato::Resource*); + void slotResourceGroupChanged(KPlato::ResourceGroup*); + void slotResourceGroupToBeInserted(const KPlato::ResourceGroup *group, int row); + void slotResourceGroupInserted(const KPlato::ResourceGroup *group); + void slotResourceGroupToBeRemoved(const KPlato::ResourceGroup *group); + void slotResourceGroupRemoved(const KPlato::ResourceGroup *group); + void slotResourceToBeInserted(const KPlato::ResourceGroup *group, int row); + void slotResourceInserted(const KPlato::Resource *resource); + void slotResourceToBeRemoved(const KPlato::Resource *resource); + void slotResourceRemoved(const KPlato::Resource *resource); protected: void filldata( Task *task ); QVariant notUsed( const ResourceGroup *res, int role ) const; QVariant allocation( const ResourceGroup *group, const Resource *res, int role ) const; QVariant allocation( const ResourceGroup *res, int role ) const; bool setAllocation( ResourceGroup *res, const QVariant &value, int role ); bool setAllocation( Resource *res, const QVariant &value, int role ); QVariant maximum( const ResourceGroup *res, int role ) const; bool setRequired( const QModelIndex &idx, const QVariant &value, int role ); QVariant required( const QModelIndex &idx, int role ) const; private: int requestedResources( const ResourceGroup *res ) const; bool hasMaterialResources() const; private: ResourceAllocationModel m_model; QMap m_resourceCache; QMap m_requiredChecked; QMap m_groupCache; }; } //KPlato namespace #endif diff --git a/src/libs/models/kptresourceappointmentsmodel.cpp b/src/libs/models/kptresourceappointmentsmodel.cpp index 58e18a9a..ae9de915 100644 --- a/src/libs/models/kptresourceappointmentsmodel.cpp +++ b/src/libs/models/kptresourceappointmentsmodel.cpp @@ -1,2030 +1,2030 @@ /* This file is part of the KDE project Copyright (C) 2007, 2011, 2012 Dag Andersen danders@get2net> 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. */ #include "kptresourceappointmentsmodel.h" #include "kptglobal.h" #include "kptcommonstrings.h" #include "kptappointment.h" #include "kptcommand.h" #include "kpteffortcostmap.h" #include "kptitemmodelbase.h" #include "kptcalendar.h" #include "kptduration.h" #include "kptnode.h" #include "kptproject.h" #include "kpttask.h" #include "kptresource.h" #include "kptdatetime.h" #include "kptdebug.h" #include #include #include #include #include namespace KPlato { ResourceAppointmentsItemModel::ResourceAppointmentsItemModel( QObject *parent ) : ItemModelBase( parent ), m_group( 0 ), m_resource( 0 ), m_showInternal( true ), m_showExternal( true ) { } ResourceAppointmentsItemModel::~ResourceAppointmentsItemModel() { } void ResourceAppointmentsItemModel::slotResourceToBeInserted( const ResourceGroup *group, int row ) { debugPlan<name()<(group); QModelIndex i = index( group ); beginInsertRows( i, row, row ); } void ResourceAppointmentsItemModel::slotResourceInserted( const Resource *r ) { debugPlan<name(); Q_ASSERT( r->parentGroup() == m_group ); endInsertRows(); m_group = 0; refresh(); - connect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); - connect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); - connect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); + connect( r, SIGNAL(externalAppointmentToBeAdded(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeInserted(KPlato::Resource*,int)) ); + connect( r, SIGNAL(externalAppointmentAdded(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentInserted(KPlato::Resource*,KPlato::Appointment*)) ); + connect( r, SIGNAL(externalAppointmentToBeRemoved(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(KPlato::Resource*,int)) ); connect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); - connect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); + connect( r, SIGNAL(externalAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)) ); } void ResourceAppointmentsItemModel::slotResourceToBeRemoved( const Resource *r ) { debugPlan<name(); int row = r->parentGroup()->indexOf( r ); beginRemoveRows( index( r->parentGroup() ), row, row ); - disconnect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); - disconnect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); - disconnect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); + disconnect( r, SIGNAL(externalAppointmentToBeAdded(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeInserted(KPlato::Resource*,int)) ); + disconnect( r, SIGNAL(externalAppointmentAdded(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentInserted(KPlato::Resource*,KPlato::Appointment*)) ); + disconnect( r, SIGNAL(externalAppointmentToBeRemoved(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(KPlato::Resource*,int)) ); disconnect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); - disconnect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); + disconnect( r, SIGNAL(externalAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)) ); } void ResourceAppointmentsItemModel::slotResourceRemoved( const Resource *resource ) { Q_UNUSED(resource); //debugPlan<name(); endRemoveRows(); refresh(); } void ResourceAppointmentsItemModel::slotResourceGroupToBeInserted( const ResourceGroup *group, int row ) { //debugPlan<name()<(group); beginInsertRows( QModelIndex(), row, row ); } void ResourceAppointmentsItemModel::slotResourceGroupInserted( const ResourceGroup *group ) { //debugPlan<name()<name()<(group); int row = index( group ).row(); beginRemoveRows( QModelIndex(), row, row ); } void ResourceAppointmentsItemModel::slotResourceGroupRemoved( const ResourceGroup *group ) { //debugPlan<name()<= 0 ); refreshData(); emit dataChanged( createExternalAppointmentIndex( row, 0, a ), createExternalAppointmentIndex( row, columnCount() - 1, a ) ); } void ResourceAppointmentsItemModel::slotProjectCalculated( ScheduleManager *sm ) { if ( sm == m_manager ) { setScheduleManager( sm ); } } int ResourceAppointmentsItemModel::rowNumber( Resource *res, Appointment *a ) const { int r = 0; if ( m_showInternal ) { r = res->appointments( id() ).indexOf( a ); if ( r > -1 ) { return r; } r = res->numAppointments(); } if ( m_showExternal ) { int rr = res->externalAppointmentList().indexOf( a ); if ( rr > -1 ) { return r + rr; } } return -1; } void ResourceAppointmentsItemModel::setShowInternalAppointments( bool show ) { if ( m_showInternal == show ) { return; } beginResetModel(); m_showInternal = show; refreshData(); endResetModel(); } void ResourceAppointmentsItemModel::setShowExternalAppointments( bool show ) { if ( m_showExternal == show ) { return; } beginResetModel(); m_showExternal = show; refreshData(); endResetModel(); } void ResourceAppointmentsItemModel::setProject( Project *project ) { beginResetModel(); debugPlan; if ( m_project ) { disconnect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - disconnect( m_project, SIGNAL(resourceChanged(Resource*)), this, SLOT(slotResourceChanged(Resource*)) ); + disconnect( m_project, SIGNAL(resourceChanged(KPlato::Resource*)), this, SLOT(slotResourceChanged(KPlato::Resource*)) ); - disconnect( m_project, SIGNAL(resourceGroupChanged(ResourceGroup*)), this, SLOT(slotResourceGroupChanged(ResourceGroup*)) ); + disconnect( m_project, SIGNAL(resourceGroupChanged(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupChanged(KPlato::ResourceGroup*)) ); - disconnect( m_project, SIGNAL(resourceGroupToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const ResourceGroup*,int)) ); + disconnect( m_project, SIGNAL(resourceGroupToBeAdded(KPlato::ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(KPlato::ResourceGroup*,int)) ); - disconnect( m_project, SIGNAL(resourceGroupToBeRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const ResourceGroup*)) ); + disconnect( m_project, SIGNAL(resourceGroupToBeRemoved(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(KPlato::ResourceGroup*)) ); - disconnect( m_project, SIGNAL(resourceToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const ResourceGroup*,int)) ); + disconnect( m_project, SIGNAL(resourceToBeAdded(KPlato::ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(KPlato::ResourceGroup*,int)) ); - disconnect( m_project, SIGNAL(resourceToBeRemoved(const Resource*)), this, SLOT(slotResourceToBeRemoved(const Resource*)) ); + disconnect( m_project, SIGNAL(resourceToBeRemoved(KPlato::Resource*)), this, SLOT(slotResourceToBeRemoved(KPlato::Resource*)) ); - disconnect( m_project, SIGNAL(resourceGroupAdded(const ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const ResourceGroup*)) ); + disconnect( m_project, SIGNAL(resourceGroupAdded(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupInserted(KPlato::ResourceGroup*)) ); - disconnect( m_project, SIGNAL(resourceGroupRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const ResourceGroup*)) ); + disconnect( m_project, SIGNAL(resourceGroupRemoved(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(KPlato::ResourceGroup*)) ); - disconnect( m_project, SIGNAL(resourceAdded(const Resource*)), this, SLOT(slotResourceInserted(const Resource*)) ); + disconnect( m_project, SIGNAL(resourceAdded(KPlato::Resource*)), this, SLOT(slotResourceInserted(KPlato::Resource*)) ); - disconnect( m_project, SIGNAL(resourceRemoved(const Resource*)), this, SLOT(slotResourceRemoved(const Resource*)) ); + disconnect( m_project, SIGNAL(resourceRemoved(KPlato::Resource*)), this, SLOT(slotResourceRemoved(KPlato::Resource*)) ); - disconnect( m_project, SIGNAL(defaultCalendarChanged(Calendar*)), this, SLOT(slotCalendarChanged(Calendar*)) ); + disconnect( m_project, SIGNAL(defaultCalendarChanged(KPlato::Calendar*)), this, SLOT(slotCalendarChanged(KPlato::Calendar*)) ); - disconnect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); + disconnect( m_project, SIGNAL(projectCalculated(KPlato::ScheduleManager*)), this, SLOT(slotProjectCalculated(KPlato::ScheduleManager*)) ); - disconnect( m_project, SIGNAL(scheduleManagerChanged(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); + disconnect( m_project, SIGNAL(scheduleManagerChanged(KPlato::ScheduleManager*)), this, SLOT(slotProjectCalculated(KPlato::ScheduleManager*)) ); foreach ( Resource *r, m_project->resourceList() ) { - disconnect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); - disconnect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); - disconnect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); + disconnect( r, SIGNAL(externalAppointmentToBeAdded(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeInserted(KPlato::Resource*,int)) ); + disconnect( r, SIGNAL(externalAppointmentAdded(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentInserted(KPlato::Resource*,KPlato::Appointment*)) ); + disconnect( r, SIGNAL(externalAppointmentToBeRemoved(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(KPlato::Resource*,int)) ); disconnect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); - disconnect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); + disconnect( r, SIGNAL(externalAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)) ); } } m_project = project; if ( m_project ) { connect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - connect( m_project, SIGNAL(resourceChanged(Resource*)), this, SLOT(slotResourceChanged(Resource*)) ); - connect( m_project, SIGNAL(resourceGroupChanged(ResourceGroup*)), this, SLOT(slotResourceGroupChanged(ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceChanged(KPlato::Resource*)), this, SLOT(slotResourceChanged(KPlato::Resource*)) ); + connect( m_project, SIGNAL(resourceGroupChanged(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupChanged(KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceGroupToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const ResourceGroup*,int)) ); + connect( m_project, SIGNAL(resourceGroupToBeAdded(KPlato::ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(KPlato::ResourceGroup*,int)) ); - connect( m_project, SIGNAL(resourceGroupToBeRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceGroupToBeRemoved(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const ResourceGroup*,int)) ); + connect( m_project, SIGNAL(resourceToBeAdded(KPlato::ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(KPlato::ResourceGroup*,int)) ); - connect( m_project, SIGNAL(resourceToBeRemoved(const Resource*)), this, SLOT(slotResourceToBeRemoved(const Resource*)) ); + connect( m_project, SIGNAL(resourceToBeRemoved(KPlato::Resource*)), this, SLOT(slotResourceToBeRemoved(KPlato::Resource*)) ); - connect( m_project, SIGNAL(resourceGroupAdded(const ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceGroupAdded(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupInserted(KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceGroupRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceGroupRemoved(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceAdded(const Resource*)), this, SLOT(slotResourceInserted(const Resource*)) ); + connect( m_project, SIGNAL(resourceAdded(KPlato::Resource*)), this, SLOT(slotResourceInserted(KPlato::Resource*)) ); - connect( m_project, SIGNAL(resourceRemoved(const Resource*)), this, SLOT(slotResourceRemoved(const Resource*)) ); + connect( m_project, SIGNAL(resourceRemoved(KPlato::Resource*)), this, SLOT(slotResourceRemoved(KPlato::Resource*)) ); - connect( m_project, SIGNAL(defaultCalendarChanged(Calendar*)), this, SLOT(slotCalendarChanged(Calendar*)) ); + connect( m_project, SIGNAL(defaultCalendarChanged(KPlato::Calendar*)), this, SLOT(slotCalendarChanged(KPlato::Calendar*)) ); - connect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); + connect( m_project, SIGNAL(projectCalculated(KPlato::ScheduleManager*)), this, SLOT(slotProjectCalculated(KPlato::ScheduleManager*)) ); - connect( m_project, SIGNAL(scheduleManagerChanged(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); + connect( m_project, SIGNAL(scheduleManagerChanged(KPlato::ScheduleManager*)), this, SLOT(slotProjectCalculated(KPlato::ScheduleManager*)) ); foreach ( Resource *r, m_project->resourceList() ) { - connect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); - connect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); - connect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); + connect( r, SIGNAL(externalAppointmentToBeAdded(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeInserted(KPlato::Resource*,int)) ); + connect( r, SIGNAL(externalAppointmentAdded(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentInserted(KPlato::Resource*,KPlato::Appointment*)) ); + connect( r, SIGNAL(externalAppointmentToBeRemoved(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(KPlato::Resource*,int)) ); connect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); - connect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); + connect( r, SIGNAL(externalAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)) ); } } refreshData(); endResetModel(); emit refreshed(); } QDate ResourceAppointmentsItemModel::startDate() const { if ( m_project && m_manager ) { return m_project->startTime( id() ).date(); } return QDate::currentDate(); } QDate ResourceAppointmentsItemModel::endDate() const { if ( m_project && m_manager ) { return m_project->endTime( id() ).date(); } return QDate::currentDate(); } void ResourceAppointmentsItemModel::setScheduleManager( ScheduleManager *sm ) { if (sm == m_manager) { return; } beginResetModel(); debugPlan<scheduleId(); } Qt::ItemFlags ResourceAppointmentsItemModel::flags( const QModelIndex &index ) const { Qt::ItemFlags flags = ItemModelBase::flags( index ); return flags &= ~Qt::ItemIsEditable; } QModelIndex ResourceAppointmentsItemModel::parent( const QModelIndex &idx ) const { if ( !idx.isValid() || m_project == 0 || m_manager == 0 ) { warnPlan<<"No data "<indexOf( r->parentGroup() ); p = createGroupIndex( row, 0, r->parentGroup() ); //debugPlan<<"Parent:"<parentGroup()->name(); Q_ASSERT( p.isValid() ); } } if ( ! p.isValid() && m_showInternal ) { Appointment *a = appointment( idx ); if ( a && a->resource() && a->resource()->resource() ) { Resource *r = a->resource()->resource(); int row = r->parentGroup()->indexOf( r ); p = createResourceIndex( row, 0, r ); //debugPlan<<"Parent:"<name(); Q_ASSERT( p.isValid() ); } } if ( ! p.isValid() && m_showExternal ) { Appointment *a = externalAppointment( idx ); Resource *r = parent( a ); if ( r ) { int row = r->parentGroup()->indexOf( r ); p = createResourceIndex( row, 0, r ); } } if ( ! p.isValid() ) { //debugPlan<<"Parent:"<resourceList() ) { if ( r->appointments( id() ).contains( const_cast( a ) ) ) { return r; } if ( r->externalAppointmentList().contains( const_cast( a ) ) ) { return r; } } return 0; } QModelIndex ResourceAppointmentsItemModel::index( int row, int column, const QModelIndex &parent ) const { if ( m_project == 0 || m_manager == 0 ) { return QModelIndex(); } if ( ! parent.isValid() ) { if ( row < m_project->numResourceGroups() ) { //debugPlan<<"Group: "<resourceGroupAt( row )<resourceGroupAt( row ) ); } return QModelIndex(); } ResourceGroup *g = resourcegroup( parent ); if ( g ) { if ( row < g->numResources() ) { //debugPlan<<"Resource: "<resourceAt( row )<resourceAt( row ) ); } return QModelIndex(); } Resource *r = resource( parent ); if ( r && ( m_showInternal || m_showExternal ) ) { int num = m_showInternal ? r->numAppointments( id() ) : 0; if ( row < num ) { //debugPlan<<"Appointment: "<appointmentAt( row, m_manager->scheduleId() ); return createAppointmentIndex( row, column, r->appointmentAt( row, id() ) ); } int extRow = row - num; //debugPlan<<"Appointment: "<externalAppointmentList().value( extRow ); Q_ASSERT( extRow >= 0 && extRow < r->externalAppointmentList().count() ); return createExternalAppointmentIndex( row, column, r->externalAppointmentList().value( extRow ) ); } return QModelIndex(); } QModelIndex ResourceAppointmentsItemModel::index( const Resource *resource ) const { if ( m_project == 0 || resource == 0 ) { return QModelIndex(); } Resource *r = const_cast(resource); int row = -1; ResourceGroup *par = r->parentGroup(); if ( par ) { row = par->indexOf( r ); return createResourceIndex( row, 0, r ); } return QModelIndex(); } QModelIndex ResourceAppointmentsItemModel::index( const ResourceGroup *group ) const { if ( m_project == 0 || group == 0 ) { return QModelIndex(); } ResourceGroup *g = const_cast(group); int row = m_project->indexOf( g ); return createGroupIndex( row, 0, g ); } void ResourceAppointmentsItemModel::refresh() { refreshData(); emit refreshed(); } void ResourceAppointmentsItemModel::refreshData() { long id = m_manager == 0 ? -1 : m_manager->scheduleId(); //debugPlan<<"Schedule id: "< ec; QMap extEff; foreach ( Resource *r, m_project->resourceList() ) { foreach (Appointment* a, r->appointments( id )) { QDate s = a->startTime().date(); QDate e = a->endTime().date(); ec[ a ] = a->plannedPrDay( s, e ); if ( ! start.isValid() || s < start ) { start = s; } if ( ! end.isValid() || e > end ) { end = e; } //debugPlan<node()->node()->name()<<": "<externalAppointmentList() ) { extEff[ a ] = a->plannedPrDay( startDate(), endDate() ); //debugPlan<name()<auxcilliaryInfo()<<": "<name()<auxcilliaryInfo()<<": "<name()<<": "<numResourceGroups()<numResourceGroups(); } ResourceGroup *g = resourcegroup( parent ); if ( g ) { //debugPlan<name()<<": "<numResources()<numResources(); } Resource *r = resource( parent ); if ( r ) { int rows = m_showInternal ? r->numAppointments( id() ) : 0; rows += m_showExternal ? r->numExternalAppointments() : 0; return rows; } return 0; } QVariant ResourceAppointmentsItemModel::name( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return res->name(); break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceAppointmentsItemModel::name( const ResourceGroup *res, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return res->name(); break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceAppointmentsItemModel::name( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return node->name(); break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceAppointmentsItemModel::name( const Appointment *app, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return app->auxcilliaryInfo(); case Qt::ToolTipRole: return i18n( "External project: %1", app->auxcilliaryInfo() ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Qt::ForegroundRole: if ( m_externalEffortMap.contains( app ) ) { return QColor( Qt::blue ); } break; } return QVariant(); } QVariant ResourceAppointmentsItemModel::total( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: { Duration d; if ( m_showInternal ) { QList lst = res->appointments( m_manager->scheduleId() ); foreach ( Appointment *a, lst ) { if ( m_effortMap.contains( a ) ) { d += m_effortMap[ a ].totalEffort(); } } } if ( m_showExternal ) { QList lst = res->externalAppointmentList(); foreach ( Appointment *a, lst ) { if ( m_externalEffortMap.contains( a ) ) { d += m_externalEffortMap[ a ].totalEffort(); } } } return QLocale().toString( d.toDouble( Duration::Unit_h ), 'f', 1 ); } case Qt::EditRole: case Qt::ToolTipRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Qt::TextAlignmentRole: return (int)(Qt::AlignRight|Qt::AlignVCenter); } return QVariant(); } QVariant ResourceAppointmentsItemModel::total( const Resource *res, const QDate &date, int role ) const { switch ( role ) { case Qt::DisplayRole: { Duration d; if ( m_showInternal ) { QList lst = res->appointments( id() ); foreach ( Appointment *a, lst ) { if ( m_effortMap.contains( a ) ) { d += m_effortMap[ a ].effortOnDate( date ); } } } if ( m_showExternal ) { QList lst = res->externalAppointmentList(); foreach ( Appointment *a, lst ) { if ( m_externalEffortMap.contains( a ) ) { d += m_externalEffortMap[ a ].effortOnDate( date ); } } } QString ds = QLocale().toString( d.toDouble( Duration::Unit_h ), 'f', 1 ); Duration avail = res->effort( 0, DateTime( date, QTime(0,0,0) ), Duration( 1.0, Duration::Unit_d ) ); QString avails = QLocale().toString( avail.toDouble( Duration::Unit_h ), 'f', 1 ); return QString( "%1(%2)").arg( ds).arg( avails ); } case Qt::EditRole: case Qt::ToolTipRole: return i18n( "The total booking on %1, along with the maximum hours for the resource", QLocale().toString( date, QLocale::ShortFormat ) ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Qt::TextAlignmentRole: return (int)(Qt::AlignRight|Qt::AlignVCenter); case Qt::BackgroundRole: { if ( res->calendar() && res->calendar()->state( date ) != CalendarDay::Working ) { QColor c( 0xf0f0f0 ); return QVariant::fromValue( c ); //return QVariant( Qt::cyan ); } break; } } return QVariant(); } QVariant ResourceAppointmentsItemModel::total( const Appointment *a, int role ) const { switch ( role ) { case Qt::DisplayRole: { Duration d; if ( m_effortMap.contains( a ) ) { d = m_effortMap[ a ].totalEffort(); } else if ( m_externalEffortMap.contains( a ) ) { d = m_externalEffortMap[ a ].totalEffort(); } return QLocale().toString( d.toDouble( Duration::Unit_h ), 'f', 1 ); } case Qt::ToolTipRole: { if ( m_effortMap.contains( a ) ) { return i18n( "Total booking by this task" ); } else if ( m_externalEffortMap.contains( a ) ) { return i18n( "Total booking by the external project" ); } return QVariant(); } case Qt::EditRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Qt::TextAlignmentRole: return (int)(Qt::AlignRight|Qt::AlignVCenter); case Qt::ForegroundRole: if ( m_externalEffortMap.contains( a ) ) { return QColor( Qt::blue ); } break; } return QVariant(); } QVariant ResourceAppointmentsItemModel::assignment( const Appointment *a, const QDate &date, int role ) const { switch ( role ) { case Qt::DisplayRole: { Duration d; if ( m_effortMap.contains( a ) ) { if ( date < m_effortMap[ a ].startDate() || date > m_effortMap[ a ].endDate() ) { return QVariant(); } d = m_effortMap[ a ].effortOnDate( date ); return QLocale().toString( d.toDouble( Duration::Unit_h ), 'f', 1 ); } else if ( m_externalEffortMap.contains( a ) ) { if ( date < m_externalEffortMap[ a ].startDate() || date > m_externalEffortMap[ a ].endDate() ) { return QVariant(); } d = m_externalEffortMap[ a ].effortOnDate( date ); return QLocale().toString( d.toDouble( Duration::Unit_h ), 'f', 1 ); } return QVariant(); } case Qt::EditRole: case Qt::ToolTipRole: { if ( m_effortMap.contains( a ) ) { return i18n( "Booking by this task on %1", QLocale().toString( date, QLocale::ShortFormat ) ); } else if ( m_externalEffortMap.contains( a ) ) { return i18n( "Booking by external project on %1",QLocale().toString( date, QLocale::ShortFormat ) ); } return QVariant(); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Qt::TextAlignmentRole: return (int)(Qt::AlignRight|Qt::AlignVCenter); case Qt::ForegroundRole: if ( m_externalEffortMap.contains( a ) ) { return QColor( Qt::blue ); } break; case Qt::BackgroundRole: { Resource *r = parent( a ); if ( r && r->calendar() && r->calendar()->state( date ) != CalendarDay::Working ) { QColor c( 0xf0f0f0 ); return QVariant::fromValue( c ); //return QVariant( Qt::cyan ); } break; } } return QVariant(); } QVariant ResourceAppointmentsItemModel::notUsed( const ResourceGroup *, int role ) const { switch ( role ) { case Qt::DisplayRole: return QString(" "); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::EditRole: case Qt::ToolTipRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceAppointmentsItemModel::data( const QModelIndex &index, int role ) const { if ( m_project == 0 || m_manager == 0 ) { return QVariant(); } QVariant result; if ( index.column() >= columnCount() ) { debugPlan<<"invalid display value column "<node()->node(), role ); break; case 1: result = total( a, role ); break; default: { QDate d = startDate().addDays( index.column()-2 ); result = assignment( a, d, role ); break; } } if ( result.isValid() ) { if ( role == Qt::DisplayRole && result.type() == QVariant::String && result.toString().isEmpty()) { // HACK to show focus in empty cells result = ' '; } return result; } return QVariant(); } a = externalAppointment( index ); if ( a ) { //debugPlan<<"external"<auxcilliaryInfo()<( resource( index ) ); if ( o ) { return o; } o = dynamic_cast( resourcegroup( index ) ); } return o; } Node *ResourceAppointmentsItemModel::node( const QModelIndex &index ) const { Appointment *a = appointment( index ); if ( a == 0 ) { return 0; } return a->node()->node(); } Appointment *ResourceAppointmentsItemModel::appointment( const QModelIndex &index ) const { if ( m_project == 0 || m_manager == 0 ) { return 0; } foreach ( Resource *r, m_project->resourceList() ) { foreach ( Appointment *a, r->appointments( id() ) ) { if ( a == index.internalPointer() ) { return a; } } } return 0; } Appointment *ResourceAppointmentsItemModel::externalAppointment( const QModelIndex &index ) const { if ( m_project == 0 || m_manager == 0 ) { return 0; } foreach ( Resource *r, m_project->resourceList() ) { foreach ( Appointment *a, r->externalAppointmentList() ) { if ( a == index.internalPointer() ) { return a; } } } return 0; } QModelIndex ResourceAppointmentsItemModel::createAppointmentIndex( int row, int col, void *ptr ) const { return createIndex( row, col, ptr ); } QModelIndex ResourceAppointmentsItemModel::createExternalAppointmentIndex( int row, int col, void *ptr ) const { if ( m_project == 0 || m_manager == 0 ) { return QModelIndex(); } QModelIndex i = createIndex( row, col, ptr ); //debugPlan<resourceList() ) { if ( r == index.internalPointer() ) { return r; } } return 0; } QModelIndex ResourceAppointmentsItemModel::createResourceIndex( int row, int col, void *ptr ) const { return createIndex( row, col, ptr ); } ResourceGroup *ResourceAppointmentsItemModel::resourcegroup( const QModelIndex &index ) const { if ( m_project == 0 ) { return 0; } foreach ( ResourceGroup *r, m_project->resourceGroups() ) { if ( r == index.internalPointer() ) { return r; } } return 0; } QModelIndex ResourceAppointmentsItemModel::createGroupIndex( int row, int col, void *ptr ) const { return createIndex( row, col, ptr ); } void ResourceAppointmentsItemModel::slotCalendarChanged( Calendar* ) { foreach ( Resource *r, m_project->resourceList() ) { if ( r->calendar( true ) == 0 ) { slotResourceChanged( r ); } } } void ResourceAppointmentsItemModel::slotResourceChanged( Resource *res ) { ResourceGroup *g = res->parentGroup(); if ( g ) { int row = g->indexOf( res ); emit dataChanged( createResourceIndex( row, 0, res ), createResourceIndex( row, columnCount() - 1, res ) ); return; } } void ResourceAppointmentsItemModel::slotResourceGroupChanged( ResourceGroup *res ) { Project *p = res->project(); if ( p ) { int row = p->resourceGroups().indexOf( res ); emit dataChanged( createGroupIndex( row, 0, res ), createGroupIndex( row, columnCount() - 1, res ) ); } } //------------------------------------------------------- class Q_DECL_HIDDEN ResourceAppointmentsRowModel::Private { public: Private( Private *par=0, void *p=0, KPlato::ObjectType t=OT_None ) : parent( par ), ptr( p ), type( t ), internalCached( false ), externalCached( false ), intervalRow( -1 ) {} ~Private() { qDeleteAll( intervals ); } QVariant data( int column, long id = -1, int role = Qt::DisplayRole ) const; Private *parent; void *ptr; KPlato::ObjectType type; bool internalCached; bool externalCached; Private *intervalAt( int row ) const; // used by interval AppointmentInterval interval; protected: QVariant groupData( int column, int role ) const; QVariant resourceData( int column, long id, int role ) const; QVariant appointmentData( int column, int role ) const; QVariant externalData( int column, int role ) const; QVariant intervalData( int column, int role ) const; private: // used by resource Appointment internal; Appointment external; // used by appointment int intervalRow; mutable QMap intervals; }; QVariant ResourceAppointmentsRowModel::Private::data( int column, long id, int role ) const { if ( role == Role::ObjectType ) { return (int)type; } switch ( type ) { case OT_ResourceGroup: return groupData( column, role ); case OT_Resource: return resourceData( column, id, role ); case OT_Appointment: return appointmentData( column, role ); case OT_External: return externalData( column, role ); case OT_Interval: return intervalData( column, role ); default: break; } return QVariant(); } QVariant ResourceAppointmentsRowModel::Private::groupData( int column, int role ) const { ResourceGroup *g = static_cast( ptr ); if ( role == Qt::DisplayRole ) { switch ( column ) { case ResourceAppointmentsRowModel::Name: return g->name(); case ResourceAppointmentsRowModel::Type: return g->typeToString( true ); case ResourceAppointmentsRowModel::StartTime: return " "; case ResourceAppointmentsRowModel::EndTime: return " "; case ResourceAppointmentsRowModel::Load: return " "; } } else if ( role == Role::Maximum ) { return g->units(); //TODO: Maximum Load } return QVariant(); } QVariant ResourceAppointmentsRowModel::Private::resourceData( int column, long id, int role ) const { KPlato::Resource *r = static_cast( ptr ); if ( role == Qt::DisplayRole ) { switch ( column ) { case ResourceAppointmentsRowModel::Name: return r->name(); case ResourceAppointmentsRowModel::Type: return r->typeToString( true ); case ResourceAppointmentsRowModel::StartTime: return " "; case ResourceAppointmentsRowModel::EndTime: return " "; case ResourceAppointmentsRowModel::Load: return " "; } } else if ( role == Role::Maximum ) { return r->units(); //TODO: Maximum Load } else if ( role == Role::InternalAppointments ) { if ( ! internalCached ) { Resource *r = static_cast( ptr ); const_cast( this )->internal.clear(); foreach ( Appointment *a, r->appointments( id ) ) { const_cast( this )->internal += *a; } const_cast( this )->internalCached = true; } return QVariant::fromValue( (void*)(&internal) ); } else if ( role == Role::ExternalAppointments ) { if ( ! externalCached ) { Resource *r = static_cast( ptr ); const_cast( this )->external.clear(); foreach ( Appointment *a, r->externalAppointmentList() ) { Appointment e; e.setIntervals( a->intervals( r->startTime( id ), r->endTime( id ) ) ); const_cast( this )->external += e; } const_cast( this )->externalCached = true; } return QVariant::fromValue( (void*)(&external) ); } return QVariant(); } QVariant ResourceAppointmentsRowModel::Private::appointmentData( int column, int role ) const { KPlato::Appointment *a = static_cast( ptr ); if ( role == Qt::DisplayRole ) { switch ( column ) { case ResourceAppointmentsRowModel::Name: return a->node()->node()->name(); case ResourceAppointmentsRowModel::Type: return a->node()->node()->typeToString( true ); case ResourceAppointmentsRowModel::StartTime: return QLocale().toString( a->startTime(), QLocale::ShortFormat ); case ResourceAppointmentsRowModel::EndTime: return QLocale().toString( a->endTime(), QLocale::ShortFormat ); case ResourceAppointmentsRowModel::Load: return " "; } } else if ( role == Qt::ToolTipRole ) { Node *n = a->node()->node(); return xi18nc( "@info:tooltip", "%1: %2%3: %4", n->wbsCode(), n->name(), QLocale().toString( a->startTime(), QLocale::ShortFormat ), KFormat().formatDuration( ( a->endTime() - a->startTime() ).milliseconds() ) ); } else if ( role == Role::Maximum ) { return a->resource()->resource()->units(); //TODO: Maximum Load } return QVariant(); } QVariant ResourceAppointmentsRowModel::Private::externalData( int column, int role ) const { KPlato::Appointment *a = static_cast( ptr ); if ( role == Qt::DisplayRole ) { switch ( column ) { case ResourceAppointmentsRowModel::Name: return a->auxcilliaryInfo(); case ResourceAppointmentsRowModel::Type: return i18n( "Project" ); case ResourceAppointmentsRowModel::StartTime: return QLocale().toString( a->startTime(), QLocale::ShortFormat ); case ResourceAppointmentsRowModel::EndTime: return QLocale().toString( a->endTime(), QLocale::ShortFormat ); case ResourceAppointmentsRowModel::Load: return " "; } } else if ( role == Qt::ForegroundRole ) { return QColor( Qt::blue ); } else if ( role == Role::Maximum ) { KPlato::Resource *r = static_cast( parent->ptr ); return r->units(); //TODO: Maximum Load } return QVariant(); } ResourceAppointmentsRowModel::Private *ResourceAppointmentsRowModel::Private::intervalAt( int row ) const { Q_ASSERT( type == OT_Appointment || type == OT_External ); Private *p = intervals.value( row ); if ( p ) { return p; } Appointment *a = static_cast( ptr ); p = new Private( const_cast( this ), 0, OT_Interval ); p->intervalRow = row; p->interval = a->intervalAt( row ); intervals.insert( row, p ); return p; } QVariant ResourceAppointmentsRowModel::Private::intervalData( int column, int role ) const { if ( role == Qt::DisplayRole ) { switch ( column ) { case ResourceAppointmentsRowModel::Name: return QVariant(); case ResourceAppointmentsRowModel::Type: return i18n( "Interval" ); case ResourceAppointmentsRowModel::StartTime: return QLocale().toString( interval.startTime(), QLocale::ShortFormat ); case ResourceAppointmentsRowModel::EndTime: return QLocale().toString( interval.endTime(), QLocale::ShortFormat ); case ResourceAppointmentsRowModel::Load: return interval.load(); } } else if ( role == Qt::ToolTipRole ) { Appointment *a = static_cast( parent->ptr ); if (a && a->node() && a->node()->node()) { Node *n = a->node()->node(); return xi18nc( "@info:tooltip", "%1: %2%3: %4Assigned: %5Available: %6", n->wbsCode(), n->name(), QLocale().toString( a->startTime(), QLocale::ShortFormat ), KFormat().formatDuration( ( a->endTime() - a->startTime() ).milliseconds() ), interval.load(), a->resource()->resource()->units() ); } } else if ( role == Role::Maximum ) { return parent->appointmentData( column, role ); } return QVariant(); } int ResourceAppointmentsRowModel::sortRole( int column ) const { switch ( column ) { case ResourceAppointmentsRowModel::StartTime: case ResourceAppointmentsRowModel::EndTime: return Qt::EditRole; default: break; } return Qt::DisplayRole; } #ifndef QT_NO_DEBUG_STREAM QDebug operator<<( QDebug dbg, KPlato::ObjectType t) { switch(t){ case KPlato::OT_None: dbg << "None"; break; case KPlato::OT_ResourceGroup: dbg << "Group"; break; case KPlato::OT_Resource: dbg << "Resource"; break; case KPlato::OT_Appointment: dbg << "Appointment"; break; case KPlato::OT_External: dbg << "External"; break; case KPlato::OT_Interval: dbg << "Interval"; break; default: dbg << "Unknown"; } return dbg; } QDebug operator<<( QDebug dbg, const ResourceAppointmentsRowModel::Private& s ) { dbg <<&s; return dbg; } QDebug operator<<( QDebug dbg, const ResourceAppointmentsRowModel::Private* s ) { if ( s == 0 ) { dbg<<"ResourceAppointmentsRowModel::Private[ ("<<(void*)s<<") ]"; } else { dbg << "ResourceAppointmentsRowModel::Private[ ("<<(void*)s<<") Type="<type<<" parent="; switch( s->type ) { case KPlato::OT_ResourceGroup: dbg<(s->ptr)->project()<(s->ptr)->project()->name(); dbg<<" ptr="<(s->ptr)<(s->ptr)->name(); break; case KPlato::OT_Resource: dbg<(s->parent->ptr)<(s->parent->ptr)->name(); dbg<<" ptr="<(s->ptr)<(s->ptr)->name(); break; case KPlato::OT_Appointment: case KPlato::OT_External: dbg<(s->parent->ptr)<(s->parent->ptr)->name(); dbg<<" ptr="<(s->ptr); break; case KPlato::OT_Interval: dbg<(s->parent->ptr)<<" ptr="<(s->ptr); break; default: dbg<parent<<" ptr="<ptr; break; } dbg<<" ]"; } return dbg; } #endif ResourceAppointmentsRowModel::ResourceAppointmentsRowModel( QObject *parent ) : ItemModelBase( parent ), m_schedule( 0 ) { } ResourceAppointmentsRowModel::~ResourceAppointmentsRowModel() { qDeleteAll( m_datamap ); } void ResourceAppointmentsRowModel::setProject( Project *project ) { beginResetModel(); //debugPlan<resourceList() ) { - disconnect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); - disconnect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); - disconnect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); + disconnect( r, SIGNAL(externalAppointmentToBeAdded(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeInserted(KPlato::Resource*,int)) ); + disconnect( r, SIGNAL(externalAppointmentAdded(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentInserted(KPlato::Resource*,KPlato::Appointment*)) ); + disconnect( r, SIGNAL(externalAppointmentToBeRemoved(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(KPlato::Resource*,int)) ); disconnect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); - disconnect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); + disconnect( r, SIGNAL(externalAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)) ); } } m_project = project; if ( m_project ) { connect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - connect( m_project, SIGNAL(resourceGroupToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const ResourceGroup*,int)) ); + connect( m_project, SIGNAL(resourceGroupToBeAdded(KPlato::ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(KPlato::ResourceGroup*,int)) ); - connect( m_project, SIGNAL(resourceGroupToBeRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceGroupToBeRemoved(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const ResourceGroup*,int)) ); + connect( m_project, SIGNAL(resourceToBeAdded(KPlato::ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(KPlato::ResourceGroup*,int)) ); - connect( m_project, SIGNAL(resourceToBeRemoved(const Resource*)), this, SLOT(slotResourceToBeRemoved(const Resource*)) ); + connect( m_project, SIGNAL(resourceToBeRemoved(KPlato::Resource*)), this, SLOT(slotResourceToBeRemoved(KPlato::Resource*)) ); - connect( m_project, SIGNAL(resourceGroupAdded(const ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceGroupAdded(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupInserted(KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceGroupRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceGroupRemoved(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceAdded(const Resource*)), this, SLOT(slotResourceInserted(const Resource*)) ); + connect( m_project, SIGNAL(resourceAdded(KPlato::Resource*)), this, SLOT(slotResourceInserted(KPlato::Resource*)) ); - connect( m_project, SIGNAL(resourceRemoved(const Resource*)), this, SLOT(slotResourceRemoved(const Resource*)) ); + connect( m_project, SIGNAL(resourceRemoved(KPlato::Resource*)), this, SLOT(slotResourceRemoved(KPlato::Resource*)) ); - connect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); + connect( m_project, SIGNAL(projectCalculated(KPlato::ScheduleManager*)), this, SLOT(slotProjectCalculated(KPlato::ScheduleManager*)) ); foreach ( Resource *r, m_project->resourceList() ) { - connect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); - connect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); - connect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); + connect( r, SIGNAL(externalAppointmentToBeAdded(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeInserted(KPlato::Resource*,int)) ); + connect( r, SIGNAL(externalAppointmentAdded(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentInserted(KPlato::Resource*,KPlato::Appointment*)) ); + connect( r, SIGNAL(externalAppointmentToBeRemoved(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(KPlato::Resource*,int)) ); connect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); - connect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); + connect( r, SIGNAL(externalAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)) ); } } endResetModel(); } void ResourceAppointmentsRowModel::setScheduleManager( ScheduleManager *sm ) { debugPlan<<"ResourceAppointmentsRowModel::setScheduleManager:"<expected() != m_schedule ) { beginResetModel(); m_manager = sm; m_schedule = sm ? sm->expected() : 0; qDeleteAll( m_datamap ); m_datamap.clear(); endResetModel(); } } long ResourceAppointmentsRowModel::id() const { return m_manager ? m_manager->scheduleId() : -1; } const QMetaEnum ResourceAppointmentsRowModel::columnMap() const { return metaObject()->enumerator( metaObject()->indexOfEnumerator("Properties") ); } int ResourceAppointmentsRowModel::columnCount( const QModelIndex & /*parent */) const { return columnMap().keyCount(); } int ResourceAppointmentsRowModel::rowCount( const QModelIndex & parent ) const { if ( m_project == 0 ) { return 0; } if ( ! parent.isValid() ) { return m_project->numResourceGroups(); } if ( ResourceGroup *g = resourcegroup( parent ) ) { return g->numResources(); } if ( m_manager == 0 ) { return 0; } if ( Resource *r = resource( parent ) ) { return r->numAppointments( id() ) + r->numExternalAppointments(); // number of tasks there are appointments with + external projects } if ( Appointment *a = appointment( parent ) ) { return a->count(); // number of appointment intervals } return 0; } QVariant ResourceAppointmentsRowModel::data( const QModelIndex &index, int role ) const { //debugPlan<(index.internalPointer() )->data( index.column(), id(), role ); } QVariant ResourceAppointmentsRowModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( orientation == Qt::Vertical ) { return QVariant(); } if ( role == Qt::DisplayRole ) { switch ( section ) { case Name: return i18n( "Name" ); case Type: return i18n( "Type" ); case StartTime: return i18n( "Start Time" ); case EndTime: return i18n( "End Time" ); case Load: return xi18nc( "@title:column noun", "Load" ); } } if ( role == Qt::TextAlignmentRole ) { switch ( section ) { case Name: case Type: case StartTime: case EndTime: return (int)(Qt::AlignLeft|Qt::AlignVCenter); case Load: return (int)(Qt::AlignRight|Qt::AlignVCenter); } } return ItemModelBase::headerData( section, orientation, role ); } QModelIndex ResourceAppointmentsRowModel::parent( const QModelIndex &idx ) const { if ( !idx.isValid() || m_project == 0 ) { warnPlan<<"No data "<indexOf( pg ); p = const_cast( this )->createGroupIndex( row, 0, m_project ); //debugPlan<<"Parent:"<parentGroup()->name(); Q_ASSERT( p.isValid() ); return p; } if ( Resource *pr = parentResource( idx ) ) { // Appointment, parent is Resource int row = pr->parentGroup()->indexOf( pr ); p = const_cast( this )->createResourceIndex( row, 0, pr->parentGroup() ); //debugPlan<<"Parent:"<parentGroup()->name(); Q_ASSERT( p.isValid() ); return p; } if ( Appointment *a = parentAppointment( idx ) ) { // AppointmentInterval, parent is Appointment Private *pi = static_cast( idx.internalPointer() ); if ( pi->parent->type == OT_Appointment ) { Q_ASSERT( a->resource()->id() == id() ); if ( a->resource() && a->resource()->resource() ) { Resource *r = a->resource()->resource(); int row = r->indexOf( a, id() ); Q_ASSERT( row >= 0 ); p = const_cast( this )->createAppointmentIndex( row, 0, r ); //debugPlan<<"Parent:"<name(); Q_ASSERT( p.isValid() ); } } else if ( pi->parent->type == OT_External ) { Resource *r = static_cast( pi->parent->parent->ptr ); int row = r->externalAppointmentList().indexOf( a ); Q_ASSERT( row >= 0 ); row += r->numAppointments( id() ); p = const_cast( this )->createAppointmentIndex( row, 0, r ); } return p; } return QModelIndex(); } QModelIndex ResourceAppointmentsRowModel::index( ResourceGroup *g ) const { if ( m_project == 0 || g == 0 ) { return QModelIndex(); } return const_cast( this )->createGroupIndex( m_project->indexOf( g ), 0, m_project ); } QModelIndex ResourceAppointmentsRowModel::index( Resource *r ) const { if ( m_project == 0 || r == 0 ) { return QModelIndex(); } return const_cast( this )->createResourceIndex( r->parentGroup()->indexOf( r ), 0, r->parentGroup() ); } QModelIndex ResourceAppointmentsRowModel::index( Appointment *a ) const { if ( m_project == 0 || m_manager == 0 || a == 0 || a->resource()->resource() ) { return QModelIndex(); } Resource *r = a->resource()->resource(); return const_cast( this )->createAppointmentIndex( r->indexOf( a, id() ), 0, r ); } QModelIndex ResourceAppointmentsRowModel::index( int row, int column, const QModelIndex &parent ) const { if ( m_project == 0 || row < 0 || column < 0 ) { return QModelIndex(); } if ( ! parent.isValid() ) { if ( row < m_project->numResourceGroups() ) { //debugPlan<<"Group: "<resourceGroupAt( row ); return const_cast( this )->createGroupIndex( row, column, m_project ); } return QModelIndex(); } if ( ResourceGroup *g = resourcegroup( parent ) ) { if ( row < g->numResources() ) { //debugPlan<<"Resource: "<resourceAt( row )<( parent.internalPointer() ); return const_cast( this )->createResourceIndex( row, column, g ); } return QModelIndex(); } if ( m_manager == 0 ) { return QModelIndex(); } if ( Resource *r = resource( parent ) ) { int num = r->numAppointments( id() ) + r->numExternalAppointments(); if ( row < num ) { //debugPlan<<"Appointment: "<appointmentAt( row, m_manager->scheduleId() )<( parent.internalPointer() ); return const_cast( this )->createAppointmentIndex( row, column, r ); } return QModelIndex(); } if ( Appointment *a = appointment( parent ) ) { int num = a->count(); if ( row < num ) { //debugPlan<<"Appointment interval at: "<( parent.internalPointer() ); return const_cast( this )->createIntervalIndex( row, column, a ); } return QModelIndex(); } return QModelIndex(); } QModelIndex ResourceAppointmentsRowModel::createGroupIndex( int row, int column, Project *project ) { ResourceGroup *group = project->resourceGroupAt( row ); Private *p = m_datamap.value( (void*)group ); if ( p == 0 ) { p = new Private( 0, group, OT_ResourceGroup ); m_datamap.insert( group, p ); } QModelIndex idx = createIndex( row, column, p ); Q_ASSERT( idx.isValid() ); return idx; } QModelIndex ResourceAppointmentsRowModel::createResourceIndex( int row, int column, ResourceGroup *g ) { Resource *res = g->resourceAt( row ); Private *p = m_datamap.value( (void*)res ); if ( p == 0 ) { Private *pg = m_datamap.value( g ); Q_ASSERT( pg ); p = new Private( pg, res, OT_Resource ); m_datamap.insert( res, p ); } QModelIndex idx = createIndex( row, column, p ); Q_ASSERT( idx.isValid() ); return idx; } QModelIndex ResourceAppointmentsRowModel::createAppointmentIndex( int row, int column, Resource *r ) { Private *p = 0; KPlato::ObjectType type; Appointment *a = 0; if ( row < r->numAppointments( id() ) ) { a = r->appointmentAt( row, id() ); type = OT_Appointment; } else { a = r->externalAppointmentList().value( row - r->numAppointments( id() ) ); type = OT_External; } Q_ASSERT( a ); p = m_datamap.value( (void*)a ); if ( p == 0 ) { Private *pr = m_datamap.value( r ); Q_ASSERT( pr ); p = new Private( pr, a, type ); m_datamap.insert( a, p ); } QModelIndex idx = createIndex( row, column, p ); Q_ASSERT( idx.isValid() ); return idx; } QModelIndex ResourceAppointmentsRowModel::createIntervalIndex( int row, int column, Appointment *a ) { AppointmentInterval i = a->intervalAt( row ); Private *pr = m_datamap.value( a ); Q_ASSERT( pr ); Private *p = pr->intervalAt( row ); Q_ASSERT( p ); QModelIndex idx = createIndex( row, column, p ); Q_ASSERT( idx.isValid() ); return idx; } void ResourceAppointmentsRowModel::slotResourceToBeInserted( const ResourceGroup *group, int row ) { debugPlan<name()<( group ) ); beginInsertRows( i, row, row ); } void ResourceAppointmentsRowModel::slotResourceInserted( const Resource *r ) { debugPlan<name(); endInsertRows(); - connect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); - connect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); - connect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); + connect( r, SIGNAL(externalAppointmentToBeAdded(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeInserted(KPlato::Resource*,int)) ); + connect( r, SIGNAL(externalAppointmentAdded(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentInserted(KPlato::Resource*,KPlato::Appointment*)) ); + connect( r, SIGNAL(externalAppointmentToBeRemoved(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(KPlato::Resource*,int)) ); connect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); - connect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); + connect( r, SIGNAL(externalAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)) ); } void ResourceAppointmentsRowModel::slotResourceToBeRemoved( const Resource *r ) { debugPlan<name(); int row = r->parentGroup()->indexOf( r ); beginRemoveRows( index( r->parentGroup() ), row, row ); - disconnect( r, SIGNAL(externalAppointmentToBeAdded(Resource*,int)), this, SLOT(slotAppointmentToBeInserted(Resource*,int)) ); - disconnect( r, SIGNAL(externalAppointmentAdded(Resource*,Appointment*)), this, SLOT(slotAppointmentInserted(Resource*,Appointment*)) ); - disconnect( r, SIGNAL(externalAppointmentToBeRemoved(Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(Resource*,int)) ); + disconnect( r, SIGNAL(externalAppointmentToBeAdded(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeInserted(KPlato::Resource*,int)) ); + disconnect( r, SIGNAL(externalAppointmentAdded(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentInserted(KPlato::Resource*,KPlato::Appointment*)) ); + disconnect( r, SIGNAL(externalAppointmentToBeRemoved(KPlato::Resource*,int)), this, SLOT(slotAppointmentToBeRemoved(KPlato::Resource*,int)) ); disconnect( r, SIGNAL(externalAppointmentRemoved()), this, SLOT(slotAppointmentRemoved()) ); - disconnect( r, SIGNAL(externalAppointmentChanged(Resource*,Appointment*)), this, SLOT(slotAppointmentChanged(Resource*,Appointment*)) ); + disconnect( r, SIGNAL(externalAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)), this, SLOT(slotAppointmentChanged(KPlato::Resource*,KPlato::Appointment*)) ); Private *p = 0; foreach ( Appointment *a, r->appointments( id() ) ) { // remove appointment p = m_datamap.value( a ); if ( p ) { m_datamap.remove( a ); delete p; } } foreach ( Appointment *a, r->externalAppointmentList() ) { // remove appointment p = m_datamap.value( a ); if ( p ) { m_datamap.remove( a ); delete p; } } // remove resource p = m_datamap.value( (void*)r ); if ( p ) { m_datamap.remove( const_cast( r ) ); delete p; } } void ResourceAppointmentsRowModel::slotResourceRemoved( const Resource *resource ) { Q_UNUSED(resource); //debugPlan<name(); endRemoveRows(); } void ResourceAppointmentsRowModel::slotResourceGroupToBeInserted( const ResourceGroup *group, int row ) { Q_UNUSED(group); beginInsertRows( QModelIndex(), row, row ); } void ResourceAppointmentsRowModel::slotResourceGroupInserted( const ResourceGroup*/*group*/ ) { endInsertRows(); } void ResourceAppointmentsRowModel::slotResourceGroupToBeRemoved( const ResourceGroup *group ) { //debugPlan<name()<indexOf( const_cast( group ) ); beginRemoveRows( QModelIndex(), row, row ); Private *p = m_datamap.value( const_cast( group ) ); if ( p ) { m_datamap.remove( const_cast( group ) ); delete p; } } void ResourceAppointmentsRowModel::slotResourceGroupRemoved( const ResourceGroup *group ) { Q_UNUSED(group); //debugPlan<name(); endRemoveRows(); } void ResourceAppointmentsRowModel::slotAppointmentToBeInserted( Resource *r, int row ) { Q_UNUSED(r); Q_UNUSED(row); // external appointments only, (Internal handled in slotProjectCalculated) } void ResourceAppointmentsRowModel::slotAppointmentInserted( Resource *r, Appointment *a ) { Q_UNUSED(a); beginResetModel(); // external appointments only, (Internal handled in slotProjectCalculated) Private *p = m_datamap.value( r ); if ( p ) { p->externalCached = false; } endResetModel(); } void ResourceAppointmentsRowModel::slotAppointmentToBeRemoved( Resource *r, int row ) { Q_UNUSED(row); // external appointments only, (Internal handled in slotProjectCalculated) Private *p = m_datamap.value( r ); if ( p ) { p->externalCached = false; } } void ResourceAppointmentsRowModel::slotAppointmentRemoved() { // external appointments only, (Internal handled in slotProjectCalculated) beginResetModel(); endResetModel(); } void ResourceAppointmentsRowModel::slotAppointmentChanged( Resource *r, Appointment *a ) { Q_UNUSED(r); Q_UNUSED(a); // external appointments only, (Internal handled in slotProjectCalculated) // will not happen atm } void ResourceAppointmentsRowModel::slotProjectCalculated( ScheduleManager *sm ) { if ( sm == m_manager ) { setScheduleManager( sm ); } } ResourceGroup *ResourceAppointmentsRowModel::parentGroup( const QModelIndex &index ) const { if ( m_project == 0 ) { return 0; } Private *ch = static_cast( index.internalPointer() ); if ( ch && ch->type == OT_Resource ) { return static_cast( ch->parent->ptr ); } return 0; } ResourceGroup *ResourceAppointmentsRowModel::resourcegroup( const QModelIndex &index ) const { if ( m_project == 0 ) { return 0; } Private *p = static_cast( index.internalPointer() ); if ( p && p->type == OT_ResourceGroup ) { return static_cast( p->ptr ); } return 0; } Resource *ResourceAppointmentsRowModel::parentResource( const QModelIndex &index ) const { if ( m_project == 0 ) { return 0; } Private *ch = static_cast( index.internalPointer() ); if ( ch && ( ch->type == OT_Appointment || ch->type == OT_External ) ) { return static_cast( ch->parent->ptr ); } return 0; } Resource *ResourceAppointmentsRowModel::resource( const QModelIndex &index ) const { if ( m_project == 0 ) { return 0; } Private *p = static_cast( index.internalPointer() ); if ( p && p->type == OT_Resource ) { return static_cast( p->ptr ); } return 0; } Appointment *ResourceAppointmentsRowModel::parentAppointment( const QModelIndex &index ) const { if ( m_project == 0 || m_manager == 0 ) { return 0; } Private *ch = static_cast( index.internalPointer() ); if ( ch && ch->type == OT_Interval ) { return static_cast( ch->parent->ptr ); } return 0; } Appointment *ResourceAppointmentsRowModel::appointment( const QModelIndex &index ) const { if ( m_project == 0 || m_manager == 0 || ! index.isValid() ) { return 0; } Private *p = static_cast( index.internalPointer() ); if ( p && ( p->type == OT_Appointment || p->type == OT_External ) ) { return static_cast( p->ptr ); } return 0; } AppointmentInterval *ResourceAppointmentsRowModel::interval( const QModelIndex &index ) const { if ( m_project == 0 || m_manager == 0 ) { return 0; } Private *p = static_cast( index.internalPointer() ); if ( p && p->type == OT_Interval ) { return &( p->interval ); } return 0; } Node *ResourceAppointmentsRowModel::node( const QModelIndex &idx ) const { Appointment *a = appointment( idx ); return ( a && a->node() ? a->node()->node() : 0 ); } //--------------------------------------------- ResourceAppointmentsGanttModel::ResourceAppointmentsGanttModel( QObject *parent ) : ResourceAppointmentsRowModel( parent ) { } ResourceAppointmentsGanttModel::~ResourceAppointmentsGanttModel() { } QVariant ResourceAppointmentsGanttModel::data( const ResourceGroup *g, int column, int role ) const { Q_UNUSED(column); switch( role ) { case KGantt::ItemTypeRole: return KGantt::TypeSummary; case KGantt::StartTimeRole: return g->startTime( id() ); case KGantt::EndTimeRole: return g->endTime( id() ); } return QVariant(); } QVariant ResourceAppointmentsGanttModel::data( const Resource *r, int column, int role ) const { Q_UNUSED(column); switch( role ) { case KGantt::ItemTypeRole: return KGantt::TypeSummary; case KGantt::StartTimeRole: return r->startTime( id() ); case KGantt::EndTimeRole: return r->endTime( id() ); } return QVariant(); } QVariant ResourceAppointmentsGanttModel::data( const Appointment *a, int column, int role ) const { Q_UNUSED(column); switch( role ) { case KGantt::ItemTypeRole: return KGantt::TypeMulti; case KGantt::StartTimeRole: return a->startTime(); case KGantt::EndTimeRole: return a->endTime(); } return QVariant(); } QVariant ResourceAppointmentsGanttModel::data( const AppointmentInterval *a, int column, int role ) const { Q_UNUSED(column); switch( role ) { case KGantt::ItemTypeRole: return KGantt::TypeTask; case KGantt::StartTimeRole: return a->startTime(); case KGantt::EndTimeRole: return a->endTime(); } return QVariant(); } QVariant ResourceAppointmentsGanttModel::data( const QModelIndex &index, int role ) const { //debugPlan< 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 KPTRESOURCEAPPOINTMENTSMODEL_H #define KPTRESOURCEAPPOINTMENTSMODEL_H #include "planmodels_export.h" #include #include "kpteffortcostmap.h" namespace KPlato { class Project; class Node; class Appointment; class AppointmentInterval; class Resource; class ResourceGroup; class ScheduleManager; class MainSchedule; class Calendar; /** The ResourceAppointmentsItemModel organizes appointments as hours booked per day (or week, month). It handles both internal and external appointments. */ class PLANMODELS_EXPORT ResourceAppointmentsItemModel : public ItemModelBase { Q_OBJECT public: explicit ResourceAppointmentsItemModel( QObject *parent = 0 ); ~ResourceAppointmentsItemModel(); virtual void setProject( Project *project ); long id() const; virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; QModelIndex index( const ResourceGroup *group ) const; QModelIndex index( const Resource *resource ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; QObject *object( const QModelIndex &index ) const; Node *node( const QModelIndex &index ) const; Appointment *appointment( const QModelIndex &index ) const; QModelIndex createAppointmentIndex( int row, int col, void *ptr ) const; Appointment *externalAppointment( const QModelIndex &index ) const; QModelIndex createExternalAppointmentIndex( int row, int col, void *ptr ) const; Resource *resource( const QModelIndex &index ) const; QModelIndex createResourceIndex( int row, int col, void *ptr ) const; ResourceGroup *resourcegroup( const QModelIndex &index ) const; QModelIndex createGroupIndex( int row, int col, void *ptr ) const; void refresh(); void refreshData(); QDate startDate() const; QDate endDate() const; Resource *parent( const Appointment *a ) const; int rowNumber( Resource *res, Appointment *a ) const; void setShowInternalAppointments( bool show ); bool showInternalAppointments() const { return m_showInternal; } void setShowExternalAppointments( bool show ); bool showExternalAppointments() const { return m_showExternal; } Q_SIGNALS: void refreshed(); - void appointmentInserted( Resource*, Appointment* ); + void appointmentInserted(KPlato::Resource*, KPlato::Appointment*); public Q_SLOTS: - virtual void setScheduleManager( ScheduleManager *sm ); + virtual void setScheduleManager(KPlato::ScheduleManager *sm); protected Q_SLOTS: - void slotResourceChanged( Resource* ); - void slotResourceGroupChanged( ResourceGroup * ); - void slotResourceGroupToBeInserted( const ResourceGroup *group, int row ); - void slotResourceGroupInserted( const ResourceGroup *group ); - void slotResourceGroupToBeRemoved( const ResourceGroup *group ); - void slotResourceGroupRemoved( const ResourceGroup *group ); - void slotResourceToBeInserted( const ResourceGroup *group, int row ); - void slotResourceInserted( const Resource *resource ); - void slotResourceToBeRemoved( const Resource *resource ); - void slotResourceRemoved( const Resource *resource ); - void slotCalendarChanged( Calendar* cal ); - void slotProjectCalculated( ScheduleManager *sm ); + void slotResourceChanged(KPlato::Resource*); + void slotResourceGroupChanged(KPlato::ResourceGroup *); + void slotResourceGroupToBeInserted(const KPlato::ResourceGroup *group, int row); + void slotResourceGroupInserted(const KPlato::ResourceGroup *group); + void slotResourceGroupToBeRemoved(const KPlato::ResourceGroup *group); + void slotResourceGroupRemoved(const KPlato::ResourceGroup *group); + void slotResourceToBeInserted(const KPlato::ResourceGroup *group, int row); + void slotResourceInserted(const KPlato::Resource *resource); + void slotResourceToBeRemoved(const KPlato::Resource *resource); + void slotResourceRemoved(const KPlato::Resource *resource); + void slotCalendarChanged(KPlato::Calendar* cal); + void slotProjectCalculated(KPlato::ScheduleManager *sm); - void slotAppointmentToBeInserted( Resource *r, int row ); - void slotAppointmentInserted( Resource*, Appointment* ); - void slotAppointmentToBeRemoved( Resource *r, int row ); + void slotAppointmentToBeInserted(KPlato::Resource *r, int row); + void slotAppointmentInserted(KPlato::Resource*, KPlato::Appointment*); + void slotAppointmentToBeRemoved(KPlato::Resource *r, int row); void slotAppointmentRemoved(); - void slotAppointmentChanged( Resource *r, Appointment *a ); + void slotAppointmentChanged(KPlato::Resource *r, KPlato::Appointment *a); protected: QVariant notUsed( const ResourceGroup *res, int role ) const; QVariant name( const Resource *res, int role ) const; QVariant name( const ResourceGroup *res, int role ) const; QVariant name( const Node *node, int role ) const; QVariant name( const Appointment *appointment, int role ) const; QVariant total( const Resource *res, int role ) const; QVariant total( const Resource *res, const QDate &date, int role ) const; QVariant total( const Appointment *a, int role ) const; QVariant assignment( const Appointment *a, const QDate &date, int role ) const; private: int m_columnCount; QMap m_effortMap; QMap m_externalEffortMap; QDate m_start; QDate m_end; ResourceGroup *m_group; // Used for sanity checks Resource *m_resource; // Used for sanity checks bool m_showInternal; bool m_showExternal; }; /** The ResourceAppointmentsRowModel returns each appointment interval as a new row. */ class PLANMODELS_EXPORT ResourceAppointmentsRowModel : public ItemModelBase { Q_OBJECT Q_ENUMS( Properties ) public: enum Properties { Name = 0, Type, StartTime, EndTime, Load }; const QMetaEnum columnMap() const; explicit ResourceAppointmentsRowModel( QObject *parent = 0 ); ~ResourceAppointmentsRowModel(); virtual void setProject( Project *project ); long id() const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; QModelIndex parent( const QModelIndex &idx = QModelIndex() ) const; QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; /// If @p index is a resource, return it's parent group, else 0 ResourceGroup *parentGroup( const QModelIndex &index ) const; /// If @p idx is a resource group, return it, else 0 ResourceGroup *resourcegroup( const QModelIndex &idx ) const; /// If @p idx is an appointment, return it's parent resource, else 0 Resource *parentResource( const QModelIndex &idx ) const; /// If @p idx is a resource, return it, else 0 Resource *resource( const QModelIndex &idx ) const; /// If @p idx is an appointment interval, return it's parent appointment, else 0 Appointment *parentAppointment( const QModelIndex &idx ) const; /// If @p idx is an appointment, return it, else 0 Appointment *appointment( const QModelIndex &idx ) const; /// If @p idx is an appointment interval, return it, else 0 AppointmentInterval *interval( const QModelIndex &idx ) const; QModelIndex index( ResourceGroup *g ) const; QModelIndex index( Resource *r ) const; QModelIndex index( Appointment *a ) const; /// If @p idx is an appointment, return the node, else 0 Node *node( const QModelIndex &idx ) const; /// Return the sortorder to be used for @p column virtual int sortRole( int column ) const; class Private; public Q_SLOTS: - virtual void setScheduleManager( ScheduleManager *sm ); + virtual void setScheduleManager(KPlato::ScheduleManager *sm); protected Q_SLOTS: - void slotResourceToBeInserted( const ResourceGroup *group, int row ); - void slotResourceInserted( const Resource *r ); - void slotResourceToBeRemoved( const Resource *r ); - void slotResourceRemoved( const Resource *resource ); - void slotResourceGroupToBeInserted( const ResourceGroup *group, int row ); - void slotResourceGroupInserted( const ResourceGroup* ); - void slotResourceGroupToBeRemoved( const ResourceGroup *group ); - void slotResourceGroupRemoved( const ResourceGroup *group ); - void slotAppointmentToBeInserted( Resource *r, int row ); - void slotAppointmentInserted( Resource *r, Appointment *a ); - void slotAppointmentToBeRemoved( Resource *r, int row ); + void slotResourceToBeInserted(const KPlato::ResourceGroup *group, int row ); + void slotResourceInserted(const KPlato::Resource *r ); + void slotResourceToBeRemoved(const KPlato::Resource *r ); + void slotResourceRemoved(const KPlato::Resource *resource ); + void slotResourceGroupToBeInserted(const KPlato::ResourceGroup *group, int row ); + void slotResourceGroupInserted(const KPlato::ResourceGroup* ); + void slotResourceGroupToBeRemoved(const KPlato::ResourceGroup *group ); + void slotResourceGroupRemoved(const KPlato::ResourceGroup *group ); + void slotAppointmentToBeInserted(KPlato::Resource *r, int row ); + void slotAppointmentInserted(KPlato::Resource *r, KPlato::Appointment *a ); + void slotAppointmentToBeRemoved(KPlato::Resource *r, int row ); void slotAppointmentRemoved(); - void slotAppointmentChanged( Resource *r, Appointment *a ); - void slotProjectCalculated( ScheduleManager *sm ); + void slotAppointmentChanged(KPlato::Resource *r, KPlato::Appointment *a ); + void slotProjectCalculated(KPlato::ScheduleManager *sm); protected: QModelIndex createGroupIndex( int row, int column, Project *project ); QModelIndex createResourceIndex( int row, int column, ResourceGroup *g ); QModelIndex createAppointmentIndex( int row, int column, Resource *r ); QModelIndex createIntervalIndex( int row, int column, Appointment *a ); protected: QMap m_datamap; MainSchedule *m_schedule; }; /** The ResourceAppointmentsGanttModel specialized for use by KGantt */ class PLANMODELS_EXPORT ResourceAppointmentsGanttModel : public ResourceAppointmentsRowModel { Q_OBJECT public: explicit ResourceAppointmentsGanttModel( QObject *parent = 0 ); ~ResourceAppointmentsGanttModel(); virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; protected: QVariant data( const ResourceGroup *g, int column, int role = Qt::DisplayRole ) const; QVariant data( const Resource *r, int column, int role = Qt::DisplayRole ) const; QVariant data( const Appointment *a, int column, int role = Qt::DisplayRole ) const; QVariant data( const AppointmentInterval *a, int column, int role = Qt::DisplayRole ) const; }; } //KPlato namespace #endif // KPTRESOURCEAPPOINTMENTSMODEL_H diff --git a/src/libs/models/kptresourcemodel.cpp b/src/libs/models/kptresourcemodel.cpp index ca555959..f6428b19 100644 --- a/src/libs/models/kptresourcemodel.cpp +++ b/src/libs/models/kptresourcemodel.cpp @@ -1,1839 +1,1839 @@ /* This file is part of the KDE project Copyright (C) 2007 Dag Andersen Copyright (C) 2011, 2012 Dag Andersen Copyright (C) 2016 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptresourcemodel.h" #include "kptlocale.h" #include "kptcommonstrings.h" #include "kptcommand.h" #include "kptitemmodelbase.h" #include "kptcalendar.h" #include "kptduration.h" #include "kptnode.h" #include "kptproject.h" #include "kpttask.h" #include "kptresource.h" #include "kptdatetime.h" #include "kptdebug.h" #include #include #include #include #include #include #include #ifdef PLAN_KCONTACTS_FOUND #include #include #endif namespace KPlato { //-------------------------------------- ResourceModel::ResourceModel( QObject *parent ) : QObject( parent ), m_project( 0 ) { } ResourceModel::~ResourceModel() { } const QMetaEnum ResourceModel::columnMap() const { return metaObject()->enumerator( metaObject()->indexOfEnumerator("Properties") ); } void ResourceModel::setProject( Project *project ) { m_project = project; } int ResourceModel::propertyCount() const { return columnMap().keyCount(); } QVariant ResourceModel::name( const Resource *res, int role ) const { //debugPlan<name()<<","<name(); case Qt::ToolTipRole: if (res->isShared()) { return xi18nc("@info:tooltip", "%1 is a Shared resource and can thus be shared with other projects", res->name()); } if ( res->autoAllocate() ) { return xi18nc( "@info:tooltip", "%1:This resource will be automatically allocated to new tasks", res->name() ); } return res->name(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Qt::DecorationRole: if ( res->isBaselined() ) { return koIcon("view-time-schedule-baselined"); } break; case Qt::CheckStateRole: return res->autoAllocate() ? Qt::Checked : Qt::Unchecked; default: break; } return QVariant(); } QVariant ResourceModel::name( const ResourceGroup *res, int role ) const { //debugPlan<name()<<","<name(); case Qt::ToolTipRole: if (!res->isShared()) { return res->name(); } return xi18nc("@info:tooltip", "%1 is a Shared resource group and can thus be shared with other projects", res->name()); break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::scope( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: return res->isShared() ? i18n("Shared") : i18n("Local"); case Qt::ToolTipRole: if (!res->isShared()) { return xi18nc("@info:tooltip", "%1 is a Local resource and can only be used in this project", res->name()); } return xi18nc("@info:tooltip", "%1 is a Shared resource and can thus be shared with other projects", res->name()); case Qt::EditRole: return res->isShared() ? "Shared" : "Local"; case Role::EnumList: return QStringList() << i18n("Local") << i18n("Shared"); case Role::EnumListValue: return res->isShared() ? 1 : 0; case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::scope( const ResourceGroup *res, int role ) const { switch ( role ) { case Qt::DisplayRole: return res->isShared() ? i18n("Shared") : i18n("Local"); case Qt::ToolTipRole: if (!res->isShared()) { return xi18nc("@info:tooltip", "%1 is a Local resource group and can only be used in this project", res->name()); } return xi18nc("@info:tooltip", "%1 is a Shared resource group and can thus be shared with other projects", res->name()); case Qt::EditRole: return res->isShared() ? "Shared" : "Local"; case Role::EnumList: return QStringList() << i18n("Local") << i18n("Shared"); case Role::EnumListValue: return res->isShared() ? 1 : 0; case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::type( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: return res->typeToString( true ); case Qt::EditRole: return res->typeToString( false ); case Role::EnumList: return res->typeToStringList( true ); case Role::EnumListValue: return (int)res->type(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::type( const ResourceGroup *res, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: return res->typeToString( true ); case Qt::EditRole: return res->typeToString( false ); case Role::EnumList: return res->typeToStringList( true ); case Role::EnumListValue: return (int)res->type(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::initials( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return res->initials(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::email( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return res->email(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::calendar( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: { if ( res->type() == Resource::Type_Team ) { return " "; } QString s = i18n( "None" ); Calendar *cal = res->calendar( true ); // don't check for default calendar if ( cal ) { s = cal->name(); } else if ( res->type() == Resource::Type_Work ) { // Do we get a default calendar cal = res->calendar(); if ( cal ) { s = i18nc( "Default (calendar name)", "Default (%1)", cal->name() ); } } return s; } case Qt::ToolTipRole: { if ( res->type() == Resource::Type_Team ) { return xi18nc( "@info:tooltip", "A team resource does not have a calendar" ); } QString s = xi18nc( "@info:tooltip", "No calendar" ); Calendar *cal = res->calendar( true ); // don't check for default calendar if ( cal ) { s = cal->name(); } else if ( res->type() == Resource::Type_Work ) { // Do we get a default calendar cal = res->calendar(); if ( cal ) { s = xi18nc( "@info:tooltip 1=calendar name", "Using default calendar: %1", cal->name() ); } } return s; } case Role::EnumList: { Calendar *cal = m_project->defaultCalendar(); QString s = i18n( "None" ); if ( cal && res->type() == Resource::Type_Work ) { s = i18nc( "Default (calendar name)", "Default (%1)", cal->name() ); } return QStringList() << s << m_project->calendarNames(); } case Qt::EditRole: case Role::EnumListValue: { Calendar *cal = res->calendar( true ); // don't check for default calendar return cal == 0 ? 0 : m_project->calendarNames().indexOf( cal->name() ) + 1; } case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::units( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return res->units(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::ToolTipRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::availableFrom( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: return QLocale().toString( res->availableFrom(), QLocale::ShortFormat ); case Qt::EditRole: return res->availableFrom(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::ToolTipRole: { if ( res->availableFrom().isValid() ) { return xi18nc( "infor:tooltip", "Available from: %1", QLocale().toString( res->availableFrom(), QLocale::LongFormat ) ); } return xi18nc( "infor:tooltip", "Available from project target start time: %1", QLocale().toString( m_project->constraintStartTime(), QLocale::LongFormat ) ); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::availableUntil( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: return QLocale().toString( res->availableUntil(), QLocale::ShortFormat ); case Qt::EditRole: return res->availableUntil(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::ToolTipRole: { if ( res->availableUntil().isValid() ) { return xi18nc( "infor:tooltip", "Available until: %1", QLocale().toString( res->availableUntil(), QLocale::LongFormat ) ); } return xi18nc( "infor:tooltip", "Available from project target finish time: %1", QLocale().toString( m_project->constraintEndTime(), QLocale::LongFormat ) ); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::normalRate( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: return m_project->locale()->formatMoney( res->normalRate() ); case Qt::EditRole: return res->normalRate(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::ToolTipRole: return i18n( "Cost per hour, normal time: %1", m_project->locale()->formatMoney( res->normalRate() ) ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::overtimeRate( const Resource *res, int role ) const { switch ( role ) { case Qt::DisplayRole: return m_project->locale()->formatMoney( res->overtimeRate() ); case Qt::EditRole: return res->overtimeRate(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::ToolTipRole: return i18n( "Cost per hour, overtime: %1", m_project->locale()->formatMoney( res->overtimeRate() ) ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::account( const Resource *resource, int role ) const { switch ( role ) { case Qt::DisplayRole: { Account *a = resource->account(); return a == 0 ? i18n( "None" ) : a->name(); } case Qt::ToolTipRole: { Account *a = resource->account(); return i18n( "Account: %1", (a == 0 ? i18n( "None" ) : a->name() ) ); } case Role::EnumListValue: case Qt::EditRole: { Account *a = resource->account(); return a == 0 ? 0 : ( m_project->accounts().costElements().indexOf( a->name() ) + 1 ); } case Role::EnumList: { QStringList lst; lst << i18n("None"); lst += m_project->accounts().costElements(); return lst; } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceModel::data( const Resource *resource, int property, int role ) const { if ( role == Role::ObjectType ) { return OT_Resource; } QVariant result; if ( resource == 0 ) { return result; } switch ( property ) { case ResourceName: result = name( resource, role ); break; case ResourceScope: result = scope( resource, role ); break; case ResourceType: result = type( resource, role ); break; case ResourceInitials: result = initials( resource, role ); break; case ResourceEmail: result = email( resource, role ); break; case ResourceCalendar: result = calendar( resource, role ); break; case ResourceLimit: result = units( resource, role ); break; case ResourceAvailableFrom: result = availableFrom( resource, role ); break; case ResourceAvailableUntil: result = availableUntil( resource, role ); break; case ResourceNormalRate: result = normalRate( resource, role ); break; case ResourceOvertimeRate: result = overtimeRate( resource, role ); break; case ResourceAccount: result = account( resource, role ); break; default: debugPlan<<"data: invalid display value: property="<name()<<","<(group); beginInsertRows( index( group ), row, row ); } void ResourceItemModel::slotResourceInserted( const Resource *resource ) { //debugPlan<name(); Q_ASSERT( resource->parentGroup() == m_group ); #ifdef NDEBUG Q_UNUSED(resource) #endif endInsertRows(); m_group = 0; emit layoutChanged(); //HACK to make the right view react! Bug in qt? } void ResourceItemModel::slotResourceToBeRemoved( const Resource *resource ) { //debugPlan<name(); Q_ASSERT( m_resource == 0 ); #ifdef NDEBUG Q_UNUSED(resource) #endif m_resource = const_cast(resource); int row = index( resource ).row(); beginRemoveRows( index( resource->parentGroup() ), row, row ); } void ResourceItemModel::slotResourceRemoved( const Resource *resource ) { //debugPlan<name(); Q_ASSERT( resource == m_resource ); #ifdef NDEBUG Q_UNUSED(resource) #endif endRemoveRows(); m_resource = 0; } void ResourceItemModel::slotResourceGroupToBeInserted( const ResourceGroup *group, int row ) { //debugPlan<name(); Q_ASSERT( m_group == 0 ); m_group = const_cast(group); beginInsertRows( QModelIndex(), row, row ); } void ResourceItemModel::slotResourceGroupInserted( const ResourceGroup *group ) { //debugPlan<name(); Q_ASSERT( group == m_group ); #ifdef NDEBUG Q_UNUSED(group) #endif endInsertRows(); m_group = 0; } void ResourceItemModel::slotResourceGroupToBeRemoved( const ResourceGroup *group ) { //debugPlan<name(); Q_ASSERT( m_group == 0 ); m_group = const_cast(group); int row = index( group ).row(); beginRemoveRows( QModelIndex(), row, row ); } void ResourceItemModel::slotResourceGroupRemoved( const ResourceGroup *group ) { //debugPlan<name(); Q_ASSERT( group == m_group ); #ifdef NDEBUG Q_UNUSED(group) #endif endRemoveRows(); m_group = 0; } void ResourceItemModel::slotLayoutChanged() { emit layoutAboutToBeChanged(); emit layoutChanged(); } void ResourceItemModel::setProject( Project *project ) { beginResetModel(); if ( m_project ) { disconnect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); disconnect( m_project, SIGNAL(localeChanged()), this, SLOT(slotLayoutChanged()) ); - disconnect( m_project, SIGNAL(resourceChanged(Resource*)), this, SLOT(slotResourceChanged(Resource*)) ); - disconnect( m_project, SIGNAL(resourceGroupChanged(ResourceGroup*)), this, SLOT(slotResourceGroupChanged(ResourceGroup*)) ); + disconnect( m_project, SIGNAL(resourceChanged(KPlato::Resource*)), this, SLOT(slotResourceChanged(KPlato::Resource*)) ); + disconnect( m_project, SIGNAL(resourceGroupChanged(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupChanged(KPlato::ResourceGroup*)) ); - disconnect( m_project, SIGNAL(resourceGroupToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const ResourceGroup*,int)) ); + disconnect( m_project, SIGNAL(resourceGroupToBeAdded(const KPlato::ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const KPlato::ResourceGroup*,int)) ); - disconnect( m_project, SIGNAL(resourceGroupToBeRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const ResourceGroup*)) ); + disconnect( m_project, SIGNAL(resourceGroupToBeRemoved(const KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const KPlato::ResourceGroup*)) ); - disconnect( m_project, SIGNAL(resourceToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const ResourceGroup*,int)) ); + disconnect( m_project, SIGNAL(resourceToBeAdded(const KPlato::ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const KPlato::ResourceGroup*,int)) ); - disconnect( m_project, SIGNAL(resourceToBeRemoved(const Resource*)), this, SLOT(slotResourceToBeRemoved(const Resource*)) ); + disconnect( m_project, SIGNAL(resourceToBeRemoved(const KPlato::Resource*)), this, SLOT(slotResourceToBeRemoved(const KPlato::Resource*)) ); - disconnect( m_project, SIGNAL(resourceGroupAdded(const ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const ResourceGroup*)) ); + disconnect( m_project, SIGNAL(resourceGroupAdded(const KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const KPlato::ResourceGroup*)) ); - disconnect( m_project, SIGNAL(resourceGroupRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const ResourceGroup*)) ); + disconnect( m_project, SIGNAL(resourceGroupRemoved(const KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const KPlato::ResourceGroup*)) ); - disconnect( m_project, SIGNAL(resourceAdded(const Resource*)), this, SLOT(slotResourceInserted(const Resource*)) ); + disconnect( m_project, SIGNAL(resourceAdded(const KPlato::Resource*)), this, SLOT(slotResourceInserted(const KPlato::Resource*)) ); - disconnect( m_project, SIGNAL(resourceRemoved(const Resource*)), this, SLOT(slotResourceRemoved(const Resource*)) ); + disconnect( m_project, SIGNAL(resourceRemoved(const KPlato::Resource*)), this, SLOT(slotResourceRemoved(const KPlato::Resource*)) ); - disconnect( m_project, SIGNAL(defaultCalendarChanged(Calendar*)), this, SLOT(slotCalendarChanged(Calendar*)) ); + disconnect( m_project, SIGNAL(defaultCalendarChanged(KPlato::Calendar*)), this, SLOT(slotCalendarChanged(KPlato::Calendar*)) ); } m_project = project; if ( m_project ) { connect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); connect( m_project, SIGNAL(localeChanged()), this, SLOT(slotLayoutChanged()) ); - connect( m_project, SIGNAL(resourceChanged(Resource*)), this, SLOT(slotResourceChanged(Resource*)) ); - connect( m_project, SIGNAL(resourceGroupChanged(ResourceGroup*)), this, SLOT(slotResourceGroupChanged(ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceChanged(KPlato::Resource*)), this, SLOT(slotResourceChanged(KPlato::Resource*)) ); + connect( m_project, SIGNAL(resourceGroupChanged(KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupChanged(KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceGroupToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const ResourceGroup*,int)) ); + connect( m_project, SIGNAL(resourceGroupToBeAdded(const KPlato::ResourceGroup*,int)), this, SLOT(slotResourceGroupToBeInserted(const KPlato::ResourceGroup*,int)) ); - connect( m_project, SIGNAL(resourceGroupToBeRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceGroupToBeRemoved(const KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupToBeRemoved(const KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceToBeAdded(const ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const ResourceGroup*,int)) ); + connect( m_project, SIGNAL(resourceToBeAdded(const KPlato::ResourceGroup*,int)), this, SLOT(slotResourceToBeInserted(const KPlato::ResourceGroup*,int)) ); - connect( m_project, SIGNAL(resourceToBeRemoved(const Resource*)), this, SLOT(slotResourceToBeRemoved(const Resource*)) ); + connect( m_project, SIGNAL(resourceToBeRemoved(const KPlato::Resource*)), this, SLOT(slotResourceToBeRemoved(const KPlato::Resource*)) ); - connect( m_project, SIGNAL(resourceGroupAdded(const ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceGroupAdded(const KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupInserted(const KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceGroupRemoved(const ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const ResourceGroup*)) ); + connect( m_project, SIGNAL(resourceGroupRemoved(const KPlato::ResourceGroup*)), this, SLOT(slotResourceGroupRemoved(const KPlato::ResourceGroup*)) ); - connect( m_project, SIGNAL(resourceAdded(const Resource*)), this, SLOT(slotResourceInserted(const Resource*)) ); + connect( m_project, SIGNAL(resourceAdded(const KPlato::Resource*)), this, SLOT(slotResourceInserted(const KPlato::Resource*)) ); - connect( m_project, SIGNAL(resourceRemoved(const Resource*)), this, SLOT(slotResourceRemoved(const Resource*)) ); + connect( m_project, SIGNAL(resourceRemoved(const KPlato::Resource*)), this, SLOT(slotResourceRemoved(const KPlato::Resource*)) ); - connect( m_project, SIGNAL(defaultCalendarChanged(Calendar*)), this, SLOT(slotCalendarChanged(Calendar*)) ); + connect( m_project, SIGNAL(defaultCalendarChanged(KPlato::Calendar*)), this, SLOT(slotCalendarChanged(KPlato::Calendar*)) ); } m_model.setProject( m_project ); endResetModel(); } Qt::ItemFlags ResourceItemModel::flags( const QModelIndex &index ) const { Qt::ItemFlags flags = ItemModelBase::flags( index ); if ( !m_readWrite ) { //debugPlan<<"read only"<( object ( index ) ); if ( r != 0 ) { flags |= Qt::ItemIsDragEnabled; if (r->isShared()) { flags &= ~Qt::ItemIsEditable; if (index.column() == ResourceModel::ResourceName) { flags |= Qt::ItemIsUserCheckable; } return flags; } switch ( index.column() ) { case ResourceModel::ResourceName: flags |= Qt::ItemIsEditable | Qt::ItemIsUserCheckable; break; case ResourceModel::ResourceScope: flags &= ~Qt::ItemIsEditable; break; case ResourceModel::ResourceType: if ( ! r->isBaselined() ) { flags |= Qt::ItemIsEditable; } break; case ResourceModel::ResourceAccount: if ( ! r->isBaselined() ) { flags |= Qt::ItemIsEditable; } break; case ResourceModel::ResourceNormalRate: if ( ! r->isBaselined() ) { flags |= Qt::ItemIsEditable; } break; case ResourceModel::ResourceOvertimeRate: if ( ! r->isBaselined() ) { flags |= Qt::ItemIsEditable; } break; default: flags |= Qt::ItemIsEditable; } //debugPlan<<"resource"<( object( index ) ); if ( g ) { if (g->isShared()) { flags &= ~Qt::ItemIsEditable; return flags; } flags |= Qt::ItemIsDropEnabled; switch ( index.column() ) { case ResourceModel::ResourceName: flags |= Qt::ItemIsEditable; break; case ResourceModel::ResourceType: flags |= Qt::ItemIsEditable; break; default: flags &= ~Qt::ItemIsEditable; } //debugPlan<<"group"<parentGroup() ) { // only resources have parent int row = m_project->indexOf( r->parentGroup() ); return createIndex( row, 0, r->parentGroup() ); } return QModelIndex(); } QModelIndex ResourceItemModel::index( int row, int column, const QModelIndex &parent ) const { if ( m_project == 0 || column < 0 || column >= columnCount() || row < 0 ) { return QModelIndex(); } if ( ! parent.isValid() ) { if ( row < m_project->numResourceGroups() ) { return createIndex( row, column, m_project->resourceGroupAt( row ) ); } return QModelIndex(); } ResourceGroup *g = group( parent ); if ( g ) { if ( row < g->numResources() ) { return createIndex( row, column, g->resourceAt( row ) ); } return QModelIndex(); } return QModelIndex(); } QModelIndex ResourceItemModel::index( const Resource *resource, int column ) const { if ( m_project == 0 || resource == 0 ) { return QModelIndex(); } Resource *r = const_cast(resource); int row = -1; ResourceGroup *par = r->parentGroup(); if ( par ) { row = par->indexOf( r ); return createIndex( row, column, r ); } return QModelIndex(); } QModelIndex ResourceItemModel::index( const ResourceGroup *group, int column ) const { if ( m_project == 0 || group == 0 ) { return QModelIndex(); } ResourceGroup *g = const_cast(group); int row = m_project->indexOf( g ); return createIndex( row, column, g ); } int ResourceItemModel::columnCount( const QModelIndex &/*parent*/ ) const { return m_model.propertyCount(); } int ResourceItemModel::rowCount( const QModelIndex &parent ) const { if ( m_project == 0 ) { return 0; } if ( ! parent.isValid() ) { return m_project->numResourceGroups(); } ResourceGroup *g = group( parent ); if ( g ) { return g->numResources(); } return 0; } QVariant ResourceItemModel::name( const ResourceGroup *res, int role ) const { //debugPlan<name()<<","<name(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } bool ResourceItemModel::setName( Resource *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toString() == res->name() ) { return false; } emit executeCommand( new ModifyResourceNameCmd( res, value.toString(), kundo2_i18n( "Modify resource name" ) ) ); return true; case Qt::CheckStateRole: emit executeCommand( new ModifyResourceAutoAllocateCmd( res, value.toBool(), kundo2_i18n( "Modify resource auto allocate" ) ) ); return true; } return false; } bool ResourceItemModel::setName( ResourceGroup *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toString() == res->name() ) { return false; } emit executeCommand( new ModifyResourceGroupNameCmd( res, value.toString(), kundo2_i18n( "Modify resourcegroup name" ) ) ); return true; } return false; } QVariant ResourceItemModel::type( const ResourceGroup *res, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: return res->typeToString( true ); case Qt::EditRole: return res->typeToString( false ); case Role::EnumList: return res->typeToStringList( true ); case Role::EnumListValue: return (int)res->type(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } bool ResourceItemModel::setType( Resource *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { Resource::Type v; QStringList lst = res->typeToStringList( false ); if ( lst.contains( value.toString() ) ) { v = static_cast( lst.indexOf( value.toString() ) ); } else { v = static_cast( value.toInt() ); } if ( v == res->type() ) { return false; } emit executeCommand( new ModifyResourceTypeCmd( res, v, kundo2_i18n( "Modify resource type" ) ) ); return true; } } return false; } bool ResourceItemModel::setType( ResourceGroup *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { ResourceGroup::Type v; QStringList lst = res->typeToStringList( false ); if ( lst.contains( value.toString() ) ) { v = static_cast( lst.indexOf( value.toString() ) ); } else { v = static_cast( value.toInt() ); } if ( v == res->type() ) { return false; } emit executeCommand( new ModifyResourceGroupTypeCmd( res, v, kundo2_i18n( "Modify resourcegroup type" ) ) ); return true; } } return false; } bool ResourceItemModel::setInitials( Resource *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toString() == res->initials() ) { return false; } emit executeCommand( new ModifyResourceInitialsCmd( res, value.toString(), kundo2_i18n( "Modify resource initials" ) ) ); return true; } return false; } bool ResourceItemModel::setEmail( Resource *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toString() == res->email() ) { return false; } emit executeCommand( new ModifyResourceEmailCmd( res, value.toString(), kundo2_i18n( "Modify resource email" ) ) ); return true; } return false; } bool ResourceItemModel::setCalendar( Resource *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { Calendar *c = 0; if ( value.toInt() > 0 ) { QStringList lst = m_model.calendar( res, Role::EnumList ).toStringList(); if ( value.toInt() < lst.count() ) { c = m_project->calendarByName( lst.at( value.toInt() ) ); } } if ( c == res->calendar( true ) ) { return false; } emit executeCommand( new ModifyResourceCalendarCmd( res, c, kundo2_i18n( "Modify resource calendar" ) ) ); return true; } } return false; } bool ResourceItemModel::setUnits( Resource *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toInt() == res->units() ) { return false; } emit executeCommand( new ModifyResourceUnitsCmd( res, value.toInt(), kundo2_i18n( "Modify resource available units" ) ) ); return true; } return false; } bool ResourceItemModel::setAvailableFrom( Resource *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toDateTime() == res->availableFrom() ) { return false; } emit executeCommand( new ModifyResourceAvailableFromCmd( res, value.toDateTime(), kundo2_i18n( "Modify resource available from" ) ) ); return true; } return false; } bool ResourceItemModel::setAvailableUntil( Resource *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toDateTime() == res->availableUntil() ) { return false; } emit executeCommand( new ModifyResourceAvailableUntilCmd( res, value.toDateTime(), kundo2_i18n( "Modify resource available until" ) ) ); return true; } return false; } bool ResourceItemModel::setNormalRate( Resource *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toDouble() == res->normalRate() ) { return false; } emit executeCommand( new ModifyResourceNormalRateCmd( res, value.toDouble(), kundo2_i18n( "Modify resource normal rate" ) ) ); return true; } return false; } bool ResourceItemModel::setOvertimeRate( Resource *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: if ( value.toDouble() == res->overtimeRate() ) { return false; } emit executeCommand( new ModifyResourceOvertimeRateCmd( res, value.toDouble(), kundo2_i18n( "Modify resource overtime rate" ) ) ); return true; } return false; } bool ResourceItemModel::setAccount( Resource *res, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { Account *a = 0; if ( value.type() == QVariant::Int ) { QStringList lst = m_model.account( res, Role::EnumList ).toStringList(); if ( value.toInt() >= lst.count() ) { return false; } a = m_project->accounts().findAccount( lst.at( value.toInt() ) ); } else if ( value.type() == QVariant::String ) { a = m_project->accounts().findAccount( value.toString() ); } Account *old = res->account(); if ( old != a ) { emit executeCommand( new ResourceModifyAccountCmd( *res, old, a, kundo2_i18n( "Modify resource account" ) ) ); return true; } } default: break; } return false; } QVariant ResourceItemModel::notUsed( const ResourceGroup *, int role ) const { switch ( role ) { case Qt::DisplayRole: return QString(" "); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::EditRole: case Qt::ToolTipRole: case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ResourceItemModel::data( const QModelIndex &index, int role ) const { QVariant result; QObject *obj = object( index ); if ( obj == 0 ) { return QVariant(); } if ( role == Qt::TextAlignmentRole ) { // use same alignment as in header (headers always horizontal) return headerData( index.column(), Qt::Horizontal, role ); } Resource *r = qobject_cast( obj ); if ( r ) { result = m_model.data( r, index.column(), role ); } else { ResourceGroup *g = qobject_cast( obj ); if ( g ) { result = m_model.data( g, index.column(), role ); } } return result; } bool ResourceItemModel::setData( const QModelIndex &index, const QVariant &value, int role ) { if ( ! index.isValid() ) { return ItemModelBase::setData( index, value, role ); } if (role != Qt::EditRole && role != Qt::CheckStateRole) { return false; } if ((flags( index ) & (Qt::ItemIsEditable | Qt::ItemIsUserCheckable)) == 0) { return false; } QObject *obj = object( index ); Resource *r = qobject_cast( obj ); if ( r ) { switch (index.column()) { case ResourceModel::ResourceName: return setName( r, value, role ); case ResourceModel::ResourceScope: return false; // Not editable case ResourceModel::ResourceType: return setType( r, value, role ); case ResourceModel::ResourceInitials: return setInitials( r, value, role ); case ResourceModel::ResourceEmail: return setEmail( r, value, role ); case ResourceModel::ResourceCalendar: return setCalendar( r, value, role ); case ResourceModel::ResourceLimit: return setUnits( r, value, role ); case ResourceModel::ResourceAvailableFrom: return setAvailableFrom( r, value, role ); case ResourceModel::ResourceAvailableUntil: return setAvailableUntil( r, value, role ); case ResourceModel::ResourceNormalRate: return setNormalRate( r, value, role ); case ResourceModel::ResourceOvertimeRate: return setOvertimeRate( r, value, role ); case ResourceModel::ResourceAccount: return setAccount( r, value, role ); default: qWarning("data: invalid display value column %d", index.column()); return false; } } else { ResourceGroup *g = qobject_cast( obj ); if ( g ) { switch (index.column()) { case ResourceModel::ResourceName: return setName( g, value, role ); case ResourceModel::ResourceScope: return false; // Not editable case ResourceModel::ResourceType: return setType( g, value, role ); default: qWarning("data: invalid display value column %d", index.column()); return false; } } } return false; } QVariant ResourceItemModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( orientation == Qt::Horizontal ) { if ( role == Qt::DisplayRole || role == Qt::TextAlignmentRole ) { return m_model.headerData( section, role ); } } if ( role == Qt::ToolTipRole ) { return m_model.headerData( section, role ); } return ItemModelBase::headerData(section, orientation, role); } QAbstractItemDelegate *ResourceItemModel::createDelegate( int col, QWidget *parent ) const { switch ( col ) { case ResourceModel::ResourceType: return new EnumDelegate( parent ); case ResourceModel::ResourceCalendar: return new EnumDelegate( parent ); case ResourceModel::ResourceAvailableFrom: return new DateTimeCalendarDelegate( parent ); case ResourceModel::ResourceAvailableUntil: return new DateTimeCalendarDelegate( parent ); case ResourceModel::ResourceAccount: return new EnumDelegate( parent ); default: break; } return 0; } QObject *ResourceItemModel::object( const QModelIndex &index ) const { QObject *o = 0; if ( index.isValid() ) { Q_ASSERT( m_project ); //debugPlan<<(void*)index.internalPointer()<resourceGroups()<resourceList(); Q_ASSERT(m_project->resourceGroups().contains(static_cast(index.internalPointer())) || m_project->resourceList().contains(static_cast(index.internalPointer()))); o = static_cast( index.internalPointer() ); Q_ASSERT( o ); } return o; } ResourceGroup *ResourceItemModel::group( const QModelIndex &index ) const { return qobject_cast( object( index ) ); } Resource *ResourceItemModel::resource( const QModelIndex &index ) const { return qobject_cast( object( index ) ); } void ResourceItemModel::slotCalendarChanged( Calendar* ) { foreach ( Resource *r, m_project->resourceList() ) { if ( r->calendar( true ) == 0 ) { slotResourceChanged( r ); } } } void ResourceItemModel::slotResourceChanged( Resource *res ) { ResourceGroup *g = res->parentGroup(); if ( g ) { int row = g->indexOf( res ); emit dataChanged( createIndex( row, 0, res ), createIndex( row, columnCount() - 1, res ) ); return; } } void ResourceItemModel::slotResourceGroupChanged( ResourceGroup *res ) { Project *p = res->project(); if ( p ) { int row = p->resourceGroups().indexOf( res ); emit dataChanged( createIndex( row, 0, res ), createIndex( row, columnCount() - 1, res ) ); } } Qt::DropActions ResourceItemModel::supportedDropActions() const { return Qt::MoveAction | Qt::CopyAction; } bool ResourceItemModel::dropAllowed( const QModelIndex &index, int dropIndicatorPosition, const QMimeData *data ) { if ( data->hasFormat( "application/x-vnd.kde.plan.resourceitemmodel.internal" ) ) { QByteArray encodedData = data->data( "application/x-vnd.kde.plan.resourceitemmodel.internal" ); QDataStream stream(&encodedData, QIODevice::ReadOnly); int i = 0; foreach ( Resource *r, resourceList( stream ) ) { if (r->isShared()) { return false; } } } //debugPlan<( object( index ) ); // Allow only on group default: break; } return false; } QStringList ResourceItemModel::mimeTypes() const { return QStringList() #ifdef PLAN_KDEPIMLIBS_FOUND << "text/x-vcard" << "text/directory" << "text/uri-list" #endif << "application/x-vnd.kde.plan.resourceitemmodel.internal"; } void ResourceItemModel::slotDataArrived( KIO::Job *job, const QByteArray &data ) { if ( m_dropDataMap.contains( job ) ) { m_dropDataMap[ job ].data += data; } } void ResourceItemModel::slotJobFinished( KJob *job ) { if ( job->error() || ! m_dropDataMap.contains( job ) ) { debugPlan<<(job->error() ? "Job error":"Error: no such job"); } else if ( QMimeDatabase().mimeTypeForData( m_dropDataMap[ job ].data ).inherits(QStringLiteral("text/x-vcard") ) ) { ResourceGroup *g = 0; if ( m_dropDataMap[ job ].parent.isValid() ) { g = qobject_cast( object( m_dropDataMap[ job ].parent ) ); } else { g = qobject_cast( object( index( m_dropDataMap[ job ].row, m_dropDataMap[ job ].column, m_dropDataMap[ job ].parent ) ) ); } if ( g == 0 ) { debugPlan<<"No group"<findResource( uid ) ) { r->setId( uid ); } r->setName( lst[a].formattedName() ); r->setEmail( lst[a].preferredEmail() ); m->addCommand( new AddResourceCmd( group, r ) ); } if ( m->isEmpty() ) { delete m; return false; } emit executeCommand( m ); return true; #else Q_UNUSED(group); Q_UNUSED(data); return false; #endif } bool ResourceItemModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) { debugPlan< 0) { return false; } ResourceGroup *g = 0; if ( parent.isValid() ) { g = qobject_cast( object( parent ) ); } else { g = qobject_cast( object( index( row, column, parent ) ) ); } if ( g == 0 ) { debugPlan<<"No group"<formats()<name(); if ( data->hasFormat( "application/x-vnd.kde.plan.resourceitemmodel.internal" ) ) { debugPlan<data( "application/x-vnd.kde.plan.resourceitemmodel.internal" ); QDataStream stream(&encodedData, QIODevice::ReadOnly); int i = 0; foreach ( Resource *r, resourceList( stream ) ) { if ( r->parentGroup() == g ) { continue; } if ( m == 0 ) m = new MacroCommand( KUndo2MagicString() ); m->addCommand( new MoveResourceCmd( g, r ) ); ++i; } if ( m ) { KUndo2MagicString msg = kundo2_i18np( "Move resource", "Move %1 resources", i ); MacroCommand *c = new MacroCommand( msg ); c->addCommand( m ); emit executeCommand( c ); } return true; } if ( action == Qt::CopyAction ) { MacroCommand *m = 0; QByteArray encodedData = data->data( "application/x-vnd.kde.plan.resourceitemmodel.internal" ); QDataStream stream(&encodedData, QIODevice::ReadOnly); int i = 0; foreach ( Resource *r, resourceList( stream ) ) { Resource *nr = new Resource( r ); if ( m == 0 ) m = new MacroCommand( KUndo2MagicString() ); m->addCommand( new AddResourceCmd( g, nr ) ); ++i; } if ( m ) { KUndo2MagicString msg = kundo2_i18np( "Copy resource", "Copy %1 resources", i ); MacroCommand *c = new MacroCommand( msg ); c->addCommand( m ); emit executeCommand( c ); } return true; } return true; } if ( data->hasFormat( "text/x-vcard" ) || data->hasFormat( "text/directory" ) ) { if ( action != Qt::CopyAction ) { return false; } QString f = data->hasFormat( "text/x-vcard" ) ? "text/x-vcard" : "text/directory"; return createResources( g, data->data( f ) ); } if ( data->hasFormat( "text/uri-list" ) ) { const QList urls = data->urls(); if ( urls.isEmpty() ) { return false; } bool result = false; foreach ( const QUrl &url, urls ) { if ( url.scheme() != "akonadi" ) { debugPlan<setSide( KIO::StatJob::SourceSide ); const bool isUrlReadable = statJob->exec(); if (! isUrlReadable ) { debugPlan<start(); result = true; } return result; } return false; } QList ResourceItemModel::resourceList( QDataStream &stream ) { QList lst; while (!stream.atEnd()) { QString id; stream >> id; Resource *r = m_project->findResource( id ); if ( r ) { lst << r; } } debugPlan< rows; foreach (const QModelIndex &index, indexes) { if ( index.isValid() && !rows.contains( index.row() ) ) { //debugPlan<( object( index ) ); if ( r ) { rows << index.row(); stream << r->id(); } else if ( ::qobject_cast( object( index ) ) ) { rows.clear(); break; } } } if ( rows.isEmpty() ) { delete m; return 0; } m->setData("application/x-vnd.kde.plan.resourceitemmodel.internal", encodedData); return m; } QModelIndex ResourceItemModel::insertGroup( ResourceGroup *g ) { //debugPlan; emit executeCommand( new AddResourceGroupCmd( m_project, g, kundo2_i18n( "Add resource group" ) ) ); int row = m_project->resourceGroups().indexOf( g ); if ( row != -1 ) { return createIndex( row, 0, g ); } return QModelIndex(); } QModelIndex ResourceItemModel::insertResource( ResourceGroup *g, Resource *r, Resource * /*after*/ ) { //debugPlan; emit executeCommand( new AddResourceCmd( g, r, kundo2_i18n( "Add resource" ) ) ); int row = g->indexOf( r ); if ( row != -1 ) { return createIndex( row, 0, r ); } return QModelIndex(); } int ResourceItemModel::sortRole( int column ) const { switch ( column ) { case ResourceModel::ResourceAvailableFrom: case ResourceModel::ResourceAvailableUntil: return Qt::EditRole; default: break; } return Qt::DisplayRole; } //------------------- ResourceItemSFModel::ResourceItemSFModel( QObject *parent ) : QSortFilterProxyModel( parent ) { setDynamicSortFilter( true ); setSourceModel( new ResourceItemModel( this ) ); } void ResourceItemSFModel::setProject( Project *project ) { static_cast( sourceModel() )->setProject( project ); } Resource *ResourceItemSFModel::resource( const QModelIndex &idx ) const { return static_cast( sourceModel() )->resource( mapToSource( idx ) ); } QModelIndex ResourceItemSFModel::index( Resource *r ) const { return mapFromSource( static_cast( sourceModel() )->index( r ) ); } Qt::ItemFlags ResourceItemSFModel::flags( const QModelIndex & index ) const { Qt::ItemFlags f = QSortFilterProxyModel::flags( index ); if ( index.isValid() && ! parent( index ).isValid() ) { // group, not selectable f &= ~Qt::ItemIsSelectable; } return f; } void ResourceItemSFModel::addFilteredResource( const Resource *r ) { if ( ! m_filteredResources.contains( r ) ) { m_filteredResources << r; } } bool ResourceItemSFModel::filterAcceptsRow( int source_row, const QModelIndex & source_parent ) const { //TODO make this general filter ResourceItemModel *m = static_cast( sourceModel() ); if ( m->index( source_row, ResourceModel::ResourceType, source_parent ).data( Role::EnumListValue ).toInt() == ResourceGroup::Type_Work ) { return false; } QModelIndex idx = m->index( source_row, 0, source_parent ); return ! m_filteredResources.contains( m->resource( idx ) ); } //----------------------- AllocatedResourceItemModel::AllocatedResourceItemModel( QObject *parent ) : QSortFilterProxyModel( parent ), m_task( 0 ) { setDynamicSortFilter( true ); setSourceModel( new ResourceItemModel( this ) ); } int AllocatedResourceItemModel::columnCount( const QModelIndex &idx ) const { Q_UNUSED(idx); return 2; } Project *AllocatedResourceItemModel::project() const { return static_cast( sourceModel() )->project(); } void AllocatedResourceItemModel::setProject( Project *project ) { debugPlan<project()<<"="<project(); if ( p ) { - disconnect(p, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*))); + disconnect(p, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*))); } static_cast( sourceModel() )->setProject( project ); if ( project ) { - connect(project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*))); + connect(project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*))); } debugPlan<rowCount(); } void AllocatedResourceItemModel::reset() { beginResetModel(); endResetModel(); emit expandAll(); emit resizeColumnToContents( 0 ); } void AllocatedResourceItemModel::slotNodeChanged( Node *n ) { debugPlan<<(n==m_task)<name(); if ( n != m_task ) { return; } reset(); } Task *AllocatedResourceItemModel::task() const { return m_task; } void AllocatedResourceItemModel::setTask( Task *task ) { debugPlan<name():""); m_task = task; reset(); debugPlan<rowCount(); } QObject* AllocatedResourceItemModel::object(const QModelIndex& idx) const { return static_cast( sourceModel() )->object( mapToSource( idx ) ); } Resource *AllocatedResourceItemModel::resource( const QModelIndex &idx ) const { return qobject_cast( object( idx ) ); } QModelIndex AllocatedResourceItemModel::index( Resource *r ) const { return mapFromSource( static_cast( sourceModel() )->index( r ) ); } Qt::ItemFlags AllocatedResourceItemModel::flags( const QModelIndex & index ) const { Qt::ItemFlags f = QSortFilterProxyModel::flags( index ); f &= ~Qt::ItemIsUserCheckable; return f; } QVariant AllocatedResourceItemModel::headerData(int section, Qt::Orientation orientation, int role) const { if ( section == 1 ) { if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) { return xi18nc( "@title:column", "Allocation" ); } return QVariant(); } return QSortFilterProxyModel::headerData( section, orientation, role ); } QVariant AllocatedResourceItemModel::allocation( const Resource *res, int role ) const { ResourceRequest *rr = m_task->requests().find( res ); ResourceGroupRequest *gr = m_task->requests().find( res->parentGroup() ); if ( rr == 0 || gr == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: { case Qt::EditRole: // xgettext: no-c-format return i18nc( "%", "%1%",rr->units() ); } case Qt::ToolTipRole: { if ( rr->units() == 0 ) { return xi18nc( "@info:tooltip", "Not allocated" ); } return xi18nc( "@info:tooltip", "%1 allocated out of %2 available", gr->count(), res->parentGroup()->numResources() ); } default: break; } return QVariant(); } QVariant AllocatedResourceItemModel::allocation( const ResourceGroup *res, int role ) const { ResourceGroupRequest *gr = m_task->requests().find( res ); if ( gr == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return QString( "%1 (%2)" ).arg( gr->units() ).arg( gr->count() ); case Qt::ToolTipRole: { QString s1 = i18ncp( "@info:tooltip", "%1 resource requested for dynamic allocation", "%1 resources requested for dynamic allocation", gr->units() ); QString s2 = i18ncp( "@info:tooltip", "%1 resource allocated", "%1 resources allocated", gr->count() ); return xi18nc( "@info:tooltip", "%1%2", s1, s2 ); } case Qt::WhatsThisRole: { return xi18nc( "@info:whatsthis", "Group allocations" "You can allocate a number of resources from a group and let" " the scheduler select from the available resources at the time of scheduling." " These dynamically allocated resources will be in addition to any resource you have allocated specifically." ); } case Role::Minimum: { return 0; } case Role::Maximum: { return res->numResources() - gr->units(); } default: break; } return QVariant(); } QVariant AllocatedResourceItemModel::data(const QModelIndex& idx, int role) const { if ( m_task == 0 || role == Qt::CheckStateRole || role == Qt::DecorationRole ) { return QVariant(); } if ( idx.column() == 1 ) { switch ( role ) { case Qt::TextAlignmentRole: return Qt::AlignLeft; default: { QObject *o = object( idx ); Resource *r = qobject_cast( o ); if ( r ) { return allocation( r, role ); } ResourceGroup *g = qobject_cast( o ); if ( g ) { return allocation( g, role ); } break; } return QVariant(); } } return QSortFilterProxyModel::data( idx, role ); } bool AllocatedResourceItemModel::filterAcceptsRow( int source_row, const QModelIndex & source_parent ) const { if ( m_task == 0 ) { return false; } QModelIndex idx = sourceModel()->index( source_row, 0, source_parent ); if ( ! idx.isValid() ) { return false; } bool result = false; const ResourceRequestCollection &req = m_task->requests(); if ( source_parent.isValid() ) { const Resource *r = static_cast( sourceModel() )->resource( idx ); result = (bool) req.find( r ); } else { const ResourceGroup *g = static_cast( sourceModel() )->group( idx ); ResourceGroupRequest *gr = req.find( g ); result = (bool) gr && ( gr->units() > 0 || gr->count() > 0 ); } debugPlan< 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 KPTRESOURCEMODEL_H #define KPTRESOURCEMODEL_H #include "planmodels_export.h" #include #include #include class QByteArray; namespace KIO { class Job; } class KJob; namespace KPlato { class Project; class Resource; class ResourceGroup; class Calendar; class Task; class Node; class PLANMODELS_EXPORT ResourceModel : public QObject { Q_OBJECT Q_ENUMS( Properties ) public: explicit ResourceModel( QObject *parent = 0 ); ~ResourceModel(); enum Properties { ResourceName = 0, ResourceScope, ResourceType, ResourceInitials, ResourceEmail, ResourceCalendar, ResourceLimit, ResourceAvailableFrom, ResourceAvailableUntil, ResourceNormalRate, ResourceOvertimeRate, ResourceAccount }; const QMetaEnum columnMap() const; void setProject( Project *project ); int propertyCount() const; QVariant data( const Resource *resource, int property, int role = Qt::DisplayRole ) const; QVariant data( const ResourceGroup *group, int property, int role = Qt::DisplayRole ) const; static QVariant headerData( int section, int role = Qt::DisplayRole ); QVariant name( const Resource *res, int role ) const; QVariant scope( const Resource *res, int role ) const; QVariant type( const Resource *res, int role ) const; QVariant initials( const Resource *res, int role ) const; QVariant email( const Resource *res, int role ) const; QVariant calendar( const Resource *res, int role ) const; QVariant units( const Resource *res, int role ) const; QVariant availableFrom( const Resource *res, int role ) const; QVariant availableUntil( const Resource *res, int role ) const; QVariant normalRate( const Resource *res, int role ) const; QVariant overtimeRate( const Resource *res, int role ) const; QVariant account( const Resource *res, int role ) const; QVariant name( const ResourceGroup *res, int role ) const; QVariant scope( const ResourceGroup *res, int role ) const; QVariant type( const ResourceGroup *res, int role ) const; private: Project *m_project; }; class PLANMODELS_EXPORT ResourceItemModel : public ItemModelBase { Q_OBJECT public: explicit ResourceItemModel( QObject *parent = 0 ); ~ResourceItemModel(); virtual const QMetaEnum columnMap() const { return m_model.columnMap(); } virtual void setProject( Project *project ); virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; QModelIndex index( const ResourceGroup *group, int column = 0 ) const; QModelIndex index( const Resource *resource, int column = 0 ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; virtual QStringList mimeTypes () const; virtual Qt::DropActions supportedDropActions() const; virtual bool dropAllowed( const QModelIndex &index, int dropIndicatorPosition, const QMimeData *data ); virtual bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ); QMimeData *mimeData( const QModelIndexList & indexes ) const; QAbstractItemDelegate *createDelegate( int col, QWidget *parent ) const; QObject *object( const QModelIndex &index ) const; ResourceGroup *group( const QModelIndex &index ) const; Resource *resource( const QModelIndex &index ) const; QModelIndex insertGroup( ResourceGroup *g ); QModelIndex insertResource( ResourceGroup *g, Resource *r, Resource *after = 0 ); virtual int sortRole( int column ) const; protected Q_SLOTS: - void slotResourceChanged( Resource* ); - void slotResourceGroupChanged( ResourceGroup * ); - void slotResourceGroupToBeInserted( const ResourceGroup *group, int row ); - void slotResourceGroupInserted( const ResourceGroup *group ); - void slotResourceGroupToBeRemoved( const ResourceGroup *group ); - void slotResourceGroupRemoved( const ResourceGroup *group ); - void slotResourceToBeInserted( const ResourceGroup *group, int row ); - void slotResourceInserted( const Resource *resource ); - void slotResourceToBeRemoved( const Resource *resource ); - void slotResourceRemoved( const Resource *resource ); - void slotCalendarChanged( Calendar* cal ); + void slotResourceChanged(KPlato::Resource*); + void slotResourceGroupChanged(KPlato::ResourceGroup *); + void slotResourceGroupToBeInserted(const KPlato::ResourceGroup *group, int row); + void slotResourceGroupInserted(const KPlato::ResourceGroup *group); + void slotResourceGroupToBeRemoved(const KPlato::ResourceGroup *group); + void slotResourceGroupRemoved(const KPlato::ResourceGroup *group); + void slotResourceToBeInserted(const KPlato::ResourceGroup *group, int row); + void slotResourceInserted(const KPlato::Resource *resource); + void slotResourceToBeRemoved(const KPlato::Resource *resource); + void slotResourceRemoved(const KPlato::Resource *resource); + void slotCalendarChanged(KPlato::Calendar* cal); void slotLayoutChanged(); void slotDataArrived( KIO::Job *job, const QByteArray &data ); void slotJobFinished( KJob *job ); protected: QVariant notUsed( const ResourceGroup *res, int role ) const; QVariant name( const ResourceGroup *res, int role ) const; bool setName( Resource *res, const QVariant &value, int role ); bool setName( ResourceGroup *res, const QVariant &value, int role ); QVariant type( const ResourceGroup *res, int role ) const; bool setType( Resource *res, const QVariant &value, int role ); bool setType( ResourceGroup *res, const QVariant &value, int role ); bool setInitials( Resource *res, const QVariant &value, int role ); bool setEmail( Resource *res, const QVariant &value, int role ); bool setCalendar( Resource *res, const QVariant &value, int role ); bool setUnits( Resource *res, const QVariant &value, int role ); bool setAvailableFrom( Resource *res, const QVariant &value, int role ); bool setAvailableUntil( Resource *res, const QVariant &value, int role ); bool setNormalRate( Resource *res, const QVariant &value, int role ); bool setOvertimeRate( Resource *res, const QVariant &value, int role ); bool setAccount( Resource *res, const QVariant &value, int role ); QList resourceList( QDataStream &stream ); bool createResources( ResourceGroup *group, const QByteArray &data ); private: ResourceGroup *m_group; // Used for sanity checks Resource *m_resource; // Used for sanity checks ResourceModel m_model; struct DropData { Qt::DropAction action; int row; int column; QModelIndex parent; QByteArray data; } m_dropData; QMap m_dropDataMap; }; class PLANMODELS_EXPORT ResourceItemSFModel : public QSortFilterProxyModel { Q_OBJECT public: explicit ResourceItemSFModel(QObject *parent = 0); void setProject( Project *project ); Resource *resource( const QModelIndex &index ) const; using QAbstractProxyModel::index; QModelIndex index( Resource *r ) const; Qt::ItemFlags flags( const QModelIndex & index ) const; void addFilteredResource( const Resource *r ); protected: bool filterAcceptsRow( int source_row, const QModelIndex & source_parent ) const; QList m_filteredResources; }; class PLANMODELS_EXPORT AllocatedResourceItemModel : public QSortFilterProxyModel { Q_OBJECT public: explicit AllocatedResourceItemModel(QObject *parent = 0); int columnCount( const QModelIndex &idx ) const; Project *project() const; Task *task() const; Resource *resource( const QModelIndex &index ) const; using QAbstractProxyModel::index; QModelIndex index( Resource *r ) const; Qt::ItemFlags flags( const QModelIndex & index ) const; QVariant headerData( int section, Qt::Orientation orientation, int role ) const; QVariant data( const QModelIndex &idx, int role ) const; public Q_SLOTS: - void setProject( Project *project ); - void setTask( Task *task ); + void setProject(KPlato::Project *project); + void setTask(KPlato::Task *task); Q_SIGNALS: void expandAll(); void resizeColumnToContents( int ); protected Q_SLOTS: - void slotNodeChanged( Node *n ); + void slotNodeChanged(KPlato::Node *n); protected: bool filterAcceptsRow( int source_row, const QModelIndex & source_parent ) const; void reset(); QObject *object( const QModelIndex &idx ) const; QVariant allocation( const Resource *r, int role ) const; QVariant allocation( const ResourceGroup *g, int role ) const; Task *m_task; }; } //KPlato namespace #endif diff --git a/src/libs/models/kptschedulemodel.cpp b/src/libs/models/kptschedulemodel.cpp index be398f4c..4aa71500 100644 --- a/src/libs/models/kptschedulemodel.cpp +++ b/src/libs/models/kptschedulemodel.cpp @@ -1,1264 +1,1264 @@ /* This file is part of the KDE project Copyright (C) 2007, 2012 Dag Andersen danders@get2net> Copyright (C) 2016 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kptschedulemodel.h" #include "kptglobal.h" #include "kptcommonstrings.h" #include "kptcommand.h" #include "kptitemmodelbase.h" #include "kptduration.h" #include "kptnode.h" #include "kptproject.h" #include "kpttask.h" #include "kptresource.h" #include "kptschedule.h" #include "kptdatetime.h" #include "kptschedulerplugin.h" #include "kptdebug.h" #include #include #include #include #include namespace KPlato { //-------------------------------------- ScheduleModel::ScheduleModel( QObject *parent ) : QObject( parent ) { } ScheduleModel::~ScheduleModel() { } const QMetaEnum ScheduleModel::columnMap() const { return metaObject()->enumerator( metaObject()->indexOfEnumerator("Properties") ); } int ScheduleModel::propertyCount() const { return columnMap().keyCount(); } //-------------------------------------- ScheduleItemModel::ScheduleItemModel( QObject *parent ) : ItemModelBase( parent ), m_manager( 0 ), m_flat( false ) { } ScheduleItemModel::~ScheduleItemModel() { } void ScheduleItemModel::slotScheduleManagerToBeInserted( const ScheduleManager *parent, int row ) { //debugPlan<(parent); beginInsertRows( index( parent ), row, row ); } void ScheduleItemModel::slotScheduleManagerInserted( const ScheduleManager *manager ) { //debugPlan<name(); if ( m_flat ) { int row = m_project->allScheduleManagers().indexOf( const_cast( manager ) ); Q_ASSERT( row >= 0 ); beginInsertRows( QModelIndex(), row, row ); m_managerlist.insert( row, const_cast( manager ) ); endInsertRows(); emit scheduleManagerAdded( const_cast( manager ) ); return; } Q_ASSERT( manager->parentManager() == m_manager ); endInsertRows(); m_manager = 0; emit scheduleManagerAdded( const_cast( manager ) ); } void ScheduleItemModel::slotScheduleManagerToBeRemoved( const ScheduleManager *manager ) { //debugPlan<name(); if ( m_flat ) { int row = m_managerlist.indexOf( const_cast( manager ) ); beginRemoveRows( QModelIndex(), row, row ); m_managerlist.removeAt( row ); return; } Q_ASSERT( m_manager == 0 ); m_manager = const_cast(manager); QModelIndex i = index( manager ); int row = i.row(); beginRemoveRows( parent( i ), row, row ); } void ScheduleItemModel::slotScheduleManagerRemoved( const ScheduleManager *manager ) { //debugPlan<name(); if ( m_flat ) { endRemoveRows(); return; } Q_ASSERT( manager == m_manager ); Q_UNUSED( manager ); endRemoveRows(); m_manager = 0; } void ScheduleItemModel::slotScheduleManagerToBeMoved( const ScheduleManager *manager ) { //debugPlan<name()<<"from"<<(manager->parentManager()?manager->parentManager()->name():"project"); slotScheduleManagerToBeRemoved( manager ); } void ScheduleItemModel::slotScheduleManagerMoved( const ScheduleManager *manager, int index ) { //debugPlan<name()<<"to"<parentManager()<parentManager(), index ); slotScheduleManagerInserted( manager ); } void ScheduleItemModel::slotScheduleToBeInserted( const ScheduleManager *, int /*row*/ ) { } void ScheduleItemModel::slotScheduleInserted( const MainSchedule * ) { } void ScheduleItemModel::slotScheduleToBeRemoved( const MainSchedule * ) { } void ScheduleItemModel::slotScheduleRemoved( const MainSchedule * ) { } void ScheduleItemModel::setProject( Project *project ) { beginResetModel(); if ( m_project ) { disconnect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - disconnect( m_project, SIGNAL(scheduleManagerChanged(ScheduleManager*)), this, SLOT(slotManagerChanged(ScheduleManager*)) ); + disconnect(m_project, SIGNAL(scheduleManagerChanged(KPlato::ScheduleManager*)), this, SLOT(slotManagerChanged(KPlato::ScheduleManager*))); - disconnect( m_project, SIGNAL(scheduleManagerToBeAdded(const ScheduleManager*,int)), this, SLOT(slotScheduleManagerToBeInserted(const ScheduleManager*,int)) ); + disconnect(m_project, SIGNAL(scheduleManagerToBeAdded(const KPlato::ScheduleManager*,int)), this, SLOT(slotScheduleManagerToBeInserted(const KPlato::ScheduleManager*,int))); - disconnect( m_project, SIGNAL(scheduleManagerToBeRemoved(const ScheduleManager*)), this, SLOT(slotScheduleManagerToBeRemoved(const ScheduleManager*)) ); + disconnect(m_project, SIGNAL(scheduleManagerToBeRemoved(const KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerToBeRemoved(const KPlato::ScheduleManager*))); - disconnect( m_project, SIGNAL(scheduleManagerAdded(const ScheduleManager*)), this, SLOT(slotScheduleManagerInserted(const ScheduleManager*)) ); + disconnect(m_project, SIGNAL(scheduleManagerAdded(const KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerInserted(const KPlato::ScheduleManager*))); - disconnect( m_project, SIGNAL(scheduleManagerRemoved(const ScheduleManager*)), this, SLOT(slotScheduleManagerRemoved(const ScheduleManager*)) ); + disconnect(m_project, SIGNAL(scheduleManagerRemoved(const KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerRemoved(const KPlato::ScheduleManager*))); - disconnect( m_project, SIGNAL(scheduleManagerToBeMoved(const ScheduleManager*)), this, SLOT(slotScheduleManagerToBeMoved(const ScheduleManager*)) ); + disconnect(m_project, SIGNAL(scheduleManagerToBeMoved(const KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerToBeMoved(const KPlato::ScheduleManager*))); - disconnect( m_project, SIGNAL(scheduleManagerMoved(const ScheduleManager*,int)), this, SLOT(slotScheduleManagerMoved(const ScheduleManager*,int)) ); + disconnect(m_project, SIGNAL(scheduleManagerMoved(const KPlato::ScheduleManager*,int)), this, SLOT(slotScheduleManagerMoved(const KPlato::ScheduleManager*,int))); - disconnect( m_project, SIGNAL(scheduleChanged(MainSchedule*)), this, SLOT(slotScheduleChanged(MainSchedule*)) ); + disconnect(m_project, SIGNAL(scheduleChanged(KPlato::MainSchedule*)), this, SLOT(slotScheduleChanged(KPlato::MainSchedule*))); - disconnect( m_project, SIGNAL(scheduleToBeAdded(const ScheduleManager*,int)), this, SLOT(slotScheduleToBeInserted(const ScheduleManager*,int)) ); + disconnect(m_project, SIGNAL(scheduleToBeAdded(const KPlato::ScheduleManager*,int)), this, SLOT(slotScheduleToBeInserted(const KPlato::ScheduleManager*,int))); - disconnect( m_project, SIGNAL(scheduleToBeRemoved(const MainSchedule*)), this, SLOT(slotScheduleToBeRemoved(const MainSchedule*)) ); + disconnect(m_project, SIGNAL(scheduleToBeRemoved(const KPlato::MainSchedule*)), this, SLOT(slotScheduleToBeRemoved(const KPlato::MainSchedule*))); - disconnect( m_project, SIGNAL(scheduleAdded(const MainSchedule*)), this, SLOT(slotScheduleInserted(const MainSchedule*)) ); + disconnect(m_project, SIGNAL(scheduleAdded(const KPlato::MainSchedule*)), this, SLOT(slotScheduleInserted(const KPlato::MainSchedule*))); - disconnect( m_project, SIGNAL(scheduleRemoved(const MainSchedule*)), this, SLOT(slotScheduleRemoved(const MainSchedule*)) ); + disconnect(m_project, SIGNAL(scheduleRemoved(const KPlato::MainSchedule*)), this, SLOT(slotScheduleRemoved(const KPlato::MainSchedule*))); } m_project = project; if ( m_project ) { connect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); - connect( m_project, SIGNAL(scheduleManagerChanged(ScheduleManager*)), this, SLOT(slotManagerChanged(ScheduleManager*)) ); + connect(m_project, SIGNAL(scheduleManagerChanged(KPlato::ScheduleManager*)), this, SLOT(slotManagerChanged(KPlato::ScheduleManager*))); - connect( m_project, SIGNAL(scheduleManagerToBeAdded(const ScheduleManager*,int)), this, SLOT(slotScheduleManagerToBeInserted(const ScheduleManager*,int)) ); + connect(m_project, SIGNAL(scheduleManagerToBeAdded(const KPlato::ScheduleManager*,int)), this, SLOT(slotScheduleManagerToBeInserted(const KPlato::ScheduleManager*,int))); - connect( m_project, SIGNAL(scheduleManagerToBeRemoved(const ScheduleManager*)), this, SLOT(slotScheduleManagerToBeRemoved(const ScheduleManager*)) ); + connect(m_project, SIGNAL(scheduleManagerToBeRemoved(const KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerToBeRemoved(const KPlato::ScheduleManager*))); - connect( m_project, SIGNAL(scheduleManagerAdded(const ScheduleManager*)), this, SLOT(slotScheduleManagerInserted(const ScheduleManager*)) ); + connect(m_project, SIGNAL(scheduleManagerAdded(const KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerInserted(const KPlato::ScheduleManager*))); - connect( m_project, SIGNAL(scheduleManagerRemoved(const ScheduleManager*)), this, SLOT(slotScheduleManagerRemoved(const ScheduleManager*)) ); + connect(m_project, SIGNAL(scheduleManagerRemoved(const KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerRemoved(const KPlato::ScheduleManager*))); - connect( m_project, SIGNAL(scheduleManagerToBeMoved(const ScheduleManager*)), this, SLOT(slotScheduleManagerToBeMoved(const ScheduleManager*)) ); + connect(m_project, SIGNAL(scheduleManagerToBeMoved(const KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerToBeMoved(const KPlato::ScheduleManager*))); - connect( m_project, SIGNAL(scheduleManagerMoved(const ScheduleManager*,int)), this, SLOT(slotScheduleManagerMoved(const ScheduleManager*,int)) ); + connect(m_project, SIGNAL(scheduleManagerMoved(const KPlato::ScheduleManager*,int)), this, SLOT(slotScheduleManagerMoved(const KPlato::ScheduleManager*,int))); - connect( m_project, SIGNAL(scheduleChanged(MainSchedule*)), this, SLOT(slotScheduleChanged(MainSchedule*)) ); + connect(m_project, SIGNAL(scheduleChanged(KPlato::MainSchedule*)), this, SLOT(slotScheduleChanged(KPlato::MainSchedule*))); - connect( m_project, SIGNAL(scheduleToBeAdded(const ScheduleManager*,int)), this, SLOT(slotScheduleToBeInserted(const ScheduleManager*,int)) ); + connect(m_project, SIGNAL(scheduleToBeAdded(const KPlato::ScheduleManager*,int)), this, SLOT(slotScheduleToBeInserted(const KPlato::ScheduleManager*,int))); - connect( m_project, SIGNAL(scheduleToBeRemoved(const MainSchedule*)), this, SLOT(slotScheduleToBeRemoved(const MainSchedule*)) ); + connect(m_project, SIGNAL(scheduleToBeRemoved(const KPlato::MainSchedule*)), this, SLOT(slotScheduleToBeRemoved(const KPlato::MainSchedule*))); - connect( m_project, SIGNAL(scheduleAdded(const MainSchedule*)), this, SLOT(slotScheduleInserted(const MainSchedule*)) ); + connect(m_project, SIGNAL(scheduleAdded(const KPlato::MainSchedule*)), this, SLOT(slotScheduleInserted(const KPlato::MainSchedule*))); - connect( m_project, SIGNAL(scheduleRemoved(const MainSchedule*)), this, SLOT(slotScheduleRemoved(const MainSchedule*)) ); + connect(m_project, SIGNAL(scheduleRemoved(const KPlato::MainSchedule*)), this, SLOT(slotScheduleRemoved(const KPlato::MainSchedule*))); } setFlat( m_flat ); // update m_managerlist endResetModel(); } void ScheduleItemModel::slotManagerChanged( ScheduleManager *sch ) { if ( m_flat ) { int row = m_managerlist.indexOf( sch ); emit dataChanged( createIndex( row, 0, sch ), createIndex( row, columnCount() - 1, sch ) ); return; } int r = sch->parentManager() ? sch->parentManager()->indexOf( sch ) : m_project->indexOf( sch ); //debugPlan<schedulerPlugin(); if ( pl == 0 ) { return flags; } int capabilities = pl->capabilities(); flags &= ~Qt::ItemIsEditable; if ( sm && ! sm->isBaselined() ) { switch ( index.column() ) { case ScheduleModel::ScheduleState: break; case ScheduleModel::ScheduleOverbooking: if ( capabilities & SchedulerPlugin::AllowOverbooking && capabilities & SchedulerPlugin::AvoidOverbooking ) { flags |= Qt::ItemIsEditable; } break; case ScheduleModel::ScheduleDirection: if ( sm->parentManager() == 0 && capabilities & SchedulerPlugin::ScheduleForward && capabilities & SchedulerPlugin::ScheduleBackward) { flags |= Qt::ItemIsEditable; } break; case ScheduleModel::SchedulePlannedStart: break; case ScheduleModel::SchedulePlannedFinish: break; case ScheduleModel::ScheduleGranularity: if ( ! sm->supportedGranularities().isEmpty() ) { flags |= Qt::ItemIsEditable; } break; default: flags |= Qt::ItemIsEditable; break; } return flags; } return flags; } QModelIndex ScheduleItemModel::parent( const QModelIndex &inx ) const { if ( !inx.isValid() || m_project == 0 || m_flat ) { return QModelIndex(); } //debugPlan<parentManager() ); } QModelIndex ScheduleItemModel::index( int row, int column, const QModelIndex &parent ) const { //debugPlan<= columnCount() || row < 0 || row >= rowCount( parent ) ) { //debugPlan<children().value( row ) ); } return createIndex( row, column, m_project->scheduleManagers().value( row ) ); } QModelIndex ScheduleItemModel::index( const ScheduleManager *manager ) const { if ( m_project == 0 || manager == 0 ) { return QModelIndex(); } if ( m_flat ) { return createIndex( m_managerlist.indexOf( const_cast( manager ) ), 0, const_cast(manager) ); } if ( manager->parentManager() == 0 ) { return createIndex( m_project->indexOf( manager ), 0, const_cast(manager) ); } return createIndex( manager->parentManager()->indexOf( manager ), 0, const_cast(manager) ); } int ScheduleItemModel::columnCount( const QModelIndex &/*parent*/ ) const { return m_model.propertyCount(); } int ScheduleItemModel::rowCount( const QModelIndex &parent ) const { if ( m_project == 0 ) { return 0; } if ( m_flat ) { return m_managerlist.count(); } if ( !parent.isValid() ) { return m_project->numScheduleManagers(); } ScheduleManager *sm = manager( parent ); if ( sm ) { //debugPlan<name()<<","<children().count(); return sm->children().count(); } return 0; } QVariant ScheduleItemModel::name( const QModelIndex &index, int role ) const { ScheduleManager *sm = manager ( index ); if ( sm == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return sm->name(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Qt::DecorationRole: if ( sm->isBaselined() ) { return koIcon("view-time-schedule-baselined"); } return QVariant(); default: break; } return QVariant(); } bool ScheduleItemModel::setName( const QModelIndex &index, const QVariant &value, int role ) { ScheduleManager *sm = manager ( index ); if ( sm == 0 ) { return false; } switch ( role ) { case Qt::EditRole: emit executeCommand( new ModifyScheduleManagerNameCmd( *sm, value.toString(), kundo2_i18n( "Modify schedule name" ) ) ); return true; } return false; } QVariant ScheduleItemModel::state( const QModelIndex &index, int role ) const { ScheduleManager *sm = manager ( index ); if ( sm == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: { if ( sm->progress() > 0 ) { return sm->progress(); } QStringList l = sm->state(); if ( l.isEmpty() ) { return ""; } return l.first(); } case Qt::EditRole: { QStringList l = sm->state(); if ( l.isEmpty() ) { return ""; } return l.first(); } case Qt::ToolTipRole: return sm->state().join(", "); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::Maximum: return sm->maxProgress(); case Role::Minimum: return 0; } return QVariant(); } bool ScheduleItemModel::setState( const QModelIndex &, const QVariant &, int role ) { switch ( role ) { case Qt::EditRole: return false; } return false; } QVariant ScheduleItemModel::allowOverbooking( const QModelIndex &index, int role ) const { ScheduleManager *sm = manager ( index ); if ( sm == 0 ) { return QVariant(); } SchedulerPlugin *pl = sm->schedulerPlugin(); if ( pl == 0 ) { return QVariant(); } int capabilities = pl->capabilities(); switch ( role ) { case Qt::EditRole: return sm->allowOverbooking(); case Qt::DisplayRole: if ( capabilities & SchedulerPlugin::AllowOverbooking && capabilities & SchedulerPlugin::AvoidOverbooking ) { return sm->allowOverbooking() ? i18n( "Allow" ) : i18n( "Avoid" ); } if ( capabilities & SchedulerPlugin::AllowOverbooking ) { return sm->allowOverbooking() ? i18n( "Allow" ) : i18n( "(Avoid)" ); } if ( capabilities & SchedulerPlugin::AvoidOverbooking ) { return sm->allowOverbooking() ? i18n( "(Allow)" ) : i18n( "Avoid" ); } break; case Qt::ToolTipRole: if ( capabilities & SchedulerPlugin::AllowOverbooking && capabilities & SchedulerPlugin::AvoidOverbooking ) { return sm->allowOverbooking() ? xi18nc( "@info:tooltip", "Allow overbooking resources" ) : xi18nc( "@info:tooltip", "Avoid overbooking resources" ); } if ( capabilities & SchedulerPlugin::AllowOverbooking ) { return sm->allowOverbooking() ? xi18nc( "@info:tooltip", "Allow overbooking of resources" ) : xi18nc( "@info:tooltip 1=scheduler name", "%1 always allows overbooking of resources", pl->name() ); } if ( capabilities & SchedulerPlugin::AvoidOverbooking ) { return sm->allowOverbooking() ? xi18nc( "@info:tooltip 1=scheduler name", "%1 always avoids overbooking of resources", pl->name() ) : xi18nc( "@info:tooltip", "Avoid overbooking resources" ); } break; case Role::EnumList: return QStringList() << xi18nc( "@label:listbox", "Avoid" ) << xi18nc( "@label:listbox", "Allow" ); case Role::EnumListValue: return sm->allowOverbooking() ? 1 : 0; case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } bool ScheduleItemModel::setAllowOverbooking( const QModelIndex &index, const QVariant &value, int role ) { ScheduleManager *sm = manager ( index ); if ( sm == 0 ) { return false; } switch ( role ) { case Qt::EditRole: emit executeCommand( new ModifyScheduleManagerAllowOverbookingCmd( *sm, value.toBool(), kundo2_i18n( "Modify allow overbooking" ) ) ); return true; } return false; } QVariant ScheduleItemModel::usePert( const QModelIndex &index, int role ) const { ScheduleManager *sm = manager ( index ); if ( sm == 0 ) { return QVariant(); } switch ( role ) { case Qt::EditRole: return sm->usePert(); case Qt::DisplayRole: return sm->usePert() ? i18n( "PERT" ) : i18n( "None" ); case Qt::ToolTipRole: return sm->usePert() ? xi18nc( "@info:tooltip", "Use PERT distribution to calculate expected estimate for the tasks" ) : xi18nc( "@info:tooltip", "Use the tasks expected estimate directly" ); case Role::EnumList: return QStringList() << xi18nc( "@label:listbox", "None" ) << xi18nc( "@label:listbox", "PERT" ); case Role::EnumListValue: return sm->usePert() ? 1 : 0; case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } bool ScheduleItemModel::setUsePert( const QModelIndex &index, const QVariant &value, int role ) { ScheduleManager *sm = manager ( index ); if ( sm == 0 ) { return false; } switch ( role ) { case Qt::EditRole: emit executeCommand( new ModifyScheduleManagerDistributionCmd( *sm, value.toBool(), kundo2_i18n( "Modify scheduling distribution" ) ) ); emit slotManagerChanged( static_cast( sm ) ); return true; } return false; } QVariant ScheduleItemModel::projectStart( const QModelIndex &index, int role ) const { if ( m_project == 0 ) { return QVariant(); } ScheduleManager *sm = manager ( index ); if ( sm == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: if ( sm->isScheduled() ) { return QLocale().toString( sm->expected()->start(), QLocale::ShortFormat ); } break; case Qt::EditRole: if ( sm->isScheduled() ) { return sm->expected()->start(); } break; case Qt::ToolTipRole: if ( sm->isScheduled() ) { return xi18nc( "@info:tooltip", "Planned start: %1Target start: %2", QLocale().toString( sm->expected()->start(), QLocale::ShortFormat ), QLocale().toString( m_project->constraintStartTime(), QLocale::ShortFormat ) ); } else { return xi18nc( "@info:tooltip", "Target start: %1", QLocale().toString( m_project->constraintStartTime(), QLocale::ShortFormat ) ); } break; case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ScheduleItemModel::projectEnd( const QModelIndex &index, int role ) const { if ( m_project == 0 ) { return QVariant(); } ScheduleManager *sm = manager ( index ); if ( sm == 0 ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: if ( sm->isScheduled() ) { return QLocale().toString( sm->expected()->end(), QLocale::ShortFormat ); } break; case Qt::EditRole: if ( sm->isScheduled() ) { return sm->expected()->end(); } break; case Qt::ToolTipRole: if ( sm->isScheduled() ) { return xi18nc( "@info:tooltip", "Planned finish: %1Target finish: %2", QLocale().toString( sm->expected()->end(), QLocale::ShortFormat ), QLocale().toString( m_project->constraintEndTime(), QLocale::ShortFormat ) ); } else { return xi18nc( "@info:tooltip", "Target finish: %1", QLocale().toString( m_project->constraintEndTime(), QLocale::ShortFormat ) ); } break; case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ScheduleItemModel::schedulingDirection( const QModelIndex &index, int role ) const { ScheduleManager *sm = manager ( index ); if ( sm == 0 ) { return QVariant(); } SchedulerPlugin *pl = sm->schedulerPlugin(); if ( pl == 0 ) { return QVariant(); } int capabilities = pl->capabilities(); switch ( role ) { case Qt::EditRole: return sm->schedulingDirection(); case Qt::DisplayRole: if ( capabilities & SchedulerPlugin::ScheduleForward && capabilities & SchedulerPlugin::ScheduleBackward ) { return sm->schedulingDirection() ? i18n( "Backwards" ) : i18n( "Forward" ); } if ( capabilities & SchedulerPlugin::ScheduleForward ) { return sm->schedulingDirection() ? i18n( "(Backwards)" ) : i18n( "Forward" ); } if ( capabilities & SchedulerPlugin::ScheduleBackward ) { return sm->schedulingDirection() ? i18n( "Backwards" ) : i18n( "(Forward)" ); } break; case Qt::ToolTipRole: if ( capabilities & SchedulerPlugin::ScheduleForward && capabilities & SchedulerPlugin::ScheduleBackward ) { return sm->schedulingDirection() ? xi18nc( "@info:tooltip", "Schedule project from target end time" ) : xi18nc( "@info:tooltip", "Schedule project from target start time" ); } if ( capabilities & SchedulerPlugin::ScheduleForward ) { return sm->schedulingDirection() ? xi18nc( "@info:tooltip 1=scheduler name", "%1 always schedules from target start time", pl->name() ) : xi18nc( "@info:tooltip", "Schedule project from target start time" ); } if ( capabilities & SchedulerPlugin::ScheduleBackward ) { return sm->schedulingDirection() ? xi18nc( "@info:tooltip", "Schedule project from target end time" ) : xi18nc( "@info:tooltip 1=scheduler name", "%1 always schedules from target end time", pl->name() ); } break; case Role::EnumList: return QStringList() << xi18nc( "@label:listbox", "Forward" ) << xi18nc( "@label:listbox", "Backwards" ); case Role::EnumListValue: return sm->schedulingDirection() ? 1 : 0; case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } bool ScheduleItemModel::setSchedulingDirection( const QModelIndex &index, const QVariant &value, int role ) { ScheduleManager *sm = manager ( index ); if ( sm == 0 ) { return false; } switch ( role ) { case Qt::EditRole: emit executeCommand(new ModifyScheduleManagerSchedulingDirectionCmd( *sm, value.toBool(), kundo2_i18n( "Modify scheduling direction" ) ) ); emit slotManagerChanged( static_cast( sm ) ); return true; } return false; } QVariant ScheduleItemModel::scheduler( const QModelIndex &index, int role ) const { ScheduleManager *sm = manager( index ); if ( sm == 0 ) { return QVariant(); } SchedulerPlugin *pl = sm->schedulerPlugin(); if ( pl ) { switch ( role ) { case Qt::EditRole: return sm->schedulerPluginId(); case Qt::DisplayRole: return pl ? pl->name() : i18n( "Unknown" ); case Qt::ToolTipRole: return pl ? pl->comment() : QString(); case Role::EnumList: return sm->schedulerPluginNames(); case Role::EnumListValue: return sm->schedulerPluginIndex(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: return QVariant(); case Qt::WhatsThisRole: { QString s = pl->description(); return s.isEmpty() ? QVariant() : QVariant( s ); } } } return QVariant(); } bool ScheduleItemModel::setScheduler( const QModelIndex &index, const QVariant &value, int role ) { ScheduleManager *sm = manager( index ); if ( sm != 0 ) { switch ( role ) { case Qt::EditRole: { emit executeCommand( new ModifyScheduleManagerSchedulerCmd( *sm, value.toInt(), kundo2_i18n( "Modify scheduler" ) ) ); return true; } } } return false; } QVariant ScheduleItemModel::isScheduled( const QModelIndex &index, int role ) const { ScheduleManager *sm = manager( index ); if ( sm == 0 ) { return QVariant(); } switch ( role ) { case Qt::EditRole: return sm->isScheduled(); case Qt::DisplayRole: return sm->isScheduled() ? i18n( "Scheduled" ) : i18n( "Not scheduled" ); case Qt::ToolTipRole: break; case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant ScheduleItemModel::granularity(const QModelIndex &index, int role) const { ScheduleManager *sm = manager( index ); if ( sm == 0 ) { return QVariant(); } switch ( role ) { case Qt::EditRole: case Role::EnumListValue: return qMin( sm->granularity(), sm->supportedGranularities().count() - 1 ); case Qt::DisplayRole: { QList lst = sm->supportedGranularities(); if ( lst.isEmpty() ) { return i18nc( "Scheduling granularity not supported", "None" ); } int idx = sm->granularity(); qulonglong g = idx < lst.count() ? lst[ idx ] : lst.last(); return KFormat().formatDuration( g ); } case Qt::ToolTipRole: { QList lst = sm->supportedGranularities(); if ( lst.isEmpty() ) { return xi18nc( "@info:tooltip", "Scheduling granularity not supported" ); } int idx = sm->granularity(); qulonglong g = idx < lst.count() ? lst[ idx ] : lst.last(); return xi18nc( "@info:tooltip", "Selected scheduling granularity: %1", KFormat().formatDuration( g ) ); } case Qt::TextAlignmentRole: return Qt::AlignRight; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::EnumList: { QStringList sl; KFormat format; foreach ( long unsigned int v, sm->supportedGranularities() ) { sl << format.formatDuration( v ); } return sl; } } return QVariant(); } bool ScheduleItemModel::setGranularity( const QModelIndex &index, const QVariant &value, int role ) { ScheduleManager *sm = manager( index ); if ( sm != 0 ) { switch ( role ) { case Qt::EditRole: { emit executeCommand( new ModifyScheduleManagerSchedulingGranularityCmd( *sm, value.toInt(), kundo2_i18n( "Modify scheduling granularity" ) ) ); return true; } } } return false; } QVariant ScheduleItemModel::data( const QModelIndex &index, int role ) const { //debugPlan<isScheduleManager( index.internalPointer() ) ) { o = static_cast( index.internalPointer() ); Q_ASSERT( o ); } return o; } void ScheduleItemModel::setFlat( bool flat ) { m_flat = flat; m_managerlist.clear(); if ( ! flat || m_project == 0 ) { return; } m_managerlist = m_project->allScheduleManagers(); } //-------------------------------------- ScheduleSortFilterModel::ScheduleSortFilterModel( QObject *parent ) : QSortFilterProxyModel( parent ) { } ScheduleSortFilterModel::~ScheduleSortFilterModel() { } ScheduleManager *ScheduleSortFilterModel::manager( const QModelIndex &index ) const { QModelIndex i = mapToSource( index ); const ScheduleItemModel *m = qobject_cast( i.model() ); return m == 0 ? 0 : m->manager( i ); } //-------------------------------------- ScheduleLogItemModel::ScheduleLogItemModel( QObject *parent ) : QStandardItemModel( parent ), m_project( 0 ), m_manager( 0 ), m_schedule( 0 ) { } ScheduleLogItemModel::~ScheduleLogItemModel() { } void ScheduleLogItemModel::slotScheduleManagerToBeRemoved( const ScheduleManager *manager ) { if ( m_manager == manager ) { setManager( 0 ); } } void ScheduleLogItemModel::slotScheduleManagerRemoved( const ScheduleManager *manager ) { debugPlan<name(); } void ScheduleLogItemModel::slotScheduleToBeInserted( const ScheduleManager *manager, int row ) { Q_UNUSED(manager); Q_UNUSED(row); if ( m_manager && m_manager->expected() /*== ??*/ ) { //TODO } } //FIXME remove const on MainSchedule void ScheduleLogItemModel::slotScheduleInserted( const MainSchedule *sch ) { debugPlan<manager() && sch == m_manager->expected() ) { m_schedule = const_cast( sch ); refresh(); } } void ScheduleLogItemModel::slotScheduleToBeRemoved( const MainSchedule *sch ) { debugPlan<"<"<expected(); refresh(); - connect( m_manager, SIGNAL(logInserted(MainSchedule*,int,int)), this, SLOT(slotLogInserted(MainSchedule*,int,int))); + connect(m_manager, SIGNAL(logInserted(KPlato::MainSchedule*,int,int)), this, SLOT(slotLogInserted(KPlato::MainSchedule*,int,int))); } } } void ScheduleLogItemModel::slotLogInserted( MainSchedule *s, int firstrow, int lastrow ) { for ( int i = firstrow; i <= lastrow; ++i ) { addLogEntry( s->logs().value( i ), i + 1 ); } } //FIXME: This only add logs (insert is not used atm) void ScheduleLogItemModel::addLogEntry( const Schedule::Log &log, int /*row*/ ) { // debugPlan< lst; if ( log.resource ) { lst.append( new QStandardItem( log.resource->name() ) ); } else if ( log.node ) { lst.append( new QStandardItem( log.node->name() ) ); } else { lst.append( new QStandardItem( "" ) ); } lst.append( new QStandardItem( m_schedule->logPhase( log.phase ) ) ); QStandardItem *item = new QStandardItem( m_schedule->logSeverity( log.severity ) ); item->setData( log.severity, SeverityRole ); lst.append( item ); lst.append( new QStandardItem( log.message ) ); foreach ( QStandardItem *itm, lst ) { if ( log.resource ) { itm->setData( log.resource->id(), IdentityRole ); } else if ( log.node ) { itm->setData( log.node->id(), IdentityRole ); } switch ( log.severity ) { case Schedule::Log::Type_Debug: itm->setData( QColor(Qt::darkYellow), Qt::ForegroundRole ); break; case Schedule::Log::Type_Info: break; case Schedule::Log::Type_Warning: itm->setData( QColor(Qt::blue), Qt::ForegroundRole ); break; case Schedule::Log::Type_Error: itm->setData( QColor(Qt::red), Qt::ForegroundRole ); break; default: break; } } appendRow( lst ); // debugPlan<<"added:"<logs().count(); int i = 1; foreach ( const Schedule::Log &l, m_schedule->logs() ) { addLogEntry( l, i++ ); } } QString ScheduleLogItemModel::identity( const QModelIndex &idx ) const { QStandardItem *itm = itemFromIndex( idx ); return itm ? itm->data( IdentityRole ).toString() : QString(); } void ScheduleLogItemModel::slotManagerChanged( ScheduleManager *manager ) { debugPlan< Copyright (C) 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTSCHEDULEMODEL_H #define KPTSCHEDULEMODEL_H #include "planmodels_export.h" #include "kptitemmodelbase.h" #include "kptschedule.h" #include #include namespace KPlato { class Project; class ScheduleManager; class MainSchedule; class Schedule; class PLANMODELS_EXPORT ScheduleModel : public QObject { Q_OBJECT Q_ENUMS( Properties ) public: explicit ScheduleModel( QObject *parent = 0 ); ~ScheduleModel(); enum Properties { ScheduleName = 0, ScheduleState, ScheduleDirection, ScheduleOverbooking, ScheduleDistribution, SchedulePlannedStart, SchedulePlannedFinish, ScheduleScheduler, ScheduleGranularity, ScheduleScheduled }; const QMetaEnum columnMap() const; int propertyCount() const; }; class PLANMODELS_EXPORT ScheduleItemModel : public ItemModelBase { Q_OBJECT public: explicit ScheduleItemModel( QObject *parent = 0 ); ~ScheduleItemModel(); const QMetaEnum columnMap() const { return m_model.columnMap(); } virtual void setProject( Project *project ); virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; QModelIndex index( const ScheduleManager *manager ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; QAbstractItemDelegate *createDelegate( int column, QWidget *parent ) const; virtual void sort( int column, Qt::SortOrder order = Qt::AscendingOrder ); virtual QMimeData * mimeData( const QModelIndexList & indexes ) const; virtual QStringList mimeTypes () const; ScheduleManager *manager( const QModelIndex &index ) const; void setFlat( bool flat ); Q_SIGNALS: - void scheduleManagerAdded( ScheduleManager* ); + void scheduleManagerAdded(KPlato::ScheduleManager* ); protected Q_SLOTS: - void slotManagerChanged( ScheduleManager *sch ); - void slotScheduleChanged( MainSchedule *sch ); - - void slotScheduleManagerToBeInserted( const ScheduleManager *manager, int row ); - void slotScheduleManagerInserted( const ScheduleManager *manager ); - void slotScheduleManagerToBeRemoved( const ScheduleManager *manager ); - void slotScheduleManagerRemoved( const ScheduleManager *manager ); - void slotScheduleManagerToBeMoved( const ScheduleManager *manager ); - void slotScheduleManagerMoved( const ScheduleManager *manager, int index ); - void slotScheduleToBeInserted( const ScheduleManager *manager, int row ); - void slotScheduleInserted( const MainSchedule *schedule ); - void slotScheduleToBeRemoved( const MainSchedule *schedule ); - void slotScheduleRemoved( const MainSchedule *schedule ); + void slotManagerChanged(KPlato::ScheduleManager *sch); + void slotScheduleChanged(KPlato::MainSchedule *sch); + + void slotScheduleManagerToBeInserted(const KPlato::ScheduleManager *manager, int row); + void slotScheduleManagerInserted(const KPlato::ScheduleManager *manager); + void slotScheduleManagerToBeRemoved(const KPlato::ScheduleManager *manager); + void slotScheduleManagerRemoved(const KPlato::ScheduleManager *manager); + void slotScheduleManagerToBeMoved(const KPlato::ScheduleManager *manager); + void slotScheduleManagerMoved(const KPlato::ScheduleManager *manager, int index); + void slotScheduleToBeInserted(const KPlato::ScheduleManager *manager, int row); + void slotScheduleInserted( const KPlato::MainSchedule *schedule); + void slotScheduleToBeRemoved( const KPlato::MainSchedule *schedule); + void slotScheduleRemoved( const KPlato::MainSchedule *schedule); protected: int row( const Schedule *sch ) const; QVariant name( const QModelIndex &index, int role ) const; bool setName( const QModelIndex &index, const QVariant &value, int role ); QVariant state( const QModelIndex &index, int role ) const; bool setState( const QModelIndex &index, const QVariant &value, int role ); QVariant allowOverbooking( const QModelIndex &index, int role ) const; bool setAllowOverbooking( const QModelIndex &index, const QVariant &value, int role ); QVariant usePert( const QModelIndex &index, int role ) const; bool setUsePert( const QModelIndex &index, const QVariant &value, int role ); QVariant projectStart( const QModelIndex &index, int role ) const; QVariant projectEnd( const QModelIndex &index, int role ) const; QVariant schedulingDirection( const QModelIndex &index, int role ) const; bool setSchedulingDirection( const QModelIndex &index, const QVariant &value, int role ); QVariant schedulingStartTime( const QModelIndex &index, int role ) const; bool setSchedulingStartTime( const QModelIndex &index, const QVariant &value, int role ); QVariant scheduler( const QModelIndex &index, int role ) const; bool setScheduler( const QModelIndex &index, const QVariant &value, int role ); QVariant isScheduled( const QModelIndex &index, int role ) const; QVariant granularity( const QModelIndex &index, int role ) const; bool setGranularity( const QModelIndex &index, const QVariant &value, int role ); private: ScheduleManager *m_manager; // for sanity check bool m_flat; ScheduleModel m_model; QList m_managerlist; }; //---------------------------------------- class PLANMODELS_EXPORT ScheduleSortFilterModel : public QSortFilterProxyModel { Q_OBJECT public: explicit ScheduleSortFilterModel( QObject *parent = 0 ); ~ScheduleSortFilterModel(); ScheduleManager *manager( const QModelIndex &index ) const; }; //---------------------------------------- class PLANMODELS_EXPORT ScheduleLogItemModel : public QStandardItemModel { Q_OBJECT public: enum DataRoles { SeverityRole = Qt::UserRole + 1, IdentityRole }; explicit ScheduleLogItemModel( QObject *parent = 0 ); ~ScheduleLogItemModel(); void setProject( Project *project ); Project *project() const { return m_project; } void setManager( ScheduleManager *manager ); ScheduleManager *manager() const { return m_manager; } virtual Qt::ItemFlags flags( const QModelIndex & index ) const; void refresh(); QString identity( const QModelIndex &idx ) const; protected Q_SLOTS: - void slotManagerChanged( ScheduleManager *sch ); - void slotScheduleChanged( MainSchedule *sch ); + void slotManagerChanged(KPlato::ScheduleManager *sch); + void slotScheduleChanged(KPlato::MainSchedule *sch); - void slotScheduleManagerToBeRemoved( const ScheduleManager *manager ); - void slotScheduleManagerRemoved( const ScheduleManager *manager ); - void slotScheduleToBeInserted( const ScheduleManager *manager, int row ); - void slotScheduleInserted( const MainSchedule *schedule ); - void slotScheduleToBeRemoved( const MainSchedule *schedule ); - void slotScheduleRemoved( const MainSchedule *schedule ); + void slotScheduleManagerToBeRemoved(const KPlato::ScheduleManager *manager); + void slotScheduleManagerRemoved(const KPlato::ScheduleManager *manager); + void slotScheduleToBeInserted(const KPlato::ScheduleManager *manager, int row); + void slotScheduleInserted( const KPlato::MainSchedule *schedule); + void slotScheduleToBeRemoved( const KPlato::MainSchedule *schedule); + void slotScheduleRemoved( const KPlato::MainSchedule *schedule); - void slotLogInserted( MainSchedule*, int firstrow, int lastrow ); + void slotLogInserted(KPlato::MainSchedule*, int firstrow, int lastrow ); void projectDeleted(); protected: void addLogEntry( const Schedule::Log &log, int row ); private: Project *m_project; ScheduleManager *m_manager; MainSchedule *m_schedule; }; } //KPlato namespace #endif diff --git a/src/libs/models/kpttaskstatusmodel.cpp b/src/libs/models/kpttaskstatusmodel.cpp index 84327126..6ed160cb 100644 --- a/src/libs/models/kpttaskstatusmodel.cpp +++ b/src/libs/models/kpttaskstatusmodel.cpp @@ -1,792 +1,792 @@ /* This file is part of the KDE project Copyright (C) 2007, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kpttaskstatusmodel.h" #include "kptglobal.h" #include "kptcommonstrings.h" #include "kptitemmodelbase.h" #include "kpttaskcompletedelegate.h" #include "kptcommand.h" #include "kptnode.h" #include "kptproject.h" #include "kpttask.h" #include "kptnodeitemmodel.h" #include "kptdebug.h" #include #include #include namespace KPlato { TaskStatusItemModel::TaskStatusItemModel( QObject *parent ) : ItemModelBase( parent ), m_period( 7 ), m_periodType( UseCurrentDate ), m_weekday( Qt::Friday ) { m_topNames << i18n( "Not Started" ); m_topTips << i18n( "Tasks that should have been started" ); m_top.append(&m_notstarted ); m_topNames << i18n( "Running" ); m_topTips << i18n( "Tasks that are running" ); m_top.append(&m_running ); m_topNames << i18n( "Finished" ); m_topTips << i18n( "Tasks that have finished during this period" ); m_top.append(&m_finished ); m_topNames << i18n( "Next Period" ); m_topTips << i18n( "Tasks that are scheduled to start next period" ); m_top.append(&m_upcoming ); /* connect( this, SIGNAL(modelAboutToBeReset()), SLOT(slotAboutToBeReset()) ); connect( this, SIGNAL(modelReset()), SLOT(slotReset()) );*/ } TaskStatusItemModel::~TaskStatusItemModel() { } void TaskStatusItemModel::slotAboutToBeReset() { debugPlan; clear(); } void TaskStatusItemModel::slotReset() { debugPlan; refresh(); } void TaskStatusItemModel::slotNodeToBeInserted( Node *, int ) { //debugPlan<name(); clear(); } void TaskStatusItemModel::slotNodeInserted( Node * /*node*/ ) { //debugPlan<getParent->name()<<"-->"<name(); refresh(); } void TaskStatusItemModel::slotNodeToBeRemoved( Node * /*node*/ ) { //debugPlan<name(); clear(); } void TaskStatusItemModel::slotNodeRemoved( Node * /*node*/ ) { //debugPlan<name(); refresh(); } void TaskStatusItemModel::slotNodeToBeMoved(Node *node, int pos, Node *newParent, int newPos) { Q_UNUSED( node ); Q_UNUSED( pos ); Q_UNUSED( newParent ); Q_UNUSED( newPos ); clear(); } void TaskStatusItemModel::slotNodeMoved( Node * /*node*/ ) { //debugPlan<name(); refresh(); } void TaskStatusItemModel::setProject( Project *project ) { beginResetModel(); clear(); if ( m_project ) { disconnect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); disconnect( m_project, SIGNAL(localeChanged()), this, SLOT(slotLayoutChanged()) ); disconnect( m_project, SIGNAL(wbsDefinitionChanged()), this, SLOT(slotWbsDefinitionChanged()) ); - disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - disconnect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); - disconnect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); - disconnect(m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotNodeToBeMoved(Node*,int,Node*,int))); + disconnect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeToBeAdded(KPlato::Node*,int)), this, SLOT(slotNodeToBeInserted(KPlato::Node*,int)) ); + disconnect( m_project, SIGNAL(nodeToBeRemoved(KPlato::Node*)), this, SLOT(slotNodeToBeRemoved(KPlato::Node*)) ); + disconnect(m_project, SIGNAL(nodeToBeMoved(KPlato::Node*,int,KPlato::Node*,int)), this, SLOT(slotNodeToBeMoved(KPlato::Node*,int,KPlato::Node*,int))); - disconnect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); - disconnect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); - disconnect(m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotNodeMoved(Node*))); + disconnect( m_project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeInserted(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*)) ); + disconnect(m_project, SIGNAL(nodeMoved(KPlato::Node*)), this, SLOT(slotNodeMoved(KPlato::Node*))); } m_project = project; m_nodemodel.setProject( project ); if ( project ) { connect(m_project, SIGNAL(aboutToBeDeleted()), this, SLOT(projectDeleted())); connect( m_project, SIGNAL(localeChanged()), this, SLOT(slotLayoutChanged()) ); connect( m_project, SIGNAL(wbsDefinitionChanged()), this, SLOT(slotWbsDefinitionChanged()) ); - connect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - connect( m_project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); - connect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); - connect(m_project, SIGNAL(nodeToBeMoved(Node*,int,Node*,int)), this, SLOT(slotNodeToBeMoved(Node*,int,Node*,int))); - - connect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); - connect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); - connect(m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotNodeMoved(Node*))); + connect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeToBeAdded(KPlato::Node*,int)), this, SLOT(slotNodeToBeInserted(KPlato::Node*,int)) ); + connect( m_project, SIGNAL(nodeToBeRemoved(KPlato::Node*)), this, SLOT(slotNodeToBeRemoved(KPlato::Node*)) ); + connect(m_project, SIGNAL(nodeToBeMoved(KPlato::Node*,int,KPlato::Node*,int)), this, SLOT(slotNodeToBeMoved(KPlato::Node*,int,KPlato::Node*,int))); + + connect( m_project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeInserted(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*)) ); + connect(m_project, SIGNAL(nodeMoved(KPlato::Node*)), this, SLOT(slotNodeMoved(KPlato::Node*))); } endResetModel(); } void TaskStatusItemModel::setScheduleManager( ScheduleManager *sm ) { beginResetModel(); if (sm == m_nodemodel.manager()) { return; } clear(); if ( m_nodemodel.manager() ) { } m_nodemodel.setManager( sm ); ItemModelBase::setScheduleManager( sm ); if ( sm ) { } endResetModel(); refresh(); } void TaskStatusItemModel::clear() { foreach ( NodeMap *l, m_top ) { int c = l->count(); if ( c > 0 ) { //FIXME: gives error msg: // Can't select indexes from different model or with different parents QModelIndex i = index( l ); debugPlan<clear(); endRemoveRows(); } } } void TaskStatusItemModel::setNow() { switch ( m_periodType ) { case UseWeekday: { QDate date = QDate::currentDate(); int wd = date.dayOfWeek(); date = date.addDays( m_weekday - wd ); if ( wd < m_weekday ) { date = date.addDays( -7 ); } m_nodemodel.setNow( date ); break; } case UseCurrentDate: m_nodemodel.setNow( QDate::currentDate() ); break; default: m_nodemodel.setNow( QDate::currentDate() ); break; } } void TaskStatusItemModel::refresh() { clear(); if ( m_project == 0 ) { return; } m_id = m_nodemodel.id(); if ( m_id == -1 ) { return; } setNow(); const QDate begin = m_nodemodel.now().addDays( -m_period ); const QDate end = m_nodemodel.now().addDays( m_period ); foreach( Node* n, m_project->allNodes() ) { if ( n->type() != Node::Type_Task && n->type() != Node::Type_Milestone ) { continue; } Task *task = static_cast( n ); const TaskStatus status = taskStatus(task, begin, end); if (status != TaskUnknownStatus) { m_top.at(status)->insert(task->wbsCode(), task); } } foreach ( NodeMap *l, m_top ) { int c = l->count(); if ( c > 0 ) { debugPlan<isScheduled( m_id ) ) { return flags; } if ( n->type() != Node::Type_Task && n->type() != Node::Type_Milestone ) { return flags; } Task *t = static_cast( n ); if ( ! t->completion().isStarted() ) { switch ( index.column() ) { case NodeModel::NodeActualStart: flags |= Qt::ItemIsEditable; break; case NodeModel::NodeCompleted: if ( t->state() & Node::State_ReadyToStart ) { flags |= Qt::ItemIsEditable; } break; default: break; } } else if ( ! t->completion().isFinished() ) { // task is running switch ( index.column() ) { case NodeModel::NodeActualFinish: case NodeModel::NodeCompleted: case NodeModel::NodeRemainingEffort: flags |= Qt::ItemIsEditable; break; case NodeModel::NodeActualEffort: if ( t->completion().entrymode() == Completion::EnterEffortPerTask || t->completion().entrymode() == Completion::EnterEffortPerResource ) { flags |= Qt::ItemIsEditable; } break; default: break; } } return flags; } QModelIndex TaskStatusItemModel::parent( const QModelIndex &index ) const { if ( !index.isValid() ) { return QModelIndex(); } //debugPlan<( index.internalPointer() ) ); if ( row != -1 ) { return QModelIndex(); // top level has no parent } Node *n = node( index ); if ( n == 0 ) { return QModelIndex(); } NodeMap *lst = 0; foreach ( NodeMap *l, m_top ) { if ( l->values().indexOf( n ) != -1 ) { lst = l; break; } } if ( lst == 0 ) { return QModelIndex(); } return createIndex( m_top.indexOf( lst ), 0, lst ); } QModelIndex TaskStatusItemModel::index( int row, int column, const QModelIndex &parent ) const { //debugPlan<= columnCount() || row < 0 ) { return QModelIndex(); } if ( ! parent.isValid() ) { if ( row >= m_top.count() ) { return QModelIndex(); } return createIndex(row, column, m_top.value( row ) ); } NodeMap *l = list( parent ); if ( l == 0 ) { return QModelIndex(); } if ( row >= rowCount( parent ) ) { warnPlan<<"Row >= rowCount, Qt4.4 asks, so we need to handle it"<values().value( row ) ); Q_ASSERT( i.internalPointer() != 0 ); return i; } QModelIndex TaskStatusItemModel::index( const Node *node ) const { if ( m_project == 0 || node == 0 ) { return QModelIndex(); } foreach( NodeMap *l, m_top ) { int row = l->values().indexOf( const_cast( node ) ); if ( row != -1 ) { return createIndex( row, 0, const_cast( node ) ); } } return QModelIndex(); } QModelIndex TaskStatusItemModel::index( const NodeMap *lst ) const { if ( m_project == 0 || lst == 0 ) { return QModelIndex(); } NodeMap *l = const_cast( lst ); int row = m_top.indexOf( l ); if ( row == -1 ) { return QModelIndex(); } return createIndex( row, 0, l ); } QVariant TaskStatusItemModel::name( int row, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: return m_topNames.value( row ); case Qt::ToolTipRole: return m_topTips.value( row ); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } bool TaskStatusItemModel::setCompletion( Node *node, const QVariant &value, int role ) { if ( role != Qt::EditRole ) { return false; } if ( node->type() == Node::Type_Task ) { Completion &c = static_cast( node )->completion(); QDateTime dt = QDateTime::currentDateTime(); QDate date = dt.date(); // xgettext: no-c-format MacroCommand *m = new MacroCommand( kundo2_i18n( "Modify completion" ) ); if ( ! c.isStarted() ) { m->addCommand( new ModifyCompletionStartedCmd( c, true ) ); m->addCommand( new ModifyCompletionStartTimeCmd( c, dt ) ); } m->addCommand( new ModifyCompletionPercentFinishedCmd( c, date, value.toInt() ) ); if ( value.toInt() == 100 ) { m->addCommand( new ModifyCompletionFinishedCmd( c, true ) ); m->addCommand( new ModifyCompletionFinishTimeCmd( c, dt ) ); } emit executeCommand( m ); // also adds a new entry if necessary if ( c.entrymode() == Completion::EnterCompleted ) { Duration planned = static_cast( node )->plannedEffort( m_nodemodel.id() ); Duration actual = ( planned * value.toInt() ) / 100; debugPlan<execute(); m->addCommand( cmd ); cmd = new ModifyCompletionRemainingEffortCmd( c, date, planned - actual ); cmd->execute(); m->addCommand( cmd ); } return true; } if ( node->type() == Node::Type_Milestone ) { Completion &c = static_cast( node )->completion(); if ( value.toInt() > 0 ) { QDateTime dt = QDateTime::currentDateTime(); QDate date = dt.date(); MacroCommand *m = new MacroCommand( kundo2_i18n( "Set finished" ) ); m->addCommand( new ModifyCompletionStartedCmd( c, true ) ); m->addCommand( new ModifyCompletionStartTimeCmd( c, dt ) ); m->addCommand( new ModifyCompletionFinishedCmd( c, true ) ); m->addCommand( new ModifyCompletionFinishTimeCmd( c, dt ) ); m->addCommand( new ModifyCompletionPercentFinishedCmd( c, date, 100 ) ); emit executeCommand( m ); // also adds a new entry if necessary return true; } return false; } return false; } bool TaskStatusItemModel::setRemainingEffort( Node *node, const QVariant &value, int role ) { if ( role == Qt::EditRole && node->type() == Node::Type_Task ) { Task *t = static_cast( node ); double d( value.toList()[0].toDouble() ); Duration::Unit unit = static_cast( value.toList()[1].toInt() ); Duration dur( d, unit ); emit executeCommand( new ModifyCompletionRemainingEffortCmd( t->completion(), QDate::currentDate(), dur, kundo2_i18n( "Modify remaining effort" ) ) ); return true; } return false; } bool TaskStatusItemModel::setActualEffort( Node *node, const QVariant &value, int role ) { if ( role == Qt::EditRole && node->type() == Node::Type_Task ) { Task *t = static_cast( node ); double d( value.toList()[0].toDouble() ); Duration::Unit unit = static_cast( value.toList()[1].toInt() ); Duration dur( d, unit ); emit executeCommand( new ModifyCompletionActualEffortCmd( t->completion(), QDate::currentDate(), dur, kundo2_i18n( "Modify actual effort" ) ) ); return true; } return false; } bool TaskStatusItemModel::setStartedTime( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { Task *t = qobject_cast( node ); if ( t == 0 ) { return false; } MacroCommand *m = new MacroCommand( kundo2_i18n( "Modify actual start time" ) ); if ( ! t->completion().isStarted() ) { m->addCommand( new ModifyCompletionStartedCmd( t->completion(), true ) ); } m->addCommand( new ModifyCompletionStartTimeCmd( t->completion(), value.toDateTime() ) ); if ( t->type() == Node::Type_Milestone ) { m->addCommand( new ModifyCompletionFinishedCmd( t->completion(), true ) ); m->addCommand( new ModifyCompletionFinishTimeCmd( t->completion(), value.toDateTime() ) ); if ( t->completion().percentFinished() < 100 ) { Completion::Entry *e = new Completion::Entry( 100, Duration::zeroDuration, Duration::zeroDuration ); m->addCommand( new AddCompletionEntryCmd( t->completion(), value.toDate(), e ) ); } } emit executeCommand( m ); return true; } } return false; } bool TaskStatusItemModel::setFinishedTime( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { Task *t = qobject_cast( node ); if ( t == 0 ) { return false; } MacroCommand *m = new MacroCommand( kundo2_i18n( "Modify actual finish time" ) ); if ( ! t->completion().isFinished() ) { m->addCommand( new ModifyCompletionFinishedCmd( t->completion(), true ) ); if ( t->completion().percentFinished() < 100 ) { Completion::Entry *e = new Completion::Entry( 100, Duration::zeroDuration, Duration::zeroDuration ); m->addCommand( new AddCompletionEntryCmd( t->completion(), value.toDate(), e ) ); } } m->addCommand( new ModifyCompletionFinishTimeCmd( t->completion(), value.toDateTime() ) ); if ( t->type() == Node::Type_Milestone ) { m->addCommand( new ModifyCompletionStartedCmd( t->completion(), true ) ); m->addCommand( new ModifyCompletionStartTimeCmd( t->completion(), value.toDateTime() ) ); } emit executeCommand( m ); return true; } } return false; } QVariant TaskStatusItemModel::data( const QModelIndex &index, int role ) const { QVariant result; if ( ! index.isValid() ) { return result; } if ( role == Qt::TextAlignmentRole ) { return alignment( index.column() ); } Node *n = node( index ); if ( n == 0 ) { switch ( index.column() ) { case NodeModel::NodeName: return name( index.row(), role ); default: break; } return QVariant(); } result = m_nodemodel.data( n, index.column(), role ); if ( role == Qt::DisplayRole ) { switch ( index.column() ) { case NodeModel::NodeActualStart: if ( ! result.isValid() ) { return m_nodemodel.data( n, NodeModel::NodeStatus, role ); } break; } } else if ( role == Qt::EditRole ) { switch ( index.column() ) { case NodeModel::NodeActualStart: case NodeModel::NodeActualFinish: if ( ! result.isValid() ) { return QDateTime::currentDateTime(); } break; } } return result; } bool TaskStatusItemModel::setData( const QModelIndex &index, const QVariant &value, int role ) { if ( ! index.isValid() ) { return ItemModelBase::setData( index, value, role ); } switch ( index.column() ) { case NodeModel::NodeCompleted: return setCompletion( node( index ), value, role ); case NodeModel::NodeRemainingEffort: return setRemainingEffort( node( index ), value, role ); case NodeModel::NodeActualEffort: return setActualEffort( node( index ), value, role ); case NodeModel::NodeActualStart: return setStartedTime( node( index ), value, role ); case NodeModel::NodeActualFinish: return setFinishedTime( node( index ), value, role ); default: break; } return false; } QVariant TaskStatusItemModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( orientation == Qt::Horizontal ) { if (role == Qt::DisplayRole || role == Qt::EditRole) { return m_nodemodel.headerData( section, role ); } else if ( role == Qt::TextAlignmentRole ) { return alignment( section ); } } if ( role == Qt::ToolTipRole ) { return m_nodemodel.headerData( section, role ); } return ItemModelBase::headerData(section, orientation, role); } QVariant TaskStatusItemModel::alignment( int column ) const { return m_nodemodel.headerData( column, Qt::TextAlignmentRole ); } QAbstractItemDelegate *TaskStatusItemModel::createDelegate( int column, QWidget *parent ) const { switch ( column ) { case NodeModel::NodeCompleted: return new TaskCompleteDelegate( parent ); case NodeModel::NodeRemainingEffort: return new DurationSpinBoxDelegate( parent ); case NodeModel::NodeActualEffort: return new DurationSpinBoxDelegate( parent ); default: return 0; } return 0; } int TaskStatusItemModel::columnCount( const QModelIndex & ) const { return m_nodemodel.propertyCount(); } int TaskStatusItemModel::rowCount( const QModelIndex &parent ) const { if ( ! parent.isValid() ) { //debugPlan<<"top="<count()<count(); } //debugPlan<<"node"< rows; foreach (const QModelIndex &index, indexes) { if ( index.isValid() && !rows.contains( index.row() ) ) { //debugPlan<id(); } } } m->setData("application/x-vnd.kde.plan.nodeitemmodel.internal", encodedData); return m; } bool TaskStatusItemModel::dropAllowed( Node *, const QMimeData * ) { return false; } bool TaskStatusItemModel::dropMimeData( const QMimeData *, Qt::DropAction , int , int , const QModelIndex & ) { return false; } NodeMap *TaskStatusItemModel::list( const QModelIndex &index ) const { if ( index.isValid() ) { Q_ASSERT( index.internalPointer() ); if ( m_top.contains( static_cast( index.internalPointer() ) ) ) { return static_cast( index.internalPointer() ); } } return 0; } Node *TaskStatusItemModel::node( const QModelIndex &index ) const { if ( index.isValid() ) { foreach ( NodeMap *l, m_top ) { int row = l->values().indexOf( static_cast( index.internalPointer() ) ); if ( row != -1 ) { return static_cast( index.internalPointer() ); } } } return 0; } TaskStatusItemModel::TaskStatus TaskStatusItemModel::taskStatus(const Task *task, const QDate &begin, const QDate &end) { TaskStatus result = TaskUnknownStatus; const Completion &completion = task->completion(); if (completion.isFinished()) { if (completion.finishTime().date() > begin) { result = TaskFinished; } } else if (completion.isStarted()) { result = TaskRunning; } else if (task->startTime(m_id).date() < m_nodemodel.now()) { // should have been started result = TaskNotStarted; } else if (task->startTime(m_id).date() <= end) { // start next period result = TaskUpcoming; } return result; } void TaskStatusItemModel::slotNodeChanged( Node *node ) { debugPlan; if (node == 0 || node->type() == Node::Type_Project || (node->type() != Node::Type_Task && node->type() != Node::Type_Milestone)) { return; } Task *task = static_cast(node); const QDate begin = m_nodemodel.now().addDays( -m_period ); const QDate end = m_nodemodel.now().addDays( m_period ); const TaskStatus status = taskStatus(task, begin, end); int row = -1; if (status != TaskUnknownStatus) { // find the row of the task const QString wbs = node->wbsCode(); // TODO: not enough to just check the result of indexOf? wbs not unique? if (m_top.at(status)->value(wbs) == node ) { row = m_top.at(status)->keys().indexOf(wbs); } } if (row >= 0) { // task in old group, just changed values emit dataChanged(createIndex(row, 0, node), createIndex(row, columnCount() - 1, node)); } else { // task is new or changed groups refresh(); } } void TaskStatusItemModel::slotWbsDefinitionChanged() { debugPlan; foreach ( NodeMap *l, m_top ) { for ( int row = 0; row < l->count(); ++row ) { emit dataChanged( createIndex( row, NodeModel::NodeWBSCode, l->values().value( row ) ), createIndex( row, NodeModel::NodeWBSCode, l->values().value( row ) ) ); } } } void TaskStatusItemModel::slotLayoutChanged() { //debugPlan<name(); emit layoutAboutToBeChanged(); emit layoutChanged(); } int TaskStatusItemModel::sortRole( int column ) const { switch ( column ) { case NodeModel::NodeStartTime: case NodeModel::NodeEndTime: case NodeModel::NodeActualStart: case NodeModel::NodeActualFinish: case NodeModel::NodeEarlyStart: case NodeModel::NodeEarlyFinish: case NodeModel::NodeLateStart: case NodeModel::NodeLateFinish: case NodeModel::NodeConstraintStart: case NodeModel::NodeConstraintEnd: return Qt::EditRole; default: break; } return Qt::DisplayRole; } } // namespace KPlato diff --git a/src/libs/models/kpttaskstatusmodel.h b/src/libs/models/kpttaskstatusmodel.h index 5a1d5e95..8acb9171 100644 --- a/src/libs/models/kpttaskstatusmodel.h +++ b/src/libs/models/kpttaskstatusmodel.h @@ -1,154 +1,154 @@ /* This file is part of the KDE project Copyright (C) 2007 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 TASKSTATUSMODEL_H #define TASKSTATUSMODEL_H #include "planmodels_export.h" #include "kptitemmodelbase.h" #include "kptnodeitemmodel.h" namespace KPlato { class Project; class Node; class Task; typedef QMap NodeMap; class PLANMODELS_EXPORT TaskStatusItemModel : public ItemModelBase { Q_OBJECT public: explicit TaskStatusItemModel( QObject *parent = 0 ); ~TaskStatusItemModel(); enum PeriodType { UseCurrentDate, UseWeekday }; int periodType() const { return m_periodType; } void setPeriodType( int type ) { m_periodType = type; } /// Returns a column number/- name map for this model virtual const QMetaEnum columnMap() const { return m_nodemodel.columnMap(); } virtual void setProject( Project *project ); virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QModelIndex parent( const QModelIndex & index ) const; virtual QModelIndex index( int row, int column, const QModelIndex & parent = QModelIndex() ) const; virtual QModelIndex index( const Node *node ) const; virtual QModelIndex index( const NodeMap *lst ) const; virtual int columnCount( const QModelIndex & parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; virtual QMimeData * mimeData( const QModelIndexList & indexes ) const; virtual QStringList mimeTypes () const; virtual Qt::DropActions supportedDropActions() const; virtual bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ); NodeMap *list( const QModelIndex &index ) const; Node *node( const QModelIndex &index ) const; QAbstractItemDelegate *createDelegate( int column, QWidget *parent ) const; NodeMap nodeList( QDataStream &stream ); using ItemModelBase::dropAllowed; bool dropAllowed( Node *on, const QMimeData *data ); void clear(); void setNow(); void setPeriod( int days ) { m_period = days; } int period() const { return m_period; } void setWeekday( int day ) { m_weekday = day; } int weekday() const { return m_weekday; } /// Return the sortorder to be used for @p column virtual int sortRole( int column ) const; public Q_SLOTS: - virtual void setScheduleManager( ScheduleManager *sm ); + virtual void setScheduleManager(KPlato::ScheduleManager *sm); virtual void refresh(); protected Q_SLOTS: void slotAboutToBeReset(); void slotReset(); - void slotNodeChanged( Node* ); - void slotNodeToBeInserted( Node *node, int row ); - void slotNodeInserted( Node *node ); - void slotNodeToBeRemoved( Node *node ); - void slotNodeRemoved( Node *node ); - void slotNodeToBeMoved( Node *node, int pos, Node *newParent, int newPos ); - void slotNodeMoved( Node *node ); + void slotNodeChanged(KPlato::Node* ); + void slotNodeToBeInserted(KPlato::Node *node, int row ); + void slotNodeInserted(KPlato::Node *node ); + void slotNodeToBeRemoved(KPlato::Node *node ); + void slotNodeRemoved(KPlato::Node *node ); + void slotNodeToBeMoved(KPlato::Node *node, int pos, KPlato::Node *newParent, int newPos ); + void slotNodeMoved(KPlato::Node *node ); void slotWbsDefinitionChanged(); void slotLayoutChanged(); protected: // keep in sync with order in m_top enum TaskStatus { TaskUnknownStatus = -1, TaskNotStarted = 0, TaskRunning = 1, TaskFinished = 2, TaskUpcoming = 3 }; QVariant alignment( int column ) const; QVariant name( int row, int role ) const; TaskStatusItemModel::TaskStatus taskStatus(const Task *task, const QDate &begin, const QDate &end); bool setCompletion( Node *node, const QVariant &value, int role ); bool setRemainingEffort( Node *node, const QVariant &value, int role ); bool setActualEffort( Node *node, const QVariant &value, int role ); bool setStartedTime( Node *node, const QVariant &value, int role ); bool setFinishedTime( Node *node, const QVariant &value, int role ); private: NodeModel m_nodemodel; QStringList m_topNames; QStringList m_topTips; QList m_top; NodeMap m_notstarted; NodeMap m_running; NodeMap m_finished; NodeMap m_upcoming; long m_id; // schedule id int m_period; // days int m_periodType; int m_weekday; }; } //namespace KPlato #endif diff --git a/src/libs/models/kptworkpackagemodel.cpp b/src/libs/models/kptworkpackagemodel.cpp index 8b52d6b2..25cdc941 100644 --- a/src/libs/models/kptworkpackagemodel.cpp +++ b/src/libs/models/kptworkpackagemodel.cpp @@ -1,558 +1,558 @@ /* This file is part of the KDE project Copyright (C) 2007, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptworkpackagemodel.h" #include "kptglobal.h" #include "kptcommonstrings.h" #include "kptflatproxymodel.h" #include "kptnodeitemmodel.h" #include "kptnode.h" #include "kpttask.h" #include "kptproject.h" #include "kptschedule.h" #include "kptdebug.h" #include #include #include namespace KPlato { QVariant WorkPackageModel::nodeName( const WorkPackage *wp, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: return wp->parentTask() ? wp->parentTask()->name() : ""; case Qt::EditRole: return wp->parentTask() ? wp->parentTask()->name() : ""; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant WorkPackageModel::ownerName( const WorkPackage *wp, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::ToolTipRole: return wp->ownerName(); case Qt::EditRole: return wp->ownerName(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant WorkPackageModel::transmitionStatus( const WorkPackage *wp, int role ) const { switch ( role ) { case Qt::DisplayRole: return wp->transmitionStatusToString( wp->transmitionStatus(), true ); case Qt::EditRole: return wp->transmitionStatus(); case Qt::ToolTipRole: { int sts = wp->transmitionStatus(); if ( sts == WorkPackage::TS_Send ) { return i18n( "Sent to %1 at %2", wp->ownerName(), transmitionTime( wp, Qt::DisplayRole ).toString() ); } if ( sts == WorkPackage::TS_Receive ) { return i18n( "Received from %1 at %2", wp->ownerName(), transmitionTime( wp, Qt::DisplayRole ).toString() ); } return i18n( "Not available" ); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant WorkPackageModel::transmitionTime( const WorkPackage *wp, int role ) const { if ( ! wp ) { return QVariant(); } switch ( role ) { case Qt::DisplayRole: return QLocale().toString( wp->transmitionTime(), QLocale::ShortFormat ); case Qt::EditRole: return wp->transmitionTime(); case Qt::ToolTipRole: { int sts = wp->transmitionStatus(); QString t = QLocale().toString( wp->transmitionTime(), QLocale::LongFormat ); if ( sts == WorkPackage::TS_Send ) { return i18n( "Work package sent at: %1", t ); } if ( sts == WorkPackage::TS_Receive ) { return i18n( "Work package transmission received at: %1", t ); } return i18n( "Not available" ); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant WorkPackageModel::completion( const WorkPackage *wp, int role ) const { switch ( role ) { case Qt::DisplayRole: if ( wp->transmitionStatus() == WorkPackage::TS_Receive ) { return wp->completion().percentFinished(); } break; case Qt::EditRole: if ( wp->transmitionStatus() == WorkPackage::TS_Receive ) { return wp->completion().percentFinished(); } break; case Qt::ToolTipRole: if ( wp->transmitionStatus() == WorkPackage::TS_Receive ) { return i18n( "Task reported %1% completed", wp->completion().percentFinished() ); } break; case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant WorkPackageModel::data( const WorkPackage *wp, int column, int role ) const { switch ( column ) { case NodeModel::WPOwnerName: case NodeModel::NodeName: return ownerName( wp, role ); case NodeModel::WPTransmitionStatus: case NodeModel::NodeStatus: return transmitionStatus( wp, role ); case NodeModel::NodeCompleted: return completion( wp, role ); case NodeModel::WPTransmitionTime: case NodeModel::NodeActualStart: return transmitionTime( wp, role ); default: break; } return QVariant(); } //----------------------------- bool WPSortFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { if ( sourceModel()->index( source_row, NodeModel::NodeType, source_parent ).data( Qt::EditRole ).toInt() != Node::Type_Task ) { return false; } if ( sourceModel()->index( source_row, NodeModel::NodeStatus, source_parent ).data( Qt::EditRole ).toInt() & Node::State_NotScheduled ) { return false; } return true; } WorkPackageProxyModel::WorkPackageProxyModel( QObject *parent ) : QAbstractProxyModel( parent ) { m_proxies << new WPSortFilterProxyModel( this ); m_proxies << new FlatProxyModel( this ); m_nodemodel = new NodeItemModel( this ); QAbstractProxyModel *p = this; foreach ( QAbstractProxyModel *m, m_proxies ) { p->setSourceModel( m ); p = m; } p->setSourceModel( m_nodemodel ); } Qt::ItemFlags WorkPackageProxyModel::flags(const QModelIndex &index) const { if ( isWorkPackageIndex( index ) ) { return Qt::ItemIsEnabled; } return QAbstractProxyModel::flags( index ); } void WorkPackageProxyModel::setSourceModel( QAbstractItemModel *model ) { if ( sourceModel() ) { disconnect(sourceModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(sourceDataChanged(QModelIndex,QModelIndex))); /* disconnect(sourceModel(), SIGNAL(headerDataChanged(Qt::Orientation,int,int)), this, SLOT(sourceHeaderDataChanged(Qt::Orientation,int,int)));*/ disconnect(sourceModel(), SIGNAL(layoutChanged()), this, SIGNAL(layoutChanged())); disconnect(sourceModel(), SIGNAL(layoutAboutToBeChanged()), this, SIGNAL(layoutAboutToBeChanged())); disconnect(sourceModel(), SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int))); disconnect(sourceModel(), SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(sourceRowsInserted(QModelIndex,int,int))); disconnect(sourceModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int))); disconnect(sourceModel(), SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int))); /* disconnect(sourceModel(), SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(sourceColumnsAboutToBeInserted(QModelIndex,int,int))); disconnect(sourceModel(), SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(sourceColumnsInserted(QModelIndex,int,int))); disconnect(sourceModel(), SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(sourceColumnsAboutToBeRemoved(QModelIndex,int,int))); disconnect(sourceModel(), SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(sourceColumnsRemoved(QModelIndex,int,int))); */ disconnect(sourceModel(), SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset())); disconnect(sourceModel(), SIGNAL(modelReset()), this, SLOT(sourceModelReset())); disconnect(sourceModel(), SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), this, SLOT(sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); disconnect(sourceModel(), SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), this, SLOT(sourceRowsMoved(QModelIndex,int,int,QModelIndex,int))); /* disconnect(sourceModel(), SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), this, SLOT(sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); disconnect(sourceModel(), SIGNAL(columnsMoved(QModelIndex&parent,int,int,QModelIndex,int)), this, SLOT(sourceColumnsMoved(QModelIndex&parent,int,int,QModelIndex,int)));*/ } QAbstractProxyModel::setSourceModel( model ); if ( model ) { connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(sourceDataChanged(QModelIndex,QModelIndex))); /* connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)), this, SLOT(sourceHeaderDataChanged(Qt::Orientation,int,int)));*/ connect(model, SIGNAL(layoutChanged()), this, SIGNAL(layoutChanged())); connect(model, SIGNAL(layoutAboutToBeChanged()), this, SIGNAL(layoutAboutToBeChanged())); connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(sourceRowsAboutToBeInserted(QModelIndex,int,int))); connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(sourceRowsInserted(QModelIndex,int,int))); connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(sourceRowsAboutToBeRemoved(QModelIndex,int,int))); connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(sourceRowsRemoved(QModelIndex,int,int))); /* connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), this, SLOT(sourceColumnsAboutToBeInserted(QModelIndex,int,int))); connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)), this, SLOT(sourceColumnsInserted(QModelIndex,int,int))); connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), this, SLOT(sourceColumnsAboutToBeRemoved(QModelIndex,int,int))); connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), this, SLOT(sourceColumnsRemoved(QModelIndex,int,int))); */ connect(model, SIGNAL(modelAboutToBeReset()), this, SLOT(sourceModelAboutToBeReset())); connect(model, SIGNAL(modelReset()), this, SLOT(sourceModelReset())); connect(model, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), this, SLOT(sourceRowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); connect(model, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), this, SLOT(sourceRowsMoved(QModelIndex,int,int,QModelIndex,int))); /* connect(model, SIGNAL(columnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), this, SLOT(sourceColumnsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int))); connect(model, SIGNAL(columnsMoved(QModelIndex&parent,int,int,QModelIndex,int)), this, SLOT(sourceColumnsMoved(QModelIndex&parent,int,int,QModelIndex,int)));*/ } } void WorkPackageProxyModel::sourceDataChanged(const QModelIndex &start, const QModelIndex &end) { emit dataChanged( mapFromSource( start ), mapFromSource( end ) ); } void WorkPackageProxyModel::sourceModelAboutToBeReset() { // debugPlan; beginResetModel(); detachTasks(); } void WorkPackageProxyModel::sourceModelReset() { // debugPlan; attachTasks(); for ( int r = 0; r < rowCount(); ++r ) { debugPlan< 0; } int WorkPackageProxyModel::rowCount( const QModelIndex &parent ) const { int rows = 0; if ( ! parent.isValid() ) { rows = sourceModel()->rowCount(); } else if ( isTaskIndex( parent ) ) { Task *task = taskFromIndex( parent ); rows = task ? task->workPackageLogCount() : 0; } // debugPlan<columnCount(); } QModelIndex WorkPackageProxyModel::mapToSource( const QModelIndex &proxyIndex ) const { if ( ! proxyIndex.isValid() ) { return QModelIndex(); } if ( isWorkPackageIndex( proxyIndex ) ) { // workpackage, not mapped to source model return QModelIndex(); } return sourceModel()->index( proxyIndex.row(), proxyIndex.column() ); } QModelIndex WorkPackageProxyModel::mapFromSource( const QModelIndex &sourceIndex ) const { // index from source model is always a node return createIndex( sourceIndex.row(), sourceIndex.column() ); } QModelIndex WorkPackageProxyModel::parent( const QModelIndex &child ) const { QModelIndex idx; if ( isWorkPackageIndex( child ) ) { // only work packages have parent idx = m_nodemodel->index( static_cast( child.internalPointer() ) ); idx = mapFromBaseModel( idx ); } // debugPlan<workPackageAt( idx.row() ), idx.column(), role ); } } // debugPlan<( idx.internalPointer() ); } else if ( idx.isValid() ) { QVariant obj = data( idx, Role::Object ); task = qobject_cast( obj.value() ); } // debugPlan<index( node ) ); } QModelIndex WorkPackageProxyModel::mapFromBaseModel( const QModelIndex &idx ) const { if ( ! idx.isValid() ) { return QModelIndex(); } QModelIndex in = idx; for ( int i = m_proxies.count() -1; i >= 0; --i ) { in = m_proxies.at( i )->mapFromSource( in ); } return mapFromSource( in ); } void WorkPackageProxyModel::setProject( Project *project ) { debugPlan<setProject( project ); } void WorkPackageProxyModel::setScheduleManager(ScheduleManager *sm) { debugPlan<setScheduleManager( sm ); } NodeItemModel *WorkPackageProxyModel::baseModel() const { return m_nodemodel; } void WorkPackageProxyModel::detachTasks( Task *task ) { if ( task ) { - disconnect(task, SIGNAL(workPackageToBeAdded(Node*,int)), this, SLOT(workPackageToBeAdded(Node*,int))); - disconnect(task, SIGNAL(workPackageAdded(Node*)), this, SLOT(workPackageAdded(Node*))); - disconnect(task, SIGNAL(workPackageToBeRemoved(Node*,int)), this, SLOT(workPackageToBeRemoved(Node*,int))); - disconnect(task, SIGNAL(workPackageRemoved(Node*)), this, SLOT(workPackageRemoved(Node*))); + disconnect(task, SIGNAL(workPackageToBeAdded(KPlato::Node*,int)), this, SLOT(workPackageToBeAdded(KPlato::Node*,int))); + disconnect(task, SIGNAL(workPackageAdded(KPlato::Node*)), this, SLOT(workPackageAdded(KPlato::Node*))); + disconnect(task, SIGNAL(workPackageToBeRemoved(KPlato::Node*,int)), this, SLOT(workPackageToBeRemoved(KPlato::Node*,int))); + disconnect(task, SIGNAL(workPackageRemoved(KPlato::Node*)), this, SLOT(workPackageRemoved(KPlato::Node*))); // debugPlan< 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 WORKPACKAGEMODEL_H #define WORKPACKAGEMODEL_H #include "planmodels_export.h" #include class QModelIndex; class QVariant; /// The main namespace namespace KPlato { class WorkPackage; class Node; class Task; class Project; class ScheduleManager; class NodeItemModel; class PLANMODELS_EXPORT WorkPackageModel : public QObject { Q_OBJECT Q_ENUMS( Properties ) public: explicit WorkPackageModel( QObject *parent = 0 ) : QObject( parent ) {} ~WorkPackageModel() {} QVariant data( const WorkPackage *wp, int column, int role = Qt::DisplayRole ) const; protected: QVariant nodeName(const WorkPackage *wp, int role ) const; QVariant ownerName(const WorkPackage *wp, int role ) const; QVariant transmitionStatus(const WorkPackage *wp, int role ) const; QVariant transmitionTime(const WorkPackage *wp, int role ) const; QVariant completion( const WorkPackage *wp, int role ) const; }; /** The WPSortFilterProxyModel only accepts scheduled tasks. */ class WPSortFilterProxyModel : public QSortFilterProxyModel { Q_OBJECT public: explicit WPSortFilterProxyModel(QObject *parent = 0) : QSortFilterProxyModel( parent ) {} protected: /// Only accept scheduled tasks bool filterAcceptsRow(int source_row, const QModelIndex &sourceParent) const; }; /** The WorkPackageProxyModel offers a flat list of tasks with workpackage log entries as children. The tasks is fetched from the WPSortFilterProxyModel, the work packages is added by this model. It uses the NodeItemModel to get the tasks, the FlatProxyModel to convert to a flat list, and the WPSortFilterProxyModel to accept only scheduled tasks. It depends on the fact that the WPSortFilterProxyModel holds a flat list. */ class PLANMODELS_EXPORT WorkPackageProxyModel : public QAbstractProxyModel { Q_OBJECT public: explicit WorkPackageProxyModel(QObject *parent = 0); Qt::ItemFlags flags(const QModelIndex &index) const; void setSourceModel( QAbstractItemModel *sourceModel ); bool hasChildren(const QModelIndex &parent) const; int rowCount( const QModelIndex &parent = QModelIndex() ) const; int columnCount( const QModelIndex &parent = QModelIndex() ) const; QModelIndex parent( const QModelIndex &child ) const; QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const; QVariant data( const QModelIndex &idx, int role = Qt::DisplayRole ) const; NodeItemModel *baseModel() const; QModelIndex mapToSource(const QModelIndex &proxyIndex) const; QModelIndex mapFromSource(const QModelIndex &sourceIndex) const; Task *taskFromIndex( const QModelIndex &idx ) const; QModelIndex indexFromTask( const Node *node ) const; public Q_SLOTS: - void setProject( Project *project ); - void setScheduleManager( ScheduleManager *sm ); + void setProject(KPlato::Project *project); + void setScheduleManager(KPlato::ScheduleManager *sm); protected Q_SLOTS: void sourceDataChanged(const QModelIndex& start, const QModelIndex& end); void sourceModelAboutToBeReset(); void sourceModelReset(); void sourceRowsAboutToBeInserted(const QModelIndex&, int, int ); void sourceRowsInserted(const QModelIndex&, int, int end); void sourceRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end); void sourceRowsRemoved(const QModelIndex& parent, int start, int); void sourceRowsAboutToBeMoved( const QModelIndex&, int sourceStart, int sourceEnd, const QModelIndex&, int destStart ); void sourceRowsMoved( const QModelIndex&, int , int , const QModelIndex&, int ); - void workPackageToBeAdded(Node*, int); - void workPackageAdded(Node*); - void workPackageToBeRemoved(Node*, int); - void workPackageRemoved(Node*); + void workPackageToBeAdded(KPlato::Node*, int); + void workPackageAdded(KPlato::Node*); + void workPackageToBeRemoved(KPlato::Node*, int); + void workPackageRemoved(KPlato::Node*); protected: QModelIndex mapFromBaseModel( const QModelIndex &idx ) const; void detachTasks( Task *task = 0 ); void attachTasks( Task *task = 0 ); inline bool isTaskIndex( const QModelIndex &idx ) const { return idx.isValid() && ! idx.internalPointer(); } inline bool isWorkPackageIndex( const QModelIndex &idx ) const { return idx.isValid() && idx.internalPointer(); } private: WorkPackageModel m_model; NodeItemModel *m_nodemodel; QList m_proxies; }; } //namespace KPlato #endif //WORKPACKAGEMODEL_H diff --git a/src/libs/ui/TasksEditDialog.h b/src/libs/ui/TasksEditDialog.h index 89106d99..913affd7 100644 --- a/src/libs/ui/TasksEditDialog.h +++ b/src/libs/ui/TasksEditDialog.h @@ -1,74 +1,74 @@ /* This file is part of the KDE project Copyright (C) 2017 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 TASKSEDITDIALOGWIDGET_H #define TASKSEDITDIALOGWIDGET_H #include "planui_export.h" #include namespace KPlato { class Accounts; class TaskGeneralPanel; class RequestResourcesPanel; class DocumentsPanel; class TaskCostPanel; class TaskDescriptionPanel; class Node; class Task; class Project; class MacroCommand; /** * The dialog that shows and allows you to alter any task. */ class PLANUI_EXPORT TasksEditDialog : public KPageDialog { Q_OBJECT public: /** * The constructor for the tasks settings dialog. * @param tasks the list of tasks to be edited * @param parent parent widget */ TasksEditDialog(Project &project, const QList &tasks, QWidget *parent=0); virtual MacroCommand *buildCommand(); protected Q_SLOTS: void accept(); void setButtonOkEnabled(bool enabled); - void slotTaskRemoved( Node *node ); + void slotTaskRemoved(KPlato::Node *node ); void slotCurrentChanged( KPageWidgetItem*, KPageWidgetItem* ); protected: Project &m_project; const QList m_tasks; Task *m_task; RequestResourcesPanel *m_resourcesTab; }; } //KPlato namespace #endif // TASKSEDITDIALOGWIDGET_H diff --git a/src/libs/ui/kptaccountseditor.h b/src/libs/ui/kptaccountseditor.h index 87e9898f..0b5b5b47 100644 --- a/src/libs/ui/kptaccountseditor.h +++ b/src/libs/ui/kptaccountseditor.h @@ -1,152 +1,152 @@ /* This file is KoDocument of the KDE project Copyright (C) 2007 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 KPTACCOUNTSEDITOR_H #define KPTACCOUNTSEDITOR_H #include "planui_export.h" #include #include "kptaccountsmodel.h" #include class KoPageLayoutWidget; class KoDocument; class QPoint; namespace KPlato { class Project; class Account; class AccountTreeView; class AccountseditorConfigDialog : public KPageDialog { Q_OBJECT public: AccountseditorConfigDialog( ViewBase *view, AccountTreeView *treeview, QWidget *parent, bool selectPrint = false ); public Q_SLOTS: void slotOk(); private: ViewBase *m_view; AccountTreeView *m_treeview; KoPageLayoutWidget *m_pagelayout; PrintingHeaderFooter *m_headerfooter; }; class PLANUI_EXPORT AccountTreeView : public TreeViewBase { Q_OBJECT public: explicit AccountTreeView(QWidget *parent); AccountItemModel *model() const { return static_cast( TreeViewBase::model() ); } Project *project() const { return model()->project(); } void setProject( Project *project ) { model()->setProject( project ); } Account *currentAccount() const; Account *selectedAccount() const; QList selectedAccounts() const; Q_SIGNALS: void currentChanged( const QModelIndex& ); void currentColumnChanged( const QModelIndex&, const QModelIndex& ); void selectionChanged( const QModelIndexList& ); void contextMenuRequested( const QModelIndex&, const QPoint& ); protected Q_SLOTS: void headerContextMenuRequested( const QPoint &pos ); virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); virtual void currentChanged ( const QModelIndex & current, const QModelIndex & previous ); protected: void contextMenuEvent ( QContextMenuEvent * event ); }; class PLANUI_EXPORT AccountsEditor : public ViewBase { Q_OBJECT public: AccountsEditor(KoPart *part, KoDocument *document, QWidget *parent); void setupGui(); Project *project() const { return m_view->project(); } virtual void draw( Project &project ); virtual void draw(); AccountItemModel *model() const { return m_view->model(); } virtual void updateReadWrite( bool readwrite ); virtual Account *currentAccount() const; KoPrintJob *createPrintJob(); bool loadContext(const KoXmlElement &context); void saveContext(QDomElement &context) const; Q_SIGNALS: - void addAccount( Account *account ); - void deleteAccounts( const QList& ); + void addAccount(KPlato::Account *account); + void deleteAccounts(const QList&); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); protected: void updateActionsEnabled( bool on ); void insertAccount( Account *account, Account *parent, int row ); protected Q_SLOTS: virtual void slotOptions(); private Q_SLOTS: void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); void slotHeaderContextMenuRequested( const QPoint &pos ); void slotSelectionChanged( const QModelIndexList& ); void slotCurrentChanged( const QModelIndex& ); void slotEnableActions( bool on ); void slotAddAccount(); void slotAddSubAccount(); void slotDeleteSelection(); void slotAccountsOk(); private: AccountTreeView *m_view; QAction *actionAddAccount; QAction *actionAddSubAccount; QAction *actionDeleteSelection; }; } //KPlato namespace #endif diff --git a/src/libs/ui/kptaccountsview.h b/src/libs/ui/kptaccountsview.h index 1ef2f68b..803c200e 100644 --- a/src/libs/ui/kptaccountsview.h +++ b/src/libs/ui/kptaccountsview.h @@ -1,117 +1,117 @@ /* This file is part of the KDE project Copyright (C) 2005 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 KPTACCOUNTSVIEW_H #define KPTACCOUNTSVIEW_H #include "planui_export.h" #include "kptviewbase.h" #include #include #include "kptaccount.h" #include "kpteffortcostmap.h" namespace KPlato { class Account; class Project; class ScheduleManager; class CostBreakdownItemModel; class PLANUI_EXPORT AccountsTreeView : public DoubleTreeViewBase { Q_OBJECT public: explicit AccountsTreeView( QWidget *parent = 0 ); CostBreakdownItemModel *model() const; bool cumulative() const; void setCumulative( bool on ); int periodType() const; void setPeriodType( int period ); int startMode() const; void setStartMode( int mode ); int endMode() const; void setEndMode( int mode ); QDate startDate() const; void setStartDate( const QDate &date ); QDate endDate() const; void setEndDate( const QDate &date ); int showMode() const; void setShowMode( int show ); protected Q_SLOTS: void slotModelReset(); private: QList m_leftHidden; }; class PLANUI_EXPORT AccountsView : public ViewBase { Q_OBJECT public: AccountsView(KoPart *part, Project *project, KoDocument *doc, QWidget *parent); //~AccountsView(); void setupGui(); Project *project() const { return m_project; } virtual void setZoom( double zoom ); virtual void setProject( Project *project ); virtual bool loadContext( const KoXmlElement &context ); virtual void saveContext( QDomElement &context ) const; CostBreakdownItemModel *model() const; KoPrintJob *createPrintJob(); public Q_SLOTS: - void setScheduleManager( ScheduleManager *sm ); + void setScheduleManager(KPlato::ScheduleManager *sm); protected Q_SLOTS: void slotContextMenuRequested( const QModelIndex&, const QPoint &pos ); void slotHeaderContextMenuRequested( const QPoint &pos ); virtual void slotOptions(); private: void init(); private: Project *m_project; ScheduleManager *m_manager; AccountsTreeView *m_view; QDate m_date; int m_period; bool m_cumulative; QDomDocument m_domdoc; }; } //KPlato namespace #endif diff --git a/src/libs/ui/kptcalendareditor.h b/src/libs/ui/kptcalendareditor.h index 0f307ef9..db695023 100644 --- a/src/libs/ui/kptcalendareditor.h +++ b/src/libs/ui/kptcalendareditor.h @@ -1,228 +1,228 @@ /* This file is part of the KDE project Copyright (C) 2007 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 KPTCALENDAREDITOR_H #define KPTCALENDAREDITOR_H #include "planui_export.h" #include "kptviewbase.h" #include "kptitemmodelbase.h" #include "kptcalendar.h" #include "kptcalendarmodel.h" #include class QPoint; class KUndo2Command; class KoDocument; namespace KPlato { class View; class Project; class Calendar; class CalendarDay; class DateTableDataModel; class KDatePicker; class PLANUI_EXPORT CalendarTreeView : public TreeViewBase { Q_OBJECT public: explicit CalendarTreeView(QWidget *parent); CalendarItemModel *model() const { return static_cast( TreeViewBase::model() ); } Project *project() const { return model()->project(); } void setProject( Project *project ) { model()->setProject( project ); } Calendar *currentCalendar() const; Calendar *selectedCalendar() const; QList selectedCalendars() const; Q_SIGNALS: void currentChanged( const QModelIndex& ); void currentColumnChanged( const QModelIndex&, const QModelIndex& ); void selectionChanged( const QModelIndexList& ); void contextMenuRequested( const QModelIndex&, const QPoint& ); void focusChanged(); protected Q_SLOTS: void headerContextMenuRequested( const QPoint &pos ); virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); virtual void currentChanged ( const QModelIndex & current, const QModelIndex & previous ); protected: void contextMenuEvent ( QContextMenuEvent * event ); void focusInEvent ( QFocusEvent * event ); void focusOutEvent ( QFocusEvent * event ); void dragMoveEvent(QDragMoveEvent *event); }; class PLANUI_EXPORT CalendarDayView : public QTableView { Q_OBJECT public: explicit CalendarDayView(QWidget *parent); CalendarDayItemModel *model() const { return m_model; } Project *project() const { return model()->project(); } void setProject( Project *project ) { model()->setProject( project ); } CalendarDay *selectedDay() const; TimeInterval *selectedInterval() const; QSize sizeHint() const; void setReadWrite( bool on ) { m_readwrite = on; } bool isReadWrite() const { return m_readwrite; } Q_SIGNALS: void currentChanged( const QModelIndex& ); void currentColumnChanged( const QModelIndex&, const QModelIndex& ); void selectionChanged( const QModelIndexList& ); void contextMenuRequested( const QModelIndex&, const QPoint& ); void focusChanged(); void executeCommand( KUndo2Command *cmd ); public Q_SLOTS: - void setCurrentCalendar( Calendar *calendar ); + void setCurrentCalendar(KPlato::Calendar *calendar); protected Q_SLOTS: void headerContextMenuRequested( const QPoint &pos ); virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); virtual void currentChanged ( const QModelIndex & current, const QModelIndex & previous ); void slotSetWork(); void slotSetVacation(); void slotSetUndefined(); void slotIntervalEditDialogFinished( int result ); protected: void contextMenuEvent ( QContextMenuEvent * event ); void focusInEvent ( QFocusEvent * event ); void focusOutEvent ( QFocusEvent * event ); private: CalendarDayItemModel *m_model; QAction *actionSetUndefined; QAction *actionSetVacation; QAction *actionSetWork; bool m_readwrite; }; class PLANUI_EXPORT CalendarEditor : public ViewBase { Q_OBJECT public: CalendarEditor(KoPart *part, KoDocument *doc, QWidget *parent); void setupGui(); Project *project() const { return m_calendarview->project(); } virtual void draw( Project &project ); virtual void draw(); virtual void updateReadWrite( bool readwrite ); virtual Calendar *currentCalendar() const; /// Loads context info into this view. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. virtual void saveContext( QDomElement &/*context*/ ) const; Q_SIGNALS: - void addCalendar( Calendar *calendar ); - void deleteCalendar( const QList& ); + void addCalendar(KPlato::Calendar *calendar); + void deleteCalendar(const QList&); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); protected: void updateActionsEnabled( bool on ); void insertCalendar( Calendar *calendar, Calendar *parent, int pos = -1 ); protected Q_SLOTS: void slotIntervalEditDialogFinished( int result ); void slotOptions(); private Q_SLOTS: void slotContextMenuCalendar( const QModelIndex& index, const QPoint& pos ); void slotContextMenuDay( const QModelIndex& index, const QPoint& pos ); void slotContextMenuDate( QMenu*, const QDate& ); void slotContextMenuDate( QMenu*, const QList& ); void slotCalendarSelectionChanged( const QModelIndexList& ); void slotCurrentCalendarChanged( const QModelIndex& ); void slotDaySelectionChanged( const QModelIndexList& ); void slotCurrentDayChanged( const QModelIndex& ); void slotEnableActions(); void slotAddCalendar(); void slotAddSubCalendar(); void slotDeleteCalendar(); void slotAddDay(); void slotAddInterval(); void slotDeleteDaySelection(); void slotSetWork(); void slotSetVacation(); void slotSetUndefined(); private: CalendarTreeView *m_calendarview; CalendarDayView *m_dayview; KDatePicker *m_datePicker; DateTableDataModel *m_model; QAction *actionAddCalendar; QAction *actionAddSubCalendar; QAction *actionDeleteSelection; QAction *actionAddDay; QAction *actionAddWorkInterval; QAction *actionDeleteDaySelection; QAction *actionSetUndefined; QAction *actionSetVacation; QAction *actionSetWork; QList m_currentMenuDateList; }; } //KPlato namespace #endif diff --git a/src/libs/ui/kptdependencyeditor.cpp b/src/libs/ui/kptdependencyeditor.cpp index 71b08201..a0ce329e 100644 --- a/src/libs/ui/kptdependencyeditor.cpp +++ b/src/libs/ui/kptdependencyeditor.cpp @@ -1,2443 +1,2443 @@ /* This file is part of the KDE project Copyright (C) 2007 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; 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. */ #include "kptdependencyeditor.h" #include "kptglobal.h" #include "kptcommonstrings.h" #include "kptitemmodelbase.h" #include "kptcommand.h" #include "kptproject.h" #include "kptrelation.h" #include "kptschedule.h" #include "kptdebug.h" #include "config.h" #include "Help.h" #include "KoPageLayoutWidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ConnectCursor Qt::DragLinkCursor namespace KPlato { void plan_paintFocusSelectedItem( QPainter *painter, const QStyleOptionGraphicsItem *option ) { if ( option->state & ( QStyle::State_Selected | QStyle::State_HasFocus ) ) { painter->save(); if (option->state & QStyle::State_Selected) { debugPlanDepEditor<<"selected"; QPalette::ColorGroup cg = option->state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled; if (cg == QPalette::Normal && !(option->state & QStyle::State_Active)) cg = QPalette::Inactive; QLinearGradient g( 0.0, option->rect.top(), 0.0, option->rect.bottom() ); QColor col = option->palette.brush(cg, QPalette::Highlight).color(); g.setColorAt( 0.0, col.lighter( 125 ) ); g.setColorAt( 1.0, col.lighter( 60 ) ); painter->setPen( Qt::NoPen ); painter->setBrush( QBrush( g ) ); painter->drawRect( option->exposedRect ); } if ( option->state & QStyle::State_HasFocus ) { debugPlanDepEditor<<"has focus"; QPalette::ColorGroup cg = option->state & QStyle::State_Enabled ? QPalette::Active : QPalette::Disabled; if (cg == QPalette::Active && !(option->state & QStyle::State_Active)) cg = QPalette::Inactive; QPen p( Qt::DotLine ); p.setWidthF( 2. ); if ( option->state & QStyle::State_Selected ) { p.setColor( option->palette.color( cg, QPalette::Shadow ) ); debugPlanDepEditor<<"focus: selected"<palette.color( cg, QPalette::Highlight ) ); debugPlanDepEditor<<"focus: not selected"<setPen( p ); painter->setBrush( Qt::NoBrush ); painter->drawRect( option->exposedRect ); } painter->restore(); } } //---------------------- DependecyViewPrintingDialog::DependecyViewPrintingDialog( ViewBase *parent, DependencyView *view ) : PrintingDialog( parent ), m_depview( view ) { debugPlanDepEditor< DependecyViewPrintingDialog::createOptionWidgets() const { QList lst; lst << createPageLayoutWidget(); lst += PrintingDialog::createOptionWidgets(); return lst; } void DependecyViewPrintingDialog::printPage( int page, QPainter &painter ) { painter.save(); QRect hRect = headerRect(); QRect fRect = footerRect(); QRect pageRect = printer().pageRect(); pageRect.moveTo( 0, 0 ); debugPlanDepEditor<project()) ); int gap = 8; int pageHeight = pageRect.height(); if ( hRect.isValid() ) { pageHeight -= ( hRect.height() + gap ); } if ( fRect.isValid() ) { pageHeight -= ( fRect.height() + gap ); } painter.translate( 0, hRect.height() + gap ); QRect r( 0, 0, pageRect.width(), pageHeight ); m_depview->itemScene()->render( &painter, r ); painter.restore(); } DependencyLinkItemBase::DependencyLinkItemBase( QGraphicsItem *parent ) : QGraphicsPathItem( parent ), m_editable( false ), predItem( 0 ), succItem( 0 ), relation( 0 ), m_arrow( new QGraphicsPathItem( this ) ) { } DependencyLinkItemBase::DependencyLinkItemBase( DependencyNodeItem *predecessor, DependencyNodeItem *successor, Relation *rel, QGraphicsItem *parent ) : QGraphicsPathItem( parent ), m_editable( false ), predItem( predecessor ), succItem( successor ), relation( rel ), m_arrow( new QGraphicsPathItem( this ) ) { } DependencyLinkItemBase::~DependencyLinkItemBase() { } DependencyScene *DependencyLinkItemBase::itemScene() const { return static_cast( scene() ); } void DependencyLinkItemBase::createPath( const QPointF &sp, int starttype, const QPointF &ep, int endtype ) { //if ( predItem && succItem ) debugPlanDepEditor<text()<<" ->"<text()<<" visible="<horizontalGap(); bool up = sp.y() > ep.y(); bool right = sp.x() < ep.x(); bool same = sp.x() == ep.x(); QPainterPath link( sp ); qreal x = sp.x(); qreal y = sp.y(); if ( right && starttype == DependencyNodeItem::Finish) { x = ep.x(); x += endtype == DependencyNodeItem::Start ? - hgap/2 - 6 : hgap/2 - 6; link.lineTo( x, y ); x += 6; QPointF cp( x, y ); y += up ? -6 : +6; link.quadTo( cp, QPointF( x, y ) ); y = up ? ep.y() + 6 : ep.y() - 6; link.lineTo( x, y ); y = ep.y(); cp = QPointF( x, y ); x += endtype == DependencyNodeItem::Start ? 6 : -6; link.quadTo( cp, QPointF( x, y ) ); } else if ( right && starttype == DependencyNodeItem::Start ) { x = sp.x() - hgap/2 + 6; link.lineTo( x, y ); x -= 6; QPointF cp( x, y ); y += up ? -6 : +6; link.quadTo( cp, QPointF( x, y ) ); y = up ? ep.y() + 6 : ep.y() - 6; link.lineTo( x, y ); y = ep.y(); cp = QPointF( x, y ); x += endtype == DependencyNodeItem::Start ? 6 : -6; link.quadTo( cp, QPointF( x, y ) ); } else if ( same ) { x = ep.x(); x += endtype == DependencyNodeItem::Start ? - hgap/2 + 6 : hgap/2 - 6; link.lineTo( x, y ); x += endtype == DependencyNodeItem::Start ? -6 : +6; QPointF cp( x, y ); y += up ? -6 : 6; link.quadTo( cp, QPointF( x, y ) ); y = up ? ep.y() + 6 : ep.y() - 6; link.lineTo( x, y ); y = ep.y(); cp = QPointF( x, y ); if ( endtype == DependencyNodeItem::Start ) { x += 6; } else { x -= 6; } link.quadTo( cp, QPointF( x, y ) ); } else { x = ep.x(); x += endtype == DependencyNodeItem::Start ? - hgap/2 + 6 : hgap/2 + 6; link.lineTo( x, y ); x -= 6; QPointF cp( x, y ); y += up ? -6 : 6; link.quadTo( cp, QPointF( x, y ) ); y = up ? ep.y() + 6 : ep.y() - 6; link.lineTo( x, y ); y = ep.y(); cp = QPointF( x, y ); x += endtype == DependencyNodeItem::Start ? 6 : -6; link.quadTo( cp, QPointF( x, y ) ); } link.lineTo( ep ); setPath( link ); QPainterPath arrow; x = endtype == DependencyNodeItem::Start ? -6 : 6; arrow.moveTo( ep ); arrow.lineTo( ep.x() + x, ep.y() - 3 ); arrow.lineTo( ep.x() + x, ep.y() + 3 ); arrow.lineTo( ep ); m_arrow->setPath( arrow ); m_arrow->show(); } //-------------------------------- DependencyLinkItem::DependencyLinkItem( DependencyNodeItem *predecessor, DependencyNodeItem *successor, Relation *rel, QGraphicsItem *parent ) : DependencyLinkItemBase( predecessor, successor, rel, parent ) { setZValue( 100.0 ); setAcceptHoverEvents( true ); //debugPlanDepEditor<text()<<"("<column()<<") -"<text(); predItem->addChildRelation( this ); succItem->addParentRelation( this ); succItem->setColumn(); m_arrow->setBrush( Qt::black ); m_pen = pen(); } DependencyLinkItem::~DependencyLinkItem() { if ( predItem ) { predItem->takeChildRelation( this ); } if ( succItem ) { succItem->takeParentRelation( this ); } } int DependencyLinkItem::newChildColumn() const { int col = predItem->column(); if ( relation->type() == Relation::FinishStart ) { ++col; } //debugPlanDepEditor<<"new col="<isVisible() && succItem->isVisible() ); } void DependencyLinkItem::createPath() { setVisible( predItem->isVisible() && succItem->isVisible() ); if ( ! isVisible() ) { //debugPlanDepEditor<<"Visible="<node()->name()<<" -"<node()->name(); return; } QPointF sp = startPoint(); QPointF ep = endPoint(); int stype = 0, etype = 0; switch ( relation->type() ) { case Relation::StartStart: stype = DependencyNodeItem::Start; etype = DependencyNodeItem::Start; break; case Relation::FinishStart: stype = DependencyNodeItem::Finish; etype = DependencyNodeItem::Start; break; case Relation::FinishFinish: stype = DependencyNodeItem::Finish; etype = DependencyNodeItem::Finish; break; default: break; } DependencyLinkItemBase::createPath( sp, stype, ep, etype ); } QPointF DependencyLinkItem::startPoint() const { if ( relation->type() == Relation::StartStart ) { return predItem->connectorPoint( DependencyNodeItem::Start ); } return predItem->connectorPoint( DependencyNodeItem::Finish ); } QPointF DependencyLinkItem::endPoint() const { if ( relation->type() == Relation::FinishFinish ) { return succItem->connectorPoint( DependencyNodeItem::Finish ); } return succItem->connectorPoint( DependencyNodeItem::Start ); } void DependencyLinkItem::hoverEnterEvent( QGraphicsSceneHoverEvent * /*event*/ ) { setZValue( zValue() + 1 ); setPen( QPen( Qt::black, 2 ) ); m_arrow->setPen( pen() ); update(); } void DependencyLinkItem::hoverLeaveEvent( QGraphicsSceneHoverEvent * /*event*/ ) { resetHooverIndication(); } void DependencyLinkItem::resetHooverIndication() { setZValue( zValue() - 1 ); setPen( m_pen ); m_arrow->setPen( m_pen ); update(); } void DependencyLinkItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { //debugPlanDepEditor; QGraphicsItem::GraphicsItemFlags f = flags(); if ( isEditable() && itemScene()->connectionMode() ) { itemScene()->clearConnection(); setFlags( f & ~QGraphicsItem::ItemIsSelectable ); } QGraphicsPathItem::mousePressEvent( event ); if ( f != flags() ) { setFlags( f ); } } //-------------------- DependencyCreatorItem::DependencyCreatorItem( QGraphicsItem *parent ) : DependencyLinkItemBase( parent ), predConnector( 0 ), succConnector( 0 ), m_editable( false ) { setZValue( 1000.0 ); clear(); setPen( QPen( Qt::blue, 2 ) ); m_arrow->setBrush( Qt::blue ); m_arrow->setPen( QPen( Qt::blue, 2 ) ); } void DependencyCreatorItem::clear() { hide(); if ( predConnector && predConnector->parentItem() ) { static_cast( predConnector->parentItem() )->setConnectorHoverMode( true ); } else if ( succConnector && succConnector->parentItem() ) { static_cast( succConnector->parentItem() )->setConnectorHoverMode( true ); } predConnector = 0; succConnector = 0; setPath( QPainterPath() ); m_arrow->setPath( QPainterPath() ); } void DependencyCreatorItem::setPredConnector( DependencyConnectorItem *item ) { predConnector = item; //static_cast( item->parentItem() )->setConnectorHoverMode( false ); } void DependencyCreatorItem::setSuccConnector( DependencyConnectorItem *item ) { succConnector = item; } void DependencyCreatorItem::createPath() { if ( predConnector == 0 ) { return; } if ( succConnector == 0 ) { return; } QPointF sp = predConnector->connectorPoint(); QPointF ep = succConnector->connectorPoint(); DependencyLinkItemBase::createPath( sp, predConnector->ctype(), ep, succConnector->ctype() ); } void DependencyCreatorItem::createPath( const QPointF &ep ) { m_arrow->hide(); if ( succConnector ) { return createPath(); } if ( predConnector == 0 ) { return; } QPointF sp = predConnector->connectorPoint(); QPainterPath link( sp ); link.lineTo( ep ); setPath( link ); } QPointF DependencyCreatorItem::startPoint() const { return predConnector == 0 ? QPointF() : predConnector->connectorPoint(); } QPointF DependencyCreatorItem::endPoint() const { return succConnector == 0 ? QPointF() : succConnector->connectorPoint(); } //-------------------- DependencyConnectorItem::DependencyConnectorItem( DependencyNodeItem::ConnectorType type, DependencyNodeItem *parent ) : QGraphicsRectItem( parent ), m_ctype( type ), m_editable( false ) { setCursor( ConnectCursor); setAcceptHoverEvents( true ); setZValue( 500.0 ); setFlag( QGraphicsItem::ItemIsFocusable ); } DependencyScene *DependencyConnectorItem::itemScene() const { return static_cast( scene() ); } DependencyNodeItem *DependencyConnectorItem::nodeItem() const { return static_cast( parentItem() ); } Node *DependencyConnectorItem::node() const { return static_cast( parentItem() )->node(); } QPointF DependencyConnectorItem::connectorPoint() const { QRectF r = rect(); return QPointF( r.x()+r.width(), r.y() + r.height()/2 ); } void DependencyConnectorItem::hoverEnterEvent( QGraphicsSceneHoverEvent * /*event*/ ) { itemScene()->connectorEntered( this, true ); } void DependencyConnectorItem::hoverLeaveEvent( QGraphicsSceneHoverEvent * /*event*/ ) { itemScene()->connectorEntered( this, false ); } void DependencyConnectorItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { if ( ! isEditable() ) { event->ignore(); return; } if (event->button() == Qt::LeftButton ) { m_mousePressPos = event->pos(); } else { event->ignore(); } } void DependencyConnectorItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { m_mousePressPos = QPointF(); if (event->button() != Qt::LeftButton ) { event->ignore(); return; } if ( rect().contains( event->scenePos() ) ) { // user clicked on this item bool multiSelect = (event->modifiers() & Qt::ControlModifier) != 0; if (multiSelect) { itemScene()->multiConnectorClicked( this ); } else { itemScene()->singleConnectorClicked( this ); } return; } QGraphicsItem *item = 0; foreach ( QGraphicsItem *i, itemScene()->items( event->scenePos() ) ) { if ( i->type() == DependencyConnectorItem::Type ) { item = i; break; } } if ( item == 0 || item == itemScene()->fromItem() ) { itemScene()->setFromItem( 0 ); return; } itemScene()->singleConnectorClicked( static_cast( item ) ); } void DependencyConnectorItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (event->buttons() == Qt::LeftButton ) { if ( ! m_mousePressPos.isNull() ) { itemScene()->setFromItem( this ); m_mousePressPos = QPointF(); } QGraphicsItem *item = 0; foreach ( QGraphicsItem *i, itemScene()->items( event->scenePos() ) ) { if ( i->type() == DependencyConnectorItem::Type ) { item = i; break; } } if ( item != this ) { itemScene()->connectorEntered( this, false ); } if ( item != 0 ) { itemScene()->connectorEntered( static_cast( item ), true ); } } else { event->ignore(); } } void DependencyConnectorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget */*widget*/) { //debugPlanDepEditor; QStyleOptionGraphicsItem opt( *option ); opt.exposedRect = rect(); if ( itemScene()->fromItem() == this ) { opt.state |= QStyle::State_Selected; } if ( itemScene()->focusItem() == this ) { opt.state |= QStyle::State_HasFocus; } plan_paintFocusSelectedItem( painter, &opt ); QRectF r = rect(); if ( ctype() == DependencyNodeItem::Start ) { r.setRect( r.right() - (r.width()/2.0) + 1.0, r.y() + ( r.height() * 0.33 ), r.width() / 2.0, r.height() * 0.33 ); } else { r.setRect( r.right() - (r.width()/2.0) - 1.0, r.y() + ( r.height() * 0.33 ), r.width() / 2.0, r.height() * 0.33 ); } painter->fillRect( r, Qt::black ); } QList DependencyConnectorItem::predecessorItems() const { return nodeItem()->predecessorItems( m_ctype ); } QList DependencyConnectorItem::successorItems() const { return nodeItem()->successorItems( m_ctype ); } //-------------------- DependencyNodeItem::DependencyNodeItem( Node *node, DependencyNodeItem *parent ) : QGraphicsRectItem( parent ), m_node( node ), m_parent( 0 ), m_editable( false ) { setAcceptHoverEvents( true ); setZValue( 400.0 ); setParentItem( parent ); m_start = new DependencyConnectorItem( DependencyNodeItem::Start, this ); m_finish = new DependencyConnectorItem( DependencyNodeItem::Finish, this ); m_text = new QGraphicsTextItem( this ); m_textFont = m_text->font(); m_textFont.setPointSize( 10 ); m_text->setFont( m_textFont ); setText(); setFlags( QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable ); // do not attach this item to the scene as it gives continuous paint events when a node item is selected m_symbol = new DependencyNodeSymbolItem(); m_symbol->setZValue( zValue() + 10.0 ); setSymbol(); m_treeIndicator = new QGraphicsPathItem( this ); m_treeIndicator->setPen( QPen( Qt::gray ) ); } DependencyNodeItem::~DependencyNodeItem() { qDeleteAll( m_childrelations ); qDeleteAll( m_parentrelations ); //qDeleteAll( m_children ); delete m_symbol; } void DependencyNodeItem::setText() { m_text->setPlainText( m_node == 0 ? QString() : QString( "%1 %2").arg( m_node->wbsCode() ).arg(m_node->name() ) ); } DependencyScene *DependencyNodeItem::itemScene() const { return static_cast( scene() ); } void DependencyNodeItem::setSymbol() { m_symbol->setSymbol( m_node->type(), itemScene()->symbolRect() ); } QPointF DependencyNodeItem::connectorPoint( DependencyNodeItem::ConnectorType type ) const { QRectF r; if ( type == Start ) { return m_start->connectorPoint(); } return m_finish->connectorPoint(); } void DependencyNodeItem::setConnectorHoverMode( bool mode ) { m_start->setAcceptHoverEvents( mode ); m_finish->setAcceptHoverEvents( mode ); } void DependencyNodeItem::setParentItem( DependencyNodeItem *parent ) { if ( m_parent ) { m_parent->takeChild( this ); } m_parent = parent; if ( m_parent ) { m_parent->addChild( this ); } } void DependencyNodeItem::setExpanded( bool mode ) { foreach ( DependencyNodeItem *ch, m_children ) { itemScene()->setItemVisible( ch, mode ); ch->setExpanded( mode ); } } void DependencyNodeItem::setItemVisible( bool show ) { setVisible( show ); //debugPlanDepEditor<name(); foreach ( DependencyLinkItem *i, m_parentrelations ) { i->setItemVisible( show ); } foreach ( DependencyLinkItem *i, m_childrelations ) { i->setItemVisible( show ); } } DependencyNodeItem *DependencyNodeItem::takeChild( DependencyNodeItem *ch ) { int i = m_children.indexOf( ch ); if ( i == -1 ) { return 0; } return m_children.takeAt( i ); } void DependencyNodeItem::setRectangle( const QRectF &rect ) { //debugPlanDepEditor<( scene() )->connectorWidth(); m_start->setRect( rect.x() + connection, rect.y(), -connection, rect.height() ); m_finish->setRect( rect.right() - connection, rect.y(), connection, rect.height() ); m_text->setPos( m_finish->rect().right() + 2.0, itemScene()->gridY( row() ) ); m_symbol->setPos( rect.topLeft() + QPointF( connection, 0 ) + QPointF( 2.0, 2.0 ) ); } void DependencyNodeItem::moveToY( qreal y ) { QRectF r = rect(); r. moveTop( y ); setRectangle( r ); //debugPlanDepEditor<createPath(); } foreach ( DependencyLinkItem *i, m_childrelations ) { i->createPath(); } DependencyNodeItem *par = this; while ( par->parentItem() ) { par = par->parentItem(); } par->setTreeIndicator( true ); } void DependencyNodeItem::setRow( int row ) { moveToY( itemScene()->itemY( row ) ); } int DependencyNodeItem::row() const { return itemScene()->row( rect().y() ); } void DependencyNodeItem::moveToX( qreal x ) { QRectF r = rect(); r. moveLeft( x ); setRectangle( r ); //debugPlanDepEditor<toPlainText()<<" to="<createPath(); } foreach ( DependencyLinkItem *i, m_childrelations ) { i->createPath(); } DependencyNodeItem *par = this; while ( par->parentItem() ) { par = par->parentItem(); } par->setTreeIndicator( true ); } void DependencyNodeItem::setColumn() { int col = m_parent == 0 ? 0 : m_parent->column() + 1; //debugPlanDepEditor<newChildColumn() ); } if ( col != column() ) { setColumn( col ); foreach ( DependencyLinkItem *i, m_childrelations ) { i->succItem->setColumn(); } //debugPlanDepEditor<setColumn(); } } } void DependencyNodeItem::setColumn( int col ) { moveToX( itemScene()->itemX( col ) ); } int DependencyNodeItem::column() const { return itemScene()->column( rect().x() ); } DependencyLinkItem *DependencyNodeItem::takeParentRelation( DependencyLinkItem *r ) { int i = m_parentrelations.indexOf( r ); if ( i == -1 ) { return 0; } DependencyLinkItem *dep = m_parentrelations.takeAt( i ); setColumn(); return dep; } DependencyLinkItem *DependencyNodeItem::takeChildRelation( DependencyLinkItem *r ) { int i = m_childrelations.indexOf( r ); if ( i == -1 ) { return 0; } return m_childrelations.takeAt( i ); } void DependencyNodeItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { debugPlanDepEditor; QGraphicsItem::GraphicsItemFlags f = flags(); if ( itemScene()->connectionMode() ) { itemScene()->clearConnection(); setFlags( f & ~QGraphicsItem::ItemIsSelectable ); } QGraphicsRectItem::mousePressEvent( event ); if ( f != flags() ) { setFlags( f ); } } void DependencyNodeItem::paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget * ) { //debugPlanDepEditor; QLinearGradient g( 0.0, rect().top(), 0.0, rect().bottom() ); g.setColorAt( 0.0, option->palette.color( QPalette::Midlight ) ); g.setColorAt( 1.0, option->palette.color( QPalette::Dark ) ); QBrush b( g ); painter->setBrush( b ); painter->setPen( QPen( Qt::NoPen ) ); painter->drawRect( rect() ); QStyleOptionGraphicsItem opt( *option ); opt.exposedRect = rect().adjusted( -m_start->rect().width(), 0.0, -m_finish->rect().width(), 0.0 ); if ( this == itemScene()->focusItem() ) { opt.state |= QStyle::State_HasFocus; } plan_paintFocusSelectedItem( painter, &opt ); // paint the symbol m_symbol->paint( itemScene()->project(), painter, &opt ); } DependencyConnectorItem *DependencyNodeItem::connectorItem( ConnectorType ctype ) const { switch ( ctype ) { case Start: return m_start; case Finish: return m_finish; default: break; } return 0; } QList DependencyNodeItem::predecessorItems( ConnectorType ctype ) const { QList lst; foreach ( DependencyLinkItem *i, m_parentrelations ) { if ( ctype == Start && ( i->relation->type() == Relation::StartStart || i->relation->type() == Relation::FinishStart ) ) { lst << i; } if ( ctype == Finish && i->relation->type() == Relation::FinishFinish ) { lst << i; } } return lst; } QList DependencyNodeItem::successorItems( ConnectorType ctype ) const { QList lst; foreach ( DependencyLinkItem *i, m_childrelations ) { if ( ctype == Start && i->relation->type() == Relation::StartStart ) { lst << i; } if ( ctype == Finish && ( i->relation->type() == Relation::FinishFinish || i->relation->type() == Relation::FinishStart ) ) { lst << i; } } return lst; } qreal DependencyNodeItem::treeIndicatorX() const { return rect().x() + 18.0; } void DependencyNodeItem::setTreeIndicator( bool on ) { paintTreeIndicator( on ); foreach ( DependencyNodeItem *i, m_children ) { if ( i->isVisible() ) { i->setTreeIndicator( on ); } } } void DependencyNodeItem::paintTreeIndicator( bool on ) { if ( ! on ) { m_treeIndicator->hide(); return; } QPainterPath p; qreal y1 = itemScene()->gridY( row() ); qreal y2 = itemScene()->gridY( row() + 1 ); for ( DependencyNodeItem *par = m_parent; par; par = par->parentItem() ) { qreal x = par->treeIndicatorX(); p.moveTo( x, y1 ); if ( par == m_parent ) { p.lineTo( x, (y1 + y2) / 2.0 ); p.lineTo( x + 6, (y1 + y2) / 2.0 ); if ( m_node->siblingAfter() ) { p.moveTo( x, (y1 + y2) / 2.0 ); p.lineTo( x, y2 ); } } else if ( par->children().last()->rect().y() > rect().y() ) { p.lineTo( x, (y1 + y2) / 2.0 ); p.lineTo( x, y2 ); } } if ( ! m_children.isEmpty() ) { qreal x = treeIndicatorX(); qreal y = rect().bottom(); p.moveTo( x, y ); p.lineTo( x, itemScene()->gridY( row() + 1 ) ); } if ( p.isEmpty() ) { m_treeIndicator->hide(); } else { m_treeIndicator->setPath( p ); m_treeIndicator->show(); } //debugPlanDepEditor<setBrush( p->config().summaryTaskDefaultColor() ); break; case Node::Type_Task: painter->setBrush( p->config().taskNormalColor() ); break; case Node::Type_Milestone: painter->setBrush( p->config().milestoneNormalColor() ); break; default: painter->setBrush( m_delegate.defaultBrush( m_itemtype ) ); break; } } else { painter->setBrush( m_delegate.defaultBrush( m_itemtype ) ); } painter->setPen( Qt::NoPen ); painter->translate( option->exposedRect.x() + 2.0, option->exposedRect.y() + 2.0 ); painter->drawPath( path() ); } //-------------------- DependencyScene::DependencyScene( QWidget *parent ) : QGraphicsScene( parent ), m_model( 0 ), m_readwrite( false ) { setSceneRect( QRectF() ); m_connectionitem = new DependencyCreatorItem(); addItem( m_connectionitem ); //debugPlanDepEditor; m_connectionitem->hide(); } DependencyScene::~DependencyScene() { //debugPlanDepEditor<<" DELETED"; clearScene(); } void DependencyScene::setFromItem( DependencyConnectorItem *item ) { DependencyConnectorItem *old = fromItem(); m_connectionitem->clear(); if ( old && old->parentItem() ) { old->parentItem()->update(); } if ( item ) { foreach ( QGraphicsItem *i, items() ) { if ( i != m_connectionitem && i->type() != DependencyConnectorItem::Type ) { i->setAcceptHoverEvents( false ); if ( i->type() == DependencyLinkItem::Type ) { static_cast( i )->resetHooverIndication(); } } } item->setCursor( ConnectCursor ); m_connectionitem->setPredConnector( item ); m_connectionitem->show(); } else { foreach ( QGraphicsItem *i, items() ) { if ( i != m_connectionitem && i->type() != DependencyConnectorItem::Type ) i->setAcceptHoverEvents( true ); } } if ( item && item->parentItem() ) { item->parentItem()->update(); } } bool DependencyScene::connectionIsValid( DependencyConnectorItem *pred, DependencyConnectorItem *succ ) { if ( pred->ctype() == DependencyNodeItem::Start && succ->ctype() == DependencyNodeItem::Finish ) { return false; } Node *par = static_cast( pred->parentItem() )->node(); Node *ch = static_cast( succ->parentItem() )->node(); return m_project->linkExists( par, ch ) || m_project->legalToLink( par, ch ); } void DependencyScene::connectorEntered( DependencyConnectorItem *item, bool entered ) { //debugPlanDepEditor<setCursor( ConnectCursor ); if ( ! entered ) { // when we leave a connector we don't have a successor m_connectionitem->setSuccConnector( 0 ); return; } if ( m_connectionitem->predConnector == item ) { // when inside the predecessor, clicking is allowed (deselects connector) item->setCursor( ConnectCursor ); return; } if ( ! m_connectionitem->isVisible() ) { // we are not in connection mode return; } if ( m_connectionitem->predConnector == 0 ) { // nothing we can do if we don't have a predecessor (shouldn't happen) return; } if ( item->parentItem() == m_connectionitem->predConnector->parentItem() ) { // not allowed to connect to the same node item->setCursor( Qt::ForbiddenCursor ); return; } if ( ! ( connectionIsValid( m_connectionitem->predConnector, item ) ) ) { // invalid connection (circular dependency, connecting to parent node, etc) item->setCursor( Qt::ForbiddenCursor ); return; } m_connectionitem->setSuccConnector( item ); m_connectionitem->createPath(); } void DependencyScene::drawBackground ( QPainter *painter, const QRectF &rect ) { QGraphicsScene::drawBackground( painter, rect ); QStyleOptionViewItem opt; QBrush br( opt.palette.brush( QPalette::AlternateBase ) ); int first = row( rect.y() ); int last = row( rect.bottom() ); for ( int r = first; r <= last; ++r ) { if ( r % 2 == 1 ) { qreal oy = gridY( r ); QRectF rct( rect.x(), oy, rect.width(), gridHeight() ); painter->fillRect( rct, br ); //debugPlanDepEditor< DependencyScene::itemList( int type ) const { QList lst; foreach ( QGraphicsItem *i, items() ) { if ( i->type() == type ) { lst << i; } } return lst; } void DependencyScene::clearScene() { m_connectionitem->clear(); QList its, deps; foreach ( QGraphicsItem *i, items() ) { if ( i->type() == DependencyNodeItem::Type && i->parentItem() == 0 ) { its << i; } else if ( i->type() == DependencyLinkItem::Type ) { deps << i; } } qDeleteAll( deps ); qDeleteAll( its ); removeItem( m_connectionitem ); qDeleteAll( items() ); setSceneRect( QRectF() ); addItem( m_connectionitem ); //debugPlanDepEditor; } QList DependencyScene::removeChildItems( DependencyNodeItem *item ) { QList lst; foreach ( DependencyNodeItem *i, item->children() ) { m_allItems.removeAt( m_allItems.indexOf( i ) ); lst << i; lst += removeChildItems( i ); } return lst; } void DependencyScene::moveItem( DependencyNodeItem *item, const QList &lst ) { //debugPlanDepEditor<text(); int idx = m_allItems.indexOf( item ); int ndx = lst.indexOf( item->node() ); Q_ASSERT( idx != -1 && ndx != -1 ); Node *oldParent = item->parentItem() == 0 ? 0 : item->parentItem()->node(); Node *newParent = item->node()->parentNode(); if ( newParent == m_project ) { newParent = 0; } else debugPlanDepEditor<name()<level(); if ( idx != ndx || oldParent != newParent ) { // If I have children, these must be moved too. QList items = removeChildItems( item ); m_allItems.removeAt( idx ); m_allItems.insert( ndx, item ); item->setParentItem( m_allItems.value( lst.indexOf( newParent ) ) ); item->setColumn(); //debugPlanDepEditor<text()<<":"<"<column()<setColumn(); //debugPlanDepEditor<text()<<": ->"<column()<flatNodeList() ); // might have been moved } m_hiddenItems.clear(); m_visibleItems.clear(); int viewrow = 0; for ( int i = 0; i < m_allItems.count(); ++i ) { DependencyNodeItem *itm = m_allItems[ i ]; if ( itm->isVisible() ) { m_visibleItems.insert( i, itm ); //debugPlanDepEditor<text()<<":"<setRow( viewrow ); ++viewrow; } else { m_hiddenItems.insert( i, itm ); } } } DependencyNodeItem *DependencyScene::findPrevItem( Node *node ) const { if ( node->numChildren() == 0 ) { return findItem( node ); } return findPrevItem( node->childNodeIterator().last() ); } DependencyNodeItem *DependencyScene::itemBefore( DependencyNodeItem *parent, Node *node ) const { Node *sib = node->siblingBefore(); DependencyNodeItem *bef = parent; if ( sib ) { bef = findPrevItem( sib ); } return bef; } DependencyNodeItem *DependencyScene::createItem( Node *node ) { DependencyNodeItem *parent = findItem( node->parentNode() ); DependencyNodeItem *after = itemBefore( parent, node ); int i = m_allItems.count()-1; if ( after ) { i = m_allItems.indexOf( after ); //debugPlanDepEditor<<"after="<node()->name()<<" pos="<scene() != this ) { addItem( item ); } item->setEditable( m_readwrite ); item->startConnector()->setEditable( m_readwrite ); item->finishConnector()->setEditable( m_readwrite ); //debugPlanDepEditor<text()<column() + 1; } item->setRectangle( QRectF( itemX( col ), itemY(), itemWidth(), itemHeight() ) ); m_allItems.insert( i+1, item ); setItemVisible( item, true ); return item; } DependencyLinkItem *DependencyScene::findItem( const Relation* rel ) const { foreach ( QGraphicsItem *i, itemList( DependencyLinkItem::Type ) ) { if ( static_cast( i )->relation == rel ) { return static_cast( i ); } } return 0; } DependencyLinkItem *DependencyScene::findItem( const DependencyConnectorItem *c1, const DependencyConnectorItem *c2, bool exact ) const { DependencyNodeItem *n1 = c1->nodeItem(); DependencyNodeItem *n2 = c2->nodeItem(); foreach ( QGraphicsItem *i, itemList( DependencyLinkItem::Type ) ) { DependencyLinkItem *link = static_cast( i ); if ( link->predItem == n1 && link->succItem == n2 ) { switch ( link->relation->type() ) { case Relation::StartStart: if ( c1->ctype() == DependencyNodeItem::Start && c2->ctype() == DependencyNodeItem::Start ) { return link; } break; case Relation::FinishStart: if ( c1->ctype() == DependencyNodeItem::Finish && c2->ctype() == DependencyNodeItem::Start ) { return link; } break; case Relation::FinishFinish: if ( c1->ctype() == DependencyNodeItem::Finish && c2->ctype() == DependencyNodeItem::Finish ) { return link; } break; default: break; } return 0; } if ( link->predItem == n2 && link->succItem == n1 ) { if ( exact ) { return 0; } switch ( link->relation->type() ) { case Relation::StartStart: if ( c2->ctype() == DependencyNodeItem::Start && c1->ctype() == DependencyNodeItem::Start ) { return link; } break; case Relation::FinishStart: if ( c1->ctype() == DependencyNodeItem::Finish && c1->ctype() == DependencyNodeItem::Start ) { return link; } break; case Relation::FinishFinish: if ( c1->ctype() == DependencyNodeItem::Finish && c1->ctype() == DependencyNodeItem::Finish ) { return link; } break; default: break; } return 0; } } return 0; } DependencyNodeItem *DependencyScene::findItem( const Node *node ) const { foreach ( QGraphicsItem *i, itemList( DependencyNodeItem::Type ) ) { if ( static_cast( i )->node() == node ) { return static_cast( i ); } } return 0; } void DependencyScene::createLinks() { foreach ( DependencyNodeItem *i, m_allItems ) { createLinks( i ); } } void DependencyScene::createLinks( DependencyNodeItem *item ) { foreach ( Relation *rel, item->node()->dependChildNodes() ) { createLink( item, rel ); } } void DependencyScene::createLink( DependencyNodeItem *parent, Relation *rel ) { DependencyNodeItem *child = findItem( rel->child() ); if ( parent == 0 || child == 0 ) { return; } DependencyLinkItem *dep = new DependencyLinkItem( parent, child, rel ); dep->setEditable( m_readwrite ); addItem( dep ); //debugPlanDepEditor; dep->createPath(); } void DependencyScene::mouseMoveEvent( QGraphicsSceneMouseEvent *mouseEvent ) { if ( m_connectionitem->isVisible() ) { int x = qMin( qMax( sceneRect().left() + 2, mouseEvent->scenePos().x() ), sceneRect().right() - 4 ); int y = qMin( qMax( sceneRect().top() + 2, mouseEvent->scenePos().y() ), sceneRect().bottom() - 4 ); m_connectionitem->createPath( QPoint( x, y ) ); } QGraphicsScene::mouseMoveEvent( mouseEvent ); //debugPlanDepEditor<scenePos()<<","<isAccepted(); } void DependencyScene::keyPressEvent( QKeyEvent *keyEvent ) { //debugPlanDepEditor<update(); } emit focusItemChanged( focusItem() ); return; } switch ( keyEvent->key() ) { case Qt::Key_Left: { if ( fitem->type() == DependencyNodeItem::Type ) { DependencyConnectorItem *item = static_cast( fitem )->startConnector(); if ( item ) { setFocusItem( item ); } } else if ( fitem->type() == DependencyConnectorItem::Type ) { DependencyConnectorItem *citem = static_cast( fitem ); if ( citem->ctype() == DependencyNodeItem::Start ) { //Goto prev nodes finishConnector DependencyNodeItem *nitem = static_cast( citem->parentItem() ); DependencyNodeItem *item = nodeItem( nitem->row() - 1 ); if ( item ) { setFocusItem( item->finishConnector() ); } } else { // Goto node item (parent) setFocusItem( citem->parentItem() ); } } break; } case Qt::Key_Right: { if ( fitem->type() == DependencyNodeItem::Type ) { DependencyConnectorItem *item = static_cast( fitem )->finishConnector(); if ( item ) { setFocusItem( item ); } } else if ( fitem->type() == DependencyConnectorItem::Type ) { DependencyConnectorItem *citem = static_cast( fitem ); if ( citem->ctype() == DependencyNodeItem::Finish ) { //Goto prev nodes startConnector DependencyNodeItem *nitem = static_cast( citem->parentItem() ); DependencyNodeItem *item = nodeItem( nitem->row() + 1 ); if ( item ) { setFocusItem( item->startConnector() ); } } else { // Goto node item (parent) setFocusItem( citem->parentItem() ); } } break; } case Qt::Key_Up: { if ( fitem->type() == DependencyNodeItem::Type ) { DependencyNodeItem *item = nodeItem( static_cast( fitem )->row() - 1 ); if ( item ) { setFocusItem( item ); } } else if ( fitem->type() == DependencyConnectorItem::Type ) { DependencyConnectorItem *citem = static_cast( fitem ); DependencyNodeItem *nitem = static_cast( citem->parentItem() ); if ( citem->ctype() == DependencyNodeItem::Finish ) { DependencyNodeItem *item = nodeItem( nitem->row() - 1 ); if ( item ) { setFocusItem( item->finishConnector() ); } } else { DependencyNodeItem *item = nodeItem( static_cast( fitem )->row() - 1 ); if ( item ) { setFocusItem( item->startConnector() ); } } } break; } case Qt::Key_Down: { if ( fitem->type() == DependencyNodeItem::Type ) { DependencyNodeItem *item = nodeItem( static_cast( fitem )->row() + 1 ); if ( item ) { setFocusItem( item ); } } else if ( fitem->type() == DependencyConnectorItem::Type ) { DependencyConnectorItem *citem = static_cast( fitem ); DependencyNodeItem *nitem = static_cast( citem->parentItem() ); if ( citem->ctype() == DependencyNodeItem::Finish ) { DependencyNodeItem *item = nodeItem( nitem->row() + 1 ); if ( item ) { setFocusItem( item->finishConnector() ); } } else { DependencyNodeItem *item = nodeItem( static_cast( fitem )->row() + 1 ); if ( item ) { setFocusItem( item->startConnector() ); } } } break; } case Qt::Key_Space: case Qt::Key_Select: { if ( fitem->type() == DependencyConnectorItem::Type ) { singleConnectorClicked( static_cast( fitem ) ); } else if ( fitem->type() == DependencyNodeItem::Type ) { singleConnectorClicked( 0 ); foreach ( QGraphicsItem *i, selectedItems() ) { i->setSelected( false ); } fitem->setSelected( true ); } return; } default: QGraphicsScene::keyPressEvent( keyEvent ); } if ( fitem ) { fitem->parentItem() ? fitem->parentItem()->update() : fitem->update(); } if ( focusItem() ) { focusItem()->parentItem() ? focusItem()->parentItem()->update() : focusItem()->update(); } if ( fitem != focusItem() ) { emit focusItemChanged( focusItem() ); } } DependencyNodeItem *DependencyScene::nodeItem( int row ) const { if ( row < 0 || m_visibleItems.isEmpty() ) { return 0; } foreach ( DependencyNodeItem *i, m_visibleItems ) { if ( i->row() == row ) { return i; } } return 0; } void DependencyScene::singleConnectorClicked( DependencyConnectorItem *item ) { //debugPlanDepEditor; clearSelection(); QList lst; if ( item == 0 || item == fromItem() ) { setFromItem( 0 ); m_clickedItems = lst; } else if ( fromItem() == 0 ) { setFromItem( item ); } else if ( connectionIsValid( fromItem(), item ) ) { emit connectItems( fromItem(), item ); setFromItem( 0 ); } else { setFromItem( 0 ); } emit connectorClicked( item ); } void DependencyScene::multiConnectorClicked( DependencyConnectorItem *item ) { //debugPlanDepEditor; singleConnectorClicked( item ); } void DependencyScene::clearConnection() { setFromItem( 0 ); m_clickedItems.clear(); } void DependencyScene::mousePressEvent( QGraphicsSceneMouseEvent *mouseEvent ) { //debugPlanDepEditor; QGraphicsScene::mousePressEvent( mouseEvent ); if ( ! mouseEvent->isAccepted() ) { clearConnection(); } } void DependencyScene::mouseDoubleClickEvent ( QGraphicsSceneMouseEvent *event ) { //debugPlanDepEditor<pos()<scenePos()<screenPos(); QGraphicsScene::mouseDoubleClickEvent( event ); emit itemDoubleClicked( itemAt( event->scenePos(), QTransform() ) ); } void DependencyScene::contextMenuEvent ( QGraphicsSceneContextMenuEvent *event ) { if ( event->reason() == QGraphicsSceneContextMenuEvent::Mouse ) { debugPlanDepEditor<<"Mouse:"<scenePos(), QTransform())<pos()<scenePos()<screenPos(); emit contextMenuRequested( itemAt( event->scenePos(), QTransform() ), event->screenPos() ); return; } if ( focusItem() ) { if ( focusItem()->type() == DependencyConnectorItem::Type ) { DependencyConnectorItem *to = static_cast( focusItem() ); DependencyConnectorItem *from = fromItem(); debugPlanDepEditor<<"DependencyConnectorItem:"<type() == DependencyConnectorItem::Type ) { static_cast( i )->setEditable( on ); } else if ( i->type() == DependencyLinkItem::Type ) { static_cast( i )->setEditable( on ); } } } //-------------------- DependencyView::DependencyView( QWidget *parent ) : QGraphicsView( parent ), m_project( 0 ), m_dirty( false ), m_active( false ) { setItemScene( new DependencyScene( this ) ); setAlignment( Qt::AlignLeft | Qt::AlignTop ); connect( scene(), SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged()) ); connect( scene(), SIGNAL(connectItems(DependencyConnectorItem*,DependencyConnectorItem*)), this, SIGNAL(makeConnection(DependencyConnectorItem*,DependencyConnectorItem*)) ); connect( scene(), SIGNAL(contextMenuRequested(QGraphicsItem*)), this, SLOT(slotContextMenuRequested(QGraphicsItem*)) ); connect( scene(), SIGNAL(dependencyContextMenuRequested(DependencyLinkItem*,DependencyConnectorItem*)), this, SLOT(slotDependencyContextMenuRequested(DependencyLinkItem*,DependencyConnectorItem*)) ); connect( scene(), SIGNAL(contextMenuRequested(QGraphicsItem*,QPoint)), this, SIGNAL(contextMenuRequested(QGraphicsItem*,QPoint)) ); connect( itemScene(), SIGNAL(focusItemChanged(QGraphicsItem*)), this, SLOT(slotFocusItemChanged(QGraphicsItem*)) ); m_autoScrollTimer.start( 100 ); connect( &m_autoScrollTimer, SIGNAL(timeout()), SLOT(slotAutoScroll()) ); } void DependencyView::slotContextMenuRequested( QGraphicsItem *item ) { if ( item ) { debugPlanDepEditor<boundingRect()<<(item->mapToScene( item->pos() ).toPoint())<<(mapToGlobal( item->mapToParent( item->pos() ).toPoint())); emit contextMenuRequested( item, mapToGlobal( item->mapToScene( item->boundingRect().topRight() ).toPoint() ) ); } } void DependencyView::slotDependencyContextMenuRequested( DependencyLinkItem *item, DependencyConnectorItem */*connector */) { if ( item ) { debugPlanDepEditor<boundingRect()<<(item->mapToScene( item->pos() ).toPoint())<<(mapToGlobal( item->mapToParent( item->pos() ).toPoint())); emit contextMenuRequested( item, mapToGlobal( item->mapToScene( item->boundingRect().topRight() ).toPoint() ) ); } } void DependencyView::slotConnectorClicked( DependencyConnectorItem *item ) { if ( itemScene()->fromItem() == 0 ) { itemScene()->setFromItem( item ); } else { //debugPlanDepEditor<<"emit makeConnection:"<( item->parentItem() )->text(); emit makeConnection( itemScene()->fromItem(), item ); } } void DependencyView::slotSelectionChanged() { //HACK because of tt bug 160653 QTimer::singleShot(0, this, SLOT(slotSelectedItems())); } void DependencyView::slotSelectedItems() { emit selectionChanged( itemScene()->selectedItems() ); } void DependencyView::slotFocusItemChanged( QGraphicsItem *item ) { ensureVisible( item, 10, 10 ); } void DependencyView::setItemScene( DependencyScene *scene ) { setScene( scene ); scene->setProject( m_project ); //slotResizeScene( m_treeview->viewport()->size() ); if ( m_project ) { createItems(); } } void DependencyView::setActive( bool activate ) { m_active = activate; if ( m_active && m_dirty ) { createItems(); } } void DependencyView::setProject( Project *project ) { if ( m_project ) { - disconnect( m_project, SIGNAL(relationAdded(Relation*)), this, SLOT(slotRelationAdded(Relation*)) ); - disconnect( m_project, SIGNAL(relationRemoved(Relation*)), this, SLOT(slotRelationRemoved(Relation*)) ); - disconnect( m_project, SIGNAL(relationModified(Relation*)), this, SLOT(slotRelationModified(Relation*)) ); + disconnect( m_project, SIGNAL(relationAdded(KPlato::Relation*)), this, SLOT(slotRelationAdded(KPlato::Relation*)) ); + disconnect( m_project, SIGNAL(relationRemoved(KPlato::Relation*)), this, SLOT(slotRelationRemoved(KPlato::Relation*)) ); + disconnect( m_project, SIGNAL(relationModified(KPlato::Relation*)), this, SLOT(slotRelationModified(KPlato::Relation*)) ); - disconnect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeAdded(Node*)) ); - disconnect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); - disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - disconnect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotNodeMoved(Node*)) ); + disconnect( m_project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeAdded(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeMoved(KPlato::Node*)), this, SLOT(slotNodeMoved(KPlato::Node*)) ); if ( itemScene() ) { itemScene()->clearScene(); } } m_project = project; if ( project ) { - connect( m_project, SIGNAL(relationAdded(Relation*)), this, SLOT(slotRelationAdded(Relation*)) ); - connect( m_project, SIGNAL(relationRemoved(Relation*)), this, SLOT(slotRelationRemoved(Relation*)) ); - connect( m_project, SIGNAL(relationModified(Relation*)), this, SLOT(slotRelationModified(Relation*)) ); - - connect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeAdded(Node*)) ); - connect( m_project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); - connect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - connect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotNodeMoved(Node*)) ); + connect( m_project, SIGNAL(relationAdded(KPlato::Relation*)), this, SLOT(slotRelationAdded(KPlato::Relation*)) ); + connect( m_project, SIGNAL(relationRemoved(KPlato::Relation*)), this, SLOT(slotRelationRemoved(KPlato::Relation*)) ); + connect( m_project, SIGNAL(relationModified(KPlato::Relation*)), this, SLOT(slotRelationModified(KPlato::Relation*)) ); + + connect( m_project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeAdded(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeMoved(KPlato::Node*)), this, SLOT(slotNodeMoved(KPlato::Node*)) ); connect( m_project, SIGNAL(wbsDefinitionChanged()), this, SLOT(slotWbsCodeChanged()) ); if ( itemScene() ) { itemScene()->setProject( project ); if ( m_active ) { createItems(); } else { m_dirty = true; } } } } DependencyLinkItem *DependencyView::findItem( const Relation* rel ) const { return itemScene()->findItem( rel ); } DependencyNodeItem *DependencyView::findItem( const Node *node ) const { return itemScene()->findItem( node ); } void DependencyView::slotRelationAdded( Relation* rel ) { if ( m_dirty ) { return; } DependencyLinkItem *item = findItem( rel ); if ( item == 0 ) { DependencyNodeItem *p = findItem( rel->parent() ); DependencyNodeItem *c = findItem( rel->child() ); DependencyLinkItem *r = new DependencyLinkItem( p, c, rel ); scene()->addItem( r ); //debugPlanDepEditor; r->createPath(); r->setVisible( c->isVisible() && p->isVisible() ); } else debugPlanDepEditor<<"Relation already exists!"; } void DependencyView::slotRelationRemoved( Relation* rel ) { if ( m_dirty ) { return; } DependencyLinkItem *item = findItem( rel ); if ( item ) { scene()->removeItem( item ); delete item; } else debugPlanDepEditor<<"Relation does not exist!"; } void DependencyView::slotRelationModified( Relation* rel ) { //debugPlanDepEditor; if ( m_dirty ) { return; } slotRelationRemoved( rel ); slotRelationAdded( rel ); } void DependencyView::slotNodeAdded( Node *node ) { //debugPlanDepEditor; if ( m_dirty ) { return; } DependencyNodeItem *item = findItem( node ); if ( item == 0 ) { item = createItem( node ); } else { //debugPlanDepEditor<name(); itemScene()->setItemVisible( item, true ); } ensureVisible( item ); slotWbsCodeChanged(); } void DependencyView::slotNodeRemoved( Node *node ) { if ( m_dirty ) { return; } DependencyNodeItem *item = findItem( node ); if ( item ) { //debugPlanDepEditor<name(); itemScene()->setItemVisible( item, false ); } else debugPlanDepEditor<<"Node does not exist!"; slotWbsCodeChanged(); } void DependencyView::slotNodeChanged( Node *node ) { if ( m_dirty ) { return; } DependencyNodeItem *item = findItem( node ); if ( item && item->isVisible() ) { item->setText(); item->setSymbol(); } else debugPlanDepEditor<<"Node does not exist!"; } void DependencyView::slotWbsCodeChanged() { if ( m_dirty ) { return; } foreach( DependencyNodeItem *i, itemScene()->nodeItems() ) { if ( i->isVisible() ) { i->setText(); } } } void DependencyView::slotNodeMoved( Node *node ) { if ( m_dirty ) { return; } slotNodeRemoved( node ); slotNodeAdded( node ); } void DependencyView::setItemExpanded( int , bool ) { } void DependencyView::createItems() { itemScene()->clearScene(); m_dirty = false; if ( m_project == 0 ) { return; } scene()->addLine( 0.0, 0.0, 1.0, 0.0 ); createItems( m_project ); createLinks(); } DependencyNodeItem *DependencyView::createItem( Node *node ) { return itemScene()->createItem( node ); } void DependencyView::createItems( Node *node ) { if ( node != m_project ) { //debugPlanDepEditor<name()<<" ("<numChildren()<<")"; DependencyNodeItem *i = createItem( node ); if ( i == 0 ) { return; } } foreach ( Node *n, node->childNodeIterator() ) { createItems( n ); } } void DependencyView::createLinks() { //debugPlanDepEditor; itemScene()->createLinks(); } void DependencyView::keyPressEvent(QKeyEvent *event) { if ( event->modifiers() & Qt::ControlModifier ) { switch ( event->key() ) { case Qt::Key_Plus: return scale( 1.1, 1.1 ); case Qt::Key_Minus: return scale( 0.9, 0.9 ); default: break; } } QGraphicsView::keyPressEvent(event); } void DependencyView::mouseMoveEvent( QMouseEvent *mouseEvent ) { m_cursorPos = mouseEvent->pos(); if ( itemScene()->connectionMode() && itemScene()->mouseGrabberItem() ) { QPointF spos = mapToScene( m_cursorPos ); Qt::CursorShape c = Qt::ArrowCursor; foreach ( QGraphicsItem *i, itemScene()->items( spos ) ) { if ( i->type() == DependencyConnectorItem::Type ) { if ( i == itemScene()->fromItem() ) { c = ConnectCursor; } else { if ( itemScene()->connectionIsValid( itemScene()->fromItem(), static_cast( i ) ) ) { c = ConnectCursor; } else { c = Qt::ForbiddenCursor; } } } } if ( viewport()->cursor().shape() != c ) { viewport()->setCursor( c ); } } QGraphicsView::mouseMoveEvent( mouseEvent ); //debugPlanDepEditor<scenePos()<<","<isAccepted(); } void DependencyView::slotAutoScroll() { if ( itemScene()->connectionMode() ) { ensureVisible( QRectF( mapToScene( m_cursorPos ), QSizeF( 1, 1 ) ), 2, 2 ); } } //----------------------------------- DependencyeditorConfigDialog::DependencyeditorConfigDialog( ViewBase *view, QWidget *p, bool selectPrint) : KPageDialog(p), m_view( view ) { setWindowTitle( i18n("Settings") ); QTabWidget *tab = new QTabWidget(); QWidget *w = ViewBase::createPageLayoutWidget( view ); tab->addTab( w, w->windowTitle() ); m_pagelayout = w->findChild(); Q_ASSERT( m_pagelayout ); m_headerfooter = ViewBase::createHeaderFooterWidget( view ); m_headerfooter->setOptions( view->printingOptions() ); tab->addTab( m_headerfooter, m_headerfooter->windowTitle() ); KPageWidgetItem *page = addPage( tab, i18n( "Printing" ) ); page->setHeader( i18n( "Printing Options" ) ); if (selectPrint) { setCurrentPage(page); } connect( this, SIGNAL(accepted()), this, SLOT(slotOk())); } void DependencyeditorConfigDialog::slotOk() { debugPlan; m_view->setPageLayout( m_pagelayout->pageLayout() ); m_view->setPrintingOptions( m_headerfooter->options() ); } //-------------------- DependencyEditor::DependencyEditor(KoPart *part, KoDocument *doc, QWidget *parent ) : ViewBase(part, doc, parent), m_currentnode( 0 ), m_manager( 0 ) { setupGui(); QVBoxLayout * l = new QVBoxLayout( this ); l->setMargin( 0 ); m_view = new DependencyView( this ); l->addWidget( m_view ); connect( m_view, SIGNAL(makeConnection(DependencyConnectorItem*,DependencyConnectorItem*)), this, SLOT(slotCreateRelation(DependencyConnectorItem*,DependencyConnectorItem*)) ); connect( m_view, SIGNAL(selectionChanged(QList)), this, SLOT(slotSelectionChanged(QList)) ); connect( m_view->itemScene(), SIGNAL(itemDoubleClicked(QGraphicsItem*)), this, SLOT(slotItemDoubleClicked(QGraphicsItem*)) ); connect( m_view, SIGNAL(contextMenuRequested(QGraphicsItem*,QPoint)), this, SLOT(slotContextMenuRequested(QGraphicsItem*,QPoint)) ); Help::add(this, xi18nc("@info:whatsthis", "Task Dependency Editor" "" "Edit dependencies between tasks." "Dependencies can be added by dragging a connection area (start or finish)" " from one task to a connection area of a different task." " You can edit or delete a dependency using the context menu." "" "This view supports printing using the context menu." "More..." "", Help::page("Manual/Task_Dependency_Editor_(Graphical)"))); } void DependencyEditor::updateReadWrite( bool on ) { m_view->itemScene()->setReadWrite( on ); ViewBase::updateReadWrite( on ); } void DependencyEditor::slotItemDoubleClicked( QGraphicsItem *item ) { //debugPlanDepEditor; if ( ! isReadWrite() ) { return; } if ( item && item->type() == DependencyLinkItem::Type ) { emit modifyRelation( static_cast( item )->relation ); return; } if ( item && item->type() == DependencyNodeItem::Type ) { emit editNode( static_cast( item )->node() ); return; } if ( item && item->type() == DependencyNodeSymbolItem::Type ) { emit editNode( static_cast( item->parentItem() )->node() ); return; } } void DependencyEditor::slotCreateRelation( DependencyConnectorItem *pred, DependencyConnectorItem *succ ) { //debugPlanDepEditor; if ( ! isReadWrite() ) { return; } Node *par = pred->node(); Node *ch = succ->node(); Relation::Type type = Relation::FinishStart; if ( pred->ctype() == DependencyNodeItem::Start ) { if ( succ->ctype() == DependencyNodeItem::Start ) { type = Relation::StartStart; } } else { if ( succ->ctype() == DependencyNodeItem::Start ) { type = Relation::FinishStart; } else { type = Relation::FinishFinish; } } Relation *rel = ch->findRelation( par ); if ( rel == 0 ) { //debugPlanDepEditor<<"New:"<name()<<" ->"<name()<<","<type() != type ) { //debugPlanDepEditor<<"Mod:"<name()<<" ->"<name()<<","<setProject( &project ); } void DependencyEditor::draw() { } void DependencyEditor::setGuiActive( bool activate ) { //debugPlanDepEditor<setActive( activate ); /* if ( activate && !m_view->selectionModel()->currentIndex().isValid() ) { m_view->selectionModel()->setCurrentIndex(m_view->model()->index( 0, 0 ), QItemSelectionModel::NoUpdate); }*/ } void DependencyEditor::slotCurrentChanged( const QModelIndex &, const QModelIndex & ) { //debugPlanDepEditor<& ) { //debugPlanDepEditor< DependencyEditor::selectedNodes() const { QList lst; foreach ( QGraphicsItem *i, m_view->itemScene()->selectedItems() ) { if ( i->type() == DependencyNodeItem::Type ) { lst << static_cast( i )->node(); } } return lst; } Node *DependencyEditor::selectedNode() const { QList lst = selectedNodes(); if ( lst.count() != 1 ) { return 0; } return lst.first(); } Node *DependencyEditor::currentNode() const { return m_currentnode; /* Node * n = 0; QGraphicsItem *i = m_view->itemScene()->focusItem(); if ( i && i->type() == DependencyNodeItem::Type ) { n = static_cast( i )->node(); } if ( n == 0 || n->type() == Node::Type_Project ) { return 0; } return n;*/ } Relation *DependencyEditor::currentRelation() const { return m_currentrelation; } void DependencyEditor::setScheduleManager( ScheduleManager *sm ) { m_manager = sm; } void DependencyEditor::slotContextMenuRequested( QGraphicsItem *item, const QPoint& pos ) { //debugPlanDepEditor<type() == DependencyNodeSymbolItem::Type ) { item = item->parentItem(); } if ( item ) { if ( item->type() == DependencyNodeItem::Type ) { m_currentnode = static_cast( item )->node(); if ( m_currentnode == 0 ) { //debugPlanDepEditor<<"No node"; return; } bool scheduled = m_manager != 0 && m_currentnode->isScheduled( m_manager->scheduleId() ); switch ( m_currentnode->type() ) { case Node::Type_Task: name = scheduled ? "task_popup" : "task_edit_popup"; break; case Node::Type_Milestone: name = scheduled ? "taskeditor_milestone_popup" : "task_edit_popup"; break; case Node::Type_Summarytask: name = "summarytask_popup"; break; default: break; } //debugPlanDepEditor<name()<<" :"<type() == DependencyLinkItem::Type ) { m_currentrelation = static_cast( item )->relation; if ( m_currentrelation ) { name = "relation_popup"; } } else if ( item->type() == DependencyConnectorItem::Type ) { DependencyConnectorItem *c = static_cast( item ); QList items; QList actions; QMenu menu; foreach ( DependencyLinkItem *i, c->predecessorItems() ) { items << i; actions << menu.addAction(koIcon("document-properties"), i->predItem->text()); } menu.addSeparator(); foreach ( DependencyLinkItem *i, c->successorItems() ) { items << i; actions << menu.addAction(koIcon("document-properties"), i->succItem->text()); } if ( ! actions.isEmpty() ) { QAction *action = menu.exec( pos ); if ( action && actions.contains( action ) ) { emit modifyRelation( items[ actions.indexOf( action ) ]->relation ); return; } } } } //debugPlanDepEditor< lst = contextActionList(); if ( ! lst.isEmpty() ) { QMenu::exec( lst, pos, lst.first() ); } } m_currentnode = 0; m_currentrelation = 0; } void DependencyEditor::slotEnableActions() { updateActionsEnabled( true ); } void DependencyEditor::updateActionsEnabled( bool on ) { if ( ! on || ! isReadWrite() ) { //FIXME: read-write is not set properly menuAddTask->setEnabled( false ); actionAddTask->setEnabled( false ); actionAddMilestone->setEnabled( false ); menuAddSubTask->setEnabled( false ); actionAddSubtask->setEnabled( false ); actionAddSubMilestone->setEnabled( false ); actionDeleteTask->setEnabled( false ); return; } int selCount = selectedNodeCount(); if ( selCount == 0 ) { menuAddTask->setEnabled( true ); actionAddTask->setEnabled( true ); actionAddMilestone->setEnabled( true ); menuAddSubTask->setEnabled( false ); actionAddSubtask->setEnabled( false ); actionAddSubMilestone->setEnabled( false ); actionDeleteTask->setEnabled( false ); return; } Node *n = selectedNode(); if ( n && n->type() != Node::Type_Task && n->type() != Node::Type_Milestone && n->type() != Node::Type_Summarytask ) { n = 0; } if ( selCount == 1 && n == 0 ) { // only project selected menuAddTask->setEnabled( true ); actionAddTask->setEnabled( true ); actionAddMilestone->setEnabled( true ); menuAddSubTask->setEnabled( true ); actionAddSubtask->setEnabled( true ); actionAddSubMilestone->setEnabled( true ); actionDeleteTask->setEnabled( false ); return; } bool baselined = false; Project *p = m_view->project(); if ( p && p->isBaselined() ) { foreach ( Node *n, selectedNodes() ) { if ( n->isBaselined() ) { baselined = true; break; } } } if ( selCount == 1 ) { menuAddTask->setEnabled( true ); actionAddTask->setEnabled( true ); actionAddMilestone->setEnabled( true ); menuAddSubTask->setEnabled( ! baselined || n->type() == Node::Type_Summarytask ); actionAddSubtask->setEnabled( ! baselined || n->type() == Node::Type_Summarytask ); actionAddSubMilestone->setEnabled( ! baselined || n->type() == Node::Type_Summarytask ); actionDeleteTask->setEnabled( ! baselined ); return; } // selCount > 1 menuAddTask->setEnabled( false ); actionAddTask->setEnabled( false ); actionAddMilestone->setEnabled( false ); menuAddSubTask->setEnabled( false ); actionAddSubtask->setEnabled( false ); actionAddSubMilestone->setEnabled( false ); actionDeleteTask->setEnabled( ! baselined ); } void DependencyEditor::setupGui() { KActionCollection *coll = actionCollection(); QString name = "taskeditor_add_list"; menuAddTask = new KActionMenu(koIcon("view-task-add"), i18n("Add Task"), this); coll->addAction("add_task", menuAddTask ); connect( menuAddTask, SIGNAL(triggered(bool)), SLOT(slotAddTask()) ); addAction( name, menuAddTask ); actionAddTask = new QAction( i18n("Add Task..."), this); actionAddTask->setShortcut( Qt::CTRL + Qt::Key_I ); connect( actionAddTask, SIGNAL(triggered(bool)), SLOT(slotAddTask()) ); menuAddTask->addAction( actionAddTask ); actionAddMilestone = new QAction( i18n("Add Milestone..."), this ); actionAddMilestone->setShortcut( Qt::CTRL + Qt::ALT + Qt::Key_I ); connect( actionAddMilestone, SIGNAL(triggered(bool)), SLOT(slotAddMilestone()) ); menuAddTask->addAction( actionAddMilestone ); menuAddSubTask = new KActionMenu(koIcon("view-task-child-add"), i18n("Add Sub-Task"), this); coll->addAction("add_subtask", menuAddTask ); connect( menuAddSubTask, SIGNAL(triggered(bool)), SLOT(slotAddSubtask()) ); addAction( name, menuAddSubTask ); actionAddSubtask = new QAction( i18n("Add Sub-Task..."), this ); actionAddSubtask->setShortcut( Qt::CTRL + Qt::SHIFT + Qt::Key_I ); connect( actionAddSubtask, SIGNAL(triggered(bool)), SLOT(slotAddSubtask()) ); menuAddSubTask->addAction( actionAddSubtask ); actionAddSubMilestone = new QAction( i18n("Add Sub-Milestone..."), this ); actionAddSubMilestone->setShortcut( Qt::CTRL + Qt::SHIFT + Qt::ALT + Qt::Key_I ); connect( actionAddSubMilestone, SIGNAL(triggered(bool)), SLOT(slotAddSubMilestone()) ); menuAddSubTask->addAction( actionAddSubMilestone ); actionDeleteTask = new QAction(koIcon("edit-delete"), xi18nc("@action", "Delete"), this); coll->addAction("delete_task", actionDeleteTask ); coll->setDefaultShortcut(actionDeleteTask, Qt::Key_Delete); connect( actionDeleteTask, SIGNAL(triggered(bool)), SLOT(slotDeleteTask()) ); addAction( name, actionDeleteTask ); createOptionActions(ViewBase::OptionPrint | ViewBase::OptionPrintPreview | ViewBase::OptionPrintPdf | ViewBase::OptionPrintConfig); } void DependencyEditor::slotOptions() { debugPlan; DependencyeditorConfigDialog *dlg = new DependencyeditorConfigDialog( this, this, sender()->objectName() == "print options" ); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } void DependencyEditor::slotAddTask() { //debugPlanDepEditor; m_currentnode = selectedNode(); emit addTask(); m_currentnode = 0; } void DependencyEditor::slotAddMilestone() { //debugPlanDepEditor; m_currentnode = selectedNode(); // sibling emit addMilestone(); m_currentnode = 0; } void DependencyEditor::slotAddSubtask() { //debugPlanDepEditor; m_currentnode = selectedNode(); if ( m_currentnode == 0 ) { return; } emit addSubtask(); m_currentnode = 0; } void DependencyEditor::slotAddSubMilestone() { debugPlanDepEditor; m_currentnode = selectedNode(); if ( m_currentnode == 0 ) { return; } emit addSubMilestone(); m_currentnode = 0; } void DependencyEditor::edit( const QModelIndex &i ) { if ( i.isValid() ) { /* QModelIndex p = m_view->itemModel()->parent( i ); m_view->treeView()->setExpanded( p, true ); m_view->treeView()->selectionModel()->setCurrentIndex( i, QItemSelectionModel::NoUpdate ); m_view->treeView()->edit( i );*/ } } void DependencyEditor::slotDeleteTask() { //debugPlanDepEditor; QList lst = selectedNodes(); while ( true ) { // remove children of selected tasks, as parents delete their children Node *ch = 0; foreach ( Node *n1, lst ) { foreach ( Node *n2, lst ) { if ( n2->isChildOf( n1 ) ) { ch = n2; break; } } if ( ch != 0 ) { break; } } if ( ch == 0 ) { break; } lst.removeAt( lst.indexOf( ch ) ); } foreach ( Node* n, lst ) { debugPlanDepEditor<name(); } emit deleteTaskList( lst ); } KoPrintJob *DependencyEditor::createPrintJob() { DependecyViewPrintingDialog *dia = new DependecyViewPrintingDialog( this, m_view ); dia->printer().setCreator( QString( "Plan %1" ).arg( PLAN_VERSION_STRING ) ); // dia->printer().setFullPage(true); // ignore printer margins return dia; } } // namespace KPlato diff --git a/src/libs/ui/kptdependencyeditor.h b/src/libs/ui/kptdependencyeditor.h index 7b425a58..a7406ee0 100644 --- a/src/libs/ui/kptdependencyeditor.h +++ b/src/libs/ui/kptdependencyeditor.h @@ -1,587 +1,587 @@ /* This file is part of the KDE project Copyright (C) 2006 -2007 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; 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 KPTDEPENDENCYEDITOR_H #define KPTDEPENDENCYEDITOR_H #include "planui_export.h" #include "kptglobal.h" #include "kptitemmodelbase.h" #include "kpttaskeditor.h" #include "kptviewbase.h" #include "kptnode.h" #include "kptganttitemdelegate.h" #include #include #include #include #include class KoPageLayoutWidget; class QModelIndex; namespace KPlato { class Project; //class Node; class Relation; class ScheduleManager; class DependencyNodeSymbolItem; class DependencyConnectorItem; class DependencyNodeItem; class DependencyScene; class DependencyView; class PLANUI_EXPORT DependecyViewPrintingDialog : public PrintingDialog { Q_OBJECT public: DependecyViewPrintingDialog( ViewBase *parent, DependencyView *view ); int documentLastPage() const; void printPage( int page, QPainter &painter ); QList createOptionWidgets() const; private: DependencyView *m_depview; }; class PLANUI_EXPORT DependencyLinkItemBase : public QGraphicsPathItem { public: explicit DependencyLinkItemBase ( QGraphicsItem * parent = 0 ); DependencyLinkItemBase ( DependencyNodeItem *predecessor, DependencyNodeItem *successor, Relation *rel, QGraphicsItem * parent = 0 ); ~DependencyLinkItemBase(); enum { Type = QGraphicsItem::UserType + 10 }; int type() const { return Type; } DependencyScene *itemScene() const; virtual void createPath() {} virtual void createPath( const QPointF &sp, int stype, const QPointF &dp, int dtype ); virtual QPointF startPoint() const { return QPointF(); } virtual QPointF endPoint() const { return QPointF(); } bool isEditable() const { return m_editable; } void setEditable( bool on ) { m_editable = on; } public: bool m_editable; DependencyNodeItem *predItem; DependencyNodeItem *succItem; Relation *relation; QGraphicsPathItem *m_arrow; }; class PLANUI_EXPORT DependencyLinkItem : public DependencyLinkItemBase { public: explicit DependencyLinkItem ( DependencyNodeItem *predecessor, DependencyNodeItem *successor, Relation *rel, QGraphicsItem * parent = 0 ); ~DependencyLinkItem(); enum { Type = QGraphicsItem::UserType + 11 }; int type() const { return Type; } int newChildColumn() const; using DependencyLinkItemBase::createPath; virtual void createPath(); virtual QPointF startPoint() const; virtual QPointF endPoint() const; void setItemVisible( bool show ); void resetHooverIndication(); protected: virtual void hoverEnterEvent( QGraphicsSceneHoverEvent *event ); virtual void hoverLeaveEvent( QGraphicsSceneHoverEvent *event ); virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); private: QPen m_pen; }; class PLANUI_EXPORT DependencyCreatorItem : public DependencyLinkItemBase { public: explicit DependencyCreatorItem ( QGraphicsItem * parent = 0 ); ~DependencyCreatorItem() {} enum { Type = QGraphicsItem::UserType + 12 }; int type() const { return Type; } void clear(); using DependencyLinkItemBase::createPath; virtual void createPath(); void createPath( const QPointF &ep ); virtual QPointF startPoint() const; virtual QPointF endPoint() const; void setItemVisible( bool show ); void setPredConnector( DependencyConnectorItem *item ); void setSuccConnector( DependencyConnectorItem *item ); bool isEditable() const { return m_editable; } void setEditable( bool on ) { m_editable = on; } public: DependencyConnectorItem *predConnector; DependencyConnectorItem *succConnector; bool m_editable; }; //----------------------- class PLANUI_EXPORT DependencyNodeItem : public QGraphicsRectItem { public: explicit DependencyNodeItem( Node *node, DependencyNodeItem *parent = 0 ); ~DependencyNodeItem(); enum { Type = QGraphicsItem::UserType + 1 }; int type() const { return Type; } DependencyNodeItem *parentItem() const { return m_parent; } void setParentItem( DependencyNodeItem *parent ); void addChild( DependencyNodeItem *ch ) { m_children.append( ch ); } DependencyNodeItem *takeChild( DependencyNodeItem *ch ); QList children() const { return m_children; } DependencyScene *itemScene() const; void setRectangle( const QRectF &rect ); void setRow( int row ); int row() const; void setColumn(); void setColumn( int column ); int column() const; Node *node() const { return m_node; } QString text() const { return m_text->toPlainText(); } void setText( const QString &text ) const { m_text->setPlainText( text ); } void setText(); enum ConnectorType { Start, Finish }; QPointF connectorPoint( ConnectorType type ) const; void setConnectorHoverMode( bool mode ); void addParentRelation( DependencyLinkItem *r ) { m_parentrelations.append( r ); } DependencyLinkItem *takeParentRelation( DependencyLinkItem *r ); QList parentRelations() const { return m_parentrelations; } void addChildRelation( DependencyLinkItem *r ) { m_childrelations.append( r ); } DependencyLinkItem *takeChildRelation( DependencyLinkItem *r ); QList childRelations() const { return m_childrelations; } void setExpanded( bool mode ); void setItemVisible( bool show ); void setSymbol(); int nodeLevel() const { return m_node == 0 ? 0 : m_node->level() - 1; } DependencyConnectorItem *startConnector() const { return m_start; } DependencyConnectorItem *finishConnector() const { return m_finish; } DependencyConnectorItem *connectorItem( ConnectorType ctype ) const; QList predecessorItems( ConnectorType ctype ) const; QList successorItems( ConnectorType ctype ) const; bool isEditable() const { return m_editable; } void setEditable( bool on ) { m_editable = on; } qreal treeIndicatorX() const; void setTreeIndicator( bool on ); protected: void moveToY( qreal y ); void moveToX( qreal x ); virtual void mousePressEvent(QGraphicsSceneMouseEvent *event); void paint( QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget ); void paintTreeIndicator( bool on ); private: Node *m_node; DependencyConnectorItem *m_start; DependencyConnectorItem *m_finish; QGraphicsTextItem *m_text; DependencyNodeSymbolItem *m_symbol; QFont m_textFont; DependencyNodeItem *m_parent; QList m_children; QList m_dependParents; QList m_dependChildren; QList m_parentrelations; QList m_childrelations; bool m_editable; QGraphicsPathItem *m_treeIndicator; }; //----------------------- class PLANUI_EXPORT DependencyNodeSymbolItem : public QGraphicsPathItem { public: explicit DependencyNodeSymbolItem( DependencyNodeItem *parent = 0 ) : QGraphicsPathItem( parent ), m_editable( false ) {} enum { Type = QGraphicsItem::UserType + 3 }; int type() const { return Type; } void setSymbol( int type, const QRectF &rect ); bool isEditable() const { return m_editable; } void setEditable( bool on ) { m_editable = on; } using QGraphicsPathItem::paint; /// Special paint method as the default cannot be used void paint( Project *p, QPainter *painter, const QStyleOptionGraphicsItem *option ); private: GanttItemDelegate m_delegate; bool m_editable; int m_nodetype; KGantt::ItemType m_itemtype; }; //----------------------- class PLANUI_EXPORT DependencyConnectorItem : public QGraphicsRectItem { public: DependencyConnectorItem( DependencyNodeItem::ConnectorType type, DependencyNodeItem *parent ); enum { Type = QGraphicsItem::UserType + 2 }; int type() const { return Type; } DependencyNodeItem::ConnectorType ctype() const { return m_ctype; } DependencyScene *itemScene() const; Node* node() const; QPointF connectorPoint() const; DependencyNodeItem *nodeItem() const; QList predecessorItems() const; QList successorItems() const; bool isEditable() const { return m_editable; } void setEditable( bool on ) { m_editable = on; } protected: void hoverEnterEvent ( QGraphicsSceneHoverEvent *event ); void hoverLeaveEvent ( QGraphicsSceneHoverEvent *event ); void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); private: DependencyNodeItem::ConnectorType m_ctype; QPointF m_mousePressPos; bool m_editable; }; //----------------------- class PLANUI_EXPORT DependencyScene : public QGraphicsScene { Q_OBJECT public: explicit DependencyScene(QWidget *parent = 0); ~DependencyScene(); void setProject( Project *p ) { m_project = p; } Project *project() const { return m_project; } QList itemList( int type ) const; void clearScene(); qreal horizontalGap() const { return 40.0; } qreal verticalGap() const { return 6.0; } qreal itemWidth() const { return 50.0; } qreal itemHeight() const { return 26.0; } QRectF symbolRect() const { return QRectF( 1.0, 1.0, 15.0, 15.0 ); } qreal connectorWidth() const { return 8.0; } qreal totalItemWidth() const { return itemWidth(); } qreal columnWidth() const { return horizontalGap() + totalItemWidth(); } qreal gridHeight() const { return verticalGap() + itemHeight(); } qreal gridWidth() const { return horizontalGap() + totalItemWidth(); } qreal gridX( int col ) const { return col * gridWidth(); } qreal itemX( int col=0 ) const { return ( horizontalGap() / 2 ) + ( gridWidth() * col ); } int column( qreal x ) const { return (int)( x / columnWidth() ); } qreal gridY( int row ) const { return row * gridHeight(); } qreal itemY( int row=0 ) const { return ( verticalGap() / 2 ) + ( gridHeight() * row ); } int row( qreal y ) const { return (int)( y / gridHeight() ); } DependencyLinkItem *findItem( const Relation *rel ) const; DependencyLinkItem *findItem( const DependencyConnectorItem *c1, const DependencyConnectorItem *c2, bool exact = true ) const; DependencyNodeItem *findItem( const Node *node ) const; DependencyNodeItem *findPrevItem( Node *node ) const; DependencyNodeItem *itemBefore( DependencyNodeItem *parent, Node *node ) const; DependencyNodeItem *createItem( Node *node ); void setItemVisible( DependencyNodeItem *item, bool show ); void createLinks(); void createLinks( DependencyNodeItem *item ); void createLink( DependencyNodeItem *parent, Relation *rel ); void connectorEntered( DependencyConnectorItem *item, bool entered ); void setFromItem( DependencyConnectorItem *item ); DependencyConnectorItem *fromItem() const { return m_connectionitem->predConnector; } bool connectionMode() const { return m_connectionitem->isVisible(); } void singleConnectorClicked( DependencyConnectorItem *item ); void multiConnectorClicked( DependencyConnectorItem *item ); bool connectionIsValid( DependencyConnectorItem *pred, DependencyConnectorItem *succ ); void clearConnection(); /// Used when a node has been moved void moveItem( DependencyNodeItem *item, const QList &lst ); QList removeChildItems( DependencyNodeItem *item ); DependencyNodeItem *nodeItem( int row ) const; const QList &nodeItems() const { return m_allItems; } void setReadWrite( bool on ); Q_SIGNALS: - void connectorClicked( DependencyConnectorItem *item ); - void connectItems( DependencyConnectorItem *pred, DependencyConnectorItem *succ ); + void connectorClicked(KPlato::DependencyConnectorItem *item); + void connectItems(KPlato::DependencyConnectorItem *pred, KPlato::DependencyConnectorItem *succ); void itemDoubleClicked( QGraphicsItem * ); void contextMenuRequested( QGraphicsItem*, const QPoint& ); void contextMenuRequested( QGraphicsItem* ); - void dependencyContextMenuRequested( DependencyLinkItem*, DependencyConnectorItem* ); + void dependencyContextMenuRequested(KPlato::DependencyLinkItem*, KPlato::DependencyConnectorItem*); void focusItemChanged( QGraphicsItem* ); protected: virtual void drawBackground ( QPainter * painter, const QRectF & rect ); virtual void mouseMoveEvent( QGraphicsSceneMouseEvent *mouseEvent ); virtual void mousePressEvent( QGraphicsSceneMouseEvent *mouseEvent ); virtual void mouseDoubleClickEvent ( QGraphicsSceneMouseEvent *mouseEvent ); virtual void keyPressEvent ( QKeyEvent *keyEvent ); virtual void contextMenuEvent ( QGraphicsSceneContextMenuEvent *contextMenuEvent ); private: Project *m_project; NodeItemModel *m_model; bool m_readwrite; QList m_allItems; QMap m_visibleItems; QMap m_hiddenItems; DependencyCreatorItem *m_connectionitem; QList m_clickedItems; }; //----------------------- class PLANUI_EXPORT DependencyView : public QGraphicsView { Q_OBJECT public: explicit DependencyView(QWidget *parent); void setProject( Project *project ); Project *project() const { return m_project; } void setItemExpanded( int x, bool mode ); DependencyNodeItem *createItem( Node *node ); void createItems( Node *node ); void createItems(); void createLinks(); DependencyLinkItem *findItem( const Relation *rel ) const; DependencyNodeItem *findItem( const Node *node ) const; DependencyScene *itemScene() const { return static_cast( scene() ); } void setItemScene(DependencyScene *scene ); void setActive( bool activate ); Q_SIGNALS: void selectionChanged(); void selectionChanged( QGraphicsItem * ); void selectionChanged( const QList& ); - void makeConnection( DependencyConnectorItem *pred, DependencyConnectorItem *succ ); + void makeConnection(KPlato::DependencyConnectorItem *pred, KPlato::DependencyConnectorItem *succ); void contextMenuRequested( QGraphicsItem*, const QPoint& ); public Q_SLOTS: - void slotNodeAdded( Node *node ); - void slotNodeRemoved( Node *node ); - void slotNodeChanged( Node *node ); - void slotNodeMoved( Node *node ); + void slotNodeAdded(KPlato::Node *node); + void slotNodeRemoved(KPlato::Node *node); + void slotNodeChanged(KPlato::Node *node); + void slotNodeMoved(KPlato::Node *node); protected: void keyPressEvent(QKeyEvent *event); void mouseMoveEvent( QMouseEvent *mouseEvent ); protected Q_SLOTS: void slotSelectionChanged(); - void slotRelationAdded( Relation* rel ); - void slotRelationRemoved( Relation* rel ); - void slotRelationModified( Relation* rel ); + void slotRelationAdded(KPlato::Relation* rel); + void slotRelationRemoved(KPlato::Relation* rel); + void slotRelationModified(KPlato::Relation* rel); void slotWbsCodeChanged(); void slotSelectedItems(); // HACK due to tt bug 160653 - void slotConnectorClicked( DependencyConnectorItem *item ); + void slotConnectorClicked(KPlato::DependencyConnectorItem *item); void slotContextMenuRequested( QGraphicsItem* ); - void slotDependencyContextMenuRequested( DependencyLinkItem *item, DependencyConnectorItem *connector ); + void slotDependencyContextMenuRequested(KPlato::DependencyLinkItem *item, KPlato::DependencyConnectorItem *connector); void slotFocusItemChanged( QGraphicsItem* ); private Q_SLOTS: void slotAutoScroll(); private: Project *m_project; bool m_dirty; bool m_active; QPoint m_cursorPos; QTimer m_autoScrollTimer; }; //-------------------- class DependencyeditorConfigDialog : public KPageDialog { Q_OBJECT public: DependencyeditorConfigDialog( ViewBase *view, QWidget *parent, bool selectPrint = false ); public Q_SLOTS: void slotOk(); private: ViewBase *m_view; KoPageLayoutWidget *m_pagelayout; PrintingHeaderFooter *m_headerfooter; }; //------------------------------ class PLANUI_EXPORT DependencyEditor : public ViewBase { Q_OBJECT public: DependencyEditor(KoPart *part, KoDocument *doc, QWidget *parent); void setupGui(); Project *project() const { return m_view->project(); } virtual void draw( Project &project ); virtual void draw(); virtual Node *currentNode() const; QList selectedNodes() const ; Node *selectedNode() const; virtual Relation *currentRelation() const; virtual void updateReadWrite( bool readwrite ); virtual KoPrintJob *createPrintJob(); DependencyView *view() const { return m_view; } Q_SIGNALS: void requestPopupMenu( const QString&, const QPoint & ); void openNode(); - void editNode( Node *node ); + void editNode(KPlato::Node *node); void addTask(); void addMilestone(); void addSubtask(); void addSubMilestone(); - void deleteTaskList( const QList& ); + void deleteTaskList(const QList&); - void addRelation( Node*, Node*, int ); - void modifyRelation( Relation*, int ); - void modifyRelation( Relation* ); + void addRelation(KPlato::Node*, KPlato::Node*, int); + void modifyRelation(KPlato::Relation*, int); + void modifyRelation(KPlato::Relation*); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); - void slotCreateRelation( DependencyConnectorItem *pred, DependencyConnectorItem *succ ); - void setScheduleManager( ScheduleManager *sm ); + void slotCreateRelation(KPlato::DependencyConnectorItem *pred, KPlato::DependencyConnectorItem *succ ); + void setScheduleManager(KPlato::ScheduleManager *sm); protected Q_SLOTS: virtual void slotOptions(); protected: void updateActionsEnabled( bool on ); int selectedNodeCount() const; private Q_SLOTS: void slotItemDoubleClicked( QGraphicsItem *item ); void slotCurrentChanged( const QModelIndex&, const QModelIndex& ); void slotSelectionChanged( const QList &lst ); void slotContextMenuRequested( QGraphicsItem *item, const QPoint& pos ); void slotEnableActions(); void slotAddTask(); void slotAddSubtask(); void slotAddMilestone(); void slotAddSubMilestone(); void slotDeleteTask(); private: void edit( const QModelIndex &index ); private: DependencyView *m_view; Node *m_currentnode; Relation *m_currentrelation; ScheduleManager *m_manager; KActionMenu *menuAddTask; KActionMenu *menuAddSubTask; QAction *actionAddTask; QAction *actionAddMilestone; QAction *actionAddSubtask; QAction *actionAddSubMilestone; QAction *actionDeleteTask; }; } //namespace KPlato #endif diff --git a/src/libs/ui/kptdocumentseditor.h b/src/libs/ui/kptdocumentseditor.h index 811f932e..dd52df7c 100644 --- a/src/libs/ui/kptdocumentseditor.h +++ b/src/libs/ui/kptdocumentseditor.h @@ -1,125 +1,125 @@ /* This file is part of the KDE project Copyright (C) 2006 - 2007 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 KPTDOCUMENTSEDITOR_H #define KPTDOCUMENTSEDITOR_H #include "planui_export.h" #include #include #include class QPoint; class KoDocument; namespace KPlato { class PLANUI_EXPORT DocumentTreeView : public TreeViewBase { Q_OBJECT public: explicit DocumentTreeView(QWidget *parent); DocumentItemModel *model() const { return static_cast( TreeViewBase::model() ); } Documents *documents() const { return model()->documents(); } void setDocuments( Documents *docs ) { model()->setDocuments( docs ); } Document *currentDocument() const; QList selectedDocuments() const; QModelIndexList selectedRows() const; using QTreeView::selectionChanged; Q_SIGNALS: void selectionChanged( const QModelIndexList& ); protected Q_SLOTS: void slotSelectionChanged( const QItemSelection &selected ); }; class PLANUI_EXPORT DocumentsEditor : public ViewBase { Q_OBJECT public: DocumentsEditor(KoPart *part, KoDocument *doc, QWidget *parent); void setupGui(); using ViewBase::draw; virtual void draw( Documents &docs ); virtual void draw(); DocumentItemModel *model() const { return m_view->model(); } virtual void updateReadWrite( bool readwrite ); virtual Document *currentDocument() const; /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &/*context*/ ) const; DocumentTreeView *view() const { return m_view; } Q_SIGNALS: void addDocument(); - void deleteDocumentList( const QList& ); - void editDocument( Document *doc ); - void viewDocument( Document *doc ); + void deleteDocumentList(const QList&); + void editDocument(KPlato::Document *doc); + void viewDocument(KPlato::Document *doc); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); protected Q_SLOTS: virtual void slotOptions(); protected: void updateActionsEnabled( bool on = true ); private Q_SLOTS: void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); void slotHeaderContextMenuRequested( const QPoint &pos ); void slotSelectionChanged( const QModelIndexList& ); void slotCurrentChanged( const QModelIndex& ); void slotEnableActions( bool on ); void slotEditDocument(); void slotViewDocument(); void slotAddDocument(); void slotDeleteSelection(); private: DocumentTreeView *m_view; QAction *actionEditDocument; QAction *actionViewDocument; QAction *actionAddDocument; QAction *actionDeleteSelection; }; } //KPlato namespace #endif diff --git a/src/libs/ui/kptganttview.cpp b/src/libs/ui/kptganttview.cpp index 2e6f7444..09c45ef4 100644 --- a/src/libs/ui/kptganttview.cpp +++ b/src/libs/ui/kptganttview.cpp @@ -1,1460 +1,1460 @@ /* This file is part of the KDE project Copyright (C) 2002 - 2007, 2012 Dag Andersen Copyright (C) 2006 Raphael Langerhorst Copyright (C) 2016 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptganttview.h" #include "kptnodeitemmodel.h" #include "kptappointment.h" #include "kptnode.h" #include "kptproject.h" #include "kpttask.h" #include "kptresource.h" #include "kptrelation.h" #include "kptschedule.h" #include "kptviewbase.h" #include "kptitemviewsettup.h" #include "kptduration.h" #include "kptdatetime.h" #include "kptresourceappointmentsmodel.h" #include "Help.h" #include "kptdebug.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 /// The main namespace namespace KPlato { class GanttItemDelegate; //------------------------------------------------- GanttChartDisplayOptionsPanel::GanttChartDisplayOptionsPanel( GanttItemDelegate *delegate, QWidget *parent ) : QWidget( parent ), m_delegate( delegate ) { setupUi( this ); setValues( *delegate ); connect( ui_showTaskName, SIGNAL(stateChanged(int)), SIGNAL(changed()) ); connect( ui_showResourceNames, SIGNAL(stateChanged(int)), SIGNAL(changed()) ); connect( ui_showDependencies, SIGNAL(stateChanged(int)), SIGNAL(changed()) ); connect( ui_showPositiveFloat, SIGNAL(stateChanged(int)), SIGNAL(changed()) ); connect( ui_showNegativeFloat, SIGNAL(stateChanged(int)), SIGNAL(changed()) ); connect( ui_showCriticalPath, SIGNAL(stateChanged(int)), SIGNAL(changed()) ); connect( ui_showCriticalTasks, SIGNAL(stateChanged(int)), SIGNAL(changed()) ); connect( ui_showCompletion, SIGNAL(stateChanged(int)), SIGNAL(changed()) ); connect( ui_showSchedulingError, SIGNAL(stateChanged(int)), SIGNAL(changed()) ); connect( ui_showTimeConstraint, SIGNAL(stateChanged(int)), SIGNAL(changed()) ); } void GanttChartDisplayOptionsPanel::slotOk() { m_delegate->showTaskName = ui_showTaskName->checkState() == Qt::Checked; m_delegate->showResources = ui_showResourceNames->checkState() == Qt::Checked; m_delegate->showTaskLinks = ui_showDependencies->checkState() == Qt::Checked; m_delegate->showPositiveFloat = ui_showPositiveFloat->checkState() == Qt::Checked; m_delegate->showNegativeFloat = ui_showNegativeFloat->checkState() == Qt::Checked; m_delegate->showCriticalPath = ui_showCriticalPath->checkState() == Qt::Checked; m_delegate->showCriticalTasks = ui_showCriticalTasks->checkState() == Qt::Checked; m_delegate->showProgress = ui_showCompletion->checkState() == Qt::Checked; m_delegate->showSchedulingError = ui_showSchedulingError->checkState() == Qt::Checked; m_delegate->showTimeConstraint = ui_showTimeConstraint->checkState() == Qt::Checked; } void GanttChartDisplayOptionsPanel::setValues( const GanttItemDelegate &del ) { ui_showTaskName->setCheckState( del.showTaskName ? Qt::Checked : Qt::Unchecked ); ui_showResourceNames->setCheckState( del.showResources ? Qt::Checked : Qt::Unchecked ); ui_showDependencies->setCheckState( del.showTaskLinks ? Qt::Checked : Qt::Unchecked ); ui_showPositiveFloat->setCheckState( del.showPositiveFloat ? Qt::Checked : Qt::Unchecked ); ui_showNegativeFloat->setCheckState( del.showNegativeFloat ? Qt::Checked : Qt::Unchecked ); ui_showCriticalPath->setCheckState( del.showCriticalPath ? Qt::Checked : Qt::Unchecked ); ui_showCriticalTasks->setCheckState( del.showCriticalTasks ? Qt::Checked : Qt::Unchecked ); ui_showCompletion->setCheckState( del.showProgress ? Qt::Checked : Qt::Unchecked ); ui_showSchedulingError->setCheckState( del.showSchedulingError ? Qt::Checked : Qt::Unchecked ); ui_showTimeConstraint->setCheckState( del.showTimeConstraint ? Qt::Checked : Qt::Unchecked ); } void GanttChartDisplayOptionsPanel::setDefault() { GanttItemDelegate del; setValues( del ); } //---- GanttViewSettingsDialog::GanttViewSettingsDialog( GanttViewBase *gantt, GanttItemDelegate *delegate, ViewBase *view, bool selectPrint ) : ItemViewSettupDialog( view, gantt->treeView(), true, view ), m_gantt( gantt ) { GanttChartDisplayOptionsPanel *panel = new GanttChartDisplayOptionsPanel( delegate ); /*KPageWidgetItem *page = */insertWidget( 1, panel, i18n( "Chart" ), i18n( "Gantt Chart Settings" ) ); QTabWidget *tab = new QTabWidget(); QWidget *w = ViewBase::createPageLayoutWidget( view ); tab->addTab( w, w->windowTitle() ); m_pagelayout = w->findChild(); Q_ASSERT( m_pagelayout ); m_printingoptions = new GanttPrintingOptionsWidget( this ); m_printingoptions->setOptions( gantt->printingOptions() ); tab->addTab( m_printingoptions, m_printingoptions->windowTitle() ); KPageWidgetItem *page = insertWidget( 2, tab, i18n( "Printing" ), i18n( "Printing Options" ) ); if (selectPrint) { setCurrentPage(page); } connect( this, SIGNAL(accepted()), this, SLOT(slotOk()) ); connect( this, SIGNAL(accepted()), panel, SLOT(slotOk()) ); connect( button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked(bool)), panel, SLOT(setDefault()) ); } void GanttViewSettingsDialog::slotOk() { debugPlan; m_gantt->setPrintingOptions( m_printingoptions->options()); ItemViewSettupDialog::slotOk(); } //------------------------- GanttPrintingOptions::GanttPrintingOptions() : printRowLabels( true ), singlePage( true ) { } bool GanttPrintingOptions::loadContext( const KoXmlElement &settings ) { KoXmlElement e = settings.namedItem( "print-options" ).toElement(); if ( ! e.isNull() ) { printRowLabels = (bool)( e.attribute( "print-rowlabels", "0" ).toInt() ); singlePage = (bool)( e.attribute( "print-singlepage", "0" ).toInt() ); } debugPlan <<"..........."<treeView()->header()->height(); // same header hight m_sceneRect = gantt->graphicsView()->sceneRect(); m_horPages = 1; qreal c = m_sceneRect.width() - printer().pageRect().width(); while ( c > 0 ) { ++m_horPages; c -= printer().pageRect().width(); } m_vertPages = 1; c = m_sceneRect.height() - printer().pageRect().height() - m_headerHeight; while ( c > 0 ) { ++m_vertPages; c -= printer().pageRect().height(); } debugPlan< pages; if ( printer().fromPage() > 0 ) { pages << printer().fromPage(); if ( ! m_gantt->m_printOptions.singlePage ) { int last = printer().toPage(); for ( int i = pages.first() + 1; i <= last; ++i ) { pages << i; } if (m_vertPages > 1) { m_image = QImage(m_sceneRect.width(), m_sceneRect.height() + m_headerHeight, QImage::Format_ARGB32); m_image.fill(Qt::white); QPainter p(&m_image); m_gantt->print(&p, m_image.rect(), m_gantt->m_printOptions.printRowLabels, true); } } } setPageRange( pages ); PrintingDialog::startPrinting( removePolicy ); } QList GanttPrintingDialog::createOptionWidgets() const { //debugPlan; GanttPrintingOptionsWidget *w = new GanttPrintingOptionsWidget(); w->setPrintRowLabels( m_gantt->m_printOptions.printRowLabels ); connect(w->ui_printRowLabels, SIGNAL(toggled(bool)), SLOT(slotPrintRowLabelsToogled(bool))); w->setSinglePage( m_gantt->m_printOptions.singlePage ); connect(w->ui_singlePage, SIGNAL(toggled(bool)), SLOT(slotSinglePageToogled(bool))); const_cast( this )->m_options = w; return QList() << createPageLayoutWidget() << m_options; } void GanttPrintingDialog::slotPrintRowLabelsToogled( bool on ) { m_gantt->m_printOptions.printRowLabels = on; } void GanttPrintingDialog::slotSinglePageToogled( bool on ) { m_gantt->m_printOptions.singlePage = on; printer().setFromTo( documentFirstPage(), documentLastPage() ); } int GanttPrintingDialog::documentLastPage() const { //debugPlan<m_printOptions.singlePage<m_printOptions.singlePage ? documentFirstPage() : m_horPages * m_vertPages; } void GanttPrintingDialog::printPage( int page, QPainter &painter ) { debugPlan<<"page:"<m_printOptions.singlePage; int vert = singlePage ? 0 : p / m_horPages; int hor = singlePage ? 0 : p % m_horPages; // painter.setClipRect( pageRect.adjusted( -1.0, -1.0, 1.0, 1.0 ) ); if (singlePage) { // single page: use KGantt m_gantt->print( &painter, m_sceneRect.left(), m_sceneRect.right(), pageRect, m_gantt->m_printOptions.printRowLabels, true ); } else if (m_vertPages == 1) { // single vertical page: use KGantt qreal hh = vert == 0 ? m_headerHeight : 0; qreal ho = vert > 0 ? m_headerHeight : 0; QRectF sourceRect = QRectF( m_sceneRect.x() + ( pageRect.width() * hor ), m_sceneRect.y() + ( ( pageRect.height() * vert ) - ho ), pageRect.width(), pageRect.height() - hh ); debugPlan<print( &painter, sourceRect.left(), sourceRect.right(), pageRect, hor == 0 && m_gantt->m_printOptions.printRowLabels, true ); } else { // print on multiple vertical pages: use pixmap // QT5TODO Make KGantt able to print multiple pages vertically QRectF sourceRect = m_image.rect(); qreal hh = vert == 0 ? m_headerHeight : 0; qreal ho = vert > 0 ? m_headerHeight : 0; sourceRect = QRectF( sourceRect.x() + ( pageRect.width() * hor ), sourceRect.y() + ( ( pageRect.height() * vert ) - ho ), pageRect.width(), pageRect.height() - hh ); debugPlan<setContextMenuPolicy( Qt::CustomContextMenu ); connect( header(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(slotHeaderContextMenuRequested(QPoint)) ); } //------------------------------------------- GanttZoomWidget::GanttZoomWidget( QWidget *parent ) : QSlider( parent ), m_hide( true ), m_grid( 0 ) { setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); setGeometry( 0, 0, 200, minimumSizeHint().height() ); setContextMenuPolicy( Qt::PreventContextMenu ); setOrientation( Qt::Horizontal ); setPageStep( 5 ); setMaximum( 125 ); connect(this, SIGNAL(valueChanged(int)), SLOT(sliderValueChanged(int))); } void GanttZoomWidget::setEnableHideOnLeave( bool hide ) { m_hide = hide; } void GanttZoomWidget::setGrid( KGantt::DateTimeGrid *grid ) { m_grid = grid; if ( grid ) { int pos = -1; // daywidth always >= 0.1 for ( qreal dw = grid->dayWidth(); dw >= 0.1 && pos < maximum(); ++pos ) { dw *= 1.0 / 1.1; } blockSignals( true ); setValue( pos ); blockSignals( false ); } } void GanttZoomWidget::leaveEvent( QEvent *e ) { if ( m_hide ) { setVisible( false ); } QSlider::leaveEvent( e ); } void GanttZoomWidget::sliderValueChanged( int value ) { //debugPlan<setDayWidth( v ); } } //------------------------------------------- GanttViewBase::GanttViewBase( QWidget *parent ) : KGantt::View( parent ) { KGantt::DateTimeGrid *g = static_cast( grid() ); g->setUserDefinedUpperScale( new KGantt::DateTimeScaleFormatter(KGantt::DateTimeScaleFormatter::Month, QString::fromLatin1("yyyy-MMMM"))); g->setUserDefinedLowerScale( new KGantt::DateTimeScaleFormatter(KGantt::DateTimeScaleFormatter::Day, QString::fromLatin1("ddd"))); QLocale locale; g->setWeekStart( locale.firstDayOfWeek() ); const QList weekdays = locale.weekdays(); QSet fd; for ( int i = Qt::Monday; i <= Qt::Sunday; ++i ) { if (!weekdays.contains(static_cast(i))) { fd << static_cast( i ); } } g->setFreeDays( fd ); m_zoomwidget = new GanttZoomWidget( graphicsView() ); m_zoomwidget->setGrid( g ); m_zoomwidget->setEnableHideOnLeave( true ); m_zoomwidget->hide(); m_zoomwidget->move( 6, 6 ); graphicsView()->installEventFilter(this); graphicsView()->setMouseTracking(true); } GanttViewBase::~GanttViewBase() { // HACK: avoid crash due to access of graphicsview scrollbar after death // KGantt tries to sync leftview scrollbar with graphicsview scrollbar // and seems sometimes graphicsview has already been deleted. // Note: this will be fixed in next KGantt release leftView()->verticalScrollBar()->disconnect(); } GanttTreeView *GanttViewBase::treeView() const { GanttTreeView *tv = qobject_cast(const_cast(leftView())); Q_ASSERT(tv); return tv; } bool GanttViewBase::eventFilter(QObject *obj, QEvent *event) { if (obj != graphicsView()) { return false; } if (event->type() == QEvent::HoverMove) { QHoverEvent *e = static_cast( event ); if (e->pos().y() > 7 && e->pos().y() < m_zoomwidget->height() + 5 && e->pos().x() > 7 && e->pos().x() < m_zoomwidget->width() + 5 ) { if ( !m_zoomwidget->isVisible()) { m_zoomwidget->show(); m_zoomwidget->setFocus(); } return true; } } return false; } bool GanttViewBase::loadContext( const KoXmlElement &settings ) { KGantt::DateTimeGrid *g = static_cast( grid() ); g->setScale( static_cast( settings.attribute( "chart-scale", "0" ).toInt() ) ); g->setDayWidth( settings.attribute( "chart-daywidth", "30" ).toDouble() ); return true; } void GanttViewBase::saveContext( QDomElement &settings ) const { KGantt::DateTimeGrid *g = static_cast( grid() ); settings.setAttribute( "chart-scale", QString::number(g->scale()) ); settings.setAttribute( "chart-daywidth", QString::number(g->dayWidth()) ); } //------------------------------------------- NodeGanttViewBase::NodeGanttViewBase( QWidget *parent ) : GanttViewBase( parent ), m_project( 0 ), m_ganttdelegate( new GanttItemDelegate( this ) ) { debugPlan<<"------------------- create NodeGanttViewBase -----------------------"; graphicsView()->setItemDelegate( m_ganttdelegate ); GanttTreeView *tv = new GanttTreeView( this ); tv->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); tv->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); tv->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel ); // needed since qt 4.2 setLeftView( tv ); m_rowController = new KGantt::TreeViewRowController( tv, ganttProxyModel() ); setRowController( m_rowController ); tv->header()->setStretchLastSection( true ); NodeSortFilterProxyModel *m = new NodeSortFilterProxyModel( &m_defaultModel, this ); KGantt::View::setModel( m ); } NodeGanttViewBase::~NodeGanttViewBase() { delete m_rowController; } NodeSortFilterProxyModel *NodeGanttViewBase::sfModel() const { return static_cast( KGantt::View::model() ); } void NodeGanttViewBase::setItemModel( ItemModelBase *model ) { sfModel()->setSourceModel( model ); } ItemModelBase *NodeGanttViewBase::model() const { return sfModel()->itemModel(); } void NodeGanttViewBase::setProject( Project *project ) { model()->setProject( project ); m_project = project; } bool NodeGanttViewBase::loadContext( const KoXmlElement &settings ) { treeView()->loadContext( model()->columnMap(), settings ); KoXmlElement e = settings.namedItem( "ganttchart" ).toElement(); if ( ! e.isNull() ) { m_ganttdelegate->showTaskLinks = (bool)( e.attribute( "show-dependencies", "0" ).toInt() ); m_ganttdelegate->showTaskName = (bool)( e.attribute( "show-taskname", "0" ).toInt() ); m_ganttdelegate->showResources = (bool)( e.attribute( "show-resourcenames", "0" ).toInt() ); m_ganttdelegate->showProgress = (bool)( e.attribute( "show-completion", "0" ).toInt() ); m_ganttdelegate->showCriticalPath = (bool)( e.attribute( "show-criticalpath", "0" ).toInt() ); m_ganttdelegate->showCriticalTasks = (bool)( e.attribute( "show-criticaltasks", "0" ).toInt() ); m_ganttdelegate->showPositiveFloat = (bool)( e.attribute( "show-positivefloat", "0" ).toInt() ); m_ganttdelegate->showSchedulingError = (bool)( e.attribute( "show-schedulingerror", "0" ).toInt() ); m_ganttdelegate->showTimeConstraint = (bool)( e.attribute( "show-timeconstraint", "0" ).toInt() ); m_ganttdelegate->showNegativeFloat = (bool)( e.attribute( "show-negativefloat", "0" ).toInt() ); GanttViewBase::loadContext( e ); m_printOptions.loadContext( e ); } return true; } void NodeGanttViewBase::saveContext( QDomElement &settings ) const { debugPlan; treeView()->saveContext( model()->columnMap(), settings ); QDomElement e = settings.ownerDocument().createElement( "ganttchart" ); settings.appendChild( e ); e.setAttribute( "show-dependencies", QString::number(m_ganttdelegate->showTaskLinks) ); e.setAttribute( "show-taskname", QString::number(m_ganttdelegate->showTaskName) ); e.setAttribute( "show-resourcenames", QString::number(m_ganttdelegate->showResources) ); e.setAttribute( "show-completion", QString::number(m_ganttdelegate->showProgress) ); e.setAttribute( "show-criticalpath", QString::number(m_ganttdelegate->showCriticalPath) ); e.setAttribute( "show-criticaltasks",QString::number(m_ganttdelegate->showCriticalTasks) ); e.setAttribute( "show-positivefloat", QString::number(m_ganttdelegate->showPositiveFloat) ); e.setAttribute( "show-schedulingerror", QString::number(m_ganttdelegate->showSchedulingError) ); e.setAttribute( "show-timeconstraint", QString::number(m_ganttdelegate->showTimeConstraint) ); e.setAttribute( "show-negativefloat", QString::number(m_ganttdelegate->showNegativeFloat) ); GanttViewBase::saveContext( e ); m_printOptions.saveContext( e ); } //------------------------------------------- MyKGanttView::MyKGanttView( QWidget *parent ) : NodeGanttViewBase( parent ), m_manager( 0 ) { debugPlan<<"------------------- create MyKGanttView -----------------------"; GanttItemModel *gm = new GanttItemModel( this ); setItemModel( gm ); treeView()->createItemDelegates( gm ); QList show; show << NodeModel::NodeName << NodeModel::NodeCompleted << NodeModel::NodeStartTime << NodeModel::NodeEndTime; treeView()->setDefaultColumns( show ); for ( int i = 0; i < model()->columnCount(); ++i ) { if ( ! show.contains( i ) ) { treeView()->hideColumn( i ); } } setConstraintModel( new KGantt::ConstraintModel( this ) ); KGantt::ProxyModel *m = static_cast( ganttProxyModel() ); m->setRole( KGantt::ItemTypeRole, KGantt::ItemTypeRole ); // To provide correct format m->setRole( KGantt::StartTimeRole, Qt::EditRole ); // To provide correct format m->setRole( KGantt::EndTimeRole, Qt::EditRole ); // To provide correct format m->removeColumn( Qt::DisplayRole ); m->setColumn( KGantt::ItemTypeRole, NodeModel::NodeType ); m->setColumn( KGantt::StartTimeRole, NodeModel::NodeStartTime ); m->setColumn( KGantt::EndTimeRole, NodeModel::NodeEndTime ); m->setColumn( KGantt::TaskCompletionRole, NodeModel::NodeCompleted ); KGantt::DateTimeGrid *g = static_cast( grid() ); g->setDayWidth( 30 ); // TODO: extend QLocale/KGantt to support formats for hourly time display // see bug #349030 // removed custom code here - connect( model(), SIGNAL(nodeInserted(Node*)), this, SLOT(slotNodeInserted(Node*)) ); + connect( model(), SIGNAL(nodeInserted(KPlato::Node*)), this, SLOT(slotNodeInserted(KPlato::Node*)) ); } GanttItemModel *MyKGanttView::model() const { return static_cast( NodeGanttViewBase::model() ); } void MyKGanttView::setProject( Project *proj ) { clearDependencies(); if ( project() ) { disconnect( project(), SIGNAL(relationToBeModified(Relation*)), this, SLOT(removeDependency(Relation*))); disconnect( project(), SIGNAL(relationModified(Relation*)), this, SLOT(addDependency(Relation*))); disconnect( project(), SIGNAL(relationAdded(Relation*)), this, SLOT(addDependency(Relation*)) ); disconnect( project(), SIGNAL(relationToBeRemoved(Relation*)), this, SLOT(removeDependency(Relation*)) ); disconnect( project(), SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); } NodeGanttViewBase::setProject( proj ); if ( proj ) { connect( project(), SIGNAL(relationToBeModified(Relation*)), this, SLOT(removeDependency(Relation*))); connect( project(), SIGNAL(relationModified(Relation*)), this, SLOT(addDependency(Relation*))); connect( proj, SIGNAL(relationAdded(Relation*)), this, SLOT(addDependency(Relation*)) ); connect( proj, SIGNAL(relationToBeRemoved(Relation*)), this, SLOT(removeDependency(Relation*)) ); connect( proj, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); } createDependencies(); } void MyKGanttView::slotProjectCalculated( ScheduleManager *sm ) { if ( m_manager == sm ) { setScheduleManager( sm ); } } void MyKGanttView::setScheduleManager( ScheduleManager *sm ) { clearDependencies(); m_manager = sm; KGantt::DateTimeGrid *g = static_cast( grid() ); if ( sm && project() ) { QDateTime start = project()->startTime( sm->scheduleId() ); if ( g->startDateTime() != start ) { g->setStartDateTime( start ); } } if ( ! g->startDateTime().isValid() ) { g->setStartDateTime( QDateTime::currentDateTime() ); } model()->setScheduleManager( sm ); createDependencies(); } void MyKGanttView::slotNodeInserted( Node *node ) { foreach( Relation *r, node->dependChildNodes() ) { addDependency( r ); } foreach( Relation *r, node->dependParentNodes() ) { addDependency( r ); } } void MyKGanttView::addDependency( Relation *rel ) { QModelIndex par = sfModel()->mapFromSource( model()->index( rel->parent() ) ); QModelIndex ch = sfModel()->mapFromSource( model()->index( rel->child() ) ); // debugPlan<<"addDependency() "<( rel->type() )/*NOTE!!*/ ); if ( ! constraintModel()->hasConstraint( con ) ) { constraintModel()->addConstraint( con ); } } } void MyKGanttView::removeDependency( Relation *rel ) { QModelIndex par = sfModel()->mapFromSource( model()->index( rel->parent() ) ); QModelIndex ch = sfModel()->mapFromSource( model()->index( rel->child() ) ); KGantt::Constraint con( par, ch, KGantt::Constraint::TypeSoft, static_cast( rel->type() )/*NOTE!!*/ ); constraintModel()->removeConstraint( con ); } void MyKGanttView::clearDependencies() { constraintModel()->clear(); // Remove old deps from view // NOTE: This should be handled by KGantt graphicsView()->updateScene(); } void MyKGanttView::createDependencies() { clearDependencies(); if ( project() == 0 || m_manager == 0 ) { return; } foreach ( Node* n, project()->allNodes() ) { foreach ( Relation *r, n->dependChildNodes() ) { addDependency( r ); } } } //------------------------------------------ GanttView::GanttView(KoPart *part, KoDocument *doc, QWidget *parent, bool readWrite) : ViewBase(part, doc, parent), m_readWrite( readWrite ), m_project( 0 ) { debugPlan <<" ---------------- KPlato: Creating GanttView ----------------"; QVBoxLayout *l = new QVBoxLayout( this ); l->setMargin( 0 ); m_splitter = new QSplitter( this ); l->addWidget( m_splitter ); m_splitter->setOrientation( Qt::Vertical ); m_gantt = new MyKGanttView( m_splitter ); connect(this, SIGNAL(expandAll()), m_gantt->treeView(), SLOT(slotExpand())); connect(this, SIGNAL(collapseAll()), m_gantt->treeView(), SLOT(slotCollapse())); setupGui(); updateReadWrite( readWrite ); //connect( m_gantt->constraintModel(), SIGNAL(constraintAdded(Constraint)), this, SLOT(update()) ); debugPlan <constraintModel(); connect( m_gantt->treeView(), SIGNAL(contextMenuRequested(QModelIndex,QPoint,QModelIndexList)), SLOT(slotContextMenuRequested(QModelIndex,QPoint)) ); connect( m_gantt->treeView(), SIGNAL(headerContextMenuRequested(QPoint)), SLOT(slotHeaderContextMenuRequested(QPoint)) ); Help::add(this, xi18nc("@info:whatsthis", "Gantt View" "" "Displays scheduled tasks in a Gantt diagram." " The chart area can be zoomed in and out with a slider" " positioned in the upper left corner of the time scale." " You need to hoover over it with the mouse for it to show." "" "This view supports configuration and printing using the context menu of the tree view." "More..." "", Help::page("Manual/Task_Gantt_View"))); } KoPrintJob *GanttView::createPrintJob() { return new GanttPrintingDialog( this, m_gantt ); } void GanttView::setZoom( double ) { //debugPlan <<"setting gantt zoom:" << zoom; //m_gantt->setZoomFactor(zoom,true); NO!!! setZoomFactor() is something else } void GanttView::setupGui() { // create context menu actions actionShowProject = new KToggleAction( i18n( "Show Project" ), this ); // FIXME: Dependencies depend on these methods being called in the correct order connect(actionShowProject, SIGNAL(triggered(bool)), m_gantt, SLOT(clearDependencies())); connect(actionShowProject, SIGNAL(triggered(bool)), m_gantt->model(), SLOT(setShowProject(bool))); connect(actionShowProject, SIGNAL(triggered(bool)), m_gantt, SLOT(createDependencies())); addContextAction( actionShowProject ); createOptionActions(ViewBase::OptionAll); } void GanttView::slotOptions() { debugPlan; GanttViewSettingsDialog *dlg = new GanttViewSettingsDialog( m_gantt, m_gantt->delegate(), this, sender()->objectName() == "print options" ); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } void GanttView::slotOptionsFinished( int result ) { GanttViewSettingsDialog *dlg = qobject_cast( sender() ); if ( dlg && result == QDialog::Accepted ) { m_gantt->graphicsView()->updateScene(); } ViewBase::slotOptionsFinished( result ); } void GanttView::clear() { // m_gantt->clear(); } void GanttView::setShowResources( bool on ) { m_gantt->delegate()->showResources = on; } void GanttView::setShowTaskName( bool on ) { m_gantt->delegate()->showTaskName = on; } void GanttView::setShowProgress( bool on ) { m_gantt->delegate()->showProgress = on; } void GanttView::setShowPositiveFloat( bool on ) { m_gantt->delegate()->showPositiveFloat = on; } void GanttView::setShowCriticalTasks( bool on ) { m_gantt->delegate()->showCriticalTasks = on; } void GanttView::setShowCriticalPath( bool on ) { m_gantt->delegate()->showCriticalPath = on; } void GanttView::setShowNoInformation( bool on ) { m_gantt->delegate()->showNoInformation = on; } void GanttView::setShowAppointments( bool on ) { m_gantt->delegate()->showAppointments = on; } void GanttView::setShowTaskLinks( bool on ) { m_gantt->delegate()->showTaskLinks = on; } void GanttView::setProject( Project *project ) { m_gantt->setProject( project ); } void GanttView::setScheduleManager( ScheduleManager *sm ) { if (!sm && scheduleManager()) { // we should only get here if the only schedule manager is scheduled, // or when last schedule manager is deleted m_domdoc.clear(); QDomElement element = m_domdoc.createElement("expanded"); m_domdoc.appendChild(element); m_gantt->treeView()->saveExpanded(element); } bool tryexpand = sm && !scheduleManager(); bool expand = sm && scheduleManager() && sm != scheduleManager(); QDomDocument doc; if (expand) { QDomElement element = doc.createElement("expanded"); doc.appendChild(element); m_gantt->treeView()->saveExpanded(element); } ViewBase::setScheduleManager(sm); m_gantt->setScheduleManager( sm ); if (expand) { m_gantt->treeView()->doExpand(doc); } else if (tryexpand) { m_gantt->treeView()->doExpand(m_domdoc); } } void GanttView::draw( Project &project ) { setProject( &project ); } void GanttView::drawChanges( Project &project ) { if ( m_project != &project ) { setProject( &project ); } } Node *GanttView::currentNode() const { QModelIndex idx = m_gantt->treeView()->selectionModel()->currentIndex(); return m_gantt->model()->node( m_gantt->sfModel()->mapToSource( idx ) ); } void GanttView::slotContextMenuRequested( const QModelIndex &idx, const QPoint &pos ) { debugPlan; QString name; Node *node = m_gantt->model()->node( m_gantt->sfModel()->mapToSource( idx ) ); if ( node ) { switch ( node->type() ) { case Node::Type_Task: name = "taskview_popup"; break; case Node::Type_Milestone: name = "taskview_milestone_popup"; break; case Node::Type_Summarytask: name = "taskview_summary_popup"; break; default: break; } } else debugPlan<<"No node"; m_gantt->treeView()->setContextMenuIndex(idx); if ( name.isEmpty() ) { slotHeaderContextMenuRequested( pos ); m_gantt->treeView()->setContextMenuIndex(QModelIndex()); debugPlan<<"No menu"; return; } emit requestPopupMenu( name, pos ); m_gantt->treeView()->setContextMenuIndex(QModelIndex()); } bool GanttView::loadContext( const KoXmlElement &settings ) { debugPlan; ViewBase::loadContext( settings ); bool show = (bool)(settings.attribute( "show-project", "0" ).toInt() ); actionShowProject->setChecked( show ); m_gantt->model()->setShowProject( show ); // why is this not called by the action? return m_gantt->loadContext( settings ); } void GanttView::saveContext( QDomElement &settings ) const { debugPlan; ViewBase::saveContext( settings ); settings.setAttribute( "show-project", QString::number(actionShowProject->isChecked()) ); m_gantt->saveContext( settings ); } void GanttView::updateReadWrite( bool on ) { // TODO: KGanttView needs read/write mode m_readWrite = on; } //---- MilestoneGanttViewSettingsDialog::MilestoneGanttViewSettingsDialog( GanttViewBase *gantt, ViewBase *view, bool selectPrint ) : ItemViewSettupDialog( view, gantt->treeView(), true, view ), m_gantt( gantt ) { QTabWidget *tab = new QTabWidget(); QWidget *w = ViewBase::createPageLayoutWidget( view ); tab->addTab( w, w->windowTitle() ); m_pagelayout = w->findChild(); Q_ASSERT( m_pagelayout ); m_printingoptions = new GanttPrintingOptionsWidget( this ); m_printingoptions->setOptions( gantt->printingOptions() ); tab->addTab( m_printingoptions, m_printingoptions->windowTitle() ); KPageWidgetItem *page = insertWidget( -1, tab, i18n( "Printing" ), i18n( "Printing Options" ) ); if (selectPrint) { setCurrentPage(page); } connect( this, SIGNAL(accepted()), this, SLOT(slotOk()) ); } void MilestoneGanttViewSettingsDialog::slotOk() { debugPlan; m_gantt->setPrintingOptions( m_printingoptions->options()); ItemViewSettupDialog::slotOk(); } //------------------------ MilestoneKGanttView::MilestoneKGanttView( QWidget *parent ) : NodeGanttViewBase( parent ), m_manager( 0 ) { debugPlan<<"------------------- create MilestoneKGanttView -----------------------"; MilestoneItemModel *mm = new MilestoneItemModel( this ); setItemModel( mm ); treeView()->createItemDelegates( mm ); sfModel()->setFilterRole ( Qt::EditRole ); sfModel()->setFilterFixedString( QString::number( Node::Type_Milestone ) ); sfModel()->setFilterKeyColumn( NodeModel::NodeType ); QList show; show << NodeModel::NodeWBSCode << NodeModel::NodeName << NodeModel::NodeStartTime; treeView()->setDefaultColumns( show ); for ( int i = 0; i < model()->columnCount(); ++i ) { if ( ! show.contains( i ) ) { treeView()->hideColumn( i ); } } treeView()->header()->moveSection(NodeModel::NodeWBSCode, show.indexOf(NodeModel::NodeWBSCode)); treeView()->setRootIsDecorated ( false ); KGantt::ProxyModel *m = static_cast( ganttProxyModel() ); m->setRole( KGantt::ItemTypeRole, KGantt::ItemTypeRole ); // To provide correct format m->setRole( KGantt::StartTimeRole, Qt::EditRole ); // To provide correct format m->setRole( KGantt::EndTimeRole, Qt::EditRole ); // To provide correct format m->removeColumn( Qt::DisplayRole ); m->setColumn( KGantt::ItemTypeRole, NodeModel::NodeType ); m->setColumn( KGantt::StartTimeRole, NodeModel::NodeStartTime ); m->setColumn( KGantt::EndTimeRole, NodeModel::NodeEndTime ); m->setColumn( KGantt::TaskCompletionRole, NodeModel::NodeCompleted ); KGantt::DateTimeGrid *g = static_cast( grid() ); g->setDayWidth( 30 ); // TODO: extend QLocale/KGantt to support formats for hourly time display // see bug #349030 // removed custom code here // TODO: add to context treeView()->sortByColumn(NodeModel::NodeWBSCode, Qt::AscendingOrder); treeView()->setSortingEnabled(true); Help::add(this, xi18nc("@info:whatsthis", "Milestone Gantt View" "" "Displays scheduled milestones in a Gantt diagram." " The chart area can be zoomed in and out with a slider" " positioned in the upper left corner of the time scale." " You need to hoover over it with the mouse for it to show." "" "This view supports configuration and printing using the context menu." "More..." "", Help::page("Manual/Milestone_Gantt_View"))); } MilestoneItemModel *MilestoneKGanttView::model() const { return static_cast( NodeGanttViewBase::model() ); } void MilestoneKGanttView::setProject( Project *proj ) { if ( project() ) { disconnect( project(), SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); } NodeGanttViewBase::setProject( proj ); if ( proj ) { connect( proj, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); } } void MilestoneKGanttView::slotProjectCalculated( ScheduleManager *sm ) { if ( m_manager == sm ) { setScheduleManager( sm ); } } void MilestoneKGanttView::setScheduleManager( ScheduleManager *sm ) { //debugPlan<setScheduleManager( 0 ); m_manager = sm; KGantt::DateTimeGrid *g = static_cast( grid() ); if ( sm && m_project ) { QDateTime start; foreach ( const Node *n, model()->mileStones() ) { QDateTime nt = n->startTime( sm->scheduleId() ); if ( ! nt.isValid() ) { continue; } if ( ! start.isValid() || start > nt ) { start = nt; debugPlan<name()<startTime( sm->scheduleId() ); } if ( g->startDateTime() != start ) { g->setStartDateTime( start ); } } if ( ! g->startDateTime().isValid() ) { g->setStartDateTime( QDateTime::currentDateTime() ); } model()->setScheduleManager( sm ); } //------------------------------------------ MilestoneGanttView::MilestoneGanttView(KoPart *part, KoDocument *doc, QWidget *parent, bool readWrite) : ViewBase(part, doc, parent), m_readWrite( readWrite ), m_project( 0 ) { debugPlan <<" ---------------- Plan: Creating Milesone GanttView ----------------"; QVBoxLayout *l = new QVBoxLayout( this ); l->setMargin( 0 ); m_splitter = new QSplitter( this ); l->addWidget( m_splitter ); m_splitter->setOrientation( Qt::Vertical ); setupGui(); m_gantt = new MilestoneKGanttView( m_splitter ); m_showTaskName = false; // FIXME m_showProgress = false; //FIXME m_showPositiveFloat = false; //FIXME m_showCriticalTasks = false; //FIXME m_showNoInformation = false; //FIXME updateReadWrite( readWrite ); connect( m_gantt->treeView(), SIGNAL(contextMenuRequested(QModelIndex,QPoint,QModelIndexList)), SLOT(slotContextMenuRequested(QModelIndex,QPoint)) ); connect( m_gantt->treeView(), SIGNAL(headerContextMenuRequested(QPoint)), SLOT(slotHeaderContextMenuRequested(QPoint)) ); } void MilestoneGanttView::setZoom( double ) { //debugPlan <<"setting gantt zoom:" << zoom; //m_gantt->setZoomFactor(zoom,true); NO!!! setZoomFactor() is something else } void MilestoneGanttView::show() { } void MilestoneGanttView::clear() { } void MilestoneGanttView::setProject( Project *project ) { m_gantt->setProject( project ); } void MilestoneGanttView::setScheduleManager( ScheduleManager *sm ) { //debugPlan<setScheduleManager( sm ); } void MilestoneGanttView::draw( Project &project ) { setProject( &project ); } void MilestoneGanttView::drawChanges( Project &project ) { if ( m_project != &project ) { setProject( &project ); } } Node *MilestoneGanttView::currentNode() const { QModelIndex idx = m_gantt->treeView()->selectionModel()->currentIndex(); return m_gantt->model()->node( m_gantt->sfModel()->mapToSource( idx ) ); } void MilestoneGanttView::setupGui() { createOptionActions(ViewBase::OptionAll); } void MilestoneGanttView::slotContextMenuRequested( const QModelIndex &idx, const QPoint &pos ) { debugPlan; QString name; Node *node = m_gantt->model()->node( m_gantt->sfModel()->mapToSource( idx ) ); if ( node ) { switch ( node->type() ) { case Node::Type_Task: name = "taskview_popup"; break; case Node::Type_Milestone: name = "taskview_milestone_popup"; break; case Node::Type_Summarytask: name = "taskview_summary_popup"; break; default: break; } } else debugPlan<<"No node"; m_gantt->treeView()->setContextMenuIndex(idx); if ( name.isEmpty() ) { debugPlan<<"No menu"; slotHeaderContextMenuRequested( pos ); m_gantt->treeView()->setContextMenuIndex(QModelIndex()); return; } emit requestPopupMenu( name, pos ); m_gantt->treeView()->setContextMenuIndex(QModelIndex()); } void MilestoneGanttView::slotOptions() { debugPlan; MilestoneGanttViewSettingsDialog *dlg = new MilestoneGanttViewSettingsDialog( m_gantt, this, sender()->objectName() == "print options" ); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } bool MilestoneGanttView::loadContext( const KoXmlElement &settings ) { debugPlan; ViewBase::loadContext( settings ); return m_gantt->loadContext( settings ); } void MilestoneGanttView::saveContext( QDomElement &settings ) const { debugPlan; ViewBase::saveContext( settings ); return m_gantt->saveContext( settings ); } void MilestoneGanttView::updateReadWrite( bool on ) { m_readWrite = on; } KoPrintJob *MilestoneGanttView::createPrintJob() { return new GanttPrintingDialog( this, m_gantt ); } //-------------------- ResourceAppointmentsGanttViewSettingsDialog::ResourceAppointmentsGanttViewSettingsDialog( GanttViewBase *gantt, ViewBase *view, bool selectPrint ) : ItemViewSettupDialog( view, gantt->treeView(), true, view ) , m_gantt(gantt) { QTabWidget *tab = new QTabWidget(); QWidget *w = ViewBase::createPageLayoutWidget( view ); tab->addTab( w, w->windowTitle() ); m_pagelayout = w->findChild(); Q_ASSERT( m_pagelayout ); m_printingoptions = new GanttPrintingOptionsWidget( this ); m_printingoptions->setOptions( gantt->printingOptions() ); tab->addTab( m_printingoptions, m_printingoptions->windowTitle() ); KPageWidgetItem *page = insertWidget( -1, tab, i18n( "Printing" ), i18n( "Printing Options" ) ); if (selectPrint) { setCurrentPage(page); } connect( this, SIGNAL(accepted()), this, SLOT(slotOk()) ); } void ResourceAppointmentsGanttViewSettingsDialog::slotOk() { debugPlan; m_gantt->setPrintingOptions( m_printingoptions->options()); ItemViewSettupDialog::slotOk(); } //------------------------------------------ ResourceAppointmentsGanttView::ResourceAppointmentsGanttView(KoPart *part, KoDocument *doc, QWidget *parent, bool readWrite) : ViewBase(part, doc, parent), m_project( 0 ), m_model( new ResourceAppointmentsGanttModel( this ) ) { debugPlan <<" ---------------- KPlato: Creating ResourceAppointmentsGanttView ----------------"; m_gantt = new GanttViewBase( this ); m_gantt->graphicsView()->setItemDelegate( new ResourceGanttItemDelegate( m_gantt ) ); GanttTreeView *tv = new GanttTreeView( m_gantt ); tv->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); tv->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); tv->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel ); // needed since qt 4.2 m_gantt->setLeftView( tv ); connect(this, SIGNAL(expandAll()), tv, SLOT(slotExpand())); connect(this, SIGNAL(collapseAll()), tv, SLOT(slotCollapse())); m_rowController = new KGantt::TreeViewRowController( tv, m_gantt->ganttProxyModel() ); m_gantt->setRowController( m_rowController ); tv->header()->setStretchLastSection( true ); tv->setTreePosition(-1); KGantt::ProxyModel *m = static_cast( m_gantt->ganttProxyModel() ); m->setRole( KGantt::ItemTypeRole, KGantt::ItemTypeRole ); m->setRole( KGantt::StartTimeRole, KGantt::StartTimeRole ); m->setRole( KGantt::EndTimeRole, KGantt::EndTimeRole ); m->setRole( KGantt::TaskCompletionRole, KGantt::TaskCompletionRole ); m_gantt->setModel( m_model ); QVBoxLayout *l = new QVBoxLayout( this ); l->setMargin( 0 ); l->addWidget( m_gantt ); setupGui(); updateReadWrite( readWrite ); connect( m_gantt->leftView(), SIGNAL(contextMenuRequested(QModelIndex,QPoint,QModelIndexList)), SLOT(slotContextMenuRequested(QModelIndex,QPoint)) ); connect( m_gantt->leftView(), SIGNAL(headerContextMenuRequested(QPoint)), SLOT(slotHeaderContextMenuRequested(QPoint)) ); Help::add(this, xi18nc("@info:whatsthis", "Resource Assignments (Gantt)" "" "Displays the scheduled resource - task assignments in a Gantt diagram." " The chart area can be zoomed in and out with a slider" " positioned in the upper left corner of the time scale." " You need to hoover over it with the mouse for it to show." "" "This view supports configuration and printing using the context menu." "More..." "", Help::page("Manual/Resource_Assignment_Gantt_View"))); } ResourceAppointmentsGanttView::~ResourceAppointmentsGanttView() { delete m_rowController; } void ResourceAppointmentsGanttView::setZoom( double ) { //debugPlan <<"setting gantt zoom:" << zoom; //m_gantt->setZoomFactor(zoom,true); NO!!! setZoomFactor() is something else } Project *ResourceAppointmentsGanttView::project() const { return m_model->project(); } void ResourceAppointmentsGanttView::setProject( Project *project ) { m_model->setProject( project ); } void ResourceAppointmentsGanttView::setScheduleManager( ScheduleManager *sm ) { //debugPlan<saveExpanded(element); } bool tryexpand = sm && !scheduleManager(); bool expand = sm && scheduleManager() && sm != scheduleManager(); QDomDocument doc; if (expand) { QDomElement element = doc.createElement("expanded"); doc.appendChild(element); treeView()->saveExpanded(element); } ViewBase::setScheduleManager(sm); m_model->setScheduleManager( sm ); if (expand) { treeView()->doExpand(doc); } else if (tryexpand) { treeView()->doExpand(m_domdoc); } } void ResourceAppointmentsGanttView::setupGui() { createOptionActions(ViewBase::OptionAll); } Node *ResourceAppointmentsGanttView::currentNode() const { QModelIndex idx = treeView()->selectionModel()->currentIndex(); return m_model->node( idx ); } void ResourceAppointmentsGanttView::slotContextMenuRequested( const QModelIndex &idx, const QPoint &pos ) { debugPlan<node( idx ); if ( n ) { name = "taskview_popup"; } } m_gantt->treeView()->setContextMenuIndex(idx); if ( name.isEmpty() ) { slotHeaderContextMenuRequested( pos ); m_gantt->treeView()->setContextMenuIndex(QModelIndex()); return; } emit requestPopupMenu( name, pos ); m_gantt->treeView()->setContextMenuIndex(QModelIndex()); } void ResourceAppointmentsGanttView::slotOptions() { debugPlan; ItemViewSettupDialog *dlg = new ResourceAppointmentsGanttViewSettingsDialog(m_gantt, this, sender()->objectName() == "print options"); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } bool ResourceAppointmentsGanttView::loadContext( const KoXmlElement &settings ) { debugPlan; ViewBase::loadContext( settings ); m_gantt->loadContext( settings ); return treeView()->loadContext( m_model->columnMap(), settings ); } void ResourceAppointmentsGanttView::saveContext( QDomElement &settings ) const { debugPlan; ViewBase::saveContext( settings ); m_gantt->saveContext( settings ); treeView()->saveContext( m_model->columnMap(), settings ); } void ResourceAppointmentsGanttView::updateReadWrite( bool on ) { m_readWrite = on; } KoPrintJob *ResourceAppointmentsGanttView::createPrintJob() { return new GanttPrintingDialog( this, m_gantt ); } } //KPlato namespace #include "moc_kptganttview.cpp" diff --git a/src/libs/ui/kptganttview.h b/src/libs/ui/kptganttview.h index 635377e3..fd52ce85 100644 --- a/src/libs/ui/kptganttview.h +++ b/src/libs/ui/kptganttview.h @@ -1,477 +1,477 @@ /* This file is part of the KDE project Copyright (C) 2005 Dag Andersen Copyright (C) 2006 Raphael Langerhorst 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 KPTGANTTVIEW_H #define KPTGANTTVIEW_H #include "planui_export.h" #include "kptviewbase.h" #include "kptitemviewsettup.h" #include "kptnodeitemmodel.h" #include "kptganttitemdelegate.h" #include "ui_kptganttprintingoptions.h" #include "ui_kptganttchartdisplayoptions.h" #include #include #include class KoDocument; class QPoint; class QSplitter; class KoPrintJob; namespace KGantt { class TreeViewRowController; } namespace KPlato { class Node; class MilestoneItemModel; class GanttItemModel; class ResourceAppointmentsGanttModel; class Task; class Project; class Relation; class ScheduleManager; class MyKGanttView; class GanttPrintingOptions; class GanttViewBase; class NodeGanttViewBase; class GanttPrintingOptionsWidget; //--------------------------------------- class GanttChartDisplayOptionsPanel : public QWidget, public Ui::GanttChartDisplayOptions { Q_OBJECT public: explicit GanttChartDisplayOptionsPanel( GanttItemDelegate *delegate, QWidget *parent = 0 ); void setValues( const GanttItemDelegate &del ); public Q_SLOTS: void slotOk(); void setDefault(); Q_SIGNALS: void changed(); private: GanttItemDelegate *m_delegate; }; class GanttViewSettingsDialog : public ItemViewSettupDialog { Q_OBJECT public: explicit GanttViewSettingsDialog( GanttViewBase *gantt, GanttItemDelegate *delegate, ViewBase *view, bool selectPrint = false ); protected Q_SLOTS: void slotOk(); private: GanttViewBase *m_gantt; GanttPrintingOptionsWidget *m_printingoptions; }; //-------------------- class GanttPrintingOptions { public: GanttPrintingOptions(); bool loadContext( const KoXmlElement &settings ); void saveContext( QDomElement &settings ) const; bool printRowLabels; bool singlePage; }; class PLANUI_EXPORT GanttPrintingOptionsWidget : public QWidget, public Ui::GanttPrintingOptionsWidget { Q_OBJECT public: explicit GanttPrintingOptionsWidget( QWidget *parent = 0 ); GanttPrintingOptions options() const; void setPrintRowLabels( bool value ) { ui_printRowLabels->setChecked( value ); } bool printRowLabels() const { return ui_printRowLabels->isChecked(); } void setSinglePage( bool value ) { value ? ui_singlePage->setChecked( false ) : ui_multiplePages->setChecked( true ); } bool singlePage() const { return ui_singlePage->isChecked(); } public Q_SLOTS: - void setOptions(const GanttPrintingOptions &opt); + void setOptions(const KPlato::GanttPrintingOptions &opt); }; class GanttPrintingDialog : public PrintingDialog { Q_OBJECT public: GanttPrintingDialog( ViewBase *view, GanttViewBase *gantt ); void startPrinting( RemovePolicy removePolicy ); QList createOptionWidgets() const; void printPage( int page, QPainter &painter ); int documentLastPage() const; protected Q_SLOTS: void slotPrintRowLabelsToogled( bool on ); void slotSinglePageToogled( bool on ); protected: GanttViewBase *m_gantt; QRectF m_sceneRect; int m_horPages; int m_vertPages; double m_headerHeight; GanttPrintingOptionsWidget *m_options; QImage m_image; }; class PLANUI_EXPORT GanttTreeView : public TreeViewBase { Q_OBJECT public: explicit GanttTreeView(QWidget *parent); }; class GanttZoomWidget : public QSlider { Q_OBJECT public: explicit GanttZoomWidget( QWidget *parent ); void setGrid( KGantt::DateTimeGrid *grid ); void setEnableHideOnLeave( bool hide ); protected: void leaveEvent( QEvent *event ); private Q_SLOTS: void sliderValueChanged( int value ); private: bool m_hide; KGantt::DateTimeGrid *m_grid; }; class PLANUI_EXPORT GanttViewBase : public KGantt::View { Q_OBJECT public: explicit GanttViewBase(QWidget *parent); ~GanttViewBase(); GanttTreeView *treeView() const; GanttPrintingOptions printingOptions() const { return m_printOptions; } virtual bool loadContext( const KoXmlElement &settings ); virtual void saveContext( QDomElement &settings ) const; public Q_SLOTS: - void setPrintingOptions( const GanttPrintingOptions &opt ) { m_printOptions = opt; } + void setPrintingOptions(const KPlato::GanttPrintingOptions &opt) { m_printOptions = opt; } protected: bool eventFilter(QObject *obj, QEvent *event); friend class GanttPrintingDialog; GanttPrintingOptions m_printOptions; private: GanttZoomWidget *m_zoomwidget; }; class NodeGanttViewBase : public GanttViewBase { Q_OBJECT public: explicit NodeGanttViewBase(QWidget *parent); ~NodeGanttViewBase(); NodeSortFilterProxyModel *sfModel() const; void setItemModel( ItemModelBase *model ); ItemModelBase *model() const; void setProject( Project *project ); Project *project() const { return m_project; } GanttItemDelegate *delegate() const { return m_ganttdelegate; } bool loadContext( const KoXmlElement &settings ); void saveContext( QDomElement &settings ) const; protected: Project *m_project; GanttItemDelegate *m_ganttdelegate; NodeItemModel m_defaultModel; KGantt::TreeViewRowController *m_rowController; }; class PLANUI_EXPORT MyKGanttView : public NodeGanttViewBase { Q_OBJECT public: explicit MyKGanttView(QWidget *parent); GanttItemModel *model() const; void setProject( Project *project ); void setScheduleManager( ScheduleManager *sm ); public Q_SLOTS: void clearDependencies(); void createDependencies(); - void addDependency( Relation *rel ); - void removeDependency( Relation *rel ); - void slotProjectCalculated( ScheduleManager *sm ); + void addDependency(KPlato::Relation *rel); + void removeDependency(KPlato::Relation *rel); + void slotProjectCalculated(KPlato::ScheduleManager *sm); - void slotNodeInserted( Node *node ); + void slotNodeInserted(KPlato::Node *node); protected: ScheduleManager *m_manager; }; class PLANUI_EXPORT GanttView : public ViewBase { Q_OBJECT public: GanttView(KoPart *part, KoDocument *doc, QWidget *parent, bool readWrite = true); //~GanttView(); virtual void setZoom( double zoom ); void setupGui(); Project *project() const { return m_gantt->project(); } virtual void setProject( Project *project ); using ViewBase::draw; virtual void draw( Project &project ); virtual void drawChanges( Project &project ); Node *currentNode() const; void clear(); virtual bool loadContext( const KoXmlElement &context ); virtual void saveContext( QDomElement &context ) const; void updateReadWrite( bool on ); KoPrintJob *createPrintJob(); void setShowSpecialInfo( bool on ) { m_gantt->model()->setShowSpecial( on ); } bool showSpecialInfo() const { return m_gantt->model()->showSpecial(); } Q_SIGNALS: - void modifyRelation( Relation *rel ) ; - void addRelation( Node *par, Node *child ); - void modifyRelation( Relation *rel, int linkType ) ; - void addRelation( Node *par, Node *child, int linkType ); + void modifyRelation(KPlato::Relation *rel) ; + void addRelation(KPlato::Node *par, KPlato::Node *child); + void modifyRelation(KPlato::Relation *rel, int linkType) ; + void addRelation(KPlato::Node *par, KPlato::Node *child, int linkType); void itemDoubleClicked(); public Q_SLOTS: - void setScheduleManager( ScheduleManager *sm ); + void setScheduleManager(KPlato::ScheduleManager *sm); void setShowResources( bool on ); void setShowTaskName( bool on ); void setShowTaskLinks( bool on ); void setShowProgress( bool on ); void setShowPositiveFloat( bool on ); void setShowCriticalTasks( bool on ); void setShowCriticalPath( bool on ); void setShowNoInformation( bool on ); void setShowAppointments( bool on ); protected Q_SLOTS: void slotContextMenuRequested( const QModelIndex&, const QPoint &pos ); virtual void slotOptions(); virtual void slotOptionsFinished( int result ); private: bool m_readWrite; int m_defaultFontSize; QSplitter *m_splitter; MyKGanttView *m_gantt; Project *m_project; QAction *actionShowProject; QDomDocument m_domdoc; }; class MilestoneGanttViewSettingsDialog : public ItemViewSettupDialog { Q_OBJECT public: MilestoneGanttViewSettingsDialog( GanttViewBase *gantt, ViewBase *view, bool selectPrint = false ); protected Q_SLOTS: virtual void slotOk(); private: GanttViewBase *m_gantt; GanttPrintingOptionsWidget *m_printingoptions; }; class PLANUI_EXPORT MilestoneKGanttView : public NodeGanttViewBase { Q_OBJECT public: explicit MilestoneKGanttView(QWidget *parent); MilestoneItemModel *model() const; void setProject( Project *project ); void setScheduleManager( ScheduleManager *sm ); public Q_SLOTS: - void slotProjectCalculated( ScheduleManager *sm ); + void slotProjectCalculated(KPlato::ScheduleManager *sm); protected: ScheduleManager *m_manager; }; class PLANUI_EXPORT MilestoneGanttView : public ViewBase { Q_OBJECT public: MilestoneGanttView(KoPart *part, KoDocument *doc, QWidget *parent, bool readWrite = true); virtual void setZoom( double zoom ); void show(); virtual void setProject( Project *project ); Project *project() const { return m_gantt->project(); } using ViewBase::draw; virtual void draw( Project &project ); virtual void drawChanges( Project &project ); void setupGui(); Node *currentNode() const; void clear(); virtual bool loadContext( const KoXmlElement &context ); virtual void saveContext( QDomElement &context ) const; void updateReadWrite( bool on ); bool showNoInformation() const { return m_showNoInformation; } KoPrintJob *createPrintJob(); Q_SIGNALS: void itemDoubleClicked(); public Q_SLOTS: - void setScheduleManager( ScheduleManager *sm ); + void setScheduleManager(KPlato::ScheduleManager *sm); void setShowTaskName( bool on ) { m_showTaskName = on; } void setShowProgress( bool on ) { m_showProgress = on; } void setShowPositiveFloat( bool on ) { m_showPositiveFloat = on; } void setShowCriticalTasks( bool on ) { m_showCriticalTasks = on; } void setShowNoInformation( bool on ) { m_showNoInformation = on; } protected Q_SLOTS: void slotContextMenuRequested( const QModelIndex&, const QPoint &pos ); virtual void slotOptions(); private: bool m_readWrite; int m_defaultFontSize; QSplitter *m_splitter; MilestoneKGanttView *m_gantt; bool m_showTaskName; bool m_showProgress; bool m_showPositiveFloat; bool m_showCriticalTasks; bool m_showNoInformation; Project *m_project; }; class ResourceAppointmentsGanttViewSettingsDialog : public ItemViewSettupDialog { Q_OBJECT public: ResourceAppointmentsGanttViewSettingsDialog(GanttViewBase *gantt, ViewBase *view, bool selectPrint = false); public Q_SLOTS: void slotOk(); private: GanttViewBase *m_gantt; GanttPrintingOptionsWidget *m_printingoptions; }; class PLANUI_EXPORT ResourceAppointmentsGanttView : public ViewBase { Q_OBJECT public: ResourceAppointmentsGanttView(KoPart *part, KoDocument *doc, QWidget *parent, bool readWrite = true); ~ResourceAppointmentsGanttView(); virtual void setZoom( double zoom ); virtual void setProject( Project *project ); Project *project() const; void setupGui(); virtual bool loadContext( const KoXmlElement &context ); virtual void saveContext( QDomElement &context ) const; void updateReadWrite( bool on ); KoPrintJob *createPrintJob(); GanttTreeView *treeView() const { return static_cast( m_gantt->leftView() ); } Node *currentNode() const; Q_SIGNALS: void itemDoubleClicked(); public Q_SLOTS: - void setScheduleManager( ScheduleManager *sm ); + void setScheduleManager(KPlato::ScheduleManager *sm); protected Q_SLOTS: void slotContextMenuRequested( const QModelIndex&, const QPoint &pos ); virtual void slotOptions(); private: GanttViewBase *m_gantt; Project *m_project; ResourceAppointmentsGanttModel *m_model; KGantt::TreeViewRowController *m_rowController; QDomDocument m_domdoc; }; } //KPlato namespace #endif diff --git a/src/libs/ui/kpthtmlview.h b/src/libs/ui/kpthtmlview.h index 59058400..0d08e10b 100644 --- a/src/libs/ui/kpthtmlview.h +++ b/src/libs/ui/kpthtmlview.h @@ -1,80 +1,80 @@ /* This file is part of the KDE project Copyright (C) 2009, 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTHTMLVIEW_H #define KPTHTMLVIEW_H #include "planui_export.h" #include "kptviewbase.h" #include "khtml_part.h" class KoDocument; class QUrl; class QPoint; namespace KPlato { class PLANUI_EXPORT HtmlView : public ViewBase { Q_OBJECT public: HtmlView(KoPart *part, KoDocument *doc, QWidget *parent); bool openHtml( const QUrl &url ); void setupGui(); virtual void updateReadWrite( bool readwrite ); KoPrintJob *createPrintJob(); KHTMLPart &htmlPart() { return *m_htmlPart; } const KHTMLPart &htmlPart() const { return *m_htmlPart; } Q_SIGNALS: - void openUrlRequest( HtmlView*, const QUrl& ); + void openUrlRequest(KPlato::HtmlView*, const QUrl&); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); void slotOpenUrlRequest(const QUrl &url, const KParts::OpenUrlArguments &arguments=KParts::OpenUrlArguments(), const KParts::BrowserArguments &browserArguments=KParts::BrowserArguments()); protected: void updateActionsEnabled( bool on = true ); private Q_SLOTS: void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); void slotEnableActions( bool on ); private: KHTMLPart *m_htmlPart; }; } //KPlato namespace #endif diff --git a/src/libs/ui/kptintervaledit.h b/src/libs/ui/kptintervaledit.h index 09ab9686..02494308 100644 --- a/src/libs/ui/kptintervaledit.h +++ b/src/libs/ui/kptintervaledit.h @@ -1,97 +1,97 @@ /* This file is part of the KDE project Copyright (C) 2004 - 2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTINTERVALEDIT_H #define KPTINTERVALEDIT_H #include "planui_export.h" #include "ui_kptintervaleditbase.h" #include "kptcalendar.h" #include namespace KPlato { class MacroCommand; class IntervalEditBase : public QWidget, public Ui::IntervalEditBase { public: explicit IntervalEditBase(QWidget *parent) : QWidget( parent ) { setupUi( this ); } }; class IntervalEditImpl : public IntervalEditBase { Q_OBJECT public: explicit IntervalEditImpl(QWidget *parent); QList intervals() const; void setIntervals(const QList &intervals); protected Q_SLOTS: void slotClearClicked(); void slotAddIntervalClicked(); void slotRemoveIntervalClicked(); void slotIntervalSelectionChanged(); void enableButtons(); Q_SIGNALS: void changed(); }; class IntervalEdit : public IntervalEditImpl { Q_OBJECT public: explicit IntervalEdit( CalendarDay *day, QWidget *parent=0); }; class PLANUI_EXPORT IntervalEditDialog : public KoDialog { Q_OBJECT public: explicit IntervalEditDialog( Calendar *calendar, const QList &days, QWidget *parent = 0 ); explicit IntervalEditDialog( Calendar *calendar, const QList &dates, QWidget *parent = 0 ); MacroCommand *buildCommand(); QList intervals() const { return m_panel->intervals(); } protected Q_SLOTS: void slotChanged(); - void slotCalendarRemoved( const Calendar *cal ); + void slotCalendarRemoved(const KPlato::Calendar *cal); protected: MacroCommand *buildCommand( Calendar *calendar, CalendarDay *day ); private: Calendar *m_calendar; QList m_days; QList m_dates; IntervalEdit *m_panel; }; } //KPlato namespace #endif // INTERVALEDIT_H diff --git a/src/libs/ui/kptmilestoneprogressdialog.cpp b/src/libs/ui/kptmilestoneprogressdialog.cpp index 97ca07d9..234f11b5 100644 --- a/src/libs/ui/kptmilestoneprogressdialog.cpp +++ b/src/libs/ui/kptmilestoneprogressdialog.cpp @@ -1,71 +1,71 @@ /* This file is part of the KDE project Copyright (C) 2005 - 2007 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. */ #include "kptmilestoneprogressdialog.h" #include "kptmilestoneprogresspanel.h" #include "kptnode.h" #include "kptproject.h" #include namespace KPlato { class MacroCommand; MilestoneProgressDialog::MilestoneProgressDialog(Task &task, QWidget *p) : KoDialog(p), m_node( &task ) { setCaption( i18n("Milestone Progress") ); setButtons( Ok|Cancel ); setDefaultButton( Ok ); showButtonSeparator( true ); m_panel = new MilestoneProgressPanel(task, this); setMainWidget(m_panel); enableButtonOk(false); connect(m_panel, SIGNAL(changed()), SLOT(slotChanged())); Project *proj = static_cast( task.projectNode() ); if ( proj ) { - connect(proj, SIGNAL(nodeRemoved(Node*)), SLOT(slotNodeRemoved(Node*))); + connect(proj, SIGNAL(nodeRemoved(KPlato::Node*)), SLOT(slotNodeRemoved(KPlato::Node*))); } } void MilestoneProgressDialog::slotNodeRemoved( Node *node ) { if ( m_node == node ) { reject(); } } void MilestoneProgressDialog::slotChanged() { enableButtonOk(true); } MacroCommand *MilestoneProgressDialog::buildCommand() { return m_panel->buildCommand(); } } //KPlato namespace diff --git a/src/libs/ui/kptmilestoneprogressdialog.h b/src/libs/ui/kptmilestoneprogressdialog.h index c769286b..01eb737c 100644 --- a/src/libs/ui/kptmilestoneprogressdialog.h +++ b/src/libs/ui/kptmilestoneprogressdialog.h @@ -1,55 +1,55 @@ /* This file is part of the KDE project Copyright (C) 2005 - 2007 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 KPTMILESTONEPROGRESSDIALOG_H #define KPTMILESTONEPROGRESSDIALOG_H #include "planui_export.h" #include namespace KPlato { class MilestoneProgressPanel; class Task; class Node; class MacroCommand; class PLANUI_EXPORT MilestoneProgressDialog : public KoDialog { Q_OBJECT public: explicit MilestoneProgressDialog(Task &task, QWidget *parent=0); MacroCommand *buildCommand(); protected Q_SLOTS: void slotChanged(); - void slotNodeRemoved( Node *node ); + void slotNodeRemoved(KPlato::Node *node); private: Node *m_node; MilestoneProgressPanel *m_panel; }; } //KPlato namespace #endif // MILESTONEPROGRESSDIALOG_H diff --git a/src/libs/ui/kptperteditor.cpp b/src/libs/ui/kptperteditor.cpp index 56587d60..718ce3a6 100644 --- a/src/libs/ui/kptperteditor.cpp +++ b/src/libs/ui/kptperteditor.cpp @@ -1,439 +1,439 @@ /* This file is part of the KDE project Copyright (C) 2007 Florian Piquemal Copyright (C) 2007 Alexis Ménard Copyright (C) 2007, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptperteditor.h" #include "kptproject.h" #include "kptrelationeditor.h" #include "kptdebug.h" #include #include #include #include namespace KPlato { //----------------------------------- PertEditor::PertEditor(KoPart *part, KoDocument *doc, QWidget *parent) : ViewBase(part, doc, parent), m_project( 0 ) { debugPlan <<" ---------------- KPlato: Creating PertEditor ----------------"; widget.setupUi(this); m_tasktree = widget.taskList; m_tasktree->setSelectionMode( QAbstractItemView::SingleSelection ); m_availableList = widget.available; m_availableList->setSelectionMode( QAbstractItemView::SingleSelection ); m_requiredList = widget.required; m_requiredList->hideColumn( 1 ); // child node name m_requiredList->setEditTriggers( QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed ); connect( m_requiredList->model(), SIGNAL(executeCommand(KUndo2Command*)), doc, SLOT(addCommand(KUndo2Command*)) ); updateReadWrite( doc->isReadWrite() ); widget.addBtn->setIcon(koIcon("arrow-right")); widget.removeBtn->setIcon(koIcon("arrow-left")); slotAvailableChanged( 0 ); slotRequiredChanged( QModelIndex() ); connect( m_tasktree, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(slotCurrentTaskChanged(QTreeWidgetItem*,QTreeWidgetItem*)) ); connect( m_availableList, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(slotAvailableChanged(QTreeWidgetItem*)) ); connect( m_requiredList->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(slotRequiredChanged(QModelIndex)) ); connect( widget.addBtn, SIGNAL(clicked()), this, SLOT(slotAddClicked()) ); connect( widget.removeBtn, SIGNAL(clicked()), this, SLOT(slotRemoveClicked()) ); connect( this, SIGNAL(executeCommand(KUndo2Command*)), doc, SLOT(addCommand(KUndo2Command*)) ); // TODO: need to use TreeViewBase here // connect(this, SIGNAL(expandAll()), m_tasktree, SLOT(slotExpand())); // connect(this, SIGNAL(collapseAll()), m_tasktree, SLOT(slotCollapse())); } void PertEditor::slotCurrentTaskChanged( QTreeWidgetItem *curr, QTreeWidgetItem *prev ) { //debugPlan<clear(); loadRequiredTasksList( 0 ); } else if ( prev == 0 ) { dispAvailableTasks(); } else { updateAvailableTasks(); loadRequiredTasksList( itemToNode( curr ) ); } slotAvailableChanged( m_availableList->currentItem() ); } void PertEditor::slotAvailableChanged( QTreeWidgetItem *item ) { //debugPlan<<(item?item->text(0):"nil")<<(item?item->data( 0, EnabledRole ).toBool():false); if ( item == 0 || item == m_availableList->currentItem() ) { widget.addBtn->setEnabled( item != 0 && item->data( 0, EnabledRole ).toBool() ); } } void PertEditor::slotRequiredChanged( const QModelIndex &item ) { //debugPlan<setEnabled( item.isValid() ); } void PertEditor::slotAddClicked() { if ( ! isReadWrite() ) { return; } QTreeWidgetItem *item = m_availableList->currentItem(); //debugPlan<currentItem(); if ( selectedTask == 0 ) { return; } Node *par = itemToNode( currentItem ); Node *child = itemToNode( selectedTask ); if ( par == 0 || child == 0 || ! m_project->legalToLink( par, child ) ) { return; } Relation *rel = new Relation ( par, child ); AddRelationCmd *addCmd = new AddRelationCmd( *m_project, rel, kundo2_noi18n(currentItem->text( 0 )) ); emit executeCommand( addCmd ); } void PertEditor::slotRemoveClicked() { if ( ! isReadWrite() ) { return; } Node *n = 0; Relation *r = m_requiredList->currentRelation(); if ( r ) { n = r->parent(); } removeTaskFromRequiredList(); setAvailableItemEnabled( n ); } void PertEditor::removeTaskFromRequiredList() { //debugPlan; Relation *r = m_requiredList->currentRelation(); if ( r == 0 ) { return; } // remove the relation emit executeCommand( new DeleteRelationCmd( *m_project, r, kundo2_i18n( "Remove task dependency" ) ) ); } void PertEditor::setProject( Project *project ) { if ( m_project ) { - disconnect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeAdded(Node*)) ); - disconnect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); - disconnect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotNodeMoved(Node*)) ); - disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - disconnect( m_project, SIGNAL(relationAdded(Relation*)), this, SLOT(slotRelationAdded(Relation*)) ); - disconnect( m_project, SIGNAL(relationRemoved(Relation*)), this, SLOT(slotRelationRemoved(Relation*)) ); + disconnect( m_project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeAdded(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeToBeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeMoved(KPlato::Node*)), this, SLOT(slotNodeMoved(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*)) ); + disconnect( m_project, SIGNAL(relationAdded(KPlato::Relation*)), this, SLOT(slotRelationAdded(KPlato::Relation*)) ); + disconnect( m_project, SIGNAL(relationRemoved(KPlato::Relation*)), this, SLOT(slotRelationRemoved(KPlato::Relation*)) ); } m_project = project; if ( m_project ) { - connect( m_project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeAdded(Node*)) ); - connect( m_project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); - connect( m_project, SIGNAL(nodeMoved(Node*)), this, SLOT(slotNodeMoved(Node*)) ); - connect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - connect( m_project, SIGNAL(relationAdded(Relation*)), this, SLOT(slotRelationAdded(Relation*)) ); - connect( m_project, SIGNAL(relationRemoved(Relation*)), this, SLOT(slotRelationRemoved(Relation*)) ); + connect( m_project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeAdded(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeToBeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeMoved(KPlato::Node*)), this, SLOT(slotNodeMoved(KPlato::Node*)) ); + connect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*)) ); + connect( m_project, SIGNAL(relationAdded(KPlato::Relation*)), this, SLOT(slotRelationAdded(KPlato::Relation*)) ); + connect( m_project, SIGNAL(relationRemoved(KPlato::Relation*)), this, SLOT(slotRelationRemoved(KPlato::Relation*)) ); } m_requiredList->setProject( project ); draw(); } void PertEditor::slotRelationAdded( Relation *rel ) { debugPlan<child() == itemToNode( m_tasktree->currentItem() ) ) { QTreeWidgetItem *item = findNodeItem( rel->parent(), m_availableList->invisibleRootItem() ); updateAvailableTasks( item ); } } void PertEditor::slotRelationRemoved( Relation *rel ) { debugPlan<child() == itemToNode( m_tasktree->currentItem() ) ) { QTreeWidgetItem *item = findNodeItem( rel->parent(), m_availableList->invisibleRootItem() ); updateAvailableTasks( item ); } } void PertEditor::slotNodeAdded( Node *node ) { debugPlan<name()<childNodeIterator(); Node *parent = node->parentNode(); int index = parent->indexOf( node ); QTreeWidgetItem *pitem = findNodeItem( parent, m_tasktree->invisibleRootItem() ); if ( pitem == 0 ) { pitem = m_tasktree->invisibleRootItem(); } QTreeWidgetItem *item = new QTreeWidgetItem(); item->setText( 0, node->name() ); item->setData( 0, NodeRole, node->id() ); pitem->insertChild( index, item ); pitem = findNodeItem( parent, m_availableList->invisibleRootItem() ); if ( pitem == 0 ) { pitem = m_availableList->invisibleRootItem(); } item = new QTreeWidgetItem(); item->setText( 0, node->name() ); item->setData( 0, NodeRole, node->id() ); item->setData( 0, EnabledRole, true ); pitem->insertChild( index, item ); setAvailableItemEnabled( item ); } void PertEditor::slotNodeRemoved( Node *node ) { //debugPlan; QTreeWidgetItem *item = findNodeItem( node, m_tasktree->invisibleRootItem() ); if ( item ) { QTreeWidgetItem *parent = item->parent(); if ( parent == 0 ) { parent = m_tasktree->invisibleRootItem(); } Q_ASSERT( parent ); parent->removeChild( item ); delete item; } item = findNodeItem( node, m_availableList->invisibleRootItem() ); if ( item ) { QTreeWidgetItem *parent = item->parent(); if ( parent == 0 ) { parent = m_availableList->invisibleRootItem(); } Q_ASSERT( parent ); parent->removeChild( item ); delete item; } } void PertEditor::slotNodeMoved( Node */*node */) { //debugPlan; draw(); } void PertEditor::slotNodeChanged( Node *node ) { QTreeWidgetItem *item = findNodeItem( node, m_tasktree->invisibleRootItem() ); if ( item ) { item->setText( 0, node->name() ); } item = findNodeItem( node, m_availableList->invisibleRootItem() ); if ( item ) { item->setText( 0, node->name() ); } } void PertEditor::draw( Project &project) { setProject( &project ); draw(); } void PertEditor::draw() { m_tasktree->clear(); if ( m_project == 0 ) { return; } drawSubTasksName( m_tasktree->invisibleRootItem(), m_project ); } void PertEditor::drawSubTasksName( QTreeWidgetItem *parent, Node * currentNode) { foreach(Node * currentChild, currentNode->childNodeIterator()){ QTreeWidgetItem * item = new QTreeWidgetItem( parent ); item->setText( 0, currentChild->name()); item->setData( 0, NodeRole, currentChild->id() ); //debugPlan<<"Added task"<name()<<"parent"<parent(); drawSubTasksName( item, currentChild); } } void PertEditor::updateReadWrite( bool rw ) { m_requiredList->setReadWrite( rw ); ViewBase::updateReadWrite( rw ); } QTreeWidgetItem *PertEditor::findNodeItem( Node *node, QTreeWidgetItem *item ) { if ( node->id() == item->data( 0, NodeRole ).toString() ) { return item; } for ( int i = 0; i < item->childCount(); ++i ) { QTreeWidgetItem *itm = findNodeItem( node, item->child( i ) ); if ( itm != 0 ) { return itm; } } return 0; } void PertEditor::dispAvailableTasks( Relation */*rel*/ ){ dispAvailableTasks(); } void PertEditor::dispAvailableTasks( Node *parent, Node *selectedTask ) { QTreeWidgetItem *pitem = findNodeItem( parent, m_availableList->invisibleRootItem() ); if ( pitem == 0 ) { pitem = m_availableList->invisibleRootItem(); } foreach(Node * currentNode, parent->childNodeIterator() ) { //debugPlan<name()<<"level="<level(); QTreeWidgetItem *item = new QTreeWidgetItem( QStringList()<name() ); item->setData( 0, NodeRole, currentNode->id() ); pitem->addChild(item); // Checks it isn't the same as the selected task in the m_tasktree setAvailableItemEnabled( item ); dispAvailableTasks( currentNode, selectedTask ); } } void PertEditor::dispAvailableTasks() { m_availableList->clear(); if ( m_project == 0 ) { return; } Node *selectedTask = itemToNode( m_tasktree->currentItem() ); loadRequiredTasksList(selectedTask); dispAvailableTasks( m_project, selectedTask ); } void PertEditor::updateAvailableTasks( QTreeWidgetItem *item ) { //debugPlan<invisibleRootItem(); } else { setAvailableItemEnabled( item ); } for ( int i=0; i < item->childCount(); ++i ) { updateAvailableTasks( item->child( i ) ); } } void PertEditor::setAvailableItemEnabled( QTreeWidgetItem *item ) { //debugPlan<currentItem() ); if ( selected == 0 || ! m_project->legalToLink( node, selected ) ) { //debugPlan<<"Disable:"<name(); item->setData( 0, EnabledRole, false ); QFont f = item->font( 0 ); f.setItalic( true ); item->setFont( 0, f ); } else { //debugPlan<<"Enable:"<name(); item->setData( 0, EnabledRole, true ); QFont f = item->font( 0 ); f.setItalic( false ); item->setFont( 0, f ); } slotAvailableChanged( item ); } void PertEditor::setAvailableItemEnabled( Node *node ) { //debugPlan<name(); setAvailableItemEnabled( nodeToItem( node, m_availableList->invisibleRootItem() ) ); } QTreeWidgetItem *PertEditor::nodeToItem( Node *node, QTreeWidgetItem *item ) { if ( itemToNode( item ) == node ) { return item; } for ( int i=0; i < item->childCount(); ++i ) { QTreeWidgetItem *itm = nodeToItem( node, item->child( i ) ); if ( itm ) { return itm; } } return 0; } Node * PertEditor::itemToNode( QTreeWidgetItem *item ) { if ( m_project == 0 || item == 0 ) { return 0; } return m_project->findNode( item->data( 0, NodeRole ).toString() ); } void PertEditor::loadRequiredTasksList(Node * taskNode) { slotRequiredChanged( QModelIndex() ); m_requiredList->setNode( taskNode ); } void PertEditor::slotUpdate() { draw(); } } // namespace KPlato diff --git a/src/libs/ui/kptperteditor.h b/src/libs/ui/kptperteditor.h index fa3a1f15..d15dbbea 100644 --- a/src/libs/ui/kptperteditor.h +++ b/src/libs/ui/kptperteditor.h @@ -1,116 +1,116 @@ /* This file is part of the KDE project Copyright (C) 2007 Florian Piquemal Copyright (C) 2007 Alexis Ménard Copyright (C) 2007 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 KPTPERTEDITOR_H #define KPTPERTEDITOR_H #include "planui_export.h" #include "kptviewbase.h" #include "kptitemmodelbase.h" #include "kpttaskeditor.h" #include #include "kptcommand.h" #include "kptnode.h" #include class KoDocument; class QTreeWidgetItem; class QTableWidgetItem; class QModelIndex; class KUndo2Command; namespace KPlato { class View; class Project; class RelationTreeView; class PLANUI_EXPORT PertEditor : public ViewBase { Q_OBJECT public: enum Roles { NodeRole = Qt::UserRole + 1, EnabledRole }; PertEditor(KoPart *part, KoDocument *doc, QWidget *parent); virtual void updateReadWrite( bool readwrite ); void setProject( Project *project ); Project *project() const { return m_project; } void draw( Project &project ); void draw(); void drawSubTasksName( QTreeWidgetItem *parent,Node * currentNode); void clearRequiredList(); void loadRequiredTasksList(Node * taskNode); Node *itemToNode( QTreeWidgetItem *item ); QTreeWidgetItem *nodeToItem( Node *node, QTreeWidgetItem *item ); QList listNodeNotView(Node * node); void updateAvailableTasks( QTreeWidgetItem *item = 0 ); void setAvailableItemEnabled( QTreeWidgetItem *item ); void setAvailableItemEnabled( Node *node ); Q_SIGNALS: void executeCommand( KUndo2Command* ); protected: bool isInRequiredList( Node *node ); QTreeWidgetItem *findNodeItem( Node *node, QTreeWidgetItem *item ); QTableWidgetItem *findRequiredItem( Node *node ); private Q_SLOTS: - void slotNodeAdded( Node* ); - void slotNodeRemoved( Node* ); - void slotNodeMoved( Node* ); - void slotNodeChanged( Node* ); - void slotRelationAdded( Relation *rel ); - void slotRelationRemoved( Relation *rel ); + void slotNodeAdded(KPlato::Node* ); + void slotNodeRemoved(KPlato::Node* ); + void slotNodeMoved(KPlato::Node* ); + void slotNodeChanged(KPlato::Node* ); + void slotRelationAdded(KPlato::Relation *rel ); + void slotRelationRemoved(KPlato::Relation *rel ); void dispAvailableTasks(); - void dispAvailableTasks( Node *parent, Node *selectedTask ); - void dispAvailableTasks( Relation *rel ); + void dispAvailableTasks(KPlato::Node *parent, KPlato::Node *selectedTask ); + void dispAvailableTasks(KPlato::Relation *rel ); void addTaskInRequiredList(QTreeWidgetItem * currentItem); void removeTaskFromRequiredList(); void slotUpdate(); void slotCurrentTaskChanged( QTreeWidgetItem *curr, QTreeWidgetItem *prev ); void slotAvailableChanged( QTreeWidgetItem *item ); void slotRequiredChanged( const QModelIndex &index ); void slotAddClicked(); void slotRemoveClicked(); private: Project * m_project; QTreeWidget *m_tasktree; QTreeWidget *m_availableList; RelationTreeView *m_requiredList; Ui::PertEditor widget; }; } //KPlato namespace #endif diff --git a/src/libs/ui/kptpertresult.cpp b/src/libs/ui/kptpertresult.cpp index 9beb4e7b..8d9a3d21 100644 --- a/src/libs/ui/kptpertresult.cpp +++ b/src/libs/ui/kptpertresult.cpp @@ -1,599 +1,599 @@ /* This file is part of the KDE project Copyright (C) 2007 Florian Piquemal Copyright (C) 2007 Alexis Ménard Copyright (C) 2007, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptpertresult.h" #include "kptproject.h" #include "kpttask.h" #include "kptnode.h" #include "kptschedule.h" #include "kptitemviewsettup.h" #include "kptdebug.h" #include #include #include #include #include #include namespace KPlato { class Project; class Node; class Task; static const double dist[][2] = { {0.00, 0.5000}, {0.02, 0.5080}, {0.04, 0.5160}, {0.06, 0.5239}, {0.08, 0.5319}, {0.10, 0.5398}, {0.12, 0.5478}, {0.14, 0.5557}, {0.16, 0.5636}, {0.18, 0.5714}, {0.20, 0.5793}, {0.22, 0.5871}, {0.24, 0.5948}, {0.26, 0.6026}, {0.28, 0.6103}, {0.30, 0.6179}, {0.32, 0.6255}, {0.34, 0.6331}, {0.36, 0.6406}, {0.38, 0.6480}, {0.40, 0.6554}, {0.42, 0.6628}, {0.44, 0.6700}, {0.46, 0.6772}, {0.48, 0.6844}, {0.50, 0.6915}, {0.52, 0.6985}, {0.54, 0.7054}, {0.56, 0.7123}, {0.58, 0.7190}, {0.60, 0.7257}, {0.62, 0.7324}, {0.64, 0.7389}, {0.66, 0.7454}, {0.68, 0.7517}, {0.70, 0.7580}, {0.72, 0.7642}, {0.74, 0.7704}, {0.76, 0.7764}, {0.78, 0.7823}, {0.80, 0.7881}, {0.82, 0.7939}, {0.84, 0.7995}, {0.86, 0.8051}, {0.88, 0.8106}, {0.90, 0.8159}, {0.92, 0.8212}, {0.94, 0.8264}, {0.96, 0.8315}, {0.98, 0.8365}, {1.00, 0.8413}, {1.02, 0.8461}, {1.04, 0.8508}, {1.06, 0.8554}, {1.08, 0.8599}, {1.10, 0.8643}, {1.12, 0.8686}, {1.14, 0.8729}, {1.16, 0.8770}, {1.18, 0.8810}, {1.20, 0.8849}, {1.22, 0.8888}, {1.24, 0.8925}, {1.26, 0.8962}, {1.28, 0.8997}, {1.30, 0.9032}, {1.32, 0.9066}, {1.34, 0.9099}, {1.36, 0.9131}, {1.38, 0.9162}, {1.40, 0.9192}, {1.42, 0.9222}, {1.44, 0.9251}, {1.46, 0.9279}, {1.48, 0.9306}, {1.50, 0.9332}, {1.52, 0.9357}, {1.54, 0.9382}, {1.56, 0.9406}, {1.58, 0.9429}, {1.60, 0.9452}, {1.62, 0.9474}, {1.64, 0.9495}, {1.66, 0.9515}, {1.68, 0.9535}, {1.70, 0.9554}, {1.72, 0.9573}, {1.74, 0.9591}, {1.76, 0.9608}, {1.78, 0.9625}, {1.80, 0.9641}, {1.82, 0.9656}, {1.84, 0.9671}, {1.86, 0.9686}, {1.88, 0.9699}, {1.90, 0.9713}, {1.92, 0.9726}, {1.94, 0.9738}, {1.96, 0.9750}, {1.98, 0.9761}, {2.00, 0.9772}, {2.02, 0.9783}, {2.34, 0.9793}, {2.36, 0.9803}, {2.38, 0.9812}, {2.10, 0.9821}, {2.12, 0.9830}, {2.34, 0.9838}, {2.36, 0.9846}, {2.38, 0.9854}, {2.20, 0.9861}, {2.22, 0.9868}, {2.34, 0.9875}, {2.36, 0.9881}, {2.38, 0.9887}, {2.30, 0.9893}, {2.32, 0.9898}, {2.34, 0.9904}, {2.36, 0.9909}, {2.38, 0.9913}, {2.40, 0.9918}, {2.42, 0.9922}, {2.44, 0.9927}, {2.46, 0.9931}, {2.48, 0.9934}, {2.50, 0.9938}, {2.52, 0.9941}, {2.54, 0.9945}, {2.56, 0.9948}, {2.58, 0.9951}, {2.60, 0.9953}, {2.62, 0.9956}, {2.64, 0.9959}, {2.66, 0.9961}, {2.68, 0.9963}, {2.70, 0.9965}, {2.72, 0.9967}, {2.74, 0.9969}, {2.76, 0.9971}, {2.78, 0.9973}, {2.80, 0.9974}, {2.82, 0.9976}, {2.84, 0.9977}, {2.86, 0.9979}, {2.88, 0.9980}, {2.90, 0.9981}, {2.92, 0.9982}, {2.94, 0.9984}, {2.96, 0.9985}, {2.98, 0.9986}, {3.00, 0.9987} }; //----------------------------------- PertResult::PertResult(KoPart *part, KoDocument *doc, QWidget *parent) : ViewBase(part, doc, parent ), m_node( 0 ), m_project( 0 ), current_schedule( 0 ) { debugPlan << " ---------------- KPlato: Creating PertResult ----------------"; widget.setupUi(this); PertResultItemModel *m = new PertResultItemModel( widget.treeWidgetTaskResult ); widget.treeWidgetTaskResult->setModel( m ); widget.treeWidgetTaskResult->setStretchLastSection( false ); widget.treeWidgetTaskResult->setSelectionMode( QAbstractItemView::ExtendedSelection ); setupGui(); QList lst1; lst1 << 1 << -1; // only display column 0 (NodeName) in left view QList show; show << NodeModel::NodeEarlyStart << NodeModel::NodeEarlyFinish << NodeModel::NodeLateStart << NodeModel::NodeLateFinish << NodeModel::NodePositiveFloat << NodeModel::NodeFreeFloat << NodeModel::NodeNegativeFloat << NodeModel::NodeStartFloat << NodeModel::NodeFinishFloat; QList lst2; for ( int i = 0; i < m->columnCount(); ++i ) { if ( ! show.contains( i ) ) { lst2 << i; } } widget.treeWidgetTaskResult->hideColumns( lst1, lst2 ); widget.treeWidgetTaskResult->masterView()->setDefaultColumns( QList() << 0 ); widget.treeWidgetTaskResult->slaveView()->setDefaultColumns( show ); connect( widget.treeWidgetTaskResult, SIGNAL(contextMenuRequested(QModelIndex,QPoint,QModelIndexList)), SLOT(slotContextMenuRequested(QModelIndex,QPoint)) ); connect( widget.treeWidgetTaskResult, SIGNAL(headerContextMenuRequested(QPoint)), SLOT(slotHeaderContextMenuRequested(QPoint)) ); connect(this, SIGNAL(expandAll()), widget.treeWidgetTaskResult, SLOT(slotExpand())); connect(this, SIGNAL(collapseAll()), widget.treeWidgetTaskResult, SLOT(slotCollapse())); } void PertResult::draw( Project &project) { setProject( &project ); //draw(); } void PertResult::draw() { debugPlan<setText( i18n( "None" ) ); widget.totalFloat->clear(); if ( m_project && model()->manager() && model()->manager()->isScheduled() ) { long id = model()->manager()->scheduleId(); if ( id == -1 ) { return; } widget.scheduleName->setText( model()->manager()->name() ); Duration f; foreach ( Node *n, m_project->allNodes() ) { if ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) { f += static_cast( n )->positiveFloat( id ); } } widget.totalFloat->setText( QLocale().toString( f.toDouble( Duration::Unit_h ), 'f', 2 ) ); } } void PertResult::setupGui() { // Add the context menu actions for the view options connect(widget.treeWidgetTaskResult->actionSplitView(), SIGNAL(triggered(bool)), SLOT(slotSplitView())); addContextAction( widget.treeWidgetTaskResult->actionSplitView() ); createOptionActions(ViewBase::OptionExpand | ViewBase::OptionCollapse | ViewBase::OptionViewConfig); } void PertResult::slotSplitView() { debugPlan; widget.treeWidgetTaskResult->setViewSplitMode( ! widget.treeWidgetTaskResult->isViewSplit() ); emit optionsModified(); } Node *PertResult::currentNode() const { return model()->node( widget.treeWidgetTaskResult->selectionModel()->currentIndex() ); } void PertResult::slotContextMenuRequested( const QModelIndex& index, const QPoint& pos ) { debugPlan<node( index ); if ( node == 0 ) { slotHeaderContextMenuRequested( pos ); return; } debugPlan<name()<<" :"<type() ) { case Node::Type_Task: name = "task_popup"; break; case Node::Type_Milestone: name = "taskeditor_milestone_popup"; break; case Node::Type_Summarytask: name = "summarytask_popup"; break; case Node::Type_Project: break; default: name = "node_popup"; break; } if ( name.isEmpty() ) { slotHeaderContextMenuRequested( pos ); return; } debugPlan< lst = contextActionList(); if ( ! lst.isEmpty() ) { QMenu::exec( lst, pos, lst.first() ); } } void PertResult::slotOptions() { debugPlan; SplitItemViewSettupDialog *dlg = new SplitItemViewSettupDialog( this, widget.treeWidgetTaskResult, this ); // Note: printing needs fixes in SplitterView/ScheduleHandlerView //dlg->addPrintingOptions(sender()->objectName() == "print options"); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } void PertResult::slotUpdate(){ draw(); } void PertResult::slotScheduleSelectionChanged( ScheduleManager *sm ) { current_schedule = sm; model()->setManager( sm ); draw(); } -void PertResult::slotProjectCalculated( ScheduleManager *sm ) +void PertResult::slotProjectCalculated(KPlato::ScheduleManager *sm) { if ( sm && sm == model()->manager() ) { //draw(); slotScheduleSelectionChanged( sm ); } } void PertResult::slotScheduleManagerToBeRemoved( const ScheduleManager *sm ) { if ( sm == model()->manager() ) { current_schedule = 0; model()->setManager( 0 ); } } void PertResult::slotScheduleManagerChanged( ScheduleManager *sm ) { if ( current_schedule && current_schedule == sm ) { slotScheduleSelectionChanged( sm ); } } void PertResult::setProject( Project *project ) { if ( m_project ) { - disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotUpdate()) ); - disconnect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); - disconnect( m_project, SIGNAL(scheduleManagerToBeRemoved(const ScheduleManager*)), this, SLOT(slotScheduleManagerToBeRemoved(const ScheduleManager*)) ); - disconnect( m_project, SIGNAL(scheduleManagerChanged(ScheduleManager*)), this, SLOT(slotScheduleManagerChanged(ScheduleManager*)) ); + disconnect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotUpdate()) ); + disconnect( m_project, SIGNAL(projectCalculated(KPlato::ScheduleManager*)), this, SLOT(slotProjectCalculated(KPlato::ScheduleManager*)) ); + disconnect( m_project, SIGNAL(scheduleManagerToBeRemoved(const KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerToBeRemoved(const KPlato::ScheduleManager*)) ); + disconnect( m_project, SIGNAL(scheduleManagerChanged(KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerChanged(KPlato::ScheduleManager*)) ); } m_project = project; model()->setProject( m_project ); if ( m_project ) { - connect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotUpdate()) ); - connect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); - connect( m_project, SIGNAL(scheduleManagerToBeRemoved(const ScheduleManager*)), this, SLOT(slotScheduleManagerToBeRemoved(const ScheduleManager*)) ); - connect( m_project, SIGNAL(scheduleManagerChanged(ScheduleManager*)), this, SLOT(slotScheduleManagerChanged(ScheduleManager*)) ); + connect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotUpdate()) ); + connect( m_project, SIGNAL(projectCalculated(KPlato::ScheduleManager*)), this, SLOT(slotProjectCalculated(KPlato::ScheduleManager*)) ); + connect( m_project, SIGNAL(scheduleManagerToBeRemoved(const KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerToBeRemoved(const KPlato::ScheduleManager*)) ); + connect( m_project, SIGNAL(scheduleManagerChanged(KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerChanged(KPlato::ScheduleManager*)) ); } draw(); } bool PertResult::loadContext( const KoXmlElement &context ) { debugPlan; ViewBase::loadContext( context ); return widget.treeWidgetTaskResult->loadContext( model()->columnMap(), context ); } void PertResult::saveContext( QDomElement &context ) const { ViewBase::saveContext( context ); widget.treeWidgetTaskResult->saveContext( model()->columnMap(), context ); } KoPrintJob *PertResult::createPrintJob() { return widget.treeWidgetTaskResult->createPrintJob( this ); } //-------------------- PertCpmView::PertCpmView(KoPart *part, KoDocument *doc, QWidget *parent) : ViewBase(part, doc, parent), m_project( 0 ), current_schedule( 0 ), block( false ) { debugPlan << " ---------------- KPlato: Creating PertCpmView ----------------"; widget.setupUi(this); widget.cpmTable->setSelectionMode( QAbstractItemView::ExtendedSelection ); widget.probabilityFrame->setVisible( false ); widget.cpmTable->setStretchLastSection ( false ); CriticalPathItemModel *m = new CriticalPathItemModel( widget.cpmTable ); widget.cpmTable->setModel( m ); setupGui(); QList lst1; lst1 << 1 << -1; // only display first column (NodeName) in left view widget.cpmTable->masterView()->setDefaultColumns( QList() << 0 ); QList show; show << NodeModel::NodeDuration << NodeModel::NodeVarianceDuration << NodeModel::NodeOptimisticDuration << NodeModel::NodePessimisticDuration << NodeModel::NodeEstimate << NodeModel::NodeExpected << NodeModel::NodeVarianceEstimate << NodeModel::NodeOptimistic << NodeModel::NodePessimistic; QList lst2; for ( int i = 0; i < m->columnCount(); ++i ) { if ( ! show.contains( i ) ) { lst2 << i; } } widget.cpmTable->hideColumns( lst1, lst2 ); for ( int s = 0; s < show.count(); ++s ) { widget.cpmTable->slaveView()->mapToSection( show[s], s ); } widget.cpmTable->slaveView()->setDefaultColumns( show ); connect( widget.cpmTable, SIGNAL(contextMenuRequested(QModelIndex,QPoint,QModelIndexList)), SLOT(slotContextMenuRequested(QModelIndex,QPoint)) ); connect( widget.cpmTable, SIGNAL(headerContextMenuRequested(QPoint)), SLOT(slotHeaderContextMenuRequested(QPoint)) ); connect( widget.finishTime, SIGNAL(dateTimeChanged(QDateTime)), SLOT(slotFinishTimeChanged(QDateTime)) ); connect( widget.probability, SIGNAL(valueChanged(int)), SLOT(slotProbabilityChanged(int)) ); } void PertCpmView::setupGui() { // Add the context menu actions for the view options connect(widget.cpmTable->actionSplitView(), SIGNAL(triggered(bool)), SLOT(slotSplitView())); addContextAction( widget.cpmTable->actionSplitView() ); createOptionActions(ViewBase::OptionExpand | ViewBase::OptionCollapse | ViewBase::OptionViewConfig); } void PertCpmView::slotSplitView() { debugPlan; widget.cpmTable->setViewSplitMode( ! widget.cpmTable->isViewSplit() ); emit optionsModified(); } Node *PertCpmView::currentNode() const { return model()->node( widget.cpmTable->selectionModel()->currentIndex() ); } void PertCpmView::slotContextMenuRequested( const QModelIndex& index, const QPoint& pos ) { debugPlan<node( index ); if ( node == 0 ) { slotHeaderContextMenuRequested( pos ); return; } debugPlan<name()<<" :"<type() ) { case Node::Type_Task: name = "task_popup"; break; case Node::Type_Milestone: name = "taskeditor_milestone_popup"; break; case Node::Type_Summarytask: name = "summarytask_popup"; break; case Node::Type_Project: break; default: name = "node_popup"; break; } if ( name.isEmpty() ) { slotHeaderContextMenuRequested( pos ); return; } debugPlan< lst = contextActionList(); if ( ! lst.isEmpty() ) { QMenu::exec( lst, pos, lst.first() ); } } void PertCpmView::slotOptions() { debugPlan; SplitItemViewSettupDialog *dlg = new SplitItemViewSettupDialog( this, widget.cpmTable, this ); // Note: printing needs fixes in SplitterView/ScheduleHandlerView //dlg->addPrintingOptions(sender()->objectName() == "print options"); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } void PertCpmView::slotScheduleSelectionChanged( ScheduleManager *sm ) { bool enbl = sm && sm->isScheduled() && sm->usePert(); debugPlan<isScheduled():false)<<(sm?sm->usePert():false)<setVisible( enbl ); current_schedule = sm; model()->setManager( sm ); draw(); } void PertCpmView::slotProjectCalculated( ScheduleManager *sm ) { if ( sm && sm == model()->manager() ) { slotScheduleSelectionChanged( sm ); } } void PertCpmView::slotScheduleManagerChanged( ScheduleManager *sm ) { if ( current_schedule == sm ) { slotScheduleSelectionChanged( sm ); } } void PertCpmView::slotScheduleManagerToBeRemoved( const ScheduleManager *sm ) { if ( sm == current_schedule ) { current_schedule = 0; model()->setManager( 0 ); widget.probabilityFrame->setVisible( false ); } } void PertCpmView::setProject( Project *project ) { if ( m_project ) { - disconnect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotUpdate()) ); - disconnect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); - disconnect( m_project, SIGNAL(scheduleManagerToBeRemoved(const ScheduleManager*)), this, SLOT(slotScheduleManagerToBeRemoved(const ScheduleManager*)) ); - disconnect( m_project, SIGNAL(scheduleManagerChanged(ScheduleManager*)), this, SLOT(slotScheduleManagerChanged(ScheduleManager*)) ); + disconnect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotUpdate()) ); + disconnect( m_project, SIGNAL(projectCalculated(KPlato::ScheduleManager*)), this, SLOT(slotProjectCalculated(KPlato::ScheduleManager*)) ); + disconnect( m_project, SIGNAL(scheduleManagerToBeRemoved(const KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerToBeRemoved(const KPlato::ScheduleManager*)) ); + disconnect( m_project, SIGNAL(scheduleManagerChanged(KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerChanged(KPlato::ScheduleManager*)) ); } m_project = project; model()->setProject( m_project ); if ( m_project ) { - connect( m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotUpdate()) ); - connect( m_project, SIGNAL(projectCalculated(ScheduleManager*)), this, SLOT(slotProjectCalculated(ScheduleManager*)) ); - connect( m_project, SIGNAL(scheduleManagerToBeRemoved(const ScheduleManager*)), this, SLOT(slotScheduleManagerToBeRemoved(const ScheduleManager*)) ); - connect( m_project, SIGNAL(scheduleManagerChanged(ScheduleManager*)), this, SLOT(slotScheduleManagerChanged(ScheduleManager*)) ); + connect( m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotUpdate()) ); + connect( m_project, SIGNAL(projectCalculated(KPlato::ScheduleManager*)), this, SLOT(slotProjectCalculated(KPlato::ScheduleManager*)) ); + connect( m_project, SIGNAL(scheduleManagerToBeRemoved(const KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerToBeRemoved(const KPlato::ScheduleManager*)) ); + connect( m_project, SIGNAL(scheduleManagerChanged(KPlato::ScheduleManager*)), this, SLOT(slotScheduleManagerChanged(KPlato::ScheduleManager*)) ); } draw(); } void PertCpmView::draw( Project &project ) { setProject( &project ); // draw() } void PertCpmView::draw() { widget.scheduleName->setText( i18n( "None" ) ); bool enbl = m_project && current_schedule && current_schedule->isScheduled() && current_schedule->usePert(); widget.probabilityFrame->setVisible( enbl ); if ( m_project && current_schedule && current_schedule->isScheduled() ) { long id = current_schedule->scheduleId(); if ( id == -1 ) { return; } widget.scheduleName->setText( current_schedule->name() ); widget.finishTime->setDateTime( m_project->endTime( id ) ); bool ro = model()->variance( Qt::EditRole ).toDouble() == 0.0; if ( ro ) { widget.probability->setValue( 50 ); } widget.finishTime->setReadOnly( ro ); widget.probability->setEnabled( ! ro ); } } void PertCpmView::slotFinishTimeChanged( const QDateTime &dt ) { debugPlan<variance( Qt::EditRole ).toDouble(); double dev = sqrt( var ); DateTime et = m_project->endTime( current_schedule->scheduleId() ); DateTime t = DateTime( dt ); double d = ( et - t ).toDouble(); d = t < et ? -d : d; double z = d / dev; double v = probability( z ); widget.probability->setValue( (int)( v * 100 ) ); //debugPlan<variance( Qt::EditRole ).toDouble(); double dev = sqrt( var ); DateTime et = m_project->endTime( current_schedule->scheduleId() ); double p = valueZ( value ); DateTime t = et + Duration( qint64( p * dev ) ); widget.finishTime->setDateTime( t ); //debugPlan< class KoDocument; /// The main namespace namespace KPlato { class DateTime; class Node; class Project; class ScheduleManager; class Task; class View; class PLANUI_EXPORT PertResult : public ViewBase { Q_OBJECT public: explicit PertResult(KoPart *part, KoDocument *doc, QWidget *parent = 0); void setupGui(); void setProject( Project *project ); Project *project() const { return m_project; } void draw( Project &project ); void draw(); PertResultItemModel *model() const { return static_cast( widget.treeWidgetTaskResult->model() ); } /// Loads context info into this view. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. virtual void saveContext( QDomElement &/*context*/ ) const; KoPrintJob *createPrintJob(); Node *currentNode() const; public Q_SLOTS: - void slotScheduleSelectionChanged( ScheduleManager *sm ); + void slotScheduleSelectionChanged(KPlato::ScheduleManager *sm); protected Q_SLOTS: - void slotProjectCalculated( ScheduleManager *sm ); - void slotScheduleManagerToBeRemoved( const ScheduleManager *sm ); - void slotScheduleManagerChanged( ScheduleManager *sm ); + void slotProjectCalculated(KPlato::ScheduleManager *sm); + void slotScheduleManagerToBeRemoved(const KPlato::ScheduleManager *sm); + void slotScheduleManagerChanged(KPlato::ScheduleManager *sm); void slotHeaderContextMenuRequested( const QPoint &pos ); void slotContextMenuRequested( const QModelIndex& index, const QPoint& pos ); void slotSplitView(); virtual void slotOptions(); private: Node * m_node; Project * m_project; ScheduleManager *current_schedule; Ui::PertResult widget; private Q_SLOTS: void slotUpdate(); }; //-------------------- class PLANUI_EXPORT PertCpmView : public ViewBase { Q_OBJECT public: explicit PertCpmView(KoPart *part, KoDocument *doc, QWidget *parent = 0); void setupGui(); void setProject( Project *project ); Project *project() const { return m_project; } void draw( Project &project ); void draw(); CriticalPathItemModel *model() const { return static_cast( widget.cpmTable->model() ); } double probability( double z ) const; double valueZ( double p ) const; /// Loads context info into this view. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. virtual void saveContext( QDomElement &/*context*/ ) const; KoPrintJob *createPrintJob(); Node *currentNode() const; public Q_SLOTS: - void slotScheduleSelectionChanged( ScheduleManager *sm ); + void slotScheduleSelectionChanged(KPlato::ScheduleManager *sm); protected Q_SLOTS: - void slotProjectCalculated( ScheduleManager *sm ); - void slotScheduleManagerToBeRemoved( const ScheduleManager *sm ); - void slotScheduleManagerChanged( ScheduleManager *sm ); + void slotProjectCalculated(KPlato::ScheduleManager *sm); + void slotScheduleManagerToBeRemoved(const KPlato::ScheduleManager *sm); + void slotScheduleManagerChanged(KPlato::ScheduleManager *sm); void slotHeaderContextMenuRequested( const QPoint &pos ); void slotContextMenuRequested( const QModelIndex& index, const QPoint& pos ); void slotSplitView(); virtual void slotOptions(); void slotFinishTimeChanged( const QDateTime &dt ); void slotProbabilityChanged( int value ); private Q_SLOTS: void slotUpdate(); private: Project * m_project; QList m_criticalPath; ScheduleManager *current_schedule; Ui::CpmWidget widget; bool block; }; } //KPlato namespace #endif diff --git a/src/libs/ui/kptrelationdialog.cpp b/src/libs/ui/kptrelationdialog.cpp index aba5a2f4..7562fb30 100644 --- a/src/libs/ui/kptrelationdialog.cpp +++ b/src/libs/ui/kptrelationdialog.cpp @@ -1,195 +1,195 @@ /* This file is part of the KDE project Copyright (C) 2003 - 2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptrelationdialog.h" #include "kptrelation.h" #include "kptnode.h" #include "kptproject.h" #include "kptcommand.h" #include namespace KPlato { RelationPanel::RelationPanel(QWidget *parent) : QWidget(parent) { setupUi(this); lagLabel->setText( xi18nc( "@label:spinbox Time lag", "Lag:" ) ); QString tt = xi18nc( "@info:tooltip", "Lag is the time the dependent task is delayed" ); lagLabel->setToolTip( tt ); lag->setToolTip( tt ); } AddRelationDialog::AddRelationDialog(Project &project, Relation *rel, QWidget *p, const QString& caption, ButtonCodes buttons) : KoDialog(p), m_project( project ), m_relation( rel ), m_deleterelation( true ) { setCaption( caption ); setButtons( buttons ); setDefaultButton( Ok ); showButtonSeparator( true ); if ( caption.isEmpty() ) { setCaption( xi18nc( "@title:window", "Add Dependency" ) ); } m_relation = rel; m_panel = new RelationPanel(this); setMainWidget(m_panel); m_panel->activateWindow(); m_panel->fromName->setText(rel->parent()->name()); m_panel->toName->setText(rel->child()->name()); if (rel->type() == Relation::FinishStart) { m_panel->bFinishStart->setChecked(true); } else if (rel->type() == Relation::FinishFinish) { m_panel->bFinishFinish->setChecked(true); } else if (rel->type() == Relation::StartStart) { m_panel->bStartStart->setChecked(true); } m_panel->lag->setUnit( Duration::Unit_h ); m_panel->lag->setValue(rel->lag().toDouble( Duration::Unit_h ) ); //FIXME store user input m_panel->relationType->setFocus(); enableButtonOk(true); //connect(m_panel->relationType, SIGNAL(clicked(int)), SLOT(typeClicked(int))); connect(m_panel->bFinishStart, SIGNAL(toggled(bool)), SLOT(slotFinishStartToggled(bool))); connect(m_panel->bFinishFinish, SIGNAL(toggled(bool)), SLOT(slotFinishFinishToggled(bool))); connect(m_panel->bStartStart, SIGNAL(toggled(bool)), SLOT(slotStartStartToggled(bool))); connect(m_panel->lag, SIGNAL(valueChanged(double)), SLOT(lagChanged())); - connect(&project, SIGNAL(nodeRemoved(Node*)), SLOT(slotNodeRemoved(Node*))); + connect(&project, SIGNAL(nodeRemoved(KPlato::Node*)), SLOT(slotNodeRemoved(KPlato::Node*))); } AddRelationDialog::~AddRelationDialog() { if ( m_deleterelation ) { delete m_relation; //in case of cancel } } void AddRelationDialog::slotNodeRemoved( Node *node ) { if ( m_relation->parent() == node || m_relation->child() == node ) { reject(); } } MacroCommand *AddRelationDialog::buildCommand() { MacroCommand *c = new MacroCommand( kundo2_i18n("Add task dependency") ); c->addCommand( new AddRelationCmd(m_project, m_relation ) ); m_deleterelation = false; // don't delete return c; } void AddRelationDialog::slotOk() { accept(); } void AddRelationDialog::slotFinishStartToggled(bool ch) { //debugPlan<type() != Relation::FinishStart) enableButtonOk(true); } void AddRelationDialog::slotFinishFinishToggled(bool ch) { //debugPlan<type() != Relation::FinishFinish) enableButtonOk(true); } void AddRelationDialog::slotStartStartToggled(bool ch) { //debugPlan<type() != Relation::StartStart) enableButtonOk(true); } void AddRelationDialog::lagChanged() { enableButtonOk(true); } void AddRelationDialog::typeClicked(int id) { if (id != m_relation->type()) enableButtonOk(true); } int AddRelationDialog::selectedRelationType() const { if (m_panel->bStartStart->isChecked()) return Relation::StartStart; else if (m_panel->bFinishFinish->isChecked()) return Relation::FinishFinish; return Relation::FinishStart; } ////////////////// ModifyRelationDialog::ModifyRelationDialog(Project &project, Relation *rel, QWidget *p) : AddRelationDialog(project, rel, p, xi18nc( "@title:window", "Edit Dependency"), Ok|Cancel|User1) { m_deleterelation = false; setButtonText( KoDialog::User1, xi18nc( "@action:button", "Delete") ); m_deleted = false; enableButtonOk(false); connect(this, SIGNAL(user1Clicked()), SLOT(slotUser1())); - connect(&project, SIGNAL(relationRemoved(Relation*)), SLOT(slotRelationRemoved(Relation*))); + connect(&project, SIGNAL(relationRemoved(KPlato::Relation*)), SLOT(slotRelationRemoved(KPlato::Relation*))); } void ModifyRelationDialog::slotRelationRemoved( Relation *relation ) { if ( m_relation == relation ) { reject(); } } // Delete void ModifyRelationDialog::slotUser1() { m_deleted = true; accept(); } MacroCommand *ModifyRelationDialog::buildCommand() { MacroCommand *cmd=0; if ( m_deleted ) { cmd = new MacroCommand( kundo2_i18n( "Delete task dependency" ) ); cmd ->addCommand( new DeleteRelationCmd( m_project, m_relation ) ); return cmd; } KUndo2MagicString s = kundo2_i18n( "Modify task dependency" ); if (selectedRelationType() != m_relation->type()) { if (cmd == 0) cmd = new MacroCommand( s ); cmd->addCommand(new ModifyRelationTypeCmd(m_relation, (Relation::Type)(selectedRelationType()))); //debugPlan<relationType->selectedId(); } Duration d(m_panel->lag->value(), m_panel->lag->unit()); if (m_relation->lag() != d) { if (cmd == 0) cmd = new MacroCommand( s ); cmd->addCommand(new ModifyRelationLagCmd(m_relation, d)); } return cmd; } } //KPlato namespace diff --git a/src/libs/ui/kptrelationdialog.h b/src/libs/ui/kptrelationdialog.h index 5d1ec619..580410ab 100644 --- a/src/libs/ui/kptrelationdialog.h +++ b/src/libs/ui/kptrelationdialog.h @@ -1,95 +1,95 @@ /* This file is part of the KDE project Copyright (C) 2002 The calligra team Copyright (C) 2003 - 2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTRELATIONDIALOG_H #define KPTRELATIONDIALOG_H #include "planui_export.h" #include "ui_relationpanel.h" #include #include namespace KPlato { class RelationPanel; class Relation; class Project; class Node; class MacroCommand; class RelationPanel : public QWidget, public Ui_RelationPanel { Q_OBJECT public: explicit RelationPanel(QWidget *parent = 0); }; class PLANUI_EXPORT AddRelationDialog : public KoDialog { Q_OBJECT public: AddRelationDialog(Project &project, Relation *rel, QWidget *p, const QString& caption=QString(), ButtonCodes buttons=Ok|Cancel); ~AddRelationDialog(); virtual MacroCommand *buildCommand(); int selectedRelationType() const; protected Q_SLOTS: void slotOk(); void lagChanged(); void typeClicked(int); void slotFinishStartToggled(bool); void slotFinishFinishToggled(bool); void slotStartStartToggled(bool); - void slotNodeRemoved( Node *node ); + void slotNodeRemoved(KPlato::Node *node); protected: Project &m_project; RelationPanel *m_panel; Relation *m_relation; bool m_deleterelation; }; class PLANUI_EXPORT ModifyRelationDialog : public AddRelationDialog { Q_OBJECT public: explicit ModifyRelationDialog(Project &project, Relation *rel, QWidget *p=0); virtual MacroCommand *buildCommand(); bool relationIsDeleted() { return m_deleted; } protected Q_SLOTS: void slotUser1(); - void slotRelationRemoved( Relation *relation ); + void slotRelationRemoved(KPlato::Relation *relation); private: bool m_deleted; }; } //KPlato namespace #endif // RELATIONDIALOG_H diff --git a/src/libs/ui/kptrelationeditor.h b/src/libs/ui/kptrelationeditor.h index b13a877d..f138dcdc 100644 --- a/src/libs/ui/kptrelationeditor.h +++ b/src/libs/ui/kptrelationeditor.h @@ -1,123 +1,123 @@ /* This file is part of the KDE project Copyright (C) 2007 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 KPTRELATIONEDITOR_H #define KPTRELATIONEDITOR_H #include "planui_export.h" #include "kptglobal.h" #include "kptviewbase.h" #include "kptrelationmodel.h" class KoDocument; namespace KPlato { class Project; class Node; class RelationItemModel; class Relation; class PLANUI_EXPORT RelationTreeView : public DoubleTreeViewBase { Q_OBJECT public: explicit RelationTreeView( QWidget *parent = 0 ); RelationItemModel *model() const { return static_cast( DoubleTreeViewBase::model() ); } Project *project() const { return model()->project(); } void setProject( Project *project ) { model()->setProject( project ); } void setNode( Node *node ) { model()->setNode( node ); } Relation *currentRelation() const { return model()->relation( selectionModel()->currentIndex() ); } Q_SIGNALS: void currentColumnChanged( const QModelIndex&, const QModelIndex& ); protected Q_SLOTS: void slotCurrentChanged(const QModelIndex &curr, const QModelIndex& ); }; class PLANUI_EXPORT RelationEditor : public ViewBase { Q_OBJECT public: /// Create a relation editor RelationEditor(KoPart *part, KoDocument *doc, QWidget *parent); void setupGui(); virtual void draw( Project &project ); virtual void draw(); virtual Relation *currentRelation() const; Relation *selectedRelation() const; virtual void updateReadWrite( bool readwrite ); RelationItemModel *model() const { return m_view->model(); } /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &/*context*/ ) const; KoPrintJob *createPrintJob(); Q_SIGNALS: void openNode(); void addRelation(); - void deleteRelation( Relation * ); + void deleteRelation(KPlato::Relation *); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); protected Q_SLOTS: virtual void slotOptions(); protected: void updateActionsEnabled( bool on ); private Q_SLOTS: void slotSelectionChanged( const QModelIndexList& ); void slotCurrentChanged( const QModelIndex&, const QModelIndex& ); void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); void slotEnableActions(); void slotAddRelation(); - void slotDeleteRelation( Relation *r ); + void slotDeleteRelation(KPlato::Relation *r); void slotSplitView(); void slotHeaderContextMenuRequested( const QPoint& ); private: void edit( const QModelIndex &index ); private: RelationTreeView *m_view; }; } //namespace KPlato #endif diff --git a/src/libs/ui/kptresourceappointmentsview.h b/src/libs/ui/kptresourceappointmentsview.h index 59780e28..e0e41938 100644 --- a/src/libs/ui/kptresourceappointmentsview.h +++ b/src/libs/ui/kptresourceappointmentsview.h @@ -1,180 +1,180 @@ /* This file is part of the KDE project Copyright (C) 2005 - 2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTRESOURCEAPPOINTMENTSVIEW_H #define KPTRESOURCEAPPOINTMENTSVIEW_H #include "planui_export.h" #include "ui_kptresourceappointmentsdisplayoptions.h" #include "kptviewbase.h" #include "kptresourceappointmentsmodel.h" #include #include class KoPageLayoutWidget; class KoDocument; class QPoint; namespace KPlato { class View; class Project; class Resource; class ResourceGroup; class ScheduleManager; class ResourceAppointmentsItemModel; //------------------------------------------------- class ResourceAppointmentsDisplayOptionsPanel : public QWidget, public Ui::ResourceAppointmentsDisplayOptions { Q_OBJECT public: explicit ResourceAppointmentsDisplayOptionsPanel( ResourceAppointmentsItemModel *model, QWidget *parent = 0 ); void setValues( const ResourceAppointmentsItemModel &del ); public Q_SLOTS: void slotOk(); void setDefault(); Q_SIGNALS: void changed(); private: ResourceAppointmentsItemModel *m_model; }; class ResourceAppointmentsSettingsDialog : public KPageDialog { Q_OBJECT public: explicit ResourceAppointmentsSettingsDialog( ViewBase *view, ResourceAppointmentsItemModel *model, QWidget *parent = 0, bool selectPrint = false ); public Q_SLOTS: void slotOk(); private: ViewBase *m_view; KoPageLayoutWidget *m_pagelayout; PrintingHeaderFooter *m_headerfooter; }; //------------------------ class PLANUI_EXPORT ResourceAppointmentsTreeView : public DoubleTreeViewBase { Q_OBJECT public: explicit ResourceAppointmentsTreeView(QWidget *parent); ResourceAppointmentsItemModel *model() const { return static_cast( DoubleTreeViewBase::model() ); } Project *project() const { return model()->project(); } void setProject( Project *project ) { model()->setProject( project ); } void setScheduleManager( ScheduleManager *sm ) { model()->setScheduleManager( sm ); } QModelIndex currentIndex() const; /// Load context info into this view. virtual bool loadContext( const KoXmlElement &context ); using DoubleTreeViewBase::loadContext; /// Save context info from this view. virtual void saveContext( QDomElement &context ) const; using DoubleTreeViewBase::saveContext; protected Q_SLOTS: void slotRefreshed(); private: ViewBase *m_view; }; class PLANUI_EXPORT ResourceAppointmentsView : public ViewBase { Q_OBJECT public: ResourceAppointmentsView(KoPart *part, KoDocument *doc, QWidget *parent); void setupGui(); virtual void setProject( Project *project ); Project *project() const { return m_view->project(); } virtual void draw( Project &project ); virtual void draw(); ResourceAppointmentsItemModel *model() const { return m_view->model(); } virtual void updateReadWrite( bool /*readwrite*/ ) {}; virtual Node *currentNode() const; virtual Resource *currentResource() const; virtual ResourceGroup *currentResourceGroup() const; /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &/*context*/ ) const; KoPrintJob *createPrintJob(); Q_SIGNALS: void requestPopupMenu( const QString&, const QPoint& ); - void addResource( ResourceGroup* ); + void addResource(KPlato::ResourceGroup*); void deleteObjectList( const QObjectList& ); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); - void setScheduleManager( ScheduleManager *sm ); + void setScheduleManager(KPlato::ScheduleManager *sm); protected Q_SLOTS: virtual void slotOptions(); protected: void updateActionsEnabled( bool on = true ); private Q_SLOTS: void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); void slotSelectionChanged( const QModelIndexList& ); void slotCurrentChanged( const QModelIndex& ); void slotEnableActions( bool on ); void slotAddResource(); void slotAddGroup(); void slotDeleteSelection(); private: ResourceAppointmentsTreeView *m_view; QAction *actionAddResource; QAction *actionAddGroup; QAction *actionDeleteSelection; QDomDocument m_domdoc; }; } //KPlato namespace #endif // KPTRESOURCEAPPOINTMENTSVIEW_H diff --git a/src/libs/ui/kptresourcedialog.h b/src/libs/ui/kptresourcedialog.h index b39435b0..7a429246 100644 --- a/src/libs/ui/kptresourcedialog.h +++ b/src/libs/ui/kptresourcedialog.h @@ -1,105 +1,105 @@ /* This file is part of the KDE project Copyright (C) 2003 - 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTRESOURCEDIALOG_H #define KPTRESOURCEDIALOG_H #include "planui_export.h" #include "ui_resourcedialogbase.h" #include "kptresource.h" #include #include namespace KPlato { class Project; class Resource; class Calendar; class MacroCommand; class ResourceDialogImpl : public QWidget, public Ui_ResourceDialogBase { Q_OBJECT public: explicit ResourceDialogImpl( const Project &m_project, Resource &resource, bool baselined, QWidget *parent ); public Q_SLOTS: void slotChanged(); void slotTypeChanged(int); void slotCalculationNeeded(const QString&); void slotChooseResource(); void setCurrentIndexes( const QModelIndexList &lst ); Q_SIGNALS: void changed(); void calculate(); protected Q_SLOTS: void slotAvailableFromChanged(const QDateTime& dt); void slotAvailableUntilChanged(const QDateTime& dt); void slotUseRequiredChanged( int state ); void slotTeamChanged( const QModelIndex &index ); private: const Project &m_project; Resource &m_resource; QList m_currentIndexes; }; class PLANUI_EXPORT ResourceDialog : public KoDialog { Q_OBJECT public: ResourceDialog(Project &project, Resource *resource, QWidget *parent=0, const char *name=0); bool calculationNeeded() { return m_calculationNeeded; } Calendar *calendar() { return m_calendars[dia->calendarList->currentIndex()]; } MacroCommand *buildCommand(); static MacroCommand *buildCommand(Resource *original, Resource &resource); protected Q_SLOTS: void enableButtonOk(); void slotCalculationNeeded(); void slotOk(); void slotCalendarChanged(int); void slotButtonClicked(int button); void slotAccountChanged( const QString &name ); - void slotResourceRemoved( const Resource *resource ); + void slotResourceRemoved(const KPlato::Resource *resource); private: Project &m_project; Resource *m_original; Resource m_resource; ResourceDialogImpl *dia; bool m_calculationNeeded; QMap m_calendars; QMap m_groups; }; } //KPlato namespace #endif diff --git a/src/libs/ui/kptresourceeditor.h b/src/libs/ui/kptresourceeditor.h index fea27173..670aab98 100644 --- a/src/libs/ui/kptresourceeditor.h +++ b/src/libs/ui/kptresourceeditor.h @@ -1,123 +1,123 @@ /* This file is part of the KDE project Copyright (C) 2006 - 2007 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 KPTRESOURCEEDITOR_H #define KPTRESOURCEEDITOR_H #include "planui_export.h" #include #include class KoDocument; class QPoint; namespace KPlato { class Project; class Resource; class ResourceGroup; class PLANUI_EXPORT ResourceTreeView : public DoubleTreeViewBase { Q_OBJECT public: explicit ResourceTreeView(QWidget *parent); ResourceItemModel *model() const { return static_cast( DoubleTreeViewBase::model() ); } Project *project() const { return model()->project(); } void setProject( Project *project ) { model()->setProject( project ); } QObject *currentObject() const; QList selectedObjects() const; QList selectedGroups() const; QList selectedResources() const; protected Q_SLOTS: void slotDropAllowed( const QModelIndex &index, int dropIndicatorPosition, QDragMoveEvent *event ); }; class PLANUI_EXPORT ResourceEditor : public ViewBase { Q_OBJECT public: ResourceEditor(KoPart *part, KoDocument *dic, QWidget *parent); void setupGui(); Project *project() const { return m_view->project(); } virtual void setProject( Project *project ); ResourceItemModel *model() const { return m_view->model(); } virtual void updateReadWrite( bool readwrite ); virtual Resource *currentResource() const; virtual ResourceGroup *currentResourceGroup() const; /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &/*context*/ ) const; KoPrintJob *createPrintJob(); Q_SIGNALS: - void addResource( ResourceGroup* ); + void addResource(KPlato::ResourceGroup*); void deleteObjectList( const QObjectList& ); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); protected Q_SLOTS: virtual void slotOptions(); protected: void updateActionsEnabled( bool on = true ); private Q_SLOTS: void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); void slotSplitView(); void slotSelectionChanged( const QModelIndexList& ); void slotCurrentChanged( const QModelIndex& ); void slotEnableActions( bool on ); void slotAddResource(); void slotAddGroup(); void slotDeleteSelection(); private: ResourceTreeView *m_view; QAction *actionAddResource; QAction *actionAddGroup; QAction *actionDeleteSelection; }; } //KPlato namespace #endif diff --git a/src/libs/ui/kptscheduleeditor.cpp b/src/libs/ui/kptscheduleeditor.cpp index 06ae5f9b..48906a13 100644 --- a/src/libs/ui/kptscheduleeditor.cpp +++ b/src/libs/ui/kptscheduleeditor.cpp @@ -1,856 +1,856 @@ /* This file is part of the KDE project Copyright (C) 2006-2011, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kptscheduleeditor.h" #include "kptcommand.h" #include "kptcalendar.h" #include "kptduration.h" #include "kptnode.h" #include "kptproject.h" #include "kpttask.h" #include "kptschedule.h" #include "kptdatetime.h" #include "kptpertresult.h" #include "kptitemviewsettup.h" #include "kptrecalculatedialog.h" #include "Help.h" #include "kptdebug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace KPlato { ScheduleTreeView::ScheduleTreeView( QWidget *parent ) : TreeViewBase( parent ) { header()->setStretchLastSection ( false ); ScheduleItemModel *m = new ScheduleItemModel( this ); setModel( m ); //setSelectionBehavior( QAbstractItemView::SelectItems ); setSelectionMode( QAbstractItemView::SingleSelection ); setSelectionBehavior( QAbstractItemView::SelectRows ); setTreePosition(-1); // always visual index 0 createItemDelegates( m ); } void ScheduleTreeView::selectionChanged( const QItemSelection &sel, const QItemSelection &desel ) { //debugPlan<selectedIndexes() ) { Q_UNUSED(i); //debugPlan<selectedIndexes() ); } void ScheduleTreeView::currentChanged( const QModelIndex & current, const QModelIndex & previous ) { //debugPlan<select( current, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect ); } ScheduleManager *ScheduleTreeView::manager( const QModelIndex &idx ) const { return model()->manager( idx ); } ScheduleManager *ScheduleTreeView::currentManager() const { return model()->manager( currentIndex() ); } QModelIndexList ScheduleTreeView::selectedRows() const { QModelIndexList lst = selectionModel()->selectedRows(); debugPlan<manager( lst.first() ); } return sm; } //----------------------------------- ScheduleEditor::ScheduleEditor(KoPart *part, KoDocument *doc, QWidget *parent) : ViewBase(part, doc, parent) { setupGui(); slotEnableActions(); QVBoxLayout * l = new QVBoxLayout( this ); l->setMargin( 0 ); m_schedulingRange = new SchedulingRange(doc, this); l->addWidget( m_schedulingRange ); m_view = new ScheduleTreeView( this ); connect(this, SIGNAL(expandAll()), m_view, SLOT(slotExpand())); connect(this, SIGNAL(collapseAll()), m_view, SLOT(slotCollapse())); l->addWidget( m_view ); m_view->setEditTriggers( m_view->editTriggers() | QAbstractItemView::EditKeyPressed ); QList show; show << ScheduleModel::ScheduleName << ScheduleModel::ScheduleState << ScheduleModel::ScheduleDirection << ScheduleModel::ScheduleOverbooking << ScheduleModel::ScheduleDistribution << ScheduleModel::SchedulePlannedStart << ScheduleModel::SchedulePlannedFinish << ScheduleModel::ScheduleScheduler << ScheduleModel::ScheduleGranularity ; QList lst; for ( int c = 0; c < model()->columnCount(); ++c ) { if ( ! show.contains( c ) ) { lst << c; } } m_view->setColumnsHidden( lst ); m_view->setDefaultColumns( show ); connect( model(), SIGNAL(executeCommand(KUndo2Command*)), doc, SLOT(addCommand(KUndo2Command*)) ); connect( m_view, SIGNAL(currentChanged(QModelIndex)), this, SLOT(slotCurrentChanged(QModelIndex)) ); connect( m_view, SIGNAL(selectionChanged(QModelIndexList)), this, SLOT(slotSelectionChanged(QModelIndexList)) ); connect( model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(updateActionsEnabled(QModelIndex)) ); connect( m_view, SIGNAL(contextMenuRequested(QModelIndex,QPoint,QModelIndexList)), this, SLOT(slotContextMenuRequested(QModelIndex,QPoint)) ); connect( m_view, SIGNAL(headerContextMenuRequested(QPoint)), SLOT(slotHeaderContextMenuRequested(QPoint)) ); Help::add(this, xi18nc("@info:whatsthis", "Schedule Editor" "" "The Schedule Editor is used to create, edit, calculate and delete schedules. " "A schedule can have sub-schedules. A sub-schedule can use the projects progress data" " in order to reschedule only tasks that are not yet finished." " Rescheduling will then use e.g. actual start and remaining effort for the tasks." "More..." "", Help::page("Manual/Schedule_Editor"))); } void ScheduleEditor::draw( Project &project ) { m_view->setProject( &project ); m_schedulingRange->setProject(&project); } void ScheduleEditor::draw() { } void ScheduleEditor::setGuiActive( bool activate ) { //debugPlan<currentIndex().isValid() ) { m_view->selectionModel()->setCurrentIndex(m_view->model()->index( 0, 0 ), QItemSelectionModel::NoUpdate); } } void ScheduleEditor::slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ) { debugPlan<setContextMenuIndex(index); if ( name.isEmpty() ) { slotHeaderContextMenuRequested( pos ); m_view->setContextMenuIndex(QModelIndex()); return; } debugPlan<setContextMenuIndex(QModelIndex()); } void ScheduleEditor::slotCurrentChanged( const QModelIndex & ) { //debugPlan<selectedRows(); // gets column 0 in each row (should be 1 or 0 rows) if ( lst.count() == 1 ) { ScheduleManager *sm = m_view->model()->manager( lst.first() ); emit scheduleSelectionChanged( sm ); } else { emit scheduleSelectionChanged( 0 ); } slotEnableActions(); } void ScheduleEditor::updateActionsEnabled( const QModelIndex &index ) { debugPlan<setEnabled( false ); actionAddSubSchedule->setEnabled( false ); actionDeleteSelection->setEnabled( false ); actionCalculateSchedule->setEnabled( false ); actionBaselineSchedule->setEnabled( false ); actionMoveLeft->setEnabled( false ); return; } QModelIndexList lst = m_view->selectedRows(); if ( lst.isEmpty() ) { actionAddSchedule->setEnabled( true ); actionAddSubSchedule->setEnabled( false ); actionDeleteSelection->setEnabled( false ); actionCalculateSchedule->setEnabled( false ); actionBaselineSchedule->setEnabled( false ); actionMoveLeft->setEnabled( false ); return; } if ( lst.count() > 1 ) { actionAddSchedule->setEnabled( false ); actionAddSubSchedule->setEnabled( false ); actionDeleteSelection->setEnabled( false ); actionCalculateSchedule->setEnabled( false ); actionBaselineSchedule->setEnabled( false ); actionMoveLeft->setEnabled( false ); return; } // one and only one manager selected ScheduleManager *sm = m_view->manager( lst.first() ); Q_ASSERT( sm ); actionAddSchedule->setEnabled( true ); actionAddSubSchedule->setEnabled( sm->isScheduled() ); actionDeleteSelection->setEnabled( ! ( sm->isBaselined() || sm->isChildBaselined() ) ); actionCalculateSchedule->setEnabled( ! sm->scheduling() && sm->childCount() == 0 && ! ( sm->isBaselined() || sm->isChildBaselined() ) ); const char *const actionBaselineScheduleIconName = sm->isBaselined() ? koIconNameCStr("view-time-schedule-baselined-remove") : koIconNameCStr("view-time-schedule-baselined-add"); actionBaselineSchedule->setIcon(QIcon::fromTheme(QLatin1String(actionBaselineScheduleIconName))); // enable if scheduled and no one else is baselined bool en = sm->isScheduled() && ( sm->isBaselined() || ! m_view->project()->isBaselined() ); actionBaselineSchedule->setEnabled( en ); actionMoveLeft->setEnabled( sm->parentManager() ); } void ScheduleEditor::setupGui() { QString name = "scheduleeditor_edit_list"; actionAddSchedule = new QAction(koIcon("view-time-schedule-insert"), i18n("Add Schedule"), this); actionCollection()->setDefaultShortcut(actionAddSchedule, Qt::CTRL + Qt::Key_I); actionCollection()->addAction("add_schedule", actionAddSchedule ); connect( actionAddSchedule, SIGNAL(triggered(bool)), SLOT(slotAddSchedule()) ); addAction( name, actionAddSchedule ); actionAddSubSchedule = new QAction(koIcon("view-time-schedule-child-insert"), i18n("Add Sub-schedule"), this); actionCollection()->setDefaultShortcut(actionAddSubSchedule, Qt::CTRL + Qt::SHIFT + Qt::Key_I); actionCollection()->addAction("add_subschedule", actionAddSubSchedule ); connect( actionAddSubSchedule, SIGNAL(triggered(bool)), SLOT(slotAddSubSchedule()) ); addAction( name, actionAddSubSchedule ); actionDeleteSelection = new QAction(koIcon("edit-delete"), xi18nc("@action", "Delete"), this ); actionCollection()->setDefaultShortcut(actionDeleteSelection, Qt::Key_Delete); actionCollection()->addAction("schedule_delete_selection", actionDeleteSelection ); connect( actionDeleteSelection, SIGNAL(triggered(bool)), SLOT(slotDeleteSelection()) ); addAction( name, actionDeleteSelection ); actionCalculateSchedule = new QAction(koIcon("view-time-schedule-calculus"), i18n("Calculate"), this); // actionCollection()->setDefaultShortcut(actionCalculateSchedule, Qt::CTRL + Qt::Key_C); actionCollection()->addAction("calculate_schedule", actionCalculateSchedule ); connect( actionCalculateSchedule, SIGNAL(triggered(bool)), SLOT(slotCalculateSchedule()) ); addAction( name, actionCalculateSchedule ); actionBaselineSchedule = new QAction(koIcon("view-time-schedule-baselined-add"), i18n("Baseline"), this); // actionCollection()->setDefaultShortcut(actionBaselineSchedule, Qt::CTRL + Qt::Key_B); actionCollection()->addAction("schedule_baseline", actionBaselineSchedule ); connect( actionBaselineSchedule, SIGNAL(triggered(bool)), SLOT(slotBaselineSchedule()) ); addAction( name, actionBaselineSchedule ); actionMoveLeft = new QAction(koIcon("go-first"), xi18nc("@action", "Detach"), this); actionCollection()->addAction("schedule_move_left", actionMoveLeft ); connect( actionMoveLeft, SIGNAL(triggered(bool)), SLOT(slotMoveLeft()) ); addAction( name, actionMoveLeft ); // Add the context menu actions for the view options createOptionActions(ViewBase::OptionExpand | ViewBase::OptionCollapse | ViewBase::OptionViewConfig); } void ScheduleEditor::updateReadWrite( bool readwrite ) { debugPlan<setReadWrite( readwrite ); slotEnableActions(); } void ScheduleEditor::slotOptions() { debugPlan; ItemViewSettupDialog *dlg = new ItemViewSettupDialog( this, m_view, true, this ); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } void ScheduleEditor::slotCalculateSchedule() { //debugPlan; ScheduleManager *sm = m_view->selectedManager(); if ( sm == 0 ) { return; } if ( sm->parentManager() ) { RecalculateDialog dlg; if ( dlg.exec() == QDialog::Rejected ) { return; } sm->setRecalculate( true ); sm->setRecalculateFrom( DateTime( dlg.dateTime() ) ); } emit calculateSchedule( m_view->project(), sm ); } void ScheduleEditor::slotAddSchedule() { //debugPlan; int idx = -1; ScheduleManager *sm = m_view->selectedManager(); if ( sm ) { idx = sm->parentManager() ? sm->parentManager()->indexOf( sm ) : m_view->project()->indexOf( sm ); if ( idx >= 0 ) { ++idx; } } if ( sm && sm->parentManager() ) { sm = sm->parentManager(); ScheduleManager *m = m_view->project()->createScheduleManager( sm->name() + QString(".%1").arg( sm->children().count() + 1 ) ); part()->addCommand( new AddScheduleManagerCmd( sm, m, idx, kundo2_i18n( "Create sub-schedule" ) ) ); QModelIndex idx = model()->index( m ); if ( idx.isValid() ) { m_view->setFocus(); m_view->scrollTo( idx ); m_view->selectionModel()->select( idx, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect ); m_view->selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); } } else { Project *p = m_view->project(); ScheduleManager *m = p->createScheduleManager(); AddScheduleManagerCmd *cmd = new AddScheduleManagerCmd( *p, m, idx, kundo2_i18n( "Add schedule %1", m->name() ) ); part() ->addCommand( cmd ); QModelIndex idx = model()->index( m ); if ( idx.isValid() ) { m_view->setFocus(); m_view->scrollTo( idx ); m_view->selectionModel()->select( idx, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect ); m_view->selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); } } } void ScheduleEditor::slotAddSubSchedule() { //debugPlan; ScheduleManager *sm = m_view->selectedManager(); if ( sm ) { int row = sm->parentManager() ? sm->parentManager()->indexOf( sm ) : m_view->project()->indexOf( sm ); if ( row >= 0 ) { ++row; } ScheduleManager *m = m_view->project()->createScheduleManager( sm->name() + QString(".%1").arg( sm->children().count() + 1 ) ); part()->addCommand( new AddScheduleManagerCmd( sm, m, row, kundo2_i18n( "Create sub-schedule" ) ) ); m_view->expand( model()->index( sm ) ); QModelIndex idx = model()->index( m ); if ( idx.isValid() ) { m_view->selectionModel()->select( idx, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect ); m_view->selectionModel()->setCurrentIndex( idx, QItemSelectionModel::NoUpdate ); } } else { slotAddSchedule(); } } void ScheduleEditor::slotBaselineSchedule() { //debugPlan; ScheduleManager *sm = m_view->selectedManager(); if ( sm ) { emit baselineSchedule( m_view->project(), sm ); } } void ScheduleEditor::slotDeleteSelection() { //debugPlan; ScheduleManager *sm = m_view->selectedManager(); if ( sm ) { emit deleteScheduleManager( m_view->project(), sm ); } } void ScheduleEditor::slotMoveLeft() { ScheduleManager *sm = m_view->selectedManager(); if ( sm ) { int index = -1; for ( ScheduleManager *m = sm; m != 0; m = m->parentManager() ) { if ( m->parentManager() == 0 ) { index = m->project().indexOf( m ) + 1; } } debugPlan<name()<loadContext( model()->columnMap(), context ); } void ScheduleEditor::saveContext( QDomElement &context ) const { m_view->saveContext( model()->columnMap(), context ); } KoPrintJob *ScheduleEditor::createPrintJob() { return m_view->createPrintJob( this ); } //----------------------------------------- ScheduleLogTreeView::ScheduleLogTreeView( QWidget *parent ) : QTreeView( parent ) { header()->setStretchLastSection ( true ); header()->setContextMenuPolicy( Qt::CustomContextMenu ); m_model = new QSortFilterProxyModel( this ); m_model->setFilterRole( Qt::UserRole+1 ); m_model->setFilterKeyColumn ( 2 ); // severity m_model->setFilterWildcard( "[^0]" ); // Filter out Debug m_model->setSourceModel( new ScheduleLogItemModel( this ) ); setModel( m_model ); setRootIsDecorated( false ); setSelectionMode( QAbstractItemView::ExtendedSelection ); setSelectionBehavior( QAbstractItemView::SelectRows ); setAlternatingRowColors( true ); connect( header(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(headerContextMenuRequested(QPoint)) ); actionShowDebug = new KToggleAction( xi18nc( "@action", "Show Debug Information" ), this ); connect( actionShowDebug, SIGNAL(toggled(bool)), SLOT(slotShowDebug(bool))); } void ScheduleLogTreeView::setFilterWildcard( const QString &filter ) { m_model->setFilterWildcard( filter ); } QRegExp ScheduleLogTreeView::filterRegExp() const { return m_model->filterRegExp(); } void ScheduleLogTreeView::slotShowDebug( bool on ) { on ? setFilterWildcard( QString() ) : setFilterWildcard("[^0]" ); } void ScheduleLogTreeView::contextMenuEvent ( QContextMenuEvent *e ) { debugPlan<pos())<<" at"<pos(); emit contextMenuRequested( indexAt( e->pos() ), e->globalPos() ); } void ScheduleLogTreeView::headerContextMenuRequested( const QPoint &pos ) { //debugPlan<logicalIndexAt(pos)<<" at"<addAction( actionShowDebug ); m->exec( mapToGlobal( pos ) ); delete m; } void ScheduleLogTreeView::selectionChanged( const QItemSelection &sel, const QItemSelection &desel ) { //debugPlan<selectedIndexes() ) { Q_UNUSED(i); //debugPlan<selectedIndexes() ); } void ScheduleLogTreeView::currentChanged( const QModelIndex & current, const QModelIndex & previous ) { //debugPlan<select( current, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect ); } void ScheduleLogTreeView::slotEditCopy() { QStringList lst; // int row = 0; QString s; QHeaderView *h = header(); foreach( const QModelIndex &i, selectionModel()->selectedRows() ) { QString s; for ( int section = 0; section < h->count(); ++section ) { QModelIndex idx = model()->index( i.row(), h->logicalIndex( section ) ); if ( ! idx.isValid() || isColumnHidden( idx.column() ) ) { continue; } if ( ! s.isEmpty() ) { s += ' '; } s = QString( "%1%2" ).arg( s ).arg( idx.data().toString(), -10 ); } if ( ! s.isEmpty() ) { lst << s; } } if ( ! lst.isEmpty() ) { QApplication::clipboard()->setText( lst.join( "\n" ) ); } } //----------------------------------- ScheduleLogView::ScheduleLogView(KoPart *part, KoDocument *doc, QWidget *parent) : ViewBase(part, doc, parent ) { setupGui(); slotEnableActions( 0 ); QVBoxLayout * l = new QVBoxLayout( this ); m_view = new ScheduleLogTreeView( this ); l->addWidget( m_view ); // m_view->setEditTriggers( m_view->editTriggers() | QAbstractItemView::EditKeyPressed ); connect( m_view, SIGNAL(currentChanged(QModelIndex)), this, SLOT(slotCurrentChanged(QModelIndex)) ); connect( m_view, SIGNAL(selectionChanged(QModelIndexList)), this, SLOT(slotSelectionChanged(QModelIndexList)) ); connect( baseModel(), SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SLOT(updateActionsEnabled(QModelIndex)) ); connect( m_view, SIGNAL(contextMenuRequested(QModelIndex,QPoint)), this, SLOT(slotContextMenuRequested(QModelIndex,QPoint)) ); } void ScheduleLogView::setProject( Project *project ) { m_view->setProject( project ); } void ScheduleLogView::draw( Project &project ) { setProject( &project ); } void ScheduleLogView::setGuiActive( bool activate ) { //debugPlan<currentIndex().isValid() ) { m_view->selectionModel()->setCurrentIndex(m_view->model()->index( 0, 0 ), QItemSelectionModel::NoUpdate); }*/ } void ScheduleLogView::slotEdit() { QString id = sender()->property( "p_identity" ).toString(); if ( id.isEmpty() ) { emit editNode( project() ); return; } Node *n = project()->findNode( id ); if ( n ) { emit editNode( n ); return; } Resource *r = project()->findResource( id ); if ( r ) { emit editResource( r ); return; } warnPlan<<"No object"; } void ScheduleLogView::slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ) { if ( ! isReadWrite() || ! index.isValid() ) { return; } QMenu *m = new QMenu( this ); QString id = index.data( ScheduleLogItemModel::IdentityRole ).toString(); if ( id.isEmpty() ) { return; } QAction *a = new QAction(koIcon("document-edit"), i18n( "Edit..." ), m); a->setProperty( "p_identity", id ); m->addAction( a ); connect(a, SIGNAL(triggered(bool)), SLOT(slotEdit())); m->addSeparator(); m->exec( pos ); delete m; } void ScheduleLogView::slotScheduleSelectionChanged( ScheduleManager *sm ) { baseModel()->setManager( sm ); } void ScheduleLogView::slotCurrentChanged( const QModelIndex & ) { //debugPlan<setReadWrite( readwrite ); //slotEnableActions( m_view->currentManager() ); } void ScheduleLogView::slotOptions() { debugPlan; } void ScheduleLogView::slotEditCopy() { m_view->slotEditCopy(); } bool ScheduleLogView::loadContext( const KoXmlElement &/*context */) { debugPlan; return true;//m_view->loadContext( model()->columnMap(), context ); } void ScheduleLogView::saveContext( QDomElement &/*context */) const { //m_view->saveContext( model()->columnMap(), context ); } //--------------------------- ScheduleHandlerView::ScheduleHandlerView(KoPart *part, KoDocument *doc, QWidget *parent ) : SplitterView(part, doc, parent) { debugPlan<<"---------------- Create ScheduleHandlerView ------------------"; m_scheduleEditor = new ScheduleEditor(part, doc, this ); m_scheduleEditor->setObjectName( "ScheduleEditor" ); addView( m_scheduleEditor ); QTabWidget *tab = addTabWidget(); PertResult *p = new PertResult(part, doc, tab); p->setObjectName( "PertResult" ); addView( p, tab, i18n( "Result" ) ); - connect( m_scheduleEditor, SIGNAL(scheduleSelectionChanged(ScheduleManager*)), p, SLOT(slotScheduleSelectionChanged(ScheduleManager*)) ); + connect( m_scheduleEditor, SIGNAL(scheduleSelectionChanged(KPlato::ScheduleManager*)), p, SLOT(slotScheduleSelectionChanged(KPlato::ScheduleManager*)) ); PertCpmView *c = new PertCpmView(part, doc, tab); c->setObjectName( "PertCpmView" ); addView( c, tab, i18n( "Critical Path" ) ); - connect( m_scheduleEditor, SIGNAL(scheduleSelectionChanged(ScheduleManager*)), c, SLOT(slotScheduleSelectionChanged(ScheduleManager*)) ); + connect( m_scheduleEditor, SIGNAL(scheduleSelectionChanged(KPlato::ScheduleManager*)), c, SLOT(slotScheduleSelectionChanged(KPlato::ScheduleManager*)) ); ScheduleLogView *v = new ScheduleLogView(part, doc, tab); v->setObjectName( "ScheduleLogView" ); addView( v, tab, i18n( "Scheduling Log" ) ); - connect( m_scheduleEditor, SIGNAL(scheduleSelectionChanged(ScheduleManager*)), v, SLOT(slotScheduleSelectionChanged(ScheduleManager*)) ); - connect(v, SIGNAL(editNode(Node*)), SIGNAL(editNode(Node*))); - connect(v, SIGNAL(editResource(Resource*)), SIGNAL(editResource(Resource*))); + connect( m_scheduleEditor, SIGNAL(scheduleSelectionChanged(KPlato::ScheduleManager*)), v, SLOT(slotScheduleSelectionChanged(KPlato::ScheduleManager*)) ); + connect(v, SIGNAL(editNode(KPlato::Node*)), SIGNAL(editNode(KPlato::Node*))); + connect(v, SIGNAL(editResource(KPlato::Resource*)), SIGNAL(editResource(KPlato::Resource*))); } void ScheduleHandlerView::currentTabChanged( int ) { } ViewBase *ScheduleHandlerView::hitView( const QPoint &/*glpos */) { //debugPlan<"<() ) { v->setGuiActive( active ); } m_activeview = active ? this : 0; emit guiActivated( this, active ); } void ScheduleHandlerView::slotGuiActivated( ViewBase *, bool ) { } QStringList ScheduleHandlerView::actionListNames() const { QStringList lst; foreach ( ViewBase *v, findChildren() ) { lst += v->actionListNames(); } return lst; } QList ScheduleHandlerView::actionList( const QString &name ) const { //debugPlan< lst; foreach ( ViewBase *v, findChildren() ) { lst += v->actionList( name ); } return lst; } SchedulingRange::SchedulingRange(KoDocument *doc, QWidget *parent) : QWidget(parent) , m_doc(doc) , m_project(0) { setupUi(this); connect(targetStartTime, SIGNAL(editingFinished()), this, SLOT(slotStartChanged())); connect(targetEndTime, SIGNAL(editingFinished()), this, SLOT(slotEndChanged())); } void SchedulingRange::setProject(Project *project) { if (m_project) { - disconnect(m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotProjectChanged(Node*))); + disconnect(m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotProjectChanged(KPlato::Node*))); } m_project = project; if (m_project) { - connect(m_project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotProjectChanged(Node*))); + connect(m_project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotProjectChanged(KPlato::Node*))); slotProjectChanged(m_project); } } void SchedulingRange::slotProjectChanged(Node *node) { if (node != m_project) { return; } if (targetStartTime->dateTime() != m_project->constraintStartTime()) { targetStartTime->setDateTime(m_project->constraintStartTime()); } if (targetEndTime->dateTime() != m_project->constraintEndTime()) { targetEndTime->setDateTime(m_project->constraintEndTime()); } } void SchedulingRange::slotStartChanged() { if (!m_project || !m_doc) { return; } if (targetStartTime->dateTime() == m_project->constraintStartTime()) { return; } ProjectModifyStartTimeCmd *cmd = new ProjectModifyStartTimeCmd(*m_project, targetStartTime->dateTime(), kundo2_i18n("Modify project target start time")); m_doc->addCommand(cmd); } void SchedulingRange::slotEndChanged() { if (!m_project || !m_doc) { return; } if (targetEndTime->dateTime() == m_project->constraintEndTime()) { return; } ProjectModifyEndTimeCmd *cmd = new ProjectModifyEndTimeCmd(*m_project, targetEndTime->dateTime(), kundo2_i18n("Modify project target end time")); m_doc->addCommand(cmd); } } // namespace KPlato diff --git a/src/libs/ui/kptscheduleeditor.h b/src/libs/ui/kptscheduleeditor.h index d1c46e27..9b05ce82 100644 --- a/src/libs/ui/kptscheduleeditor.h +++ b/src/libs/ui/kptscheduleeditor.h @@ -1,290 +1,290 @@ /* This file is part of the KDE project Copyright (C) 2006-2008 Dag Andersen Copyright (C) 2006-2007 Menard Alexis 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 KPTSCHEDULEEDITOR_H #define KPTSCHEDULEEDITOR_H #include "planui_export.h" #include #include "kptsplitterview.h" #include "kptschedulemodel.h" #include "ui_kptscheduleeditor.h" #include class KoDocument; class KToggleAction; class QPoint; class QSortFilterProxyModel; namespace KPlato { class Project; class ScheduleManager; class SchedulingRange; class PLANUI_EXPORT ScheduleTreeView : public TreeViewBase { Q_OBJECT public: explicit ScheduleTreeView(QWidget *parent); ScheduleItemModel *model() const { return static_cast( TreeViewBase::model() ); } Project *project() const { return model()->project(); } void setProject( Project *project ) { model()->setProject( project ); } ScheduleManager *manager( const QModelIndex &idx ) const; ScheduleManager *currentManager() const; ScheduleManager *selectedManager() const; QModelIndexList selectedRows() const; Q_SIGNALS: void currentChanged( const QModelIndex& ); void currentColumnChanged( const QModelIndex&, const QModelIndex& ); void selectionChanged( const QModelIndexList& ); protected Q_SLOTS: virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); virtual void currentChanged ( const QModelIndex & current, const QModelIndex & previous ); }; class PLANUI_EXPORT ScheduleEditor : public ViewBase { Q_OBJECT public: ScheduleEditor(KoPart *part, KoDocument *doc, QWidget *parent); void setupGui(); Project *project() const { return m_view->project(); } virtual void draw( Project &project ); virtual void draw(); ScheduleItemModel *model() const { return m_view->model(); } virtual void updateReadWrite( bool readwrite ); /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &/*context*/ ) const; KoPrintJob *createPrintJob(); Q_SIGNALS: - void calculateSchedule( Project*, ScheduleManager* ); - void baselineSchedule( Project*, ScheduleManager* ); - void addScheduleManager( Project* ); - void deleteScheduleManager( Project*, ScheduleManager* ); + void calculateSchedule(KPlato::Project*, KPlato::ScheduleManager*); + void baselineSchedule(KPlato::Project*, KPlato::ScheduleManager*); + void addScheduleManager(KPlato::Project*); + void deleteScheduleManager(KPlato::Project*, KPlato::ScheduleManager*); void SelectionScheduleChanged(); /** * Emitted when schedule selection changes. * @param sm is the new schedule manager. If @p is 0, no schedule is selected. */ - void scheduleSelectionChanged( ScheduleManager *sm ); + void scheduleSelectionChanged(KPlato::ScheduleManager *sm); - void moveScheduleManager( ScheduleManager *sm, ScheduleManager *newparent, int index ); + void moveScheduleManager(KPlato::ScheduleManager *sm, KPlato::ScheduleManager *newparent, int index); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); protected Q_SLOTS: virtual void slotOptions(); private Q_SLOTS: void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); void slotSelectionChanged( const QModelIndexList& ); void slotCurrentChanged( const QModelIndex& ); void updateActionsEnabled( const QModelIndex &index ); void slotEnableActions(); void slotCalculateSchedule(); void slotBaselineSchedule(); void slotAddSchedule(); void slotAddSubSchedule(); void slotDeleteSelection(); void slotMoveLeft(); private: ScheduleTreeView *m_view; SchedulingRange *m_schedulingRange; QAction *actionCalculateSchedule; QAction *actionBaselineSchedule; QAction *actionAddSchedule; QAction *actionAddSubSchedule; QAction *actionDeleteSelection; QAction *actionMoveLeft; }; //----------------------------- class PLANUI_EXPORT ScheduleLogTreeView : public QTreeView { Q_OBJECT public: explicit ScheduleLogTreeView(QWidget *parent); Project *project() const { return logModel()->project(); } void setProject( Project *project ) { logModel()->setProject( project ); } ScheduleLogItemModel *logModel() const { return static_cast( m_model->sourceModel() ); } ScheduleManager *scheduleManager() const { return logModel()->manager(); } void setScheduleManager( ScheduleManager *manager ) { logModel()->setManager( manager ); } void setFilterWildcard( const QString &filter ); QRegExp filterRegExp() const; Q_SIGNALS: void currentChanged( const QModelIndex& ); void currentColumnChanged( const QModelIndex&, const QModelIndex& ); void selectionChanged( const QModelIndexList& ); void contextMenuRequested( const QModelIndex&, const QPoint& ); public Q_SLOTS: void slotEditCopy(); protected Q_SLOTS: void contextMenuEvent ( QContextMenuEvent *e ); void headerContextMenuRequested( const QPoint &pos ); virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); virtual void currentChanged ( const QModelIndex & current, const QModelIndex & previous ); void slotShowDebug( bool ); private: QSortFilterProxyModel *m_model; KToggleAction *actionShowDebug; }; //---------------------------------------------- class PLANUI_EXPORT ScheduleLogView : public ViewBase { Q_OBJECT public: ScheduleLogView(KoPart *part, KoDocument *doc, QWidget *parent); void setupGui(); virtual void setProject( Project *project ); Project *project() const { return m_view->project(); } using ViewBase::draw; virtual void draw( Project &project ); ScheduleLogItemModel *baseModel() const { return m_view->logModel(); } virtual void updateReadWrite( bool readwrite ); /// Loads context info into this view. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. virtual void saveContext( QDomElement &/*context*/ ) const; Q_SIGNALS: - void editNode( Node *node ); - void editResource( Resource *resource ); + void editNode(KPlato::Node *node); + void editResource(KPlato::Resource *resource); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); void slotEditCopy(); void slotEdit(); protected Q_SLOTS: virtual void slotOptions(); private Q_SLOTS: void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); - void slotScheduleSelectionChanged( ScheduleManager *sm ); + void slotScheduleSelectionChanged(KPlato::ScheduleManager *sm); + void slotEnableActions(const KPlato::ScheduleManager *sm); void slotSelectionChanged( const QModelIndexList& ); void slotCurrentChanged( const QModelIndex& ); void updateActionsEnabled( const QModelIndex &index ); - void slotEnableActions( const ScheduleManager *sm ); private: ScheduleLogTreeView *m_view; }; //----------------------------- class PLANUI_EXPORT ScheduleHandlerView : public SplitterView { Q_OBJECT public: ScheduleHandlerView(KoPart *part, KoDocument *doc, QWidget *parent); Project *project() const { return 0; } ScheduleEditor *scheduleEditor() const { return m_scheduleEditor; } /// Returns a list of actionlist names for all shown views QStringList actionListNames() const; /// Returns the list of actions associated with the action list @p name virtual QList actionList( const QString &name ) const; /// Always returns this (if we are called, we are hit) virtual ViewBase *hitView( const QPoint &glpos ); Q_SIGNALS: - void currentScheduleManagerChanged( ScheduleManager* ); - void editNode( Node *node ); - void editResource( Resource *resource ); + void currentScheduleManagerChanged(KPlato::ScheduleManager*); + void editNode(KPlato::Node *node); + void editResource(KPlato::Resource *resource); public Q_SLOTS: /// Activate/deactivate the gui (also of subviews) virtual void setGuiActive( bool activate ); protected Q_SLOTS: /// Noop, we handle subviews ourselves - virtual void slotGuiActivated( ViewBase *v, bool active ); + virtual void slotGuiActivated(KPlato::ViewBase *v, bool active ); virtual void currentTabChanged( int i ); private: ScheduleEditor *m_scheduleEditor; }; class SchedulingRange : public QWidget, public Ui::SchedulingRange { Q_OBJECT public: SchedulingRange(KoDocument *doc, QWidget *parent = 0); public Q_SLOTS: - void setProject(Project *project); - void slotProjectChanged(Node*); + void setProject(KPlato::Project *project); + void slotProjectChanged(KPlato::Node*); void slotStartChanged(); void slotEndChanged(); protected: KoDocument *m_doc; Project *m_project; }; } //KPlato namespace #endif diff --git a/src/libs/ui/kptsplitterview.h b/src/libs/ui/kptsplitterview.h index 023ffa0c..43f3a31f 100644 --- a/src/libs/ui/kptsplitterview.h +++ b/src/libs/ui/kptsplitterview.h @@ -1,131 +1,131 @@ /* This file is part of the KDE project Copyright (C) 2007 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 KPTSPLITTERVIEW_H #define KPTSPLITTERVIEW_H #include "planui_export.h" #include "kptviewbase.h" #include class KoDocument; class QSplitter; class QTabWidget; /// The main namespace namespace KPlato { class Project; class Node; class Resource; class ResourceGroup; class Calendar; class Relation; class Context; /** * SplitterView is a view with a vertical QSplitter that can contain * other ViewBase based views and/or QTabWidgets that can hold * ViewVase based views as well. * This splitter view is created by the main View, and subviews can then be * added with addView(). A QTabWidget is added with addTabWidget(). * * To have context info loaded, views added to this splitter must have a * unique objectName(). */ class PLANUI_EXPORT SplitterView : public ViewBase { Q_OBJECT public: /// Constructor SplitterView(KoPart *part, KoDocument *doc, QWidget *parent); /// Destructor virtual ~SplitterView() {} /// Set the project this view shall handle. virtual void setProject( Project *project ); /// Draw data from current part / project virtual void draw(); /// Draw data from project. virtual void draw( Project &project ); /// Set readWrite mode virtual void updateReadWrite( bool ); /// Return the view that has focus ViewBase *focusView() const; /// Returns the list of action lists that shall be plugged/unplugged virtual QStringList actionListNames() const; /// Returns the list of actions associated with the action list name virtual QList actionList( const QString &name ) const; /// Returns the list of context menu actions for the active view virtual QList contextActionList() const; /// Sets context info to this view. Reimplement. virtual bool setContext( const Context &/*context*/ ) { return false; } /// Gets context info from this view. Reimplement. virtual void getContext( Context &/*context*/ ) const {} /// Add a QTabWidget to the splitter QTabWidget *addTabWidget(); /// Add the @p view to the splitter void addView( ViewBase *view ); /// Add the @p view to the @p tab. Set the tabs label to @p label void addView( ViewBase *view, QTabWidget *tab, const QString &label ); /// Return the active view at @p pos ViewBase *findView( const QPoint &pos ) const; /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &/*context*/ ) const; virtual Node* currentNode() const; virtual Resource* currentResource() const; virtual ResourceGroup* currentResourceGroup() const; virtual Calendar* currentCalendar() const; virtual Relation *currentRelation() const; public Q_SLOTS: /// Activate/deactivate the gui (also of subviews) virtual void setGuiActive( bool activate ); - virtual void setScheduleManager( ScheduleManager *sm ); + virtual void setScheduleManager(KPlato::ScheduleManager *sm); virtual void slotEditCopy(); protected Q_SLOTS: - virtual void slotGuiActivated( ViewBase *v, bool active ); + virtual void slotGuiActivated(KPlato::ViewBase *v, bool active); virtual void currentTabChanged( int i ); protected: QSplitter *m_splitter; ViewBase *m_activeview; }; } // namespace KPlato #endif diff --git a/src/libs/ui/kptsummarytaskdialog.cpp b/src/libs/ui/kptsummarytaskdialog.cpp index 9222310b..259fc692 100644 --- a/src/libs/ui/kptsummarytaskdialog.cpp +++ b/src/libs/ui/kptsummarytaskdialog.cpp @@ -1,88 +1,88 @@ /* This file is part of the KDE project Copyright (C) 2002 Bo Thorsen bo@sonofthor.dk Copyright (C) 2004 - 2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kptsummarytaskdialog.h" #include "kptsummarytaskgeneralpanel.h" #include "kptcommand.h" #include "kptnode.h" #include "kpttask.h" #include "kptproject.h" #include namespace KPlato { SummaryTaskDialog::SummaryTaskDialog(Task &task, QWidget *p) : KoDialog(p), m_node( &task ) { setCaption( i18n("Summary Task Settings") ); setButtons( Ok|Cancel ); setDefaultButton( Ok ); showButtonSeparator( true ); m_generalTab = new SummaryTaskGeneralPanel(task, this); setMainWidget(m_generalTab); enableButtonOk(false); connect(m_generalTab, SIGNAL(obligatedFieldsFilled(bool)), SLOT(enableButtonOk(bool))); Project *proj = static_cast( task.projectNode() ); if ( proj ) { - connect(proj, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotTaskRemoved(Node*))); + connect(proj, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotTaskRemoved(KPlato::Node*))); } } void SummaryTaskDialog::slotTaskRemoved( Node *node ) { if ( node == m_node ) { reject(); } } MacroCommand *SummaryTaskDialog::buildCommand() { MacroCommand *m = new MacroCommand(kundo2_i18n("Modify Summary Task")); bool modified = false; MacroCommand *cmd = m_generalTab->buildCommand(); if (cmd) { m->addCommand(cmd); modified = true; } if (!modified) { delete m; return 0; } return m; } void SummaryTaskDialog::slotButtonClicked(int button) { if (button == KoDialog::Ok) { if (!m_generalTab->ok()) return; accept(); } else { KoDialog::slotButtonClicked(button); } } } //KPlato namespace diff --git a/src/libs/ui/kptsummarytaskdialog.h b/src/libs/ui/kptsummarytaskdialog.h index ab3fbfcb..89388201 100644 --- a/src/libs/ui/kptsummarytaskdialog.h +++ b/src/libs/ui/kptsummarytaskdialog.h @@ -1,63 +1,63 @@ /* This file is part of the KDE project Copyright (C) 2002 Bo Thorsen bo@sonofthor.dk Copyright (C) 2004 - 2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTSUMMARYTASKDIALOG_H #define KPTSUMMARYTASKDIALOG_H #include "planui_export.h" #include namespace KPlato { class SummaryTaskGeneralPanel; class Task; class Node; class MacroCommand; /** * The dialog that shows and allows you to alter summary tasks. */ class PLANUI_EXPORT SummaryTaskDialog : public KoDialog { Q_OBJECT public: /** * The constructor for the summary task settings dialog. * @param task the task to edit * @param parent parent widget */ explicit SummaryTaskDialog(Task &task, QWidget *parent=0); MacroCommand *buildCommand(); protected Q_SLOTS: void slotButtonClicked(int button); - void slotTaskRemoved( Node *node ); + void slotTaskRemoved(KPlato::Node *node); private: Node *m_node; SummaryTaskGeneralPanel *m_generalTab; }; } //KPlato namespace #endif // SUMMARYTASKDIALOG_H diff --git a/src/libs/ui/kpttaskdialog.cpp b/src/libs/ui/kpttaskdialog.cpp index 0c9e057c..43bdbcd7 100644 --- a/src/libs/ui/kpttaskdialog.cpp +++ b/src/libs/ui/kpttaskdialog.cpp @@ -1,226 +1,226 @@ /* This file is part of the KDE project Copyright (C) 2002 Bo Thorsen bo@sonofthor.dk Copyright (C) 2004 -2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kpttaskdialog.h" #include "kpttaskcostpanel.h" #include "kpttaskgeneralpanel.h" #include "kptrequestresourcespanel.h" #include "kptdocumentspanel.h" #include "kpttaskdescriptiondialog.h" #include "kptcommand.h" #include "kptnode.h" #include "kpttask.h" #include "kptproject.h" #include #include namespace KPlato { TaskDialog::TaskDialog( Project &project, Task &task, Accounts &accounts, QWidget *p) : KPageDialog(p), m_project( project ), m_node( &task ) { setWindowTitle( i18n("Task Settings") ); setFaceType( KPageDialog::Tabbed ); KoVBox *page; // Create all the tabs. page = new KoVBox(); addPage(page, i18n("&General")); m_generalTab = new TaskGeneralPanel(project, task, page); page = new KoVBox(); addPage(page, i18n("&Resources")); m_resourcesTab = new RequestResourcesPanel(page, project, task); page = new KoVBox(); addPage(page, i18n("&Documents")); m_documentsTab = new DocumentsPanel( task, page ); page = new KoVBox(); addPage(page, i18n("&Cost")); m_costTab = new TaskCostPanel(task, accounts, page); page = new KoVBox(); addPage(page, i18n("D&escription")); m_descriptionTab = new TaskDescriptionPanel(task, page); m_descriptionTab->namefield->hide(); m_descriptionTab->namelabel->hide(); setButtonOkEnabled(false); connect(this, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)), SLOT(slotCurrentChanged(KPageWidgetItem*,KPageWidgetItem*))); connect(m_generalTab, SIGNAL(obligatedFieldsFilled(bool)), this, SLOT(setButtonOkEnabled(bool))); connect(m_resourcesTab, SIGNAL(changed()), m_generalTab, SLOT(checkAllFieldsFilled())); connect(m_documentsTab, SIGNAL(changed()), m_generalTab, SLOT(checkAllFieldsFilled())); connect(m_costTab, SIGNAL(changed()), m_generalTab, SLOT(checkAllFieldsFilled())); connect(m_descriptionTab, SIGNAL(textChanged(bool)), m_generalTab, SLOT(checkAllFieldsFilled())); - connect(&project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotTaskRemoved(Node*))); + connect(&project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotTaskRemoved(KPlato::Node*))); } void TaskDialog::setButtonOkEnabled(bool enabled) { buttonBox()->button(QDialogButtonBox::Ok)->setEnabled(enabled); } void TaskDialog::slotCurrentChanged( KPageWidgetItem *current, KPageWidgetItem */*prev*/ ) { //debugPlan<widget()<parent(); // HACK: KPageDialog grabs focus when a tab is clicked. // KRichTextWidget still flashes the caret so the user thinks it has the focus. // For now, just give the KRichTextWidget focus. if ( current->widget() == m_descriptionTab->parent() ) { m_descriptionTab->descriptionfield->setFocus(); } } void TaskDialog::slotTaskRemoved( Node *node ) { if ( node == m_node ) { reject(); } } MacroCommand *TaskDialog::buildCommand() { MacroCommand *m = new MacroCommand(kundo2_i18n("Modify task")); bool modified = false; MacroCommand *cmd = m_generalTab->buildCommand(); if (cmd) { m->addCommand(cmd); modified = true; } cmd = m_resourcesTab->buildCommand(); if (cmd) { m->addCommand(cmd); modified = true; } cmd = m_documentsTab->buildCommand(); if (cmd) { m->addCommand(cmd); modified = true; } cmd = m_costTab->buildCommand(); if (cmd) { m->addCommand(cmd); modified = true; } cmd = m_descriptionTab->buildCommand(); if (cmd) { m->addCommand(cmd); modified = true; } if (!modified) { delete m; return 0; } return m; } void TaskDialog::accept() { if (!m_generalTab->ok()) return; if (!m_resourcesTab->ok()) return; if (!m_descriptionTab->ok()) return; KPageDialog::accept(); } //--------------------------- TaskAddDialog::TaskAddDialog(Project &project, Task &task, Node *currentNode, Accounts &accounts, QWidget *p) : TaskDialog(project, task, accounts, p) { m_currentnode = currentNode; // do not know wbs code yet m_generalTab->hideWbs(); - connect(&project, SIGNAL(nodeRemoved(Node*)), SLOT(slotNodeRemoved(Node*))); + connect(&project, SIGNAL(nodeRemoved(KPlato::Node*)), SLOT(slotNodeRemoved(KPlato::Node*))); } TaskAddDialog::~TaskAddDialog() { delete m_node; // in case of cancel } void TaskAddDialog::slotNodeRemoved( Node *node ) { if ( m_currentnode == node ) { reject(); } } MacroCommand *TaskAddDialog::buildCommand() { MacroCommand *c = new MacroCommand( kundo2_i18n( "Add task" ) ); c->addCommand( new TaskAddCmd( &m_project, m_node, m_currentnode ) ); MacroCommand *m = TaskDialog::buildCommand(); if ( m ) { c->addCommand( m ); } m_node = 0; // don't delete task return c; } //--------------------------- SubTaskAddDialog::SubTaskAddDialog(Project &project, Task &task, Node *currentNode, Accounts &accounts, QWidget *p) : TaskDialog(project, task, accounts, p) { m_currentnode = currentNode; // do not know wbs code yet m_generalTab->hideWbs(); - connect(&project, SIGNAL(nodeRemoved(Node*)), SLOT(slotNodeRemoved(Node*))); + connect(&project, SIGNAL(nodeRemoved(KPlato::Node*)), SLOT(slotNodeRemoved(KPlato::Node*))); } SubTaskAddDialog::~SubTaskAddDialog() { delete m_node; // in case of cancel } void SubTaskAddDialog::slotNodeRemoved( Node *node ) { if ( m_currentnode == node ) { reject(); } } MacroCommand *SubTaskAddDialog::buildCommand() { KUndo2MagicString s = kundo2_i18n( "Add sub-task" ); if ( m_currentnode == 0 ) { s = kundo2_i18n( "Add task" ); // it will be added to project } MacroCommand *c = new MacroCommand( s ); c->addCommand( new SubtaskAddCmd( &m_project, m_node, m_currentnode ) ); MacroCommand *m = TaskDialog::buildCommand(); if ( m ) { c->addCommand( m ); } m_node = 0; // don't delete task return c; } } //KPlato namespace diff --git a/src/libs/ui/kpttaskdialog.h b/src/libs/ui/kpttaskdialog.h index aabe7cba..fa469b6c 100644 --- a/src/libs/ui/kpttaskdialog.h +++ b/src/libs/ui/kpttaskdialog.h @@ -1,109 +1,109 @@ /* This file is part of the KDE project Copyright (C) 2002 Bo Thorsen bo@sonofthor.dk Copyright (C) 2004 -2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTTASKDIALOG_H #define KPTTASKDIALOG_H #include "planui_export.h" #include namespace KPlato { class Accounts; class TaskGeneralPanel; class RequestResourcesPanel; class DocumentsPanel; class TaskCostPanel; class TaskDescriptionPanel; class Node; class Task; class Project; class MacroCommand; /** * The dialog that shows and allows you to alter any task. */ class PLANUI_EXPORT TaskDialog : public KPageDialog { Q_OBJECT public: /** * The constructor for the task settings dialog. * @param task the task to show * @param accounts all defined accounts * @param parent parent widget */ TaskDialog(Project &project, Task &task, Accounts &accounts, QWidget *parent=0); virtual MacroCommand *buildCommand(); protected Q_SLOTS: void accept(); void setButtonOkEnabled(bool enabled); - void slotTaskRemoved( Node *node ); + void slotTaskRemoved(KPlato::Node *node); void slotCurrentChanged( KPageWidgetItem*, KPageWidgetItem* ); protected: Project &m_project; Node *m_node; TaskGeneralPanel *m_generalTab; RequestResourcesPanel *m_resourcesTab; DocumentsPanel *m_documentsTab; TaskCostPanel *m_costTab; TaskDescriptionPanel *m_descriptionTab; }; class PLANUI_EXPORT TaskAddDialog : public TaskDialog { Q_OBJECT public: TaskAddDialog(Project &project, Task &task, Node *currentNode, Accounts &accounts, QWidget *parent=0); ~TaskAddDialog(); virtual MacroCommand *buildCommand(); protected Q_SLOTS: - void slotNodeRemoved( Node* ); + void slotNodeRemoved(KPlato::Node*); private: Node *m_currentnode; }; class PLANUI_EXPORT SubTaskAddDialog : public TaskDialog { Q_OBJECT public: SubTaskAddDialog(Project &project, Task &task, Node *currentNode, Accounts &accounts, QWidget *parent=0); ~SubTaskAddDialog(); virtual MacroCommand *buildCommand(); protected Q_SLOTS: - void slotNodeRemoved( Node* ); + void slotNodeRemoved(KPlato::Node*); private: Node *m_currentnode; }; } //KPlato namespace #endif // TASKDIALOG_H diff --git a/src/libs/ui/kpttaskeditor.cpp b/src/libs/ui/kpttaskeditor.cpp index 91db5acb..3b3a658d 100644 --- a/src/libs/ui/kpttaskeditor.cpp +++ b/src/libs/ui/kpttaskeditor.cpp @@ -1,1711 +1,1711 @@ /* This file is part of the KDE project Copyright (C) 2006 - 2010, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kpttaskeditor.h" #include "kptglobal.h" #include "kptcommonstrings.h" #include "kptnodeitemmodel.h" #include "kptcommand.h" #include "kptproject.h" #include "kptitemviewsettup.h" #include "kptworkpackagesenddialog.h" #include "kptworkpackagesendpanel.h" #include "kptdatetime.h" #include "kptdebug.h" #include "kptresourcemodel.h" #include "kptresourceallocationmodel.h" #include "ResourceAllocationView.h" #include "kpttaskdialog.h" #include "TasksEditController.h" #include "Help.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace KPlato { //-------------------- TaskEditorItemModel::TaskEditorItemModel( QObject *parent ) : NodeItemModel( parent ) { } Qt::ItemFlags TaskEditorItemModel::flags( const QModelIndex &index ) const { if ( index.column() == NodeModel::NodeType ) { if ( ! m_readWrite || isColumnReadOnly( index.column() ) ) { return QAbstractItemModel::flags( index ); } Node *n = node( index ); bool baselined = n ? n->isBaselined() : false; if ( n && ! baselined && ( n->type() == Node::Type_Task || n->type() == Node::Type_Milestone ) ) { return QAbstractItemModel::flags( index ) | Qt::ItemIsEditable | Qt::ItemIsDropEnabled; } return QAbstractItemModel::flags( index ) | Qt::ItemIsDropEnabled; } return NodeItemModel::flags( index ); } QVariant TaskEditorItemModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( orientation == Qt::Horizontal && section == NodeModel::NodeType ) { if ( role == Qt::ToolTipRole ) { return xi18nc( "@info:tooltip", "The type of task or the estimate type of the task" ); } else if ( role == Qt::WhatsThisRole ) { return xi18nc( "@info:whatsthis", "

Indicates the type of task or the estimate type of the task.

" "The type can be set to Milestone, Effort or Duration." "If the type is Summary or Project the type is not editable."); } } return NodeItemModel::headerData(section, orientation, role); } QVariant TaskEditorItemModel::data( const QModelIndex &index, int role ) const { if ( role == Qt::TextAlignmentRole ) { return NodeItemModel::data( index, role ); } Node *n = node( index ); if ( n != 0 && index.column() == NodeModel::NodeType ) { return type( n, role ); } return NodeItemModel::data( index, role ); } bool TaskEditorItemModel::setData( const QModelIndex &index, const QVariant &value, int role ) { Node *n = node( index ); if ( n != 0 && role == Qt::EditRole && index.column() == NodeModel::NodeType ) { return setType( n, value, role ); } return NodeItemModel::setData( index, value, role ); } QVariant TaskEditorItemModel::type( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: { if ( node->type() == Node::Type_Task ) { return node->estimate()->typeToString( true ); } return node->typeToString( true ); } case Qt::EditRole: return node->type(); case Qt::TextAlignmentRole: return Qt::AlignCenter; case Qt::ToolTipRole: { if ( node->type() == Node::Type_Task ) { return xi18nc( "@info:tooltip", "Task with estimate type: %1", node->estimate()->typeToString( true ) ); } return xi18nc( "@info:tooltip", "Task type: %1", node->typeToString( true ) ); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); case Role::EnumListValue: { if ( node->type() == Node::Type_Milestone ) { return 0; } if ( node->type() == Node::Type_Task ) { return node->estimate()->type() + 1; } return -1; } case Role::EnumList: { QStringList lst; lst << Node::typeToString( Node::Type_Milestone, true ); lst += Estimate::typeToStringList( true ); return lst; } } return QVariant(); } bool TaskEditorItemModel::setType( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { if ( node->type() == Node::Type_Summarytask ) { return false; } int v = value.toInt(); switch ( v ) { case 0: { // Milestone NamedCommand *cmd = 0; if ( node->constraint() == Node::FixedInterval ) { cmd = new NodeModifyConstraintEndTimeCmd( *node, node->constraintStartTime(), kundo2_i18n( "Set type to Milestone" ) ); } else { cmd = new ModifyEstimateCmd( *node, node->estimate()->expectedEstimate(), 0.0, kundo2_i18n( "Set type to Milestone" ) ); } emit executeCommand( cmd ); return true; } default: { // Estimate --v; MacroCommand *m = new MacroCommand( kundo2_i18n( "Set type to %1", Estimate::typeToString( (Estimate::Type)v, true ) ) ); m->addCommand( new ModifyEstimateTypeCmd( *node, node->estimate()->type(), v ) ); if ( node->type() == Node::Type_Milestone ) { if ( node->constraint() == Node::FixedInterval ) { m->addCommand( new NodeModifyConstraintEndTimeCmd( *node, node->constraintStartTime().addDays( 1 ) ) ); } else { m->addCommand( new ModifyEstimateUnitCmd( *node, node->estimate()->unit(), Duration::Unit_d ) ); m->addCommand( new ModifyEstimateCmd( *node, node->estimate()->expectedEstimate(), 1.0 ) ); } } emit executeCommand( m ); return true; } } break; } default: break; } return false; } //-------------------- TaskEditorTreeView::TaskEditorTreeView( QWidget *parent ) : DoubleTreeViewBase( parent ) { TaskEditorItemModel *m = new TaskEditorItemModel( this ); setModel( m ); //setSelectionBehavior( QAbstractItemView::SelectItems ); setSelectionMode( QAbstractItemView::ExtendedSelection ); setSelectionBehavior( QAbstractItemView::SelectRows ); createItemDelegates( m ); setItemDelegateForColumn( NodeModel::NodeType, new EnumDelegate( this ) ); connect( this, SIGNAL(dropAllowed(QModelIndex,int,QDragMoveEvent*)), SLOT(slotDropAllowed(QModelIndex,int,QDragMoveEvent*)) ); } NodeItemModel *TaskEditorTreeView::baseModel() const { NodeSortFilterProxyModel *pr = proxyModel(); if ( pr ) { return static_cast( pr->sourceModel() ); } return static_cast( model() ); } void TaskEditorTreeView::slotDropAllowed( const QModelIndex &index, int dropIndicatorPosition, QDragMoveEvent *event ) { QModelIndex idx = index; NodeSortFilterProxyModel *pr = proxyModel(); if ( pr ) { idx = pr->mapToSource( index ); } event->ignore(); if ( baseModel()->dropAllowed( idx, dropIndicatorPosition, event->mimeData() ) ) { event->accept(); } } //-------------------- NodeTreeView::NodeTreeView( QWidget *parent ) : DoubleTreeViewBase( parent ) { NodeItemModel *m = new NodeItemModel( this ); setModel( m ); //setSelectionBehavior( QAbstractItemView::SelectItems ); setSelectionMode( QAbstractItemView::ExtendedSelection ); setSelectionBehavior( QAbstractItemView::SelectRows ); createItemDelegates( m ); connect( this, SIGNAL(dropAllowed(QModelIndex,int,QDragMoveEvent*)), SLOT(slotDropAllowed(QModelIndex,int,QDragMoveEvent*)) ); } NodeItemModel *NodeTreeView::baseModel() const { NodeSortFilterProxyModel *pr = proxyModel(); if ( pr ) { return static_cast( pr->sourceModel() ); } return static_cast( model() ); } void NodeTreeView::slotDropAllowed( const QModelIndex &index, int dropIndicatorPosition, QDragMoveEvent *event ) { QModelIndex idx = index; NodeSortFilterProxyModel *pr = proxyModel(); if ( pr ) { idx = pr->mapToSource( index ); } event->ignore(); if ( baseModel()->dropAllowed( idx, dropIndicatorPosition, event->mimeData() ) ) { event->accept(); } } //----------------------------------- TaskEditor::TaskEditor(KoPart *part, KoDocument *doc, QWidget *parent) : ViewBase(part, doc, parent ) { debugPlan<<"----------------- Create TaskEditor ----------------------"; QVBoxLayout * l = new QVBoxLayout( this ); l->setMargin( 0 ); m_view = new TaskEditorTreeView( this ); connect(this, SIGNAL(expandAll()), m_view, SLOT(slotExpand())); connect(this, SIGNAL(collapseAll()), m_view, SLOT(slotCollapse())); l->addWidget( m_view ); debugPlan<actionSplitView(); setupGui(); m_view->setEditTriggers( m_view->editTriggers() | QAbstractItemView::EditKeyPressed ); m_view->setDragDropMode( QAbstractItemView::DragDrop ); m_view->setDropIndicatorShown( true ); m_view->setDragEnabled ( true ); m_view->setAcceptDrops( true ); m_view->setAcceptDropsOnView( true ); QList lst1; lst1 << 1 << -1; // only display column 0 (NodeName) in left view QList show; show << NodeModel::NodeResponsible << NodeModel::NodeAllocation << NodeModel::NodeType << NodeModel::NodeEstimateCalendar << NodeModel::NodeEstimate << NodeModel::NodeOptimisticRatio << NodeModel::NodePessimisticRatio << NodeModel::NodeRisk << NodeModel::NodeConstraint << NodeModel::NodeConstraintStart << NodeModel::NodeConstraintEnd << NodeModel::NodeRunningAccount << NodeModel::NodeStartupAccount << NodeModel::NodeStartupCost << NodeModel::NodeShutdownAccount << NodeModel::NodeShutdownCost << NodeModel::NodeDescription; QList lst2; for ( int i = 0; i < model()->columnCount(); ++i ) { if ( ! show.contains( i ) ) { lst2 << i; } } for ( int i = 0; i < show.count(); ++i ) { int sec = m_view->slaveView()->header()->visualIndex( show[ i ] ); //debugPlan<<"move section:"<slaveView()->header()->moveSection( sec, i ); } } m_view->hideColumns( lst1, lst2 ); m_view->masterView()->setDefaultColumns( QList() << NodeModel::NodeName ); m_view->slaveView()->setDefaultColumns( show ); connect( model(), SIGNAL(executeCommand(KUndo2Command*)), doc, SLOT(addCommand(KUndo2Command*)) ); connect( m_view, SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(slotCurrentChanged(QModelIndex,QModelIndex)) ); connect( m_view, SIGNAL(selectionChanged(QModelIndexList)), this, SLOT(slotSelectionChanged(QModelIndexList)) ); connect( m_view, SIGNAL(contextMenuRequested(QModelIndex,QPoint,QModelIndexList)), SLOT(slotContextMenuRequested(QModelIndex,QPoint,QModelIndexList)) ); connect( m_view, SIGNAL(headerContextMenuRequested(QPoint)), SLOT(slotHeaderContextMenuRequested(QPoint)) ); connect(baseModel(), SIGNAL(projectShownChanged(bool)), SLOT(slotProjectShown(bool))); connect(model(), SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), this, SLOT(slotEnableActions())); Help::add(this, xi18nc("@info:whatsthis", "Task Editor" "" "The Task Editor is used to create, edit, and delete tasks. " "Tasks are organized into a Work Breakdown Structure (WBS) to any depth." "" "This view supports configuration and printing using the context menu." "More..." "", Help::page("Manual/Task_Editor"))); } void TaskEditor::slotProjectShown( bool on ) { debugPlan<rowCount() > 0 ) { idx = proxyModel()->index( 0, 0 ); m_view->selectionModel()->setCurrentIndex( idx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows ); } } else if ( baseModel() && baseModel()->rowCount() > 0 ) { idx = baseModel()->index( 0, 0 ); m_view->selectionModel()->setCurrentIndex( idx, QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows ); } if ( on && idx.isValid() ) { m_view->masterView()->expand( idx ); } slotEnableActions(); } void TaskEditor::updateReadWrite( bool rw ) { m_view->setReadWrite( rw ); ViewBase::updateReadWrite( rw ); } void TaskEditor::setProject( Project *project ) { debugPlan<setProject( project ); ViewBase::setProject( project ); } void TaskEditor::createDockers() { // Add dockers DockWidget *ds = 0; { ds = new DockWidget( this, "Allocations", xi18nc( "@title resource allocations", "Allocations" ) ); QTreeView *x = new QTreeView( ds ); AllocatedResourceItemModel *m1 = new AllocatedResourceItemModel( x ); x->setModel( m1 ); m1->setProject( project() ); // x->setHeaderHidden( true ); x->setSelectionBehavior( QAbstractItemView::SelectRows ); x->setSelectionMode( QAbstractItemView::ExtendedSelection ); x->expandAll(); x->resizeColumnToContents( 0 ); x->setDragDropMode( QAbstractItemView::DragOnly ); x->setDragEnabled ( true ); ds->setWidget( x ); - connect(this, SIGNAL(projectChanged(Project*)), m1, SLOT(setProject(Project*))); - connect(this, SIGNAL(taskSelected(Task*)), m1, SLOT(setTask(Task*))); + connect(this, SIGNAL(projectChanged(KPlato::Project*)), m1, SLOT(setProject(KPlato::Project*))); + connect(this, SIGNAL(taskSelected(KPlato::Task*)), m1, SLOT(setTask(KPlato::Task*))); connect(m1, SIGNAL(expandAll()), x, SLOT(expandAll())); connect(m1, SIGNAL(resizeColumnToContents(int)), x, SLOT(resizeColumnToContents(int))); addDocker( ds ); } { ds = new DockWidget( this, "Resources", xi18nc( "@title", "Resources" ) ); ds->setToolTip( xi18nc( "@info:tooltip", "Drag resources into the Task Editor" " and drop into the allocations- or responsible column" ) ); ResourceAllocationView *e = new ResourceAllocationView(part(), ds ); ResourceItemModel *m = new ResourceItemModel( e ); e->setModel( m ); m->setProject( project() ); m->setReadWrite( isReadWrite() ); QList show; show << ResourceModel::ResourceName; for ( int i = m->columnCount() - 1; i >= 0; --i ) { e->setColumnHidden( i, ! show.contains( i ) ); } e->setHeaderHidden( true ); e->setSelectionBehavior( QAbstractItemView::SelectRows ); e->setSelectionMode( QAbstractItemView::ExtendedSelection ); e->expandAll(); e->resizeColumnToContents( ResourceModel::ResourceName ); e->setDragDropMode( QAbstractItemView::DragOnly ); e->setDragEnabled ( true ); ds->setWidget( e ); connect(m_view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)), e, SLOT(setSelectedTasks(const QItemSelection&, const QItemSelection&))); - connect(this, SIGNAL(projectChanged(Project*)), m, SLOT(setProject(Project*))); + connect(this, SIGNAL(projectChanged(KPlato::Project*)), m, SLOT(setProject(KPlato::Project*))); connect(this, SIGNAL(readWriteChanged(bool)), m, SLOT(setReadWrite(bool))); connect(m, SIGNAL(executeCommand(KUndo2Command*)), part(), SLOT(addCommand(KUndo2Command*))); addDocker( ds ); } { ds = new DockWidget( this, "Taskmodules", xi18nc( "@title", "Task Modules" ) ); ds->setToolTip( xi18nc( "@info:tooltip", "Drag a task module into the Task Editor to add it to the project" ) ); ds->setLocation( Qt::LeftDockWidgetArea ); ds->setShown(false); // hide by default QTreeView *e = new QTreeView( ds ); QSortFilterProxyModel *sf = new QSortFilterProxyModel(e); TaskModuleModel *m = new TaskModuleModel(sf); sf->setSourceModel(m); e->setModel(sf); e->sortByColumn(0, Qt::AscendingOrder); e->setSortingEnabled(true); e->setHeaderHidden( true ); e->setRootIsDecorated( false ); e->setSelectionBehavior( QAbstractItemView::SelectRows ); e->setSelectionMode( QAbstractItemView::SingleSelection ); // e->resizeColumnToContents( 0 ); e->setDragDropMode( QAbstractItemView::DragDrop ); e->setAcceptDrops( true ); e->setDragEnabled ( true ); ds->setWidget( e ); connect(e, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(taskModuleDoubleClicked(QModelIndex))); connect(this, SIGNAL(loadTaskModules(QStringList)), m, SLOT(loadTaskModules(QStringList))); connect(m, SIGNAL(saveTaskModule(QUrl,Project*)), this, SIGNAL(saveTaskModule(QUrl,Project*))); connect(m, SIGNAL(removeTaskModule(QUrl)), this, SIGNAL(removeTaskModule(QUrl))); addDocker( ds ); } } void TaskEditor::taskModuleDoubleClicked(QModelIndex idx) { QUrl url = idx.data(Qt::UserRole).toUrl(); if (url.isValid()) { emit openDocument(url); } } void TaskEditor::setTaskModules(const QStringList& files) { emit loadTaskModules( files ); } void TaskEditor::setGuiActive( bool activate ) { debugPlan<selectionModel()->currentIndex().isValid() && m_view->model()->rowCount() > 0 ) { m_view->selectionModel()->setCurrentIndex(m_view->model()->index( 0, 0 ), QItemSelectionModel::NoUpdate); } } void TaskEditor::slotCurrentChanged( const QModelIndex &curr, const QModelIndex & ) { debugPlan<( selectedNode() ) ); } QModelIndexList TaskEditor::selectedRows() const { #if 0 // Qt bug? return m_view->selectionModel()->selectedRows(); #else QModelIndexList lst; foreach ( QModelIndex i, m_view->selectionModel()->selectedIndexes() ) { if ( i.column() == 0 ) { lst << i; } } return lst; #endif } int TaskEditor::selectedRowCount() const { return selectedRows().count(); } QList TaskEditor::selectedNodes() const { QList lst; foreach ( const QModelIndex &i, selectedRows() ) { Node * n = m_view->baseModel()->node( i ); if ( n != 0 && n->type() != Node::Type_Project ) { lst.append( n ); } } return lst; } Node *TaskEditor::selectedNode() const { QList lst = selectedNodes(); if ( lst.count() != 1 ) { return 0; } return lst.first(); } Node *TaskEditor::currentNode() const { Node * n = m_view->baseModel()->node( m_view->selectionModel()->currentIndex() ); if ( n == 0 || n->type() == Node::Type_Project ) { return 0; } return n; } void TaskEditor::slotContextMenuRequested( const QModelIndex& index, const QPoint& pos, const QModelIndexList &rows ) { QString name; if (rows.count() > 1) { debugPlan< summarytasks; QList tasks; QList milestones; for (const QModelIndex &idx : rows) { Node *node = m_view->baseModel()->node( idx ); if (node) { switch ( node->type() ) { case Node::Type_Task: tasks << static_cast(node); break; case Node::Type_Milestone: milestones << static_cast(node); break; case Node::Type_Summarytask: summarytasks << static_cast(node); break; default: break; } } } if (!tasks.isEmpty()) { editTasks(tasks, pos); return; } return; } Node *node = m_view->baseModel()->node( index ); if ( node == 0 ) { return; } debugPlan<name()<<" :"<type() ) { case Node::Type_Project: name = "task_edit_popup"; break; case Node::Type_Task: name = node->isScheduled( baseModel()->id() ) ? "task_popup" : "task_edit_popup"; break; case Node::Type_Milestone: name = node->isScheduled( baseModel()->id() ) ? "taskeditor_milestone_popup" : "task_edit_popup"; break; case Node::Type_Summarytask: name = "summarytask_popup"; break; default: name = "node_popup"; break; } m_view->setContextMenuIndex(index); if ( name.isEmpty() ) { slotHeaderContextMenuRequested( pos ); m_view->setContextMenuIndex(QModelIndex()); return; } debugPlan<setContextMenuIndex(QModelIndex()); } void TaskEditor::editTasks(const QList &tasks, const QPoint &pos) { QList lst; QAction tasksEdit(i18n( "Edit..."), nullptr); if (!tasks.isEmpty()) { TasksEditController *ted = new TasksEditController(*project(), tasks, this); connect(&tasksEdit, SIGNAL(triggered(bool)), ted, SLOT(activate())); connect(ted, SIGNAL(addCommand(KUndo2Command*)), koDocument(), SLOT(addCommand(KUndo2Command*))); lst << &tasksEdit; } lst += contextActionList(); if (!lst.isEmpty()) { QMenu::exec( lst, pos, lst.first() ); } } void TaskEditor::setScheduleManager( ScheduleManager *sm ) { if (!sm && scheduleManager()) { // we should only get here if the only schedule manager is scheduled, // or when last schedule manager is deleted m_domdoc.clear(); QDomElement element = m_domdoc.createElement("expanded"); m_domdoc.appendChild(element); m_view->masterView()->saveExpanded(element); } bool tryexpand = sm && !scheduleManager(); QDomDocument doc; bool expand = sm && scheduleManager(); if (expand) { m_view->masterView()->setObjectName("TaskEditor"); QDomElement element = doc.createElement("expanded"); doc.appendChild(element); m_view->masterView()->saveExpanded(element); } ViewBase::setScheduleManager(sm); m_view->baseModel()->setScheduleManager( sm ); if (expand) { m_view->masterView()->doExpand(doc); } else if (tryexpand) { m_view->masterView()->doExpand(m_domdoc); } } void TaskEditor::slotEnableActions() { updateActionsEnabled( isReadWrite() ); } void TaskEditor::updateActionsEnabled( bool on ) { // debugPlan<setEnabled( false ); actionAddTask->setEnabled( false ); actionAddMilestone->setEnabled( false ); menuAddSubTask->setEnabled( false ); actionAddSubtask->setEnabled( false ); actionAddSubMilestone->setEnabled( false ); actionDeleteTask->setEnabled( false ); actionMoveTaskUp->setEnabled( false ); actionMoveTaskDown->setEnabled( false ); actionIndentTask->setEnabled( false ); actionUnindentTask->setEnabled( false ); return; } int selCount = selectedRowCount(); if ( selCount == 0 ) { if ( currentNode() ) { // there are tasks but none is selected menuAddTask->setEnabled( false ); actionAddTask->setEnabled( false ); actionAddMilestone->setEnabled( false ); menuAddSubTask->setEnabled( false ); actionAddSubtask->setEnabled( false ); actionAddSubMilestone->setEnabled( false ); actionDeleteTask->setEnabled( false ); actionMoveTaskUp->setEnabled( false ); actionMoveTaskDown->setEnabled( false ); actionIndentTask->setEnabled( false ); actionUnindentTask->setEnabled( false ); } else { // we need to be able to add the first task menuAddTask->setEnabled( true ); actionAddTask->setEnabled( true ); actionAddMilestone->setEnabled( true ); menuAddSubTask->setEnabled( false ); actionAddSubtask->setEnabled( false ); actionAddSubMilestone->setEnabled( false ); actionDeleteTask->setEnabled( false ); actionMoveTaskUp->setEnabled( false ); actionMoveTaskDown->setEnabled( false ); actionIndentTask->setEnabled( false ); actionUnindentTask->setEnabled( false ); } return; } Node *n = selectedNode(); // 0 if not a single task, summarytask or milestone if ( selCount == 1 && n == 0 ) { // only project selected menuAddTask->setEnabled( true ); actionAddTask->setEnabled( true ); actionAddMilestone->setEnabled( true ); menuAddSubTask->setEnabled( true ); actionAddSubtask->setEnabled( true ); actionAddSubMilestone->setEnabled( true ); actionDeleteTask->setEnabled( false ); actionMoveTaskUp->setEnabled( false ); actionMoveTaskDown->setEnabled( false ); actionIndentTask->setEnabled( false ); actionUnindentTask->setEnabled( false ); return; } if ( selCount == 1 && n != currentNode() ) { // multi selection in progress menuAddTask->setEnabled( false ); actionAddTask->setEnabled( false ); actionAddMilestone->setEnabled( false ); menuAddSubTask->setEnabled( false ); actionAddSubtask->setEnabled( false ); actionAddSubMilestone->setEnabled( false ); actionDeleteTask->setEnabled( false ); actionMoveTaskUp->setEnabled( false ); actionMoveTaskDown->setEnabled( false ); actionIndentTask->setEnabled( false ); actionUnindentTask->setEnabled( false ); return; } bool baselined = false; Project *p = m_view->project(); if ( p && p->isBaselined() ) { foreach ( Node *n, selectedNodes() ) { if ( n->isBaselined() ) { baselined = true; break; } } } if ( selCount == 1 ) { menuAddTask->setEnabled( true ); actionAddTask->setEnabled( true ); actionAddMilestone->setEnabled( true ); menuAddSubTask->setEnabled( ! baselined || n->type() == Node::Type_Summarytask ); actionAddSubtask->setEnabled( ! baselined || n->type() == Node::Type_Summarytask ); actionAddSubMilestone->setEnabled( ! baselined || n->type() == Node::Type_Summarytask ); actionDeleteTask->setEnabled( ! baselined ); Node *s = n->siblingBefore(); actionMoveTaskUp->setEnabled( s ); actionMoveTaskDown->setEnabled( n->siblingAfter() ); s = n->siblingBefore(); actionIndentTask->setEnabled( ! baselined && s && ! s->isBaselined() ); actionUnindentTask->setEnabled( ! baselined && n->level() > 1 ); return; } // selCount > 1 menuAddTask->setEnabled( false ); actionAddTask->setEnabled( false ); actionAddMilestone->setEnabled( false ); menuAddSubTask->setEnabled( false ); actionAddSubtask->setEnabled( false ); actionAddSubMilestone->setEnabled( false ); actionDeleteTask->setEnabled( ! baselined ); actionMoveTaskUp->setEnabled( false ); actionMoveTaskDown->setEnabled( false ); actionIndentTask->setEnabled( false ); actionUnindentTask->setEnabled( false ); } void TaskEditor::setupGui() { QString name = "taskeditor_add_list"; menuAddTask = new KActionMenu(koIcon("view-task-add"), i18n("Add Task"), this); actionCollection()->addAction("add_task", menuAddTask ); connect( menuAddTask, SIGNAL(triggered(bool)), SLOT(slotAddTask()) ); addAction( name, menuAddTask ); actionAddTask = new QAction( i18n( "Add Task" ), this); actionAddTask->setShortcut( Qt::CTRL + Qt::Key_I ); connect( actionAddTask, SIGNAL(triggered(bool)), SLOT(slotAddTask()) ); menuAddTask->addAction( actionAddTask ); actionAddMilestone = new QAction( i18n( "Add Milestone" ), this ); actionAddMilestone->setShortcut( Qt::CTRL + Qt::ALT + Qt::Key_I ); connect( actionAddMilestone, SIGNAL(triggered(bool)), SLOT(slotAddMilestone()) ); menuAddTask->addAction( actionAddMilestone ); menuAddSubTask = new KActionMenu(koIcon("view-task-child-add"), i18n("Add Sub-Task"), this); actionCollection()->addAction("add_subtask", menuAddTask ); connect( menuAddSubTask, SIGNAL(triggered(bool)), SLOT(slotAddSubtask()) ); addAction( name, menuAddSubTask ); actionAddSubtask = new QAction( i18n( "Add Sub-Task" ), this ); actionAddSubtask->setShortcut( Qt::CTRL + Qt::SHIFT + Qt::Key_I ); connect( actionAddSubtask, SIGNAL(triggered(bool)), SLOT(slotAddSubtask()) ); menuAddSubTask->addAction( actionAddSubtask ); actionAddSubMilestone = new QAction( i18n( "Add Sub-Milestone" ), this ); actionAddSubMilestone->setShortcut( Qt::CTRL + Qt::SHIFT + Qt::ALT + Qt::Key_I ); connect( actionAddSubMilestone, SIGNAL(triggered(bool)), SLOT(slotAddSubMilestone()) ); menuAddSubTask->addAction( actionAddSubMilestone ); actionDeleteTask = new QAction(koIcon("edit-delete"), xi18nc("@action", "Delete"), this); actionCollection()->setDefaultShortcut( actionDeleteTask, Qt::Key_Delete ); actionCollection()->addAction("delete_task", actionDeleteTask ); connect( actionDeleteTask, SIGNAL(triggered(bool)), SLOT(slotDeleteTask()) ); addAction( name, actionDeleteTask ); name = "taskeditor_move_list"; actionIndentTask = new QAction(koIcon("format-indent-more"), i18n("Indent Task"), this); actionCollection()->addAction("indent_task", actionIndentTask ); connect(actionIndentTask, SIGNAL(triggered(bool)), SLOT(slotIndentTask())); addAction( name, actionIndentTask ); actionUnindentTask = new QAction(koIcon("format-indent-less"), i18n("Unindent Task"), this); actionCollection()->addAction("unindent_task", actionUnindentTask ); connect(actionUnindentTask, SIGNAL(triggered(bool)), SLOT(slotUnindentTask())); addAction( name, actionUnindentTask ); actionMoveTaskUp = new QAction(koIcon("arrow-up"), i18n("Move Up"), this); actionCollection()->addAction("move_task_up", actionMoveTaskUp ); connect(actionMoveTaskUp, SIGNAL(triggered(bool)), SLOT(slotMoveTaskUp())); addAction( name, actionMoveTaskUp ); actionMoveTaskDown = new QAction(koIcon("arrow-down"), i18n("Move Down"), this); actionCollection()->addAction("move_task_down", actionMoveTaskDown ); connect(actionMoveTaskDown, SIGNAL(triggered(bool)), SLOT(slotMoveTaskDown())); addAction( name, actionMoveTaskDown ); // Add the context menu actions for the view options actionShowProject = new KToggleAction( i18n( "Show Project" ), this ); connect(actionShowProject, SIGNAL(triggered(bool)), baseModel(), SLOT(setShowProject(bool))); addContextAction( actionShowProject ); connect(m_view->actionSplitView(), SIGNAL(triggered(bool)), SLOT(slotSplitView())); addContextAction( m_view->actionSplitView() ); createOptionActions(ViewBase::OptionAll); createDockers(); } void TaskEditor::slotSplitView() { debugPlan; m_view->setViewSplitMode( ! m_view->isViewSplit() ); emit optionsModified(); } void TaskEditor::slotOptions() { debugPlan; SplitItemViewSettupDialog *dlg = new SplitItemViewSettupDialog( this, m_view, this ); dlg->addPrintingOptions(sender()->objectName() == "print options"); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } void TaskEditor::slotAddTask() { debugPlan; if ( selectedRowCount() == 0 || ( selectedRowCount() == 1 && selectedNode() == 0 ) ) { m_view->closePersistentEditor( m_view->selectionModel()->currentIndex() ); Task *t = m_view->project()->createTask( m_view->project()->taskDefaults() ); QModelIndex idx = m_view->baseModel()->insertSubtask( t, m_view->project() ); Q_ASSERT( idx.isValid() ); edit( idx ); return; } Node *sib = selectedNode(); if ( sib == 0 ) { return; } m_view->closePersistentEditor( m_view->selectionModel()->currentIndex() ); Task *t = m_view->project()->createTask( m_view->project()->taskDefaults() ); QModelIndex idx = m_view->baseModel()->insertTask( t, sib ); Q_ASSERT( idx.isValid() ); edit( idx ); } void TaskEditor::slotAddMilestone() { debugPlan; if ( selectedRowCount() == 0 || ( selectedRowCount() == 1 && selectedNode() == 0 ) ) { // None selected or only project selected: insert under main project m_view->closePersistentEditor( m_view->selectionModel()->currentIndex() ); Task *t = m_view->project()->createTask(); t->estimate()->clear(); QModelIndex idx = m_view->baseModel()->insertSubtask( t, m_view->project() ); Q_ASSERT( idx.isValid() ); edit( idx ); return; } Node *sib = selectedNode(); // sibling if ( sib == 0 ) { return; } m_view->closePersistentEditor( m_view->selectionModel()->currentIndex() ); Task *t = m_view->project()->createTask(); t->estimate()->clear(); QModelIndex idx = m_view->baseModel()->insertTask( t, sib ); Q_ASSERT( idx.isValid() ); edit( idx ); } void TaskEditor::slotAddSubMilestone() { debugPlan; Node *parent = selectedNode(); if ( parent == 0 && selectedRowCount() == 1 ) { // project selected parent = m_view->project(); } if ( parent == 0 ) { return; } m_view->closePersistentEditor( m_view->selectionModel()->currentIndex() ); Task *t = m_view->project()->createTask( m_view->project()->taskDefaults() ); t->estimate()->clear(); QModelIndex idx = m_view->baseModel()->insertSubtask( t, parent ); Q_ASSERT( idx.isValid() ); edit( idx ); } void TaskEditor::slotAddSubtask() { debugPlan; Node *parent = selectedNode(); if ( parent == 0 && selectedRowCount() == 1 ) { // project selected parent = m_view->project(); } if ( parent == 0 ) { return; } m_view->closePersistentEditor( m_view->selectionModel()->currentIndex() ); Task *t = m_view->project()->createTask( m_view->project()->taskDefaults() ); QModelIndex idx = m_view->baseModel()->insertSubtask( t, parent ); Q_ASSERT( idx.isValid() ); edit( idx ); } void TaskEditor::edit( const QModelIndex &i ) { if ( i.isValid() ) { m_view->selectionModel()->setCurrentIndex( i, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect ); m_view->setParentsExpanded( i, true ); // in case treeview does not have focus m_view->edit( i ); } } void TaskEditor::slotDeleteTask() { //debugPlan; QList lst = selectedNodes(); while ( true ) { // remove children of selected tasks, as parents delete their children Node *ch = 0; foreach ( Node *n1, lst ) { foreach ( Node *n2, lst ) { if ( n2->isChildOf( n1 ) ) { ch = n2; break; } } if ( ch != 0 ) { break; } } if ( ch == 0 ) { break; } lst.removeAt( lst.indexOf( ch ) ); } //foreach ( Node* n, lst ) { debugPlan<name(); } emit deleteTaskList( lst ); QModelIndex i = m_view->selectionModel()->currentIndex(); if ( i.isValid() ) { m_view->selectionModel()->select( i, QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect ); m_view->selectionModel()->setCurrentIndex( i, QItemSelectionModel::NoUpdate ); } } void TaskEditor::slotIndentTask() { debugPlan; Node *n = selectedNode(); if ( n ) { emit indentTask(); QModelIndex i = baseModel()->index( n ); m_view->selectionModel()->select( i, QItemSelectionModel::Rows | QItemSelectionModel::Current | QItemSelectionModel::ClearAndSelect ); m_view->selectionModel()->setCurrentIndex( i, QItemSelectionModel::NoUpdate ); m_view->setParentsExpanded( i, true ); } } void TaskEditor::slotUnindentTask() { debugPlan; Node *n = selectedNode(); if ( n ) { emit unindentTask(); QModelIndex i = baseModel()->index( n ); m_view->selectionModel()->select( i, QItemSelectionModel::Rows | QItemSelectionModel::Current | QItemSelectionModel::ClearAndSelect ); m_view->selectionModel()->setCurrentIndex( i, QItemSelectionModel::NoUpdate ); } } void TaskEditor::slotMoveTaskUp() { debugPlan; Node *n = selectedNode(); if ( n ) { emit moveTaskUp(); QModelIndex i = baseModel()->index( n ); m_view->selectionModel()->select( i, QItemSelectionModel::Rows | QItemSelectionModel::Current | QItemSelectionModel::ClearAndSelect ); m_view->selectionModel()->setCurrentIndex( i, QItemSelectionModel::NoUpdate ); } } void TaskEditor::slotMoveTaskDown() { debugPlan; Node *n = selectedNode(); if ( n ) { emit moveTaskDown(); QModelIndex i = baseModel()->index( n ); m_view->selectionModel()->select( i, QItemSelectionModel::Rows | QItemSelectionModel::Current | QItemSelectionModel::ClearAndSelect ); m_view->selectionModel()->setCurrentIndex( i, QItemSelectionModel::NoUpdate ); } } bool TaskEditor::loadContext( const KoXmlElement &context ) { ViewBase::loadContext( context ); bool show = (bool)(context.attribute( "show-project", "0" ).toInt() ); actionShowProject->setChecked( show ); baseModel()->setShowProject( show ); // why is this not called by the action? bool res = m_view->loadContext( baseModel()->columnMap(), context ); return res; } void TaskEditor::saveContext( QDomElement &context ) const { ViewBase::saveContext( context ); context.setAttribute( "show-project", QString::number(baseModel()->projectShown()) ); m_view->saveContext( baseModel()->columnMap(), context ); } KoPrintJob *TaskEditor::createPrintJob() { return m_view->createPrintJob( this ); } //----------------------------------- TaskView::TaskView(KoPart *part, KoDocument *doc, QWidget *parent) : ViewBase(part, doc, parent) { QVBoxLayout * l = new QVBoxLayout( this ); l->setMargin( 0 ); m_view = new NodeTreeView( this ); connect(this, SIGNAL(expandAll()), m_view, SLOT(slotExpand())); connect(this, SIGNAL(collapseAll()), m_view, SLOT(slotCollapse())); NodeSortFilterProxyModel *p = new NodeSortFilterProxyModel( m_view->baseModel(), m_view ); m_view->setModel( p ); l->addWidget( m_view ); setupGui(); //m_view->setEditTriggers( m_view->editTriggers() | QAbstractItemView::EditKeyPressed ); m_view->setDragDropMode( QAbstractItemView::InternalMove ); m_view->setDropIndicatorShown( false ); m_view->setDragEnabled ( true ); m_view->setAcceptDrops( false ); m_view->setAcceptDropsOnView( false ); QList readonly; readonly << NodeModel::NodeName << NodeModel::NodeResponsible << NodeModel::NodeAllocation << NodeModel::NodeEstimateType << NodeModel::NodeEstimateCalendar << NodeModel::NodeEstimate << NodeModel::NodeOptimisticRatio << NodeModel::NodePessimisticRatio << NodeModel::NodeRisk << NodeModel::NodeConstraint << NodeModel::NodeConstraintStart << NodeModel::NodeConstraintEnd << NodeModel::NodeRunningAccount << NodeModel::NodeStartupAccount << NodeModel::NodeStartupCost << NodeModel::NodeShutdownAccount << NodeModel::NodeShutdownCost << NodeModel::NodeDescription; foreach ( int c, readonly ) { m_view->baseModel()->setReadOnly( c, true ); } QList lst1; lst1 << 1 << -1; QList show; show << NodeModel::NodeStatus << NodeModel::NodeCompleted << NodeModel::NodeResponsible << NodeModel::NodeAssignments << NodeModel::NodePerformanceIndex << NodeModel::NodeBCWS << NodeModel::NodeBCWP << NodeModel::NodeACWP << NodeModel::NodeDescription; for ( int s = 0; s < show.count(); ++s ) { m_view->slaveView()->mapToSection( show[s], s ); } QList lst2; for ( int i = 0; i < m_view->model()->columnCount(); ++i ) { if ( ! show.contains( i ) ) { lst2 << i; } } m_view->hideColumns( lst1, lst2 ); m_view->masterView()->setDefaultColumns( QList() << 0 ); m_view->slaveView()->setDefaultColumns( show ); connect( m_view->baseModel(), SIGNAL(executeCommand(KUndo2Command*)), doc, SLOT(addCommand(KUndo2Command*)) ); connect( m_view, SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(slotCurrentChanged(QModelIndex,QModelIndex)) ); connect( m_view, SIGNAL(selectionChanged(QModelIndexList)), this, SLOT(slotSelectionChanged(QModelIndexList)) ); connect( m_view, SIGNAL(contextMenuRequested(QModelIndex,QPoint,QModelIndexList)), SLOT(slotContextMenuRequested(QModelIndex,QPoint)) ); connect( m_view, SIGNAL(headerContextMenuRequested(QPoint)), SLOT(slotHeaderContextMenuRequested(QPoint)) ); Help::add(this, xi18nc("@info:whatsthis", "Task Execution View" "" "The view is used to edit and inspect task progress during project execution." "" "This view supports configuration and printing using the context menu." "More..." "", Help::page("Manual/Task_Execution_View"))); } void TaskView::updateReadWrite( bool rw ) { m_view->setReadWrite( rw ); ViewBase::updateReadWrite( rw ); } void TaskView::draw( Project &project ) { m_view->setProject( &project ); } void TaskView::draw() { } void TaskView::setGuiActive( bool activate ) { debugPlan<selectionModel()->currentIndex().isValid() && m_view->model()->rowCount() > 0 ) { m_view->selectionModel()->setCurrentIndex(m_view->model()->index( 0, 0 ), QItemSelectionModel::NoUpdate); } } void TaskView::slotCurrentChanged( const QModelIndex &curr, const QModelIndex & ) { debugPlan<selectionModel(); return sm->selectedRows().count(); } QList TaskView::selectedNodes() const { QList lst; QItemSelectionModel* sm = m_view->selectionModel(); if ( sm == 0 ) { return lst; } foreach ( const QModelIndex &i, sm->selectedRows() ) { Node * n = m_view->baseModel()->node( proxyModel()->mapToSource( i ) ); if ( n != 0 && n->type() != Node::Type_Project ) { lst.append( n ); } } return lst; } Node *TaskView::selectedNode() const { QList lst = selectedNodes(); if ( lst.count() != 1 ) { return 0; } return lst.first(); } Node *TaskView::currentNode() const { Node * n = m_view->baseModel()->node( proxyModel()->mapToSource( m_view->selectionModel()->currentIndex() ) ); if ( n == 0 || n->type() == Node::Type_Project ) { return 0; } return n; } void TaskView::slotContextMenuRequested( const QModelIndex& index, const QPoint& pos ) { QString name; Node *node = m_view->baseModel()->node( proxyModel()->mapToSource( index ) ); if ( node ) { switch ( node->type() ) { case Node::Type_Task: name = "taskview_popup"; break; case Node::Type_Milestone: name = "taskview_milestone_popup"; break; case Node::Type_Summarytask: name = "taskview_summary_popup"; break; default: break; } } else debugPlan<<"No node: "<setContextMenuIndex(index); emit requestPopupMenu( name, pos ); m_view->setContextMenuIndex(QModelIndex()); } void TaskView::setScheduleManager( ScheduleManager *sm ) { //debugPlan<masterView()->saveExpanded(element); } bool tryexpand = sm && !scheduleManager(); QDomDocument doc; bool expand = sm && scheduleManager() && sm != scheduleManager(); if (expand) { m_view->masterView()->setObjectName("TaskEditor"); QDomElement element = doc.createElement("expanded"); doc.appendChild(element); m_view->masterView()->saveExpanded(element); } ViewBase::setScheduleManager(sm); m_view->baseModel()->setScheduleManager( sm ); if (expand) { m_view->masterView()->doExpand(doc); } else if (tryexpand) { m_view->masterView()->doExpand(m_domdoc); } } void TaskView::slotEnableActions() { updateActionsEnabled( true ); } void TaskView::updateActionsEnabled( bool /*on*/ ) { } void TaskView::setupGui() { // KActionCollection *coll = actionCollection(); // Add the context menu actions for the view options actionShowProject = new KToggleAction( i18n( "Show Project" ), this ); connect(actionShowProject, SIGNAL(triggered(bool)), baseModel(), SLOT(setShowProject(bool))); addContextAction( actionShowProject ); connect(m_view->actionSplitView(), SIGNAL(triggered(bool)), SLOT(slotSplitView())); addContextAction( m_view->actionSplitView() ); createOptionActions(ViewBase::OptionAll); } void TaskView::slotSplitView() { debugPlan; m_view->setViewSplitMode( ! m_view->isViewSplit() ); emit optionsModified(); } void TaskView::slotOptions() { debugPlan; SplitItemViewSettupDialog *dlg = new SplitItemViewSettupDialog( this, m_view, this ); dlg->addPrintingOptions(sender()->objectName() == "print options"); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } bool TaskView::loadContext( const KoXmlElement &context ) { ViewBase::loadContext( context ); bool show = (bool)(context.attribute( "show-project", "0" ).toInt() ); actionShowProject->setChecked( show ); baseModel()->setShowProject( show ); // why is this not called by the action? return m_view->loadContext( m_view->baseModel()->columnMap(), context ); } void TaskView::saveContext( QDomElement &context ) const { ViewBase::saveContext( context ); context.setAttribute( "show-project", QString::number(baseModel()->projectShown()) ); m_view->saveContext( m_view->baseModel()->columnMap(), context ); } KoPrintJob *TaskView::createPrintJob() { return m_view->createPrintJob( this ); } //--------------------------------- WorkPackageTreeView::WorkPackageTreeView( QWidget *parent ) : DoubleTreeViewBase( parent ) { debugPlan<<"----------"<baseModel(); } void WorkPackageTreeView::slotDropAllowed( const QModelIndex &index, int dropIndicatorPosition, QDragMoveEvent *event ) { Q_UNUSED(index); Q_UNUSED(dropIndicatorPosition); Q_UNUSED(event); /* QModelIndex idx = index; NodeSortFilterProxyModel *pr = proxyModel(); if ( pr ) { idx = pr->mapToSource( index ); } event->ignore(); if ( baseModel()->dropAllowed( idx, dropIndicatorPosition, event->mimeData() ) ) { event->accept(); }*/ } //-------------------------------- TaskWorkPackageView::TaskWorkPackageView(KoPart *part, KoDocument *doc, QWidget *parent) : ViewBase(part, doc, parent ), m_cmd( 0 ) { QVBoxLayout * l = new QVBoxLayout( this ); l->setMargin( 0 ); m_view = new WorkPackageTreeView( this ); connect(this, SIGNAL(expandAll()), m_view, SLOT(slotExpand())); connect(this, SIGNAL(collapseAll()), m_view, SLOT(slotCollapse())); l->addWidget( m_view ); setupGui(); //m_view->setEditTriggers( m_view->editTriggers() | QAbstractItemView::EditKeyPressed ); m_view->setDragDropMode( QAbstractItemView::InternalMove ); m_view->setDropIndicatorShown( false ); m_view->setDragEnabled ( true ); m_view->setAcceptDrops( false ); m_view->setAcceptDropsOnView( false ); QList readonly; readonly << NodeModel::NodeName << NodeModel::NodeResponsible << NodeModel::NodeAllocation << NodeModel::NodeEstimateType << NodeModel::NodeEstimateCalendar << NodeModel::NodeEstimate << NodeModel::NodeOptimisticRatio << NodeModel::NodePessimisticRatio << NodeModel::NodeRisk << NodeModel::NodeConstraint << NodeModel::NodeConstraintStart << NodeModel::NodeConstraintEnd << NodeModel::NodeRunningAccount << NodeModel::NodeStartupAccount << NodeModel::NodeStartupCost << NodeModel::NodeShutdownAccount << NodeModel::NodeShutdownCost << NodeModel::NodeDescription; foreach ( int c, readonly ) { m_view->baseModel()->setReadOnly( c, true ); } QList lst1; lst1 << 1 << -1; QList show; show << NodeModel::NodeStatus << NodeModel::NodeCompleted << NodeModel::NodeResponsible << NodeModel::NodeAssignments << NodeModel::NodeDescription; for ( int s = 0; s < show.count(); ++s ) { m_view->slaveView()->mapToSection( show[s], s ); } QList lst2; for ( int i = 0; i < m_view->model()->columnCount(); ++i ) { if ( ! show.contains( i ) ) { lst2 << i; } } m_view->hideColumns( lst1, lst2 ); m_view->masterView()->setDefaultColumns( QList() << 0 ); m_view->slaveView()->setDefaultColumns( show ); connect( m_view->baseModel(), SIGNAL(executeCommand(KUndo2Command*)), doc, SLOT(addCommand(KUndo2Command*)) ); connect( m_view, SIGNAL(currentChanged(QModelIndex,QModelIndex)), this, SLOT(slotCurrentChanged(QModelIndex,QModelIndex)) ); connect( m_view, SIGNAL(selectionChanged(QModelIndexList)), this, SLOT(slotSelectionChanged(QModelIndexList)) ); connect( m_view, SIGNAL(contextMenuRequested(QModelIndex,QPoint,QModelIndexList)), SLOT(slotContextMenuRequested(QModelIndex,QPoint)) ); connect( m_view, SIGNAL(headerContextMenuRequested(QPoint)), SLOT(slotHeaderContextMenuRequested(QPoint)) ); } Project *TaskWorkPackageView::project() const { return m_view->project(); } void TaskWorkPackageView::setProject( Project *project ) { m_view->setProject( project ); } WorkPackageProxyModel *TaskWorkPackageView::proxyModel() const { return m_view->proxyModel(); } void TaskWorkPackageView::updateReadWrite( bool rw ) { m_view->setReadWrite( rw ); ViewBase::updateReadWrite( rw ); } void TaskWorkPackageView::setGuiActive( bool activate ) { debugPlan<selectionModel()->currentIndex().isValid() && m_view->model()->rowCount() > 0 ) { m_view->selectionModel()->setCurrentIndex(m_view->model()->index( 0, 0 ), QItemSelectionModel::NoUpdate); } } void TaskWorkPackageView::slotRefreshView() { emit checkForWorkPackages(); } void TaskWorkPackageView::slotCurrentChanged( const QModelIndex &curr, const QModelIndex & ) { debugPlan<selectionModel(); return sm->selectedRows().count(); } QList TaskWorkPackageView::selectedNodes() const { QList lst; QItemSelectionModel* sm = m_view->selectionModel(); if ( sm == 0 ) { return lst; } foreach ( const QModelIndex &i, sm->selectedRows() ) { Node * n = proxyModel()->taskFromIndex( i ); if ( n != 0 && n->type() != Node::Type_Project ) { lst.append( n ); } } return lst; } Node *TaskWorkPackageView::selectedNode() const { QList lst = selectedNodes(); if ( lst.count() != 1 ) { return 0; } return lst.first(); } Node *TaskWorkPackageView::currentNode() const { Node * n = proxyModel()->taskFromIndex( m_view->selectionModel()->currentIndex() ); if ( n == 0 || n->type() == Node::Type_Project ) { return 0; } return n; } void TaskWorkPackageView::slotContextMenuRequested( const QModelIndex& index, const QPoint& pos ) { QString name; Node *node = proxyModel()->taskFromIndex( index ); if ( node ) { switch ( node->type() ) { case Node::Type_Task: name = "workpackage_popup"; break; case Node::Type_Milestone: name = "taskview_milestone_popup"; break; case Node::Type_Summarytask: name = "taskview_summary_popup"; break; default: break; } } else debugPlan<<"No node: "<setContextMenuIndex(index); emit requestPopupMenu( name, pos ); m_view->setContextMenuIndex(QModelIndex()); } void TaskWorkPackageView::setScheduleManager( ScheduleManager *sm ) { //debugPlan<baseModel()->setScheduleManager( sm ); } void TaskWorkPackageView::slotEnableActions() { updateActionsEnabled( true ); } void TaskWorkPackageView::updateActionsEnabled( bool on ) { bool o = ! selectedNodes().isEmpty(); actionMailWorkpackage->setEnabled( o && on ); } void TaskWorkPackageView::setupGui() { // KActionCollection *coll = actionCollection(); QString name = "workpackage_list"; actionMailWorkpackage = new QAction(koIcon("mail-send"), i18n("Send..."), this); actionCollection()->setDefaultShortcut( actionMailWorkpackage, Qt::CTRL + Qt::Key_M ); actionCollection()->addAction("send_workpackage", actionMailWorkpackage ); connect( actionMailWorkpackage, SIGNAL(triggered(bool)), SLOT(slotMailWorkpackage()) ); addAction( name, actionMailWorkpackage ); // Add the context menu actions for the view options connect(m_view->actionSplitView(), SIGNAL(triggered(bool)), SLOT(slotSplitView())); addContextAction( m_view->actionSplitView() ); createOptionActions(ViewBase::OptionAll); } void TaskWorkPackageView::slotMailWorkpackage() { QList lst = selectedNodes(); if ( ! lst.isEmpty() ) { // TODO find a better way to log to avoid undo/redo m_cmd = new MacroCommand( kundo2_i18n( "Log Send Workpackage" ) ); QPointer dlg = new WorkPackageSendDialog( lst, scheduleManager(), this ); connect ( dlg->panel(), SIGNAL(sendWorkpackages(QList,Resource*)), this, SIGNAL(mailWorkpackages(QList,Resource*)) ); connect ( dlg->panel(), SIGNAL(sendWorkpackages(QList,Resource*)), this, SLOT(slotWorkPackageSent(QList,Resource*)) ); dlg->exec(); delete dlg; if ( ! m_cmd->isEmpty() ) { part()->addCommand( m_cmd ); m_cmd = 0; } delete m_cmd; m_cmd = 0; } } void TaskWorkPackageView::slotWorkPackageSent( const QList &nodes, Resource *resource ) { foreach ( Node *n, nodes ) { WorkPackage *wp = new WorkPackage( static_cast( n )->workPackage() ); wp->setOwnerName( resource->name() ); wp->setOwnerId( resource->id() ); wp->setTransmitionTime( DateTime::currentDateTime() ); wp->setTransmitionStatus( WorkPackage::TS_Send ); m_cmd->addCommand( new WorkPackageAddCmd( static_cast( n->projectNode() ), n, wp ) ); } } void TaskWorkPackageView::slotSplitView() { debugPlan; m_view->setViewSplitMode( ! m_view->isViewSplit() ); emit optionsModified(); } void TaskWorkPackageView::slotOptions() { debugPlan; SplitItemViewSettupDialog *dlg = new SplitItemViewSettupDialog( this, m_view, this ); dlg->addPrintingOptions(sender()->objectName() == "print options"); connect(dlg, SIGNAL(finished(int)), SLOT(slotOptionsFinished(int))); dlg->show(); dlg->raise(); dlg->activateWindow(); } bool TaskWorkPackageView::loadContext( const KoXmlElement &context ) { debugPlan; ViewBase::loadContext( context ); return m_view->loadContext( m_view->baseModel()->columnMap(), context ); } void TaskWorkPackageView::saveContext( QDomElement &context ) const { ViewBase::saveContext( context ); m_view->saveContext( m_view->baseModel()->columnMap(), context ); } KoPrintJob *TaskWorkPackageView::createPrintJob() { return m_view->createPrintJob( this ); } } // namespace KPlato diff --git a/src/libs/ui/kpttaskeditor.h b/src/libs/ui/kpttaskeditor.h index 7990620a..763b99c4 100644 --- a/src/libs/ui/kpttaskeditor.h +++ b/src/libs/ui/kpttaskeditor.h @@ -1,356 +1,356 @@ /* This file is part of the KDE project Copyright (C) 2006 -20010 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 KPTTASKEDITOR_H #define KPTTASKEDITOR_H #include "planui_export.h" #include "kptglobal.h" #include "kptnodeitemmodel.h" #include "kptviewbase.h" class KoDocument; class KActionMenu; namespace KPlato { class Project; class Node; class NodeItemModel; class MacroCommand; class PLANUI_EXPORT TaskEditorItemModel : public NodeItemModel { Q_OBJECT public: explicit TaskEditorItemModel( QObject *parent = 0 ); virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const; virtual QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant &value, int role = Qt::EditRole ); protected: QVariant type( const Node *node, int role ) const; virtual bool setType( Node *node, const QVariant &value, int role ); }; class PLANUI_EXPORT TaskEditorTreeView : public DoubleTreeViewBase { Q_OBJECT public: explicit TaskEditorTreeView(QWidget *parent); //void setSelectionModel( QItemSelectionModel *selectionModel ); NodeItemModel *baseModel() const; NodeSortFilterProxyModel *proxyModel() const { return qobject_cast( model() ); } Project *project() const { return baseModel()->project(); } void setProject( Project *project ) { baseModel()->setProject( project ); } Q_SIGNALS: void currentColumnChanged( const QModelIndex&, const QModelIndex& ); protected Q_SLOTS: void slotDropAllowed( const QModelIndex &index, int dropIndicatorPosition, QDragMoveEvent *event ); }; class PLANUI_EXPORT NodeTreeView : public DoubleTreeViewBase { Q_OBJECT public: explicit NodeTreeView(QWidget *parent); //void setSelectionModel( QItemSelectionModel *selectionModel ); NodeItemModel *baseModel() const; NodeSortFilterProxyModel *proxyModel() const { return qobject_cast( model() ); } Project *project() const { return baseModel()->project(); } void setProject( Project *project ) { baseModel()->setProject( project ); } Q_SIGNALS: void currentColumnChanged( const QModelIndex&, const QModelIndex& ); protected Q_SLOTS: void slotDropAllowed( const QModelIndex &index, int dropIndicatorPosition, QDragMoveEvent *event ); }; class PLANUI_EXPORT TaskEditor : public ViewBase { Q_OBJECT public: TaskEditor(KoPart *part, KoDocument *doc, QWidget *parent); void setupGui(); void setProject( Project *project ); Project *project() const { return m_view->project(); } virtual void createDockers(); virtual Node *currentNode() const; QList selectedNodes() const ; Node *selectedNode() const; virtual void updateReadWrite( bool readwrite ); NodeItemModel *baseModel() const { return m_view->baseModel(); } NodeSortFilterProxyModel *proxyModel() const { return m_view->proxyModel(); } QAbstractItemModel *model() const { return m_view->model(); } /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &/*context*/ ) const; virtual KoPrintJob *createPrintJob(); Q_SIGNALS: - void taskSelected( Task *task ); + void taskSelected(KPlato::Task *task); void openNode(); void addTask(); void addMilestone(); void addSubtask(); void addSubMilestone(); - void deleteTaskList( const QList& ); + void deleteTaskList(const QList&); void moveTaskUp(); void moveTaskDown(); void indentTask(); void unindentTask(); void loadTaskModules( const QStringList &files ); - void saveTaskModule( const QUrl &url, Project *project ); + void saveTaskModule(const QUrl &url, KPlato::Project *project); void removeTaskModule( const QUrl &url ); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); - void setScheduleManager( ScheduleManager *sm ); + void setScheduleManager(KPlato::ScheduleManager *sm); void setTaskModules( const QStringList &files ); protected: void updateActionsEnabled( bool on ); int selectedRowCount() const; QModelIndexList selectedRows() const; void editTasks(const QList &tasks, const QPoint &pos); protected Q_SLOTS: virtual void slotOptions(); private Q_SLOTS: void slotSelectionChanged( const QModelIndexList& ); void slotCurrentChanged( const QModelIndex&, const QModelIndex& ); void slotContextMenuRequested(const QModelIndex &index, const QPoint& pos , const QModelIndexList &rows); void slotEnableActions(); void slotAddTask(); void slotAddSubtask(); void slotAddMilestone(); void slotAddSubMilestone(); void slotDeleteTask(); void slotIndentTask(); void slotUnindentTask(); void slotMoveTaskUp(); void slotMoveTaskDown(); void slotSplitView(); void slotProjectShown( bool ); void taskModuleDoubleClicked(QModelIndex idx); private: void edit( const QModelIndex &index ); private: TaskEditorTreeView *m_view; KActionMenu *menuAddTask; KActionMenu *menuAddSubTask; QAction *actionAddTask; QAction *actionAddMilestone; QAction *actionAddSubtask; QAction *actionAddSubMilestone; QAction *actionDeleteTask; QAction *actionMoveTaskUp; QAction *actionMoveTaskDown; QAction *actionIndentTask; QAction *actionUnindentTask; QAction *actionShowProject; QDomDocument m_domdoc; }; class PLANUI_EXPORT TaskView : public ViewBase { Q_OBJECT public: TaskView(KoPart *part, KoDocument *doc, QWidget *parent); void setupGui(); Project *project() const { return m_view->project(); } virtual void draw( Project &project ); virtual void draw(); NodeItemModel *baseModel() const { return m_view->baseModel(); } NodeSortFilterProxyModel *proxyModel() const { return m_view->proxyModel(); } virtual Node *currentNode() const; QList selectedNodes() const ; Node *selectedNode() const; virtual void updateReadWrite( bool readwrite ); /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &/*context*/ ) const; KoPrintJob *createPrintJob(); Q_SIGNALS: void openNode(); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); - void setScheduleManager( ScheduleManager *sm ); + void setScheduleManager(KPlato::ScheduleManager *sm); protected: void updateActionsEnabled( bool on ); int selectedNodeCount() const; protected Q_SLOTS: virtual void slotOptions(); private Q_SLOTS: void slotSelectionChanged( const QModelIndexList& ); void slotCurrentChanged( const QModelIndex&, const QModelIndex& ); void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); void slotEnableActions(); void slotSplitView(); private: NodeTreeView *m_view; QAction *actionShowProject; QDomDocument m_domdoc; }; //----------------------------------- class WorkPackageTreeView : public DoubleTreeViewBase { Q_OBJECT public: explicit WorkPackageTreeView(QWidget *parent); //void setSelectionModel( QItemSelectionModel *selectionModel ); NodeItemModel *baseModel() const; WorkPackageProxyModel *proxyModel() const { return m; } Project *project() const { return baseModel()->project(); } void setProject( Project *project ) { m->setProject( project ); } ScheduleManager *scheduleManager() const { return baseModel()->manager(); } Q_SIGNALS: void currentColumnChanged( const QModelIndex&, const QModelIndex& ); protected Q_SLOTS: void slotDropAllowed( const QModelIndex &index, int dropIndicatorPosition, QDragMoveEvent *event ); protected: WorkPackageProxyModel *m; }; class PLANUI_EXPORT TaskWorkPackageView : public ViewBase { Q_OBJECT public: TaskWorkPackageView(KoPart *part, KoDocument *doc, QWidget *parent); void setupGui(); Project *project() const; void setProject( Project *project ); ScheduleManager *scheduleManager() const { return m_view->scheduleManager(); } WorkPackageProxyModel *proxyModel() const; virtual Node *currentNode() const; QList selectedNodes() const ; Node *selectedNode() const; virtual void updateReadWrite( bool readwrite ); /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &/*context*/ ) const; KoPrintJob *createPrintJob(); Q_SIGNALS: - void mailWorkpackage( Node *n, Resource *r = 0 ); - void mailWorkpackages( const QList &nodes, Resource *r ); + void mailWorkpackage(KPlato::Node *n, KPlato::Resource *r = 0); + void mailWorkpackages(const QList &nodes, KPlato::Resource *r); void checkForWorkPackages(); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); void slotRefreshView(); - void setScheduleManager( ScheduleManager *sm ); + void setScheduleManager(KPlato::ScheduleManager *sm); protected: void updateActionsEnabled( bool on ); int selectedNodeCount() const; protected Q_SLOTS: virtual void slotOptions(); void slotMailWorkpackage(); - void slotWorkPackageSent( const QList &nodes, Resource *resource ); + void slotWorkPackageSent(const QList &nodes, KPlato::Resource *resource); private Q_SLOTS: void slotSelectionChanged( const QModelIndexList& ); void slotCurrentChanged( const QModelIndex&, const QModelIndex& ); void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); void slotEnableActions(); void slotSplitView(); private: WorkPackageTreeView *m_view; MacroCommand *m_cmd; QAction *actionMailWorkpackage; }; } //namespace KPlato #endif diff --git a/src/libs/ui/kpttaskprogressdialog.cpp b/src/libs/ui/kpttaskprogressdialog.cpp index b3c6364e..ada7e000 100644 --- a/src/libs/ui/kpttaskprogressdialog.cpp +++ b/src/libs/ui/kpttaskprogressdialog.cpp @@ -1,80 +1,80 @@ /* This file is part of the KDE project Copyright (C) 2005-2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kpttaskprogressdialog.h" #include "kpttaskprogresspanel.h" #include "kptcommand.h" #include "kptproject.h" #include "kpttask.h" #include "kptnode.h" #include namespace KPlato { TaskProgressDialog::TaskProgressDialog(Task &task, ScheduleManager *sm, StandardWorktime *workTime, QWidget *p) : KoDialog( p), m_node( &task ) { setCaption( i18n("Task Progress") ); setButtons( Ok|Cancel ); setDefaultButton( Ok ); showButtonSeparator( true ); m_panel = new TaskProgressPanel(task, sm, workTime, this); setMainWidget(m_panel); enableButtonOk(false); connect(m_panel, SIGNAL(changed()), SLOT(slotChanged())); Project *proj = static_cast( task.projectNode() ); if ( proj ) { - connect(proj, SIGNAL(nodeRemoved(Node*)), SLOT(slotNodeRemoved(Node*))); + connect(proj, SIGNAL(nodeRemoved(KPlato::Node*)), SLOT(slotNodeRemoved(KPlato::Node*))); } } void TaskProgressDialog::slotNodeRemoved( Node *node ) { if ( m_node == node ) { reject(); } } void TaskProgressDialog::slotChanged() { enableButtonOk(true); } MacroCommand *TaskProgressDialog::buildCommand() { MacroCommand *m = new MacroCommand(kundo2_i18n("Modify Task Progress")); bool modified = false; MacroCommand *cmd = m_panel->buildCommand(); if (cmd) { m->addCommand(cmd); modified = true; } if (!modified) { delete m; return 0; } return m; } } //KPlato namespace diff --git a/src/libs/ui/kpttaskprogressdialog.h b/src/libs/ui/kpttaskprogressdialog.h index c8bc544e..bd60e4e3 100644 --- a/src/libs/ui/kpttaskprogressdialog.h +++ b/src/libs/ui/kpttaskprogressdialog.h @@ -1,57 +1,57 @@ /* This file is part of the KDE project Copyright (C) 2005-2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation;; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KPTTASKPROGRESSDIALOG_H #define KPTTASKPROGRESSDIALOG_H #include "planui_export.h" #include namespace KPlato { class TaskProgressPanel; class Task; class Node; class StandardWorktime; class ScheduleManager; class MacroCommand; class PLANUI_EXPORT TaskProgressDialog : public KoDialog { Q_OBJECT public: TaskProgressDialog(Task &task, ScheduleManager *sm, StandardWorktime *workTime, QWidget *parent=0); MacroCommand *buildCommand(); protected Q_SLOTS: void slotChanged(); - void slotNodeRemoved( Node *node ); + void slotNodeRemoved(KPlato::Node *node); private: Node *m_node; TaskProgressPanel *m_panel; }; } //KPlato namespace #endif // TASKPROGRESSDIALOG_H diff --git a/src/libs/ui/kpttaskstatusview.h b/src/libs/ui/kpttaskstatusview.h index d1898959..778b634c 100644 --- a/src/libs/ui/kpttaskstatusview.h +++ b/src/libs/ui/kpttaskstatusview.h @@ -1,501 +1,501 @@ /* This file is part of the KDE project Copyright (C) 2007 - 2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef TASKSTATUSVIEW_H #define TASKSTATUSVIEW_H #include "planui_export.h" #include "kptitemmodelbase.h" #include "kptviewbase.h" #include "ui_kpttaskstatusviewsettingspanel.h" #include "kptitemviewsettup.h" #include "ui_kptperformancestatus.h" #include "ui_kptperformancestatusviewsettingspanel.h" #include "kptnodechartmodel.h" #include #include class QItemSelection; class KoDocument; class KoPageLayoutWidget; class PrintingHeaderFooter; namespace KChart { class CartesianCoordinatePlane; class CartesianAxis; class Legend; }; namespace KPlato { class Project; class Node; class ScheduleManager; class TaskStatusItemModel; class NodeItemModel; class PerformanceStatusBase; typedef QList NodeList; class PLANUI_EXPORT TaskStatusTreeView : public DoubleTreeViewBase { Q_OBJECT public: explicit TaskStatusTreeView(QWidget *parent); //void setSelectionModel( QItemSelectionModel *selectionModel ); TaskStatusItemModel *model() const; Project *project() const; void setProject( Project *project ); int defaultWeekday() const { return Qt::Friday; } int weekday() const; void setWeekday( int day ); int defaultPeriod() const { return 7; } int period() const; void setPeriod( int days ); int defaultPeriodType() const; int periodType() const; void setPeriodType( int type ); protected: void dragMoveEvent(QDragMoveEvent *event); }; class PLANUI_EXPORT TaskStatusView : public ViewBase { Q_OBJECT public: TaskStatusView(KoPart *part, KoDocument *doc, QWidget *parent); void setupGui(); virtual void setProject( Project *project ); Project *project() const { return m_view->project(); } using ViewBase::draw; virtual void draw( Project &project ); TaskStatusItemModel *model() const { return m_view->model(); } virtual void updateReadWrite( bool readwrite ); virtual Node *currentNode() const; /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &/*context*/ ) const; KoPrintJob *createPrintJob(); Q_SIGNALS: void openNode(); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); - void setScheduleManager( ScheduleManager *sm ); + void setScheduleManager(KPlato::ScheduleManager *sm); virtual void slotRefreshView(); protected Q_SLOTS: virtual void slotOptions(); protected: void updateActionsEnabled( bool on ); private Q_SLOTS: void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); - void slotContextMenuRequested( Node *node, const QPoint& pos ); + void slotContextMenuRequested(KPlato::Node *node, const QPoint& pos); void slotSplitView(); private: Project *m_project; int m_id; TaskStatusTreeView *m_view; QDomDocument m_domdoc; }; //-------------------------------------- class TaskStatusViewSettingsPanel : public QWidget, public Ui::TaskStatusViewSettingsPanel { Q_OBJECT public: explicit TaskStatusViewSettingsPanel( TaskStatusTreeView *view, QWidget *parent = 0 ); public Q_SLOTS: void slotOk(); void setDefault(); Q_SIGNALS: void changed(); private: TaskStatusTreeView *m_view; }; class TaskStatusViewSettingsDialog : public SplitItemViewSettupDialog { Q_OBJECT public: explicit TaskStatusViewSettingsDialog( ViewBase *view, TaskStatusTreeView *treeview, QWidget *parent = 0 ); }; struct PerformanceChartInfo { bool showBarChart; bool showLineChart; bool showTableView; bool showBaseValues; bool showIndices; bool showCost; bool showBCWSCost; bool showBCWPCost; bool showACWPCost; bool showEffort; bool showBCWSEffort; bool showBCWPEffort; bool showACWPEffort; bool showSpiCost; bool showCpiCost; bool showSpiEffort; bool showCpiEffort; bool effortShown() const { return ( showBaseValues && showEffort ) || ( showIndices && ( showSpiEffort || showCpiEffort ) ); } bool costShown() const { return ( showBaseValues && showCost ) || ( showIndices && ( showSpiCost || showCpiCost ) ); } bool bcwsCost() const { return showBaseValues && showCost && showBCWSCost; } bool bcwpCost() const { return showBaseValues && showCost && showBCWPCost; } bool acwpCost() const { return showBaseValues && showCost && showACWPCost; } bool bcwsEffort() const { return showBaseValues && showEffort && showBCWSEffort; } bool bcwpEffort() const { return showBaseValues && showEffort && showBCWPEffort; } bool acwpEffort() const { return showBaseValues && showEffort && showACWPEffort; } bool spiCost() const { return showIndices && showSpiCost; } bool cpiCost() const { return showIndices && showCpiCost; } bool spiEffort() const { return showIndices && showSpiEffort; } bool cpiEffort() const { return showIndices && showCpiEffort; } PerformanceChartInfo() { showBarChart = false; showLineChart = true; showTableView = false; showBaseValues = true; showIndices = false; showCost = showBCWSCost = showBCWPCost = showACWPCost = true; showEffort = showBCWSEffort = showBCWPEffort = showACWPEffort = true; showSpiCost = showCost = showSpiEffort = showCpiEffort = true; } bool operator!=( const PerformanceChartInfo &o ) const { return ! operator==( o ); } bool operator==( const PerformanceChartInfo &o ) const { return showBarChart == o.showBarChart && showLineChart == o.showLineChart && showBaseValues == o.showBaseValues && showIndices == o.showIndices && showCost == o.showCost && showBCWSCost == o.showBCWSCost && showBCWPCost == o.showBCWPCost && showACWPCost == o.showACWPCost && showEffort == o.showEffort && showBCWSEffort == o.showBCWSEffort && showBCWPEffort == o.showBCWPEffort && showACWPEffort == o.showACWPEffort && showSpiCost == o.showSpiCost && showCpiCost == o.showCpiCost && showSpiEffort == o.showSpiEffort && showCpiEffort == o.showCpiEffort; } }; //---------------------------------- class PLANUI_EXPORT PerformanceStatusPrintingDialog : public PrintingDialog { Q_OBJECT public: PerformanceStatusPrintingDialog( ViewBase *view, PerformanceStatusBase *chart, Project *project = 0 ); ~PerformanceStatusPrintingDialog() {} virtual int documentLastPage() const; virtual QList createOptionWidgets() const; protected: virtual void printPage( int pageNumber, QPainter &painter ); private: PerformanceStatusBase *m_chart; Project *m_project; }; class PerformanceStatusBase : public QWidget, public Ui::PerformanceStatus { Q_OBJECT public: explicit PerformanceStatusBase( QWidget *parent ); void setProject( Project *project ); void setScheduleManager( ScheduleManager *sm ); ChartItemModel *model() const { return const_cast( &m_chartmodel ); } void setupChart(); void setChartInfo( const PerformanceChartInfo &info ); PerformanceChartInfo chartInfo() const { return m_chartinfo; } /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &context ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &context ) const; /// Create a print job dialog KoPrintJob *createPrintJob( ViewBase *parent ); void setNodes( const QList &nodes ); public Q_SLOTS: void refreshChart(); protected: void contextMenuEvent( QContextMenuEvent *event ); void createBarChart(); void createLineChart(); void setEffortValuesVisible( bool visible ); void setCostValuesVisible( bool visible ); protected Q_SLOTS: void slotUpdate(); void slotLocaleChanged(); private: struct ChartContents { ~ChartContents() { delete dateaxis; delete effortaxis; delete costaxis; delete effortplane; delete costplane; delete effortdiagram; delete costdiagram; } ChartProxyModel costproxy; ChartProxyModel effortproxy; KChart::CartesianCoordinatePlane *effortplane; KChart::CartesianCoordinatePlane *costplane; KChart::AbstractDiagram *effortdiagram; KChart::AbstractDiagram *costdiagram; KChart::CartesianAxis *effortaxis; KChart::CartesianAxis *costaxis; KChart::CartesianAxis *dateaxis; ChartProxyModel piproxy; KChart::CartesianCoordinatePlane *piplane; KChart::AbstractDiagram *pidiagram; KChart::CartesianAxis *piaxis; }; void setupChart( ChartContents &cc ); private: Project *m_project; ScheduleManager *m_manager; PerformanceChartInfo m_chartinfo; ChartItemModel m_chartmodel; KChart::Legend *m_legend; KChart::BarDiagram m_legenddiagram; struct ChartContents m_barchart; struct ChartContents m_linechart; }; //---------------------------------- class PLANUI_EXPORT ProjectStatusView : public ViewBase { Q_OBJECT public: ProjectStatusView(KoPart *part, KoDocument *doc, QWidget *parent ); void setupGui(); Project *project() const { return m_project; } virtual void setProject( Project *project ); /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &/*context*/ ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &/*context*/ ) const; KoPrintJob *createPrintJob(); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); - void setScheduleManager( ScheduleManager *sm ); + void setScheduleManager(KPlato::ScheduleManager *sm); protected: void updateActionsEnabled( bool on ); protected Q_SLOTS: virtual void slotOptions(); private: Project *m_project; PerformanceStatusBase *m_view; }; //---------------------------------- class PerformanceStatusTreeView : public QSplitter { Q_OBJECT public: explicit PerformanceStatusTreeView( QWidget *parent ); NodeItemModel *nodeModel() const; Project *project() const; void setProject( Project *project ); void setScheduleManager( ScheduleManager *sm ); /// Loads context info into this view. virtual bool loadContext( const KoXmlElement &context ); /// Save context info from this view. virtual void saveContext( QDomElement &context ) const; TreeViewBase *treeView() const { return m_tree; } PerformanceStatusBase *chartView() const { return m_chart; } KoPrintJob *createPrintJob( ViewBase *view ); protected Q_SLOTS: void slotSelectionChanged( const QItemSelection & selected, const QItemSelection & deselected ); void resizeSplitters(); private: TreeViewBase *m_tree; PerformanceStatusBase *m_chart; ScheduleManager *m_manager; QDomDocument m_domdoc; }; //---------------------------------- class PLANUI_EXPORT PerformanceStatusView : public ViewBase { Q_OBJECT public: PerformanceStatusView(KoPart *part, KoDocument *doc, QWidget *parent ); void setupGui(); Project *project() const { return m_view->project(); } virtual void setProject( Project *project ); /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &context ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &context ) const; Node *currentNode() const; KoPrintJob *createPrintJob(); public Q_SLOTS: /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); - void setScheduleManager( ScheduleManager *sm ); + void setScheduleManager(KPlato::ScheduleManager *sm); protected Q_SLOTS: virtual void slotOptions(); protected: void updateActionsEnabled( bool on ); private Q_SLOTS: - void slotContextMenuRequested( Node *node, const QPoint& pos ); + void slotContextMenuRequested(KPlato::Node *node, const QPoint& pos); void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); private: PerformanceStatusTreeView *m_view; }; //-------------------------------------- class PerformanceStatusViewSettingsPanel : public QWidget, public Ui::PerformanceStatusViewSettingsPanel { Q_OBJECT public: explicit PerformanceStatusViewSettingsPanel( PerformanceStatusBase *view, QWidget *parent = 0 ); public Q_SLOTS: void slotOk(); void setDefault(); Q_SIGNALS: void changed(); protected Q_SLOTS: void switchStackWidget(); private: PerformanceStatusBase *m_view; }; class PerformanceStatusViewSettingsDialog : public ItemViewSettupDialog { Q_OBJECT public: explicit PerformanceStatusViewSettingsDialog( PerformanceStatusView *view, PerformanceStatusTreeView *treeview, QWidget *parent = 0, bool selectPrint = false ); }; class ProjectStatusViewSettingsDialog : public KPageDialog { Q_OBJECT public: explicit ProjectStatusViewSettingsDialog( ViewBase *base, PerformanceStatusBase *view, QWidget *parent = 0, bool selectPrint = false ); protected Q_SLOTS: void slotOk(); private: ViewBase *m_base; KoPageLayoutWidget *m_pagelayout; PrintingHeaderFooter *m_headerfooter; }; } //namespace KPlato #endif diff --git a/src/libs/ui/kptusedefforteditor.h b/src/libs/ui/kptusedefforteditor.h index 6559eb4a..93019034 100644 --- a/src/libs/ui/kptusedefforteditor.h +++ b/src/libs/ui/kptusedefforteditor.h @@ -1,207 +1,207 @@ /* This file is part of the KDE project Copyright (C) 2007, 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KPTUSEDEFFORTEDITOR_H #define KPTUSEDEFFORTEDITOR_H #include "planui_export.h" #include #include #include "kpttask.h" namespace KPlato { class Completion; class Resource; class Project; class PLANUI_EXPORT UsedEffortItemModel : public QAbstractItemModel { Q_OBJECT public: explicit UsedEffortItemModel(QWidget *parent = 0); void setProject( Project *project ) { m_project = project; } virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex &index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QModelIndex parent(const QModelIndex &) const { return QModelIndex(); } QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const; void setCompletion( Completion *completion ); const Resource *resource(const QModelIndex &index ) const; Completion::UsedEffort *usedEffort(const QModelIndex &index ) const; void setCurrentMonday( const QDate &date ); QModelIndex addRow(); QMap freeResources() const; void setReadOnly( bool ro ) { m_readonly = ro; } bool readOnly() const { return m_readonly; } Q_SIGNALS: void rowInserted( const QModelIndex& ); void changed(); public Q_SLOTS: bool submit(); void revert(); private: Project *m_project; Completion *m_completion; QList m_dates; QStringList m_headers; QList m_resourcelist; QMap m_editlist; bool m_readonly; }; class PLANUI_EXPORT UsedEffortEditor : public QTableView { Q_OBJECT public: explicit UsedEffortEditor(QWidget *parent); void setProject( Project *project ); void setCompletion( Completion *completion ); void setCurrentMonday( const QDate &date ); void addResource(); bool hasFreeResources() const; UsedEffortItemModel *model() const { return static_cast( QTableView::model() ); } Q_SIGNALS: void changed(); void resourceAdded(); private: }; //-------------------------------------------- class PLANUI_EXPORT CompletionEntryItemModel : public QAbstractItemModel { Q_OBJECT public: enum Properties { Property_Date, /// Date of entry Property_Completion, /// % Completed Property_UsedEffort, /// Used Effort Property_RemainingEffort, /// Remaining Effort Property_PlannedEffort /// Planned Effort }; explicit CompletionEntryItemModel(QObject *parent = 0); void setTask( Task *t ); virtual Qt::ItemFlags flags( const QModelIndex & index ) const; virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex &index, const QVariant & value, int role = Qt::EditRole ); virtual QVariant headerData ( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const; virtual int rowCount( const QModelIndex & parent = QModelIndex() ) const; virtual QModelIndex parent(const QModelIndex &) const { return QModelIndex(); } QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const; void setCompletion( Completion *completion ); const Resource *resource(const QModelIndex &index ) const; Completion::UsedEffort *usedEffort(const QModelIndex &index ) const; void setCurrentMonday( const QDate &date ); QModelIndex addRow(); void removeRow( int row ); /// These flags are in addition to flags return from QAbstractItemModel::flags() void setFlags( int col, Qt::ItemFlags flags ) { m_flags[ col ] = flags; } long id() const { return m_manager == 0 ? -1 : m_manager->scheduleId(); } Q_SIGNALS: void rowInserted( const QDate& ); void rowRemoved( const QDate& ); void changed(); public Q_SLOTS: bool submit(); void revert(); void slotDataChanged(); - void setManager( ScheduleManager *sm ); + void setManager(KPlato::ScheduleManager *sm); protected: QVariant date ( int row, int role = Qt::DisplayRole ) const; QVariant percentFinished ( int row, int role ) const; QVariant remainingEffort ( int row, int role ) const; virtual QVariant actualEffort ( int row, int role ) const; QVariant plannedEffort ( int row, int role ) const; void removeEntry( const QDate& date ); void addEntry( const QDate& date ); void refresh(); QList scales() const; protected: Task *m_node; Project *m_project; ScheduleManager *m_manager; Completion *m_completion; QList m_dates; QStringList m_headers; QList m_datelist; QList m_flags; }; class PLANUI_EXPORT CompletionEntryEditor : public QTableView { Q_OBJECT public: explicit CompletionEntryEditor(QWidget *parent); void setCompletion( Completion *completion ); CompletionEntryItemModel *model() const { return static_cast( QTableView::model() ); } void setCompletionModel( CompletionEntryItemModel *m ); Q_SIGNALS: void changed(); void rowInserted( const QDate& ); void rowRemoved( const QDate& ); void selectionChanged( const QItemSelection&, const QItemSelection& ); public Q_SLOTS: void addEntry(); void removeEntry(); private: }; } //KPlato namespace #endif // KPTUSEDEFFORTEDITOR_H diff --git a/src/libs/ui/kptviewbase.h b/src/libs/ui/kptviewbase.h index 4cd26977..516b87d8 100644 --- a/src/libs/ui/kptviewbase.h +++ b/src/libs/ui/kptviewbase.h @@ -1,683 +1,683 @@ /* This file is part of the KDE project Copyright (C) 2006 -2010 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KPTVIEWBASE_H #define KPTVIEWBASE_H #include "planui_export.h" #include "kptitemmodelbase.h" #include "ui_kptprintingheaderfooter.h" #include #include #include //#include #include #include #include #include #include #include class QMetaEnum; class QAbstractItemModel; class QDomElement; class QModelIndex; class KoDocument; class KoPrintJob; class KoPart; /// The main namespace namespace KPlato { class Project; class Node; class Resource; class ResourceGroup; class Relation; class Calendar; class ViewBase; class TreeViewBase; class DoubleTreeViewBase; //------------------ class PLANUI_EXPORT DockWidget : public QDockWidget { Q_OBJECT public: DockWidget( ViewBase *v, const QString &identity, const QString &title ); void activate( KoMainWindow *mainWindow ); void deactivate( KoMainWindow *mainWindow ); bool shown() const; bool saveXml( QDomElement &context ) const; void loadXml( const KoXmlElement &context ); const ViewBase *view; /// The view this docker belongs to QString id; /// Docker identity Qt::DockWidgetArea location; /// The area the docker should go when visible bool editor; /// Editor dockers will not be shown in read only mode public Q_SLOTS: void setShown( bool show ); void setLocation( Qt::DockWidgetArea area ); private: bool m_shown; /// The dockers visibility when the view is active }; //------------------ class PLANUI_EXPORT PrintingOptions { public: PrintingOptions() { headerOptions.group = true; headerOptions.project = Qt::Checked; headerOptions.date = Qt::Checked; headerOptions.manager = Qt::Checked; headerOptions.page = Qt::Checked; footerOptions.group = false; footerOptions.project = Qt::Checked; footerOptions.date = Qt::Checked; footerOptions.manager = Qt::Checked; footerOptions.page = Qt::Checked; } ~PrintingOptions() {} bool loadXml( KoXmlElement &element ); void saveXml( QDomElement &element ) const; struct Data { bool group; Qt::CheckState project; Qt::CheckState date; Qt::CheckState manager; Qt::CheckState page; }; struct Data headerOptions; struct Data footerOptions; }; //------------------ class PLANUI_EXPORT PrintingHeaderFooter : public QWidget, public Ui::PrintingHeaderFooter { Q_OBJECT public: explicit PrintingHeaderFooter( const PrintingOptions &opt, QWidget *parent = 0 ); ~PrintingHeaderFooter(); void setOptions( const PrintingOptions &options ); PrintingOptions options() const; Q_SIGNALS: - void changed(const PrintingOptions&); + void changed(const KPlato::PrintingOptions&); protected Q_SLOTS: void slotChanged(); private: PrintingOptions m_options; }; //------------------ class PLANUI_EXPORT PrintingDialog : public KoPrintingDialog { Q_OBJECT public: explicit PrintingDialog(ViewBase *view); ~PrintingDialog(); virtual QList createOptionWidgets() const; // virtual QList shapesOnPage(int); QRect headerRect() const; QRect footerRect() const; void paintHeaderFooter( QPainter &p, const PrintingOptions &options, int pageNumber, const Project &project ); PrintingOptions printingOptions() const; QWidget *createPageLayoutWidget() const; QAbstractPrintDialog::PrintDialogOptions printDialogOptions() const; Q_SIGNALS: - void changed( const PrintingOptions &opt ); + void changed(const KPlato::PrintingOptions &opt); void changed(); public Q_SLOTS: - void setPrintingOptions( const PrintingOptions &opt); + void setPrintingOptions(const KPlato::PrintingOptions &opt); void setPrinterPageLayout( const KoPageLayout &pagelayout ); virtual void startPrinting(RemovePolicy removePolicy = DoNotDelete); protected: virtual void paint( QPainter &p, const PrintingOptions::Data &options, const QRect &rect, int pageNumber, const Project &project ); int headerFooterHeight( const PrintingOptions::Data &options ) const; void drawRect( QPainter &p, const QRect &r, Qt::Edges edges = Qt::LeftEdge | Qt::RightEdge | Qt::BottomEdge ); protected: ViewBase *m_view; PrintingHeaderFooter *m_widget; int m_textheight; }; class PLANUI_EXPORT ViewActionLists { public: ViewActionLists() : actionOptions( 0 ) {} virtual ~ViewActionLists() {} /// Returns the list of action lists that shall be plugged/unplugged virtual QStringList actionListNames() const { return m_actionListMap.keys(); } /// Returns the list of actions associated with the action list name virtual QList actionList( const QString &name ) const { return m_actionListMap[name]; } /// Add an action to the specified action list void addAction( const QString &list, QAction *action ) { m_actionListMap[list].append( action ); } virtual QList viewlistActionList() const { return m_viewlistActionList; } void addViewlistAction( QAction *action ) { m_viewlistActionList.append( action ); } QList contextActionList() const { return m_contextActionList; } void addContextAction( QAction *action ) { m_contextActionList.append( action ); } protected: /// List of all menu/toolbar actions (used for plug/unplug) QMap > m_actionListMap; /// List of actions that will be shown in the viewlist context menu QList m_viewlistActionList; /// List of actions that will be shown in the views header context menu QList m_contextActionList; // View options context menu QAction *actionOptions; }; /** ViewBase is the baseclass of all sub-views to View. */ class PLANUI_EXPORT ViewBase : public KoView, public ViewActionLists { Q_OBJECT public: enum OptionTypes { OptionExpand = 1, OptionCollapse = 2, OptionPrint = 4, OptionPrintPreview = 8, OptionPrintPdf = 16, OptionPrintConfig = 32, OptionViewConfig = 64, OptionAll = 0xffff }; /// Constructor ViewBase(KoPart *part, KoDocument *doc, QWidget *parent); /// Destructor virtual ~ViewBase(); /// Return the part (document) this view handles KoDocument *part() const; /// Return the page layout used for printing this view virtual KoPageLayout pageLayout() const; /// Return the type of view this is (class name) QString viewType() const { return metaObject()->className(); } /// Returns true if this view or any child widget has focus bool isActive() const; /// Set the project this view shall handle. virtual void setProject( Project *project ); /// Return the project virtual Project *project() const { return m_proj; } /// Return the schedule manager virtual ScheduleManager *scheduleManager() const { return m_schedulemanager; } /// Draw data from current part / project virtual void draw() {} /// Draw data from project. virtual void draw(Project &/*project*/) {} /// Draw changed data from project. virtual void drawChanges(Project &project) { draw(project); } /// Set readWrite mode virtual void updateReadWrite( bool ); bool isReadWrite() const { return m_readWrite; } /// Reimplement if your view handles nodes virtual Node* currentNode() const { return 0; } /// Reimplement if your view handles resources virtual Resource* currentResource() const { return 0; } /// Reimplement if your view handles resource groups virtual ResourceGroup* currentResourceGroup() const { return 0; } /// Reimplement if your view handles calendars virtual Calendar* currentCalendar() const { return 0; } /// Reimplement if your view handles relations virtual Relation *currentRelation() const { return 0; } /// Reimplement if your view handles zoom // virtual KoZoomController *zoomController() const { return 0; } /// Loads context info (printer settings) into this view. virtual bool loadContext( const KoXmlElement &context ); /// Save context info (printer settings) from this view. virtual void saveContext( QDomElement &context ) const; virtual KoPrintJob *createPrintJob(); PrintingOptions printingOptions() const { return m_printingOptions; } static QWidget *createPageLayoutWidget( ViewBase *view ); static PrintingHeaderFooter *createHeaderFooterWidget( ViewBase *view ); void addAction( const QString &list, QAction *action ) { ViewActionLists::addAction( list, action ); } virtual void createDockers() {} void addDocker( DockWidget *ds ); QList dockers() const; DockWidget *findDocker( const QString &id ) const; public Q_SLOTS: - void setPrintingOptions( const PrintingOptions &opt ) { m_printingOptions = opt; } + void setPrintingOptions(const KPlato::PrintingOptions &opt) { m_printingOptions = opt; } /// Activate/deactivate the gui virtual void setGuiActive( bool activate ); - virtual void setScheduleManager( ScheduleManager *sm ) { m_schedulemanager = sm; } + virtual void setScheduleManager(KPlato::ScheduleManager *sm) { m_schedulemanager = sm; } void slotUpdateReadWrite( bool ); virtual void slotHeaderContextMenuRequested( const QPoint &pos ); virtual void slotEditCopy() {} virtual void slotEditCut() {} virtual void slotEditPaste() {} virtual void slotRefreshView() {} void setPageLayout( const KoPageLayout &layout ); Q_SIGNALS: /// Emitted when the gui has been activated or deactivated - void guiActivated( ViewBase*, bool ); + void guiActivated(KPlato::ViewBase*, bool); /// Request for a context menu popup void requestPopupMenu( const QString&, const QPoint & ); /// Emitted when options are modified void optionsModified(); - void projectChanged( Project *project ); + void projectChanged(KPlato::Project *project); void readWriteChanged( bool ); void expandAll(); void collapseAll(); void openDocument(const QUrl &url); protected Q_SLOTS: virtual void slotOptions() {} virtual void slotOptionsFinished( int result ); protected: void createOptionActions(int actions); bool m_readWrite; PrintingOptions m_printingOptions; Project *m_proj; ScheduleManager *m_schedulemanager; KoPageLayout m_pagelayout; QList m_dockers; }; //------------------ class PLANUI_EXPORT TreeViewPrintingDialog : public PrintingDialog { Q_OBJECT public: TreeViewPrintingDialog( ViewBase *view, TreeViewBase *treeview, Project *project = 0 ); ~TreeViewPrintingDialog() {} virtual int documentFirstPage() const { return 1; } virtual int documentLastPage() const; QList createOptionWidgets() const; protected: virtual void printPage( int pageNumber, QPainter &painter ); int firstRow( int page ) const; private: TreeViewBase *m_tree; Project *m_project; int m_firstRow; }; //----------------- class PLANUI_EXPORT TreeViewBase : public QTreeView { Q_OBJECT public: explicit TreeViewBase( QWidget *parent = 0 ); void setReadWrite( bool rw ); virtual void createItemDelegates( ItemModelBase *model ); void setArrowKeyNavigation( bool on ) { m_arrowKeyNavigation = on; } bool arrowKeyNavigation() const { return m_arrowKeyNavigation; } /// Move move to first visual QModelIndex firstColumn( int row, const QModelIndex &parent ); /// Move move to last visual QModelIndex lastColumn( int row, const QModelIndex &parent ); /// Move from @p current to next item QModelIndex nextColumn( const QModelIndex ¤t ); /// Move from @p current to next item QModelIndex previousColumn( const QModelIndex ¤t ); /// Move to first editable index in @p row with @p parent QModelIndex firstEditable( int row, const QModelIndex &parent ); /// Move to last editable index in @p row with @p parent QModelIndex lastEditable( int row, const QModelIndex &parent ); void setAcceptDropsOnView( bool mode ) { m_acceptDropsOnView = mode; } virtual void setModel( QAbstractItemModel *model ); virtual void setSelectionModel( QItemSelectionModel *model ); void setStretchLastSection( bool ); void mapToSection( int column, int section ); int section( int col ) const; void setColumnsHidden( const QList &list ); /// Loads context info into this view. Reimplement. virtual bool loadContext(const QMetaEnum &map, const KoXmlElement &element, bool expand = true); /// Save context info from this view. Reimplement. virtual void saveContext(const QMetaEnum &map, QDomElement &context , bool expand = true) const; /** Reimplemented to fix qt bug 160083: Doesn't scroll horizontally. Scroll the contents of the tree view until the given model item \a index is visible. The \a hint parameter specifies more precisely where the item should be located after the operation. If any of the parents of the model item are collapsed, they will be expanded to ensure that the model item is visible. */ void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible); void setDefaultColumns( const QList &lst ) { m_defaultColumns = lst; } QList defaultColumns() const { return m_defaultColumns; } KoPrintJob *createPrintJob( ViewBase *parent ); QModelIndex firstVisibleIndex( const QModelIndex &idx ) const; ItemModelBase *itemModel() const; void setContextMenuIndex(const QModelIndex &idx); void loadExpanded(const KoXmlElement &element); void saveExpanded(QDomElement &element, const QModelIndex &parent = QModelIndex()) const; void expandRecursivly(QDomElement element, const QModelIndex &parent = QModelIndex()); void doExpand(QDomDocument &doc); public Q_SLOTS: void slotExpand(); void slotCollapse(); Q_SIGNALS: /// Context menu requested from viewport at global position @p pos void contextMenuRequested( const QModelIndex&, const QPoint &pos, const QModelIndexList& ); /// Context menu requested from header at global position @p pos void headerContextMenuRequested( const QPoint &pos ); void moveAfterLastColumn( const QModelIndex & ); void moveBeforeFirstColumn( const QModelIndex & ); void editAfterLastColumn( const QModelIndex & ); void editBeforeFirstColumn( const QModelIndex & ); void dropAllowed( const QModelIndex &index, int dropIndicatorPosition, QDragMoveEvent *event ); protected: void keyPressEvent(QKeyEvent *event); void mousePressEvent( QMouseEvent *event ); /** Reimplemented from QTreeView to make tab/backtab in editor work reasonably well. Move the cursor in the way described by \a cursorAction, *not* using the information provided by the button \a modifiers. */ QModelIndex moveCursor( CursorAction cursorAction, Qt::KeyboardModifiers modifiers ); /// Move cursor from @p index in direction @p cursorAction. @p modifiers is not used. QModelIndex moveCursor( const QModelIndex &index, CursorAction cursorAction, Qt::KeyboardModifiers = Qt::NoModifier ); /// Move from @p index to next editable item, in direction @p cursorAction. QModelIndex moveToEditable( const QModelIndex &index, CursorAction cursorAction ); void contextMenuEvent ( QContextMenuEvent * event ); void dragMoveEvent(QDragMoveEvent *event); void dropEvent( QDropEvent *e ); void updateSelection( const QModelIndex &oldidx, const QModelIndex &newidx, QKeyEvent *event ); void expandRecursive(const QModelIndex &parent, bool xpand); protected Q_SLOTS: /// Close the @p editor, using sender()->endEditHint(). /// Use @p hint if sender is not of type ItemDelegate. virtual void closeEditor(QWidget *editor, QAbstractItemDelegate::EndEditHint hint); virtual void slotCurrentChanged ( const QModelIndex & current, const QModelIndex & previous ); void slotHeaderContextMenuRequested( const QPoint& ); //Copied from QAbstractItemView inline QItemSelectionModel::SelectionFlags selectionBehaviorFlags() const { switch (selectionBehavior()) { case QAbstractItemView::SelectRows: return QItemSelectionModel::Rows; case QAbstractItemView::SelectColumns: return QItemSelectionModel::Columns; case QAbstractItemView::SelectItems: default: return QItemSelectionModel::NoUpdate; } } void doContextExpanded(); void doExpanded(); protected: virtual void focusInEvent(QFocusEvent *event); bool m_arrowKeyNavigation; bool m_acceptDropsOnView; QList m_hideList; bool m_readWrite; QList m_defaultColumns; QPersistentModelIndex m_contextMenuIndex; QDomDocument m_loadContextDoc; QDomDocument m_expandDoc; }; //------------------ class PLANUI_EXPORT DoubleTreeViewPrintingDialog : public PrintingDialog { Q_OBJECT public: DoubleTreeViewPrintingDialog( ViewBase *view, DoubleTreeViewBase *treeview, Project *project ); ~DoubleTreeViewPrintingDialog() {} virtual int documentFirstPage() const { return 1; } virtual int documentLastPage() const; QList createOptionWidgets() const; protected: virtual void printPage( int pageNumber, QPainter &painter ); int firstRow( int page ) const; private: DoubleTreeViewBase *m_tree; Project *m_project; int m_firstRow; }; class PLANUI_EXPORT DoubleTreeViewBase : public QSplitter { Q_OBJECT public: explicit DoubleTreeViewBase( QWidget *parent ); DoubleTreeViewBase( bool mode, QWidget *parent ); ~DoubleTreeViewBase(); void setReadWrite( bool rw ); void closePersistentEditor( const QModelIndex &index ); void setModel( QAbstractItemModel *model ); QAbstractItemModel *model() const; void setArrowKeyNavigation( bool on ) { m_arrowKeyNavigation = on; } bool arrowKeyNavigation() const { return m_arrowKeyNavigation; } QItemSelectionModel *selectionModel() const { return m_selectionmodel; } void setSelectionModel( QItemSelectionModel *model ); void setSelectionMode( QAbstractItemView::SelectionMode mode ); void setSelectionBehavior( QAbstractItemView::SelectionBehavior mode ); virtual void createItemDelegates( ItemModelBase *model ); void setItemDelegateForColumn( int col, QAbstractItemDelegate * delegate ); void setEditTriggers ( QAbstractItemView::EditTriggers ); QAbstractItemView::EditTriggers editTriggers() const; void setAcceptDrops( bool ); void setAcceptDropsOnView( bool ); void setDropIndicatorShown( bool ); void setDragDropMode( QAbstractItemView::DragDropMode mode ); void setDragDropOverwriteMode( bool mode ); void setDragEnabled ( bool mode ); void setDefaultDropAction( Qt::DropAction action ); void setStretchLastSection( bool ); /// Hide columns in the @p hideList, show all other columns. /// If the hideList.last() == -1, the rest of the columns are hidden. void hideColumns( TreeViewBase *view, const QList &hideList ); void hideColumns( const QList &masterList, const QList &slaveList = QList() ); void hideColumn( int col ) { m_leftview->hideColumn( col ); if ( m_rightview ) m_rightview->hideColumn( col ); } void showColumn( int col ) { if ( col == 0 || m_rightview == 0 ) m_leftview->showColumn( col ); else m_rightview->showColumn( col ); } bool isColumnHidden( int col ) const { return m_rightview ? m_rightview->isColumnHidden( col ) : m_leftview->isColumnHidden( col ); } TreeViewBase *masterView() const { return m_leftview; } TreeViewBase *slaveView() const { return m_rightview; } /// Loads context info into this view. Reimplement. virtual bool loadContext( const QMetaEnum &map, const KoXmlElement &element ); /// Save context info from this view. Reimplement. virtual void saveContext( const QMetaEnum &map, QDomElement &context ) const; void setViewSplitMode( bool split ); bool isViewSplit() const { return m_mode; } QAction *actionSplitView() const { return m_actionSplitView; } void setRootIsDecorated ( bool show ); KoPrintJob *createPrintJob( ViewBase *parent ); void setStretchFactors(); QModelIndex indexAt( const QPoint &pos ) const; void setParentsExpanded( const QModelIndex &idx, bool expanded ); void setSortingEnabled( bool on ) { m_leftview->setSortingEnabled( on ); m_rightview->setSortingEnabled( on ); } void sortByColumn( int col, Qt::SortOrder order = Qt::AscendingOrder ) { if ( ! m_leftview->isColumnHidden( col ) || ! m_rightview->isVisible() || m_rightview->isColumnHidden( col ) ) { m_leftview->sortByColumn( col, order ); } else { m_rightview->sortByColumn( col, order ); } } void setContextMenuIndex(const QModelIndex &idx); Q_SIGNALS: /// Context menu requested from the viewport, pointer over @p index at global position @p pos void contextMenuRequested( const QModelIndex &index, const QPoint& pos, const QModelIndexList& ); /// Context menu requested from master- or slave header at global position @p pos void headerContextMenuRequested( const QPoint &pos ); /// Context menu requested from master header at global position @p pos void masterHeaderContextMenuRequested( const QPoint &pos ); /// Context menu requested from slave header at global position @p pos void slaveHeaderContextMenuRequested( const QPoint &pos ); void currentChanged ( const QModelIndex & current, const QModelIndex & previous ); void selectionChanged( const QModelIndexList& ); void dropAllowed( const QModelIndex &index, int dropIndicatorPosition, QDragMoveEvent *event ); public Q_SLOTS: void edit( const QModelIndex &index ); void slotExpand(); void slotCollapse(); protected Q_SLOTS: void slotSelectionChanged( const QItemSelection &sel, const QItemSelection & ); void slotToRightView( const QModelIndex &index ); void slotToLeftView( const QModelIndex &index ); void slotEditToRightView( const QModelIndex &index ); void slotEditToLeftView( const QModelIndex &index ); void slotRightHeaderContextMenuRequested( const QPoint &pos ); void slotLeftHeaderContextMenuRequested( const QPoint &pos ); void slotLeftSortIndicatorChanged( int logicalIndex, Qt::SortOrder order ); void slotRightSortIndicatorChanged( int logicalIndex, Qt::SortOrder order ); protected: void init(); QList expandColumnList( const QList &lst ) const; protected: TreeViewBase *m_leftview; TreeViewBase *m_rightview; QItemSelectionModel *m_selectionmodel; bool m_arrowKeyNavigation; bool m_readWrite; bool m_mode; QAction *m_actionSplitView; }; } // namespace KPlato #endif diff --git a/src/libs/ui/kptworkpackagesendpanel.h b/src/libs/ui/kptworkpackagesendpanel.h index 47ceaaee..cffb419d 100644 --- a/src/libs/ui/kptworkpackagesendpanel.h +++ b/src/libs/ui/kptworkpackagesendpanel.h @@ -1,58 +1,58 @@ /* This file is part of the KDE project Copyright (C) 2007 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 KPTWORKPACKAGESENDPANEL_H #define KPTWORKPACKAGESENDPANEL_H #include "planui_export.h" #include "ui_kptworkpackagesendpanel.h" #include #include class QPushButton; namespace KPlato { class Resource; class Node; class ScheduleManager; class PLANUI_EXPORT WorkPackageSendPanel : public QWidget, public Ui_WorkPackageSendPanel { Q_OBJECT public: explicit WorkPackageSendPanel( const QList &tasks, ScheduleManager *sm, QWidget *parent=0 ); Q_SIGNALS: - void sendWorkpackages( const QList&, Resource* ); + void sendWorkpackages(const QList&, KPlato::Resource*); protected Q_SLOTS: void slotSendClicked(); protected: QMap > m_resMap; QMap m_pbMap; }; } //KPlato namespace #endif // KPTWORKPACKAGESENDPANEL_H diff --git a/src/plugins/schedulers/rcps/KPlatoRCPSPlugin.cpp b/src/plugins/schedulers/rcps/KPlatoRCPSPlugin.cpp index 2a9cefea..dec70831 100644 --- a/src/plugins/schedulers/rcps/KPlatoRCPSPlugin.cpp +++ b/src/plugins/schedulers/rcps/KPlatoRCPSPlugin.cpp @@ -1,166 +1,166 @@ /* This file is part of the KDE project * Copyright (C) 2009, 2012 Dag Andersen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KPlatoRCPSPlugin.h" #include "kptschedulerplugin_macros.h" #include "kptdebug.h" #include "KPlatoRCPSScheduler.h" #include "kptproject.h" #include "kptschedule.h" #include #include #include #include #ifndef PLAN_NOPLUGIN PLAN_SCHEDULERPLUGIN_EXPORT(KPlatoRCPSPlugin, "planrcpsscheduler.json") #endif using namespace KPlato; KPlatoRCPSPlugin::KPlatoRCPSPlugin( QObject * parent, const QVariantList & ) : KPlato::SchedulerPlugin(parent) { debugPlan<RCPS Scheduler" "The Resource Constrained Project Scheduler (RCPS) focuses on scheduling" " the project to avoid overbooking resources." " It still respects task dependencies and also tries to fulfill time constraints." " However, time constraints can make it very difficult to find a good solution," " so it may be preferable to use a different scheduler in these cases." ); } int KPlatoRCPSPlugin::capabilities() const { return SchedulerPlugin::AvoidOverbooking | SchedulerPlugin::ScheduleForward | SchedulerPlugin::ScheduleBackward; } ulong KPlatoRCPSPlugin::currentGranularity() const { ulong v = m_granularities.value( m_granularity ); return qMax( v, (ulong)60000 ); // minimum 1 min } void KPlatoRCPSPlugin::calculate( KPlato::Project &project, KPlato::ScheduleManager *sm, bool nothread ) { foreach ( SchedulerThread *j, m_jobs ) { if ( j->manager() == sm ) { return; } } sm->setScheduling( true ); KPlatoRCPSScheduler *job = new KPlatoRCPSScheduler( &project, sm, currentGranularity() ); m_jobs << job; connect(job, SIGNAL(jobFinished(SchedulerThread*)), SLOT(slotFinished(SchedulerThread*))); project.changed( sm ); -// connect(this, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*)), &project, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*))); -// connect(this, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*)), &project, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*))); +// connect(this, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*)), &project, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*))); +// connect(this, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*)), &project, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*))); connect(job, SIGNAL(maxProgressChanged(int)), sm, SLOT(setMaxProgress(int))); connect(job, SIGNAL(progressChanged(int)), sm, SLOT(setProgress(int))); if ( nothread ) { job->doRun(); } else { job->start(); } } void KPlatoRCPSPlugin::stopAllCalculations() { foreach ( SchedulerThread *s, m_jobs ) { stopCalculation( s ); } } void KPlatoRCPSPlugin::stopCalculation( SchedulerThread *sch ) { if ( sch ) { //FIXME: this should just call stopScheduling() and let the job finish "normally" disconnect( sch, SIGNAL(jobFinished(KPlatoRCPSScheduler*)), this, SLOT(slotFinished(KPlatoRCPSScheduler*)) ); sch->stopScheduling(); // wait max 20 seconds. sch->mainManager()->setCalculationResult( ScheduleManager::CalculationStopped ); if ( ! sch->wait( 20000 ) ) { sch->deleteLater(); m_jobs.removeAt( m_jobs.indexOf( sch ) ); } else { slotFinished( sch ); } } } void KPlatoRCPSPlugin::slotStarted( SchedulerThread */*job*/ ) { // debugPlan<<"KPlatoRCPSPlugin::slotStarted:"; } void KPlatoRCPSPlugin::slotFinished( SchedulerThread *j ) { KPlatoRCPSScheduler *job = static_cast( j ); Project *mp = job->mainProject(); ScheduleManager *sm = job->mainManager(); //debugPlan<<"KPlatoRCPSPlugin::slotFinished:"<isStopped(); if ( job->isStopped() ) { sm->setCalculationResult( ScheduleManager::CalculationCanceled ); } else { updateLog( job ); Project *tp = job->project(); ScheduleManager *tm = job->manager(); updateProject( tp, tm, mp, sm ); sm->setCalculationResult( ScheduleManager::CalculationDone ); } sm->setScheduling( false ); m_jobs.removeAt( m_jobs.indexOf( job ) ); if ( m_jobs.isEmpty() ) { m_synctimer.stop(); } emit sigCalculationFinished( mp, sm ); - disconnect(this, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*)), mp, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*))); - disconnect(this, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*)), mp, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*))); + disconnect(this, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*)), mp, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*))); + disconnect(this, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*)), mp, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*))); job->deleteLater(); } #include "KPlatoRCPSPlugin.moc" diff --git a/src/plugins/schedulers/rcps/KPlatoRCPSPlugin.h b/src/plugins/schedulers/rcps/KPlatoRCPSPlugin.h index 6b7919d5..be4b46c9 100644 --- a/src/plugins/schedulers/rcps/KPlatoRCPSPlugin.h +++ b/src/plugins/schedulers/rcps/KPlatoRCPSPlugin.h @@ -1,67 +1,67 @@ /* This file is part of the KDE project * Copyright (C) 2009 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 PLANRCPSPLUGIN_H #define PLANRCPSPLUGIN_H #include "kptschedulerplugin.h" #include namespace KPlato { class Project; class ScheduleManager; class Schedule; } using namespace KPlato; class KPlatoRCPSPlugin : public SchedulerPlugin { Q_OBJECT public: KPlatoRCPSPlugin( QObject * parent, const QVariantList & ); ~KPlatoRCPSPlugin(); virtual QString description() const; virtual int capabilities() const; /// Calculate the project virtual void calculate( Project &project, ScheduleManager *sm, bool nothread = false ); /// Return the scheduling granularity in milliseconds ulong currentGranularity() const; Q_SIGNALS: - void sigCalculationStarted(Project*, ScheduleManager*); - void sigCalculationFinished(Project*, ScheduleManager*); + void sigCalculationStarted(KPlato::Project*, KPlato::ScheduleManager*); + void sigCalculationFinished(KPlato::Project*, KPlato::ScheduleManager*); public Q_SLOTS: void stopAllCalculations(); - void stopCalculation( SchedulerThread *sch ); + void stopCalculation(KPlato::SchedulerThread *sch); protected Q_SLOTS: - void slotStarted( SchedulerThread *job ); - void slotFinished( SchedulerThread *job ); + void slotStarted(KPlato::SchedulerThread *job); + void slotFinished(KPlato::SchedulerThread *job); }; #endif // PLANRCPSPLUGIN_H diff --git a/src/plugins/schedulers/rcps/KPlatoRCPSScheduler.cpp b/src/plugins/schedulers/rcps/KPlatoRCPSScheduler.cpp index e3ae9733..d378091c 100644 --- a/src/plugins/schedulers/rcps/KPlatoRCPSScheduler.cpp +++ b/src/plugins/schedulers/rcps/KPlatoRCPSScheduler.cpp @@ -1,1376 +1,1376 @@ /* This file is part of the KDE project * Copyright (C) 2009, 2010, 2012 Dag Andersen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KPlatoRCPSScheduler.h" #include "kptproject.h" #include "kptschedule.h" #include "kptresource.h" #include "kpttask.h" #include "kptrelation.h" #include "kptdebug.h" #include #include #include #include #include #include #include #include #define GENERATION_MIN_LIMIT 5000 #define PROGRESS_CALLBACK_FREQUENCY 100 #define PROGRESS_MAX_VALUE 120000 #define PROGRESS_INIT_VALUE 12000 #define PROGRESS_INIT_STEP 2000 /* low weight == late, high weight == early */ #define WEIGHT_ASAP 50 #define WEIGHT_ALAP 1 #define WEIGHT_CONSTRAINT 1000 #define WEIGHT_FINISH 1000 #define GROUP_TARGETTIME 1 #define GROUP_CONSTRAINT 2 class ProgressInfo { public: explicit ProgressInfo() : init( true ), base( 0 ), progress( 0 ) { fitness.group = 0; fitness.weight = 0; } bool init; int base; int progress; struct rcps_fitness fitness; }; KPlatoRCPSScheduler::KPlatoRCPSScheduler( Project *project, ScheduleManager *sm, ulong granularity, QObject *parent ) : SchedulerThread( project, sm, parent ), result( -1 ), m_schedule( 0 ), m_recalculate( false ), m_usePert( false ), m_backward( false ), m_problem( 0 ), m_timeunit( granularity / 1000 ), m_offsetFromTime_t( 0 ), m_progressinfo( new ProgressInfo() ) { - connect(this, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*)), project, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*))); + connect(this, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*)), project, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*))); emit sigCalculationStarted( project, sm ); - connect( this, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*)), project, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*)) ); + connect( this, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*)), project, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*)) ); } KPlatoRCPSScheduler::~KPlatoRCPSScheduler() { delete m_progressinfo; qDeleteAll( m_duration_info_list ); qDeleteAll( m_weight_info_list ); rcps_problem_free( m_problem ); } int KPlatoRCPSScheduler::progress_callback( int generations, struct rcps_fitness fitness, void *arg ) { if ( arg == 0 ) { return -1; } KPlatoRCPSScheduler *self = static_cast( arg ); //debugPlan<<"KPlatoRCPSScheduler::progress_callback"<progress( generations, fitness ); } int KPlatoRCPSScheduler::progress( int generations, struct rcps_fitness fitness ) { if ( m_haltScheduling ) { debugPlan<<"KPlatoRCPSScheduler::progress:"<<"halt"; return -1; } if ( m_stopScheduling ) { m_schedule->logWarning( i18n( "Scheduling halted after %1 generations", generations ), 1 ); debugPlan<<"KPlatoRCPSScheduler::progress:"<<"stop"; return -1; } // std::cout << "Progress after: " << generations << " generations\n"; if ( m_progressinfo->init ) { if ( generations == 0 ) { m_progressinfo->progress += PROGRESS_INIT_STEP; } else { m_progressinfo->progress = PROGRESS_INIT_VALUE; m_progressinfo->init = false; // std::cout << "Population generated: "<< generations << "\n"; } } else { m_progressinfo->progress = PROGRESS_INIT_VALUE + generations; } // detect change in fitness if ( rcps_fitness_cmp( &m_progressinfo->fitness, &fitness ) != 0 ) { // std::cout << "Fitness changed in generation: " << generations << " group=["<fitness.group<<"->"<fitness.weight<<"->"<fitness = fitness; m_progressinfo->base = generations; } m_manager->setProgress( m_progressinfo->progress ); setProgress( m_progressinfo->progress ); // stop if fitness does not change in GENERATION_MIN_LIMIT generations /* int result = ( generations >= m_progressinfo->base + GENERATION_MIN_LIMIT ? 1 : 0 ); if ( result ) { //debugPlan<<"KPlatoRCPSScheduler::progress, stop after"<progress; m_schedule->logDebug( QString( "Acceptable solution found after %1 generations" ).arg( generations ), 1 ); std::cout << "Acceptable solution found after " << generations << " generations\n"; }*/ return 0; } int KPlatoRCPSScheduler::duration_callback( int direction, int time, int nominal_duration, void *arg ) { //debugPlan<<"plan_duration:"<( arg ); return info->self->duration( direction, time, nominal_duration, info ); } int KPlatoRCPSScheduler::duration( int direction, int time, int nominal_duration, KPlatoRCPSScheduler::duration_info *info ) { if ( m_haltScheduling || m_manager == 0 ) { return nominal_duration; } ++(info->calls); if ( info->cache.contains( QPair( time, direction ) ) ) { return info->cache[ QPair( time, direction ) ]; } if ( m_manager->recalculate() && info->task->completion().isFinished() ) { return 0; } int dur = 0; if ( info->task->constraint() == Node::FixedInterval ) { // duration may depend on daylight saving so we need to calculate // NOTE: dur may not be correct if time != info->task->constraintStartTime, let's see what happens... dur = ( info->task->constraintEndTime() - info->task->constraintStartTime() ).seconds() / m_timeunit; info->task->schedule()->logDebug( QString( "Fixed interval: Time=%1, duration=%2 ( %3, %4 )" ).arg( time ).arg( dur ).arg( fromRcpsTime( time ).toString() ).arg( Duration( (qint64)(dur) * m_timeunit * 1000 ).toDouble( Duration::Unit_h ) ) ); } else if ( info->estimatetype == Estimate::Type_Effort ) { if ( info->requests.isEmpty() ) { dur = info->estimate.seconds() / m_timeunit; } else { dur = info->task->requests().duration( info->requests, fromRcpsTime( time ), info->estimate, 0, /*no schedule*/ m_backward ? ! direction : direction ).seconds() / m_timeunit; //debugPlan<task->name()<< QString( "duration_callback effort: backward=%5, direction=%6 (direction=%7); Time=%1, duration=%2 ( %3, %4 )" ).arg( time ).arg( dur ).arg( fromRcpsTime( time ).toString() ).arg( Duration( (qint64)(dur) * m_timeunit * 1000 ).toDouble( Duration::Unit_h ) ).arg( m_backward ).arg( direction ).arg( m_backward ? !direction : direction ); } } else { dur = info->task->length( fromRcpsTime( time ), info->estimate, 0, /*no schedule*/ m_backward ? ! direction : direction ).seconds() / m_timeunit; } info->cache[ QPair( time, direction ) ] = dur; info->task->schedule()->logDebug( QString( "duration_callback: Time=%1, duration=%2 ( %3, %4 )" ).arg( time ).arg( dur ).arg( fromRcpsTime( time ).toString() ).arg( Duration( (qint64)(dur) * m_timeunit * 1000 ).toDouble( Duration::Unit_h ) ) ); return dur; } int KPlatoRCPSScheduler::weight_callback( int time, int duration, struct rcps_fitness *nominal_weight, void* weight_arg, void* fitness_arg ) { //debugPlan<<"plan_weight:"<weight *= time; return 0; } KPlatoRCPSScheduler::weight_info *winfo = static_cast( weight_arg ); KPlatoRCPSScheduler::fitness_info *finfo = static_cast( fitness_arg ); return winfo->self->weight( time, duration, nominal_weight, winfo, finfo ); } void *KPlatoRCPSScheduler::fitness_callback_init( void *arg ) { Q_ASSERT( arg ); KPlatoRCPSScheduler::fitness_info *info = static_cast( arg ); Q_ASSERT( info ); fitness_info *finfo = new fitness_info; finfo->self = info->self; // debugPlan<self; return finfo; } int KPlatoRCPSScheduler::fitness_callback_result( struct rcps_fitness *fit, void *arg ) { KPlatoRCPSScheduler::fitness_info *info = static_cast( arg ); info->self->fitness( fit, info ); delete info; return 0; } int KPlatoRCPSScheduler::fitness( struct rcps_fitness *fit, KPlatoRCPSScheduler::fitness_info *info ) { /* std::cout << ">-------------------------------------------\n"; std::cout << "Sequence: "; foreach ( Task *t, info->jobs ) { std::cout << (t ? t->name().toLocal8Bit().data() : "End") << ", "; } std::cout << "\n"; debugPlan<map;*/ QMultiMap >::const_iterator it = info->map.constFind( GROUP_CONSTRAINT ); if ( it != info->map.constEnd() ) { // constraint fit->group = GROUP_CONSTRAINT; for ( ; it.key() == GROUP_CONSTRAINT && it != info->map.constEnd(); ++it ) { fit->weight += it.value().first; QString s = it.value().second ? it.value().second->name() : "End node"; // std::cout << s.toLocal8Bit().data() << ": group=" << it.key() << " weight=" << it.value().first << "\n"; // m_schedule->logDebug( QString( "%3: %1 %2" ).arg( it.key() ).arg( it.value().first ).arg( it.value().second->name() ) ); } // std::cout << "Result: group= " << fit->group << " weight=" << fit->weight << "\n--------------------------\n"; return 0; } it = info->map.constFind( GROUP_TARGETTIME ); if ( it != info->map.constEnd() ) { // missed target time fit->group = GROUP_TARGETTIME; for ( ; it.key() == GROUP_TARGETTIME && it != info->map.constEnd(); ++it ) { fit->weight += it.value().first; QString s = it.value().second ? it.value().second->name() : "End node"; // std::cout << s.toLocal8Bit().data() << ": group=" << it.key() << " weight=" << it.value().first << "\n"; // m_schedule->logDebug( QString( "%3: %1 %2" ).arg( it.key() ).arg( it.value().first ).arg( it.value().second->name() ) ); } // std::cout << "Result: group= " << fit->group << " weight=" << fit->weight << "\n--------------------------\n"; return 0; } fit->group = 0; for ( it = info->map.constBegin(); it != info->map.constEnd(); ++it ) { fit->weight += it.value().first; QString s = it.value().second ? it.value().second->name() : "End node"; // std::cout << s.toLocal8Bit().data() << ": group=" << it.key() << " weight=" << it.value().first << "\n"; // m_schedule->logDebug( QString( "%3: %1 %2" ).arg( it.key() ).arg( it.value().first ).arg( it.value().second->name() ) ); } // std::cout << "Result: group= " << fit->group << " weight=" << fit->weight << "\n--------------------------\n"; return 0; } int KPlatoRCPSScheduler::weight( int time, int duration, struct rcps_fitness *nominal_weight, KPlatoRCPSScheduler::weight_info* info, KPlatoRCPSScheduler::fitness_info* finfo ) { if ( m_haltScheduling || m_manager == 0 ) { return 0; } if ( m_manager->recalculate() && info->task->completion().isFinished() ) { return 0; } struct rcps_fitness &f = *nominal_weight; f.group = 0; f.weight = time; if ( info->isEndJob ) { if ( info->finish == 0 ) { info->finish = time; /* const char *s = QString( "First : %1 %2 %3 End job" ).arg( time, 10 ).arg( duration, 10 ).arg( w, 10 ).toLatin1(); std::cout<finish / ( time > 0 ? time : 1 ); if ( time > info->targettime ) { w = w + ( WEIGHT_CONSTRAINT * ( time - info->targettime ) ); }*/ if ( time > info->targettime ) { f.group = GROUP_TARGETTIME; f.weight = time - info->targettime; } /* const char *s = QString( "End job: %1 %2 %3 End job target: %4" ).arg( time, 10 ).arg( duration, 10 ).arg( w, 10 ).arg( info->targettime ).toLatin1(); std::cout<task->constraint() ) { case Node::FinishNotLater: if ( info->targettime > time ) { f.group = GROUP_CONSTRAINT; f.weight = WEIGHT_CONSTRAINT * ( info->targettime - time ); } break; case Node::MustFinishOn: if ( info->targettime != time ) { f.group = GROUP_CONSTRAINT; f.weight = WEIGHT_CONSTRAINT * abs( info->targettime - time ); } break; case Node::StartNotEarlier: if ( info->targettime < time ) { f.group = GROUP_CONSTRAINT; f.weight = WEIGHT_CONSTRAINT * ( time - info->targettime ); } break; case Node::MustStartOn: case Node::FixedInterval: if ( info->targettime != time ) { f.group = GROUP_CONSTRAINT; f.weight = WEIGHT_CONSTRAINT * abs( info->targettime - time ); } break; default: break; } /* const char *s = QString( "Backward: %1 %2 %3 %4 (target: %5)" ).arg( time, 10 ).arg( duration, 10 ).arg( w, 10 ).arg( info->task->name() ).arg( info->targettime ).toLatin1(); std::cout<task->constraint() ) { case Node::StartNotEarlier: if ( time < info->targettime ) { f.group = GROUP_CONSTRAINT; f.weight = WEIGHT_CONSTRAINT * ( info->targettime - time ); } break; case Node::MustStartOn: case Node::FixedInterval: if ( info->targettime != time ) { f.group = GROUP_CONSTRAINT; f.weight = WEIGHT_CONSTRAINT * ( abs( info->targettime - time ) ); } break; case Node::FinishNotLater: // std::cout << "FNL " << info->task->name().toLocal8Bit().data() << ": end="< info->targettime ) { f.group = GROUP_CONSTRAINT; f.weight = WEIGHT_CONSTRAINT * ( time - info->targettime ); } // std::cout << info->task->name().toLocal8Bit().data() << ": group=" << f.group << " weight=" << f.weight << "\n"; break; case Node::MustFinishOn: // std::cout << "MSO " << info->task->name().toLocal8Bit().data() << ": end="<targettime != time + duration ) { f.group = GROUP_CONSTRAINT; f.weight = WEIGHT_CONSTRAINT * abs( info->targettime - time ); } // std::cout << info->task->name().toLocal8Bit().data() << ": group=" << f.group << " weight=" << f.weight << "\n"; break; default: break; } /* const char *s = QString( "Forward: %1 %2 %3 %4 (target: %5)" ).arg( time, 10 ).arg( duration, 10 ).arg( w, 10 ).arg( info->task->name() ).arg( info->targettime ).toLatin1(); std::cout<task ? info->task->name() : "End node"; if ( finfo ) { finfo->map.insert( f.group, QPair( f.weight, info->task ) ); finfo->jobs << info->task; // debugPlan<map; }// else debugPlan< m_projectMutex.lock(); m_managerMutex.lock(); m_project = new Project(); loadProject( m_project, m_pdoc ); m_project->setName( "Schedule: " + m_project->name() ); //Debug m_project->stopcalculation = false; m_manager = m_project->scheduleManager( m_mainmanagerId ); Q_CHECK_PTR( m_manager ); Q_ASSERT( m_manager->expected() ); Q_ASSERT( m_manager != m_mainmanager ); Q_ASSERT( m_manager->scheduleId() == m_mainmanager->scheduleId() ); Q_ASSERT( m_manager->expected() != m_mainmanager->expected() ); m_manager->setName( "Schedule: " + m_manager->name() ); //Debug m_schedule = m_manager->expected(); connect(m_manager, SIGNAL(sigLogAdded(Schedule::Log)), this, SLOT(slotAddLog(Schedule::Log))); m_project->initiateCalculation( *m_schedule ); m_project->initiateCalculationLists( *m_schedule ); m_problem = rcps_problem_new(); rcps_problem_setfitness_mode( m_problem, FITNESS_WEIGHT ); m_usePert = m_manager->usePert(); m_recalculate = m_manager->recalculate(); if ( m_recalculate ) { m_starttime = m_manager->recalculateFrom(); m_backward = false; } else { m_backward = m_manager->schedulingDirection(); m_starttime = m_backward ? m_project->constraintEndTime() : m_project->constraintStartTime(); } m_targettime = m_backward ? m_project->constraintStartTime() : m_project->constraintEndTime(); m_project->setCurrentSchedule( m_manager->expected()->id() ); m_schedule->setPhaseName( 0, i18n( "Init" ) ); QLocale locale; if ( ! m_backward ) { m_schedule->logDebug( QString( "Schedule project using RCPS Scheduler, starting at %1, granularity %2 sec" ).arg( locale.toString(QDateTime::currentDateTime(), QLocale::ShortFormat) ).arg( m_timeunit ), 0 ); if ( m_recalculate ) { m_schedule->logInfo( i18n( "Re-calculate project from start time: %1", locale.toString(m_starttime, QLocale::ShortFormat) ), 0 ); } else { m_schedule->logInfo( i18n( "Schedule project from start time: %1", locale.toString(m_starttime, QLocale::ShortFormat) ), 0 ); } } else { m_schedule->logDebug( QString( "Schedule project backward using RCPS Scheduler, starting at %1, granularity %2 sec" ).arg( locale.toString( QDateTime::currentDateTime(), QLocale::ShortFormat) ).arg( m_timeunit ), 0 ); m_schedule->logInfo( i18n( "Schedule project from end time: %1", locale.toString(m_starttime, QLocale::ShortFormat) ), 0 ); } m_managerMutex.unlock(); m_projectMutex.unlock(); } // <--- mutex m_progressinfo->progress += PROGRESS_INIT_STEP / 5; setProgress( m_progressinfo->progress ); result = kplatoToRCPS(); if ( result != 0 ) { m_schedule->logError( i18n( "Failed to build a valid RCPS project" ) ); setProgress( PROGRESS_MAX_VALUE ); return; } m_schedule->setPhaseName( 1, i18n( "Schedule" ) ); setMaxProgress( PROGRESS_MAX_VALUE ); solve(); if ( m_haltScheduling ) { deleteLater(); return; } if ( result != 0 ) { m_schedule->logError( i18n( "Invalid scheduling solution. Result: %1", result ), 1 ); } kplatoFromRCPS(); setProgress( PROGRESS_MAX_VALUE ); } int KPlatoRCPSScheduler::check() { return rcps_check( m_problem ); } void KPlatoRCPSScheduler::solve() { debugPlan<<"KPlatoRCPSScheduler::solve()"; struct rcps_solver *s = rcps_solver_new(); rcps_solver_set_progress_callback(s, PROGRESS_CALLBACK_FREQUENCY, this, &KPlatoRCPSScheduler::progress_callback); rcps_solver_set_duration_callback(s, &KPlatoRCPSScheduler::duration_callback ); rcps_problem_set_weight_callback( m_problem, &KPlatoRCPSScheduler::weight_callback ); fitness_init_arg.self = this; rcps_problem_set_fitness_callback( m_problem, &KPlatoRCPSScheduler::fitness_callback_init, &fitness_init_arg, &KPlatoRCPSScheduler::fitness_callback_result ); Q_ASSERT( check() == 0 ); rcps_solver_setparam( s, SOLVER_PARAM_POPSIZE, 1000 ); rcps_solver_solve( s, m_problem ); result = rcps_solver_getwarnings( s ); rcps_solver_free( s ); } int KPlatoRCPSScheduler::kplatoToRCPS() { addResources(); addTasks(); addDependencies(); addRequests(); setWeights(); setConstraints(); int r = check(); return r; } void KPlatoRCPSScheduler::taskFromRCPSForward( struct rcps_job *job, Task *task, QMap > &resourcemap ) { if ( m_haltScheduling || m_manager == 0 ) { return; } QLocale locale; Schedule *cs = task->currentSchedule(); Q_ASSERT( cs ); struct rcps_mode *mode = rcps_mode_get(job, rcps_job_getmode_res(job)); /* get the duration of this mode */ KPlatoRCPSScheduler::duration_info *info = static_cast( rcps_mode_get_cbarg(mode) ); qint64 dur = 0; qint64 st = rcps_job_getstart_res(job); if ( info == 0 ) { dur = rcps_mode_getduration(mode); } else { cs->logDebug( QString( "Task '%1' estimate: %2" ).arg( task->name() ).arg( task->estimate()->value( Estimate::Use_Expected, false ).toString() ), 1 ); cs->logDebug( QString( "Task '%1' duration called %2 times, cached values: %3" ).arg( rcps_job_getname(job) ).arg( info->calls ).arg( info->cache.count() ) ); dur = duration_callback( 0, st, rcps_mode_getduration(mode), info ); for ( QMap, int>::ConstIterator it = info->cache.constBegin(); it != info->cache.constEnd(); ++it ) { cs->logDebug( QString( "Task '%1' start: %2, duration: %3 (%4, %5 hours)" ).arg( rcps_job_getname(job) ).arg( it.key().first ).arg( it.value() ).arg( fromRcpsTime( it.key().first ).toString() ).arg( (double)(it.value())/60.0 ), 1 ); } } DateTime start = m_starttime.addSecs(st * m_timeunit); DateTime end = start + Duration( dur * m_timeunit * 1000 ); cs->logDebug( QString( "Task '%1' start=%2, duration=%3: %4 - %5" ).arg( rcps_job_getname(job) ).arg( st ).arg( dur ).arg( locale.toString(start, QLocale::ShortFormat) ).arg( locale.toString(end, QLocale::ShortFormat ) ), 1 ); task->setStartTime( start ); task->setEndTime( end ); for ( int reqs = 0; reqs < rcps_request_count(mode); ++reqs ) { struct rcps_request *req = rcps_request_get(mode, reqs); struct rcps_alternative *alt = rcps_alternative_get(req, rcps_request_getalternative_res(req)); int amount = rcps_alternative_getamount(alt); struct rcps_resource *res = rcps_alternative_getresource(alt); cs->logDebug( QString( "Job %1: resource %2 is %3 available" ).arg( rcps_job_getname(job) ).arg( rcps_resource_getname(res) ).arg( amount ), 1 ); // do actual appointments etc ResourceRequest *r = m_requestmap.value( req ); if ( r == 0 ) { cs->logWarning( i18n( "No resource request is registered" ), 1 ); continue; } resourcemap[ task ] << r; cs->logDebug( QString( "Make appointments to resource %1" ).arg( r->resource()->name() ), 1 ); r->makeAppointment( cs, amount ); } if ( m_recalculate ) { if ( task->completion().isFinished() ) { task->copySchedule(); if ( m_manager ) { cs->logDebug( QString( "Task is completed, copied schedule: %2 to %3" ).arg( task->name() ).arg( locale.toString(task->startTime(), QLocale::ShortFormat) ).arg( locale.toString(task->endTime(), QLocale::ShortFormat) ), 1 ); } } else if ( task->completion().isStarted() ) { task->copyAppointments( DateTime(), start ); if ( m_manager ) { cs->logDebug( QString( "Task is %4% completed, copied appointments from %2 to %3" ).arg( task->name() ).arg( locale.toString(task->startTime(), QLocale::ShortFormat) ).arg( locale.toString(start, QLocale::ShortFormat) ).arg( task->completion().percentFinished() ), 1 ); } } } cs->setScheduled( true ); if ( task->estimate()->type() == Estimate::Type_Effort ) { if ( task->appointmentStartTime().isValid() ) { task->setStartTime( task->appointmentStartTime() ); } if ( task->appointmentEndTime().isValid() ) { task->setEndTime( task->appointmentEndTime() ); } if ( info && info->requests.isEmpty() ) { cs->setResourceError( true ); cs->logError( i18n( "No resource has been allocated" ), 1 ); } } else if ( task->estimate()->calendar() ) { DateTime t = task->estimate()->calendar()->firstAvailableAfter( task->startTime(), task->endTime() ); if ( t.isValid() ) { task->setStartTime( t ); } t = task->estimate()->calendar()->firstAvailableBefore( task->endTime(), task->startTime() ); if ( t.isValid() ) { task->setEndTime( t ); } } //else Fixed duration task->setDuration( task->endTime() - task->startTime() ); cs->logInfo( i18n( "Scheduled task to start at %1 and finish at %2", locale.toString(task->startTime(), QLocale::ShortFormat), locale.toString(task->endTime(), QLocale::ShortFormat ) ), 1 ); } void KPlatoRCPSScheduler::kplatoFromRCPS() { if ( m_backward ) { kplatoFromRCPSBackward(); } else { kplatoFromRCPSForward(); } } void KPlatoRCPSScheduler::kplatoFromRCPSForward() { //debugPlan<<"KPlatoRCPSScheduler::kplatoFromRCPSForward:"; MainSchedule *cs = static_cast( m_project->currentSchedule() ); QMap > resourcemap; int count = rcps_job_count(m_problem); int step = ( PROGRESS_MAX_VALUE - m_progressinfo->progress ) / count; DateTime projectstart = m_starttime.addSecs( rcps_job_getstart_res(m_jobstart) * m_timeunit ); for ( int i = 0; i < count; ++i ) { m_progressinfo->progress += step; m_manager->setProgress( m_progressinfo->progress ); setProgress( m_progressinfo->progress ); struct rcps_job *job = rcps_job_get( m_problem, i ); Task *task = m_taskmap.value( job ); if ( task == 0 ) { continue; //might be dummy task for lag, ... } taskFromRCPSForward( job, task, resourcemap ); if ( projectstart > task->startTime() ) { projectstart = task->startTime(); } } qint64 st = rcps_job_getstart_res(m_jobstart) * m_timeunit; DateTime start = m_starttime.addSecs( st ); qint64 et = rcps_job_getstart_res(m_jobend) * m_timeunit; DateTime end = m_starttime.addSecs( et ); m_project->setStartTime( projectstart ); m_project->setEndTime( end ); adjustSummaryTasks( m_schedule->summaryTasks() ); calculatePertValues( resourcemap ); QLocale locale; cs->logInfo( i18n( "Project scheduled to start at %1 and finish at %2", locale.toString(projectstart, QLocale::ShortFormat), locale.toString(end, QLocale::ShortFormat) ), 1 ); if ( m_manager ) { cs->logDebug( QString( "Project scheduling finished at %1" ).arg( QDateTime::currentDateTime().toString() ), 1 ); m_project->finishCalculation( *m_manager ); m_manager->scheduleChanged( cs ); } } void KPlatoRCPSScheduler::taskFromRCPSBackward( struct rcps_job *job, Task *task, QMap > &resourcemap ) { if ( m_haltScheduling || m_manager == 0 ) { return; } QLocale locale; Schedule *cs = task->currentSchedule(); Q_ASSERT( cs ); struct rcps_mode *mode = rcps_mode_get( job, rcps_job_getmode_res( job ) ); /* get the duration of this mode */ KPlatoRCPSScheduler::duration_info *info = static_cast( rcps_mode_get_cbarg( mode ) ); qint64 dur = 0; qint64 st = rcps_job_getstart_res( job ); if ( info == 0 ) { dur = rcps_mode_getduration( mode ); } else { cs->logDebug( QString( "Task '%1' estimate: %2" ).arg( task->name() ).arg( task->estimate()->value( Estimate::Use_Expected, false ).toString() ), 1 ); cs->logDebug( QString( "Task '%1' duration called %2 times, cached values: %3" ).arg( rcps_job_getname( job ) ).arg( info->calls ).arg( info->cache.count() ) ); dur = duration_callback( 0, st, rcps_mode_getduration( mode ), info ); for ( QMap, int>::ConstIterator it = info->cache.constBegin(); it != info->cache.constEnd(); ++it ) { cs->logDebug( QString( "Task '%1' start: %2, duration: %3 (%4, %5 hours)" ).arg( rcps_job_getname(job) ).arg( it.key().first ).arg( it.value() ).arg( fromRcpsTime( it.key().first ).toString() ).arg( (double)(it.value())/60.0 ), 1 ); } } DateTime end = fromRcpsTime( st ); DateTime start = fromRcpsTime( st + dur ); cs->logDebug( QString( "Task '%1' start=%2, duration=%3: %4 - %5" ).arg( rcps_job_getname(job) ).arg( st ).arg( dur ).arg( locale.toString(start, QLocale::ShortFormat) ).arg( locale.toString(end, QLocale::ShortFormat) ), 1 ); task->setStartTime( start ); task->setEndTime( end ); for ( int reqs = 0; reqs < rcps_request_count( mode ); ++reqs ) { struct rcps_request *req = rcps_request_get( mode, reqs ); struct rcps_alternative *alt = rcps_alternative_get( req, rcps_request_getalternative_res( req ) ); int amount = rcps_alternative_getamount( alt ); struct rcps_resource *res = rcps_alternative_getresource( alt ); cs->logDebug( QString( "Job %1: resource %2 is %3 available" ).arg( rcps_job_getname( job ) ).arg( rcps_resource_getname( res ) ).arg( amount ), 1 ); // do actual appointments etc ResourceRequest *r = m_requestmap.value( req ); if ( r == 0 ) { cs->logWarning( i18n( "No resource request is registered" ), 1 ); continue; } resourcemap[ task ] << r; cs->logDebug( QString( "Make appointments to resource %1" ).arg( r->resource()->name() ), 1 ); r->makeAppointment( cs, amount ); } if ( m_recalculate ) { if ( task->completion().isFinished() ) { task->copySchedule(); if ( m_manager ) { cs->logDebug( QString( "Task is completed, copied schedule: %2 to %3" ).arg( task->name() ).arg( locale.toString(task->startTime(), QLocale::ShortFormat) ).arg( locale.toString(task->endTime(), QLocale::ShortFormat) ), 1 ); } } else if ( task->completion().isStarted() ) { task->copyAppointments( DateTime(), start ); if ( m_manager ) { cs->logDebug( QString( "Task is %4% completed, copied appointments from %2 to %3" ).arg( task->name() ).arg( locale.toString(task->startTime(), QLocale::ShortFormat) ).arg( locale.toString(start, QLocale::ShortFormat) ).arg( task->completion().percentFinished() ), 1 ); } } } cs->setScheduled( true ); if ( task->estimate()->type() == Estimate::Type_Effort ) { if ( task->appointmentStartTime().isValid() ) { task->setStartTime( task->appointmentStartTime() ); } if ( task->appointmentEndTime().isValid() ) { task->setEndTime( task->appointmentEndTime() ); } if ( info && info->requests.isEmpty() ) { cs->setResourceError( true ); cs->logError( i18n( "No resource has been allocated" ), 1 ); } } else if ( task->estimate()->calendar() ) { DateTime t = task->estimate()->calendar()->firstAvailableAfter( task->startTime(), task->endTime() ); if ( t.isValid() ) { task->setStartTime( t ); } t = task->estimate()->calendar()->firstAvailableBefore( task->endTime(), task->startTime() ); if ( t.isValid() ) { task->setEndTime( t ); } } //else Fixed duration task->setDuration( task->endTime() - task->startTime() ); cs->logInfo( i18n( "Scheduled task to start at %1 and finish at %2", locale.toString(task->startTime(), QLocale::ShortFormat), locale.toString(task->endTime(), QLocale::ShortFormat) ), 1 ); } void KPlatoRCPSScheduler::kplatoFromRCPSBackward() { QLocale locale; //debugPlan<<"KPlatoRCPSScheduler::kplatoFromRCPSBackward:"; MainSchedule *cs = static_cast( m_project->currentSchedule() ); QMap > resourcemap; int count = rcps_job_count( m_problem ); int step = ( PROGRESS_MAX_VALUE - m_progressinfo->progress ) / count; DateTime projectstart = fromRcpsTime( rcps_job_getstart_res( m_jobend ) ); for ( int i = 0; i < count; ++i ) { m_progressinfo->progress += step; m_manager->setProgress( m_progressinfo->progress ); setProgress( m_progressinfo->progress ); struct rcps_job *job = rcps_job_get( m_problem, i ); Task *task = m_taskmap.value( job ); if ( task == 0 ) { continue; //might be dummy task for lag, ... } taskFromRCPSBackward( job, task, resourcemap ); if ( projectstart > task->startTime() ) { projectstart = task->startTime(); } } DateTime end = fromRcpsTime( rcps_job_getstart_res( m_jobstart ) ); m_project->setStartTime( projectstart ); m_project->setEndTime( end ); cs->logInfo( i18n( "Project scheduled to start at %1 and finish at %2", locale.toString(projectstart, QLocale::ShortFormat), locale.toString(end, QLocale::ShortFormat) ), 1 ); if ( projectstart < m_project->constraintStartTime() ) { cs->setConstraintError( true ); cs->logError( i18n( "Must start project early in order to finish in time: %1", locale.toString(m_project->constraintStartTime(), QLocale::ShortFormat) ), 1 ); } adjustSummaryTasks( m_schedule->summaryTasks() ); calculatePertValues( resourcemap ); if ( m_manager ) { cs->logDebug( QString( "Project scheduling finished at %1" ).arg( QDateTime::currentDateTime().toString() ), 1 ); m_project->finishCalculation( *m_manager ); m_manager->scheduleChanged( cs ); } } void KPlatoRCPSScheduler::adjustSummaryTasks( const QList &nodes ) { foreach ( Node *n, nodes ) { adjustSummaryTasks( n->childNodeIterator() ); if ( n->parentNode()->type() == Node::Type_Summarytask ) { DateTime pt = n->parentNode()->startTime(); DateTime nt = n->startTime(); if ( ! pt.isValid() || pt > nt ) { n->parentNode()->setStartTime( nt ); } pt = n->parentNode()->endTime(); nt = n->endTime(); if ( ! pt.isValid() || pt < nt ) { n->parentNode()->setEndTime( nt ); } } } } void KPlatoRCPSScheduler::calculatePertValues( const QMap > &map ) { if ( m_manager ) { m_schedule->setPhaseName( 2, i18nc( "Project Evaluation and Review Technique", "PERT" ) ); } foreach ( Node *n, m_project->allNodes() ) { if ( n->type() != Node::Type_Task && n->type() != Node::Type_Milestone ) { continue; } Task *t = static_cast( n ); if ( n->isStartNode() ) { (void)calculateLateStuff( map, static_cast( n ) ); } if ( n->isEndNode() ) { (void)calculateEarlyStuff( map, static_cast( n ) ); } switch ( n->constraint() ) { case Node::StartNotEarlier: n->schedule()->setNegativeFloat( n->startTime() < n->constraintStartTime() ? n->startTime() - n->constraintStartTime() : Duration::zeroDuration ); break; case Node::MustStartOn: case Node::FixedInterval: n->schedule()->setNegativeFloat( n->startTime() > n->constraintStartTime() ? n->startTime() - n->constraintStartTime() : n->constraintStartTime() - n->startTime() ); break; case Node::FinishNotLater: n->schedule()->setNegativeFloat( n->endTime() > n->constraintEndTime() ? n->endTime() - n->constraintEndTime() : Duration::zeroDuration ); break; case Node::MustFinishOn: n->schedule()->setNegativeFloat( n->endTime() > n->constraintEndTime() ? n->endTime() - n->constraintEndTime() : n->constraintEndTime() - n->endTime() ); break; default: break; } if ( t->negativeFloat() != 0 ) { n->schedule()->setConstraintError( true ); n->schedule()->logError( i18nc( "1=type of constraint", "%1: Failed to meet constraint. Negative float=%2", n->constraintToString( true ), KFormat().formatDuration( t->negativeFloat().milliseconds() ) ) ); } } } Duration KPlatoRCPSScheduler::calculateLateStuff( const QMap > &map, Task *task ) { Schedule *cs = task->currentSchedule(); Duration pf = m_project->endTime() - m_project->startTime(); QList lst = task->dependChildNodes() + task->childProxyRelations(); if ( lst.isEmpty() ) { // end node DateTime end = task->endTime(); if ( task->estimate()->type() == Estimate::Type_Effort ) { foreach ( ResourceRequest *r, map.value( static_cast( task ) ) ) { DateTime x = r->resource()->availableBefore( m_project->endTime(), task->endTime(), 0 ); cs->logDebug( QString( "Resource '%1' available before %2: %3" ).arg( r->resource()->name() ).arg( m_project->endTime().toString() ).arg( x.toString() ), 2 ); if ( x.isValid() && x > end ) { end = x; } } } else if ( task->estimate()->calendar() ) { end = task->estimate()->calendar()->firstAvailableBefore( m_project->endTime(), task->endTime() ); cs->logDebug( QString( "Calendar work time before %1: %2" ).arg( m_project->endTime().toString() ).arg( end.toString() ), 2 ); } // TODO must calculate backwards to get late *start* of task pf = end.isValid() ? end - task->endTime() : m_project->endTime() - task->endTime(); task->setFreeFloat( pf ); } else { Duration prev = pf; Duration x = pf; foreach ( Relation *r, lst ) { prev = qMin( prev, calculateLateStuff( map, static_cast( r->child() ) ) ); DateTime end = task->endTime(); if ( task->estimate()->type() == Estimate::Type_Effort ) { foreach ( ResourceRequest *req, map.value( static_cast( task ) ) ) { DateTime y = req->resource()->availableBefore( r->child()->startTime(), task->endTime(), 0 ); cs->logDebug( QString( "Resource '%1' available before %2: %3" ).arg( req->resource()->name() ).arg( r->child()->startTime().toString() ).arg( y.toString() ), 2 ); if ( y.isValid() && y > end ) { end = y; } } } else if ( task->estimate()->calendar() ) { end = task->estimate()->calendar()->firstAvailableBefore( r->child()->startTime(), task->endTime() ); cs->logDebug( QString( "Calendar work time before %1: %2" ).arg( r->child()->startTime().toString() ).arg( end.toString() ), 2 ); } x = qMin( x, end.isValid() ? end - task->endTime() : r->child()->startTime() - task->endTime() ); } task->setFreeFloat( x ); // TODO must calculate backwards to get late *start* of task pf = prev + x; } task->setPositiveFloat( pf ); task->setLateFinish( task->endTime() + pf ); task->setLateStart( task->lateFinish() - ( task->endTime() - task->startTime() ) ); QLocale locale; cs->logDebug( QString( "Late start %1, late finish %2, positive float %3" ).arg( locale.toString(task->lateStart(), QLocale::ShortFormat ) ).arg( locale.toString(task->lateFinish(), QLocale::ShortFormat) ).arg( pf.toString() ), 2 ); return pf; } Duration KPlatoRCPSScheduler::calculateEarlyStuff( const QMap > &map, Task *task ) { Schedule *cs = task->currentSchedule(); Duration tot = m_project->endTime() - m_project->startTime(); QList lst = task->dependParentNodes() + task->parentProxyRelations(); if ( lst.isEmpty() ) { // start node DateTime earlystart = task->startTime(); if ( task->estimate()->type() == Estimate::Type_Effort ) { foreach ( ResourceRequest *r, map.value( static_cast( task ) ) ) { DateTime x = r->resource()->availableAfter( m_project->startTime(), task->startTime(), 0 ); cs->logDebug( QString( "Resource '%1' available after %2 (%4): %3" ).arg( r->resource()->name() ).arg( m_project->startTime().toString() ).arg( x.toString() ).arg( task->startTime().toString() ), 2 ); if ( x.isValid() && x < earlystart ) { earlystart = x; } } } else if ( task->estimate()->calendar() ) { earlystart = task->estimate()->calendar()->firstAvailableAfter( m_project->startTime(), task->startTime() ); cs->logDebug( QString( "Calendar work time after %1: %2" ).arg( m_project->startTime().toString() ).arg( earlystart.toString() ), 2 ); } // TODO must calculate forward to get early *????* of task tot = earlystart.isValid() ? task->startTime() - earlystart : task->startTime() - m_project->startTime(); } else { Duration prev = tot; Duration x = tot; foreach ( Relation *r, lst ) { prev = qMin( prev, calculateEarlyStuff( map, static_cast( r->parent() ) ) ); DateTime earlystart = task->startTime(); if ( task->estimate()->type() == Estimate::Type_Effort ) { foreach ( ResourceRequest *req, map.value( static_cast( task ) ) ) { DateTime y = req->resource()->availableAfter( r->parent()->endTime(), task->startTime(), 0 ); cs->logDebug( QString( "Resource '%1' available after %2: %3" ).arg( req->resource()->name() ).arg( r->parent()->endTime().toString() ).arg( y.toString() ), 2 ); if ( y.isValid() && y < earlystart ) { earlystart = y; } } } else if ( task->estimate()->calendar() ) { earlystart = task->estimate()->calendar()->firstAvailableAfter( r->parent()->endTime(), task->startTime() ); cs->logDebug( QString( "Calendar work time after %1: %2" ).arg( r->parent()->endTime().toString() ).arg( earlystart.toString() ), 2 ); } x = qMin( x, earlystart.isValid() ? task->startTime() - earlystart : task->startTime() - r->parent()->startTime() ); } // TODO must calculate backwards to get late *start* of task tot = prev + x; } task->setEarlyStart( task->startTime() - tot ); task->setEarlyFinish( task->earlyStart() + ( task->endTime() - task->startTime() ) ); QLocale locale; cs->logDebug( QString( "Early start %1, early finish %2" ).arg( locale.toString(task->earlyStart(), QLocale::ShortFormat) ).arg( locale.toString(task->earlyFinish(), QLocale::ShortFormat) ), 2 ); return tot; } struct rcps_resource *KPlatoRCPSScheduler::addResource( KPlato::Resource *r) { if ( m_resourcemap.values().contains( r ) ) { warnPlan<name()<<"already exist"; return 0; } struct rcps_resource *res = rcps_resource_new(); rcps_resource_setname( res, r->name().toLocal8Bit().data() ); rcps_resource_setavail( res, r->units() ); rcps_resource_add( m_problem, res ); m_resourcemap[res] = r; return res; } void KPlatoRCPSScheduler::addResources() { debugPlan; QList list = m_project->resourceList(); for (int i = 0; i < list.count(); ++i) { addResource( list.at(i) ); } } int KPlatoRCPSScheduler::toRcpsTime( const DateTime &time ) const { return ( m_backward ? time.secsTo( m_starttime ) : m_starttime.secsTo( time ) ) / m_timeunit; } DateTime KPlatoRCPSScheduler::fromRcpsTime( int time ) const { return m_starttime.addSecs( ( m_backward ? -time : time ) * m_timeunit ); } struct rcps_job *KPlatoRCPSScheduler::addTask( KPlato::Task *task ) { struct rcps_job *job = rcps_job_new(); rcps_job_setname( job, task->name().toLocal8Bit().data() ); rcps_job_add( m_problem, job ); m_taskmap[job] = task; return job; } void KPlatoRCPSScheduler::addTasks() { debugPlan; // Add a start job m_jobstart = rcps_job_new(); rcps_job_setname( m_jobstart, "RCPS start job" ); rcps_job_add( m_problem, m_jobstart ); struct rcps_mode *mode = rcps_mode_new(); rcps_mode_add( m_jobstart, mode ); QList list = m_project->allNodes(); for (int i = 0; i < list.count(); ++i) { Node *n = list.at(i); switch ( n->type() ) { case Node::Type_Summarytask: m_schedule->insertSummaryTask( n ); break; case Node::Type_Task: case Node::Type_Milestone: addTask( static_cast( n ) ); break; default: break; } } // Add an end job m_jobend = rcps_job_new(); rcps_job_setname( m_jobend, "RCPS end job" ); rcps_job_add( m_problem, m_jobend ); mode = rcps_mode_new(); rcps_mode_add( m_jobend, mode ); // add a weight callback argument struct KPlatoRCPSScheduler::weight_info *info = new KPlatoRCPSScheduler::weight_info; info->self = this; info->task = 0; info->targettime = toRcpsTime( m_targettime ); info->isEndJob = true; info->finish = 0; rcps_mode_set_weight_cbarg( mode, info ); m_weight_info_list[ m_jobend ] = info; for( int i = 0; i < rcps_job_count( m_problem ); ++i ) { debugPlan<<"Task:"<dependParentNodes().isEmpty() && task->parentProxyRelations().isEmpty() ) { rcps_job_successor_add( m_jobstart, job, SUCCESSOR_FINISH_START ); } if ( task->dependChildNodes().isEmpty() && task->childProxyRelations().isEmpty() ) { rcps_job_successor_add( job, m_jobend, SUCCESSOR_FINISH_START ); } foreach ( Relation *r, task->dependChildNodes() ) { Node *n = r->child(); if ( n == 0 || n->type() == Node::Type_Summarytask ) { continue; } int type = SUCCESSOR_FINISH_START; switch ( r->type() ) { case Relation::FinishStart: type = SUCCESSOR_FINISH_START; break; case Relation::FinishFinish: type = SUCCESSOR_FINISH_FINISH; break; case Relation::StartStart: type = SUCCESSOR_START_START; break; } if ( r->lag() == Duration::zeroDuration ) { rcps_job_successor_add( job, m_taskmap.key( static_cast( n ) ), type ); } else { // Add a dummy job to represent the lag struct rcps_job *dummy = addJob( r->lag().toString(), r->lag().seconds() / m_timeunit ); rcps_job_successor_add( job, dummy, type ); int t = type == SUCCESSOR_FINISH_FINISH ? type : SUCCESSOR_FINISH_START; rcps_job_successor_add( dummy, m_taskmap.key( static_cast( n ) ), t ); } } foreach ( Relation *r, task->childProxyRelations() ) { Node *n = r->child(); if ( n == 0 || n->type() == Node::Type_Summarytask ) { continue; } int type = SUCCESSOR_FINISH_START; switch ( r->type() ) { case Relation::FinishStart: type = SUCCESSOR_FINISH_START; break; case Relation::FinishFinish: type = SUCCESSOR_FINISH_FINISH; break; case Relation::StartStart: type = SUCCESSOR_START_START; break; } if ( r->lag() == Duration::zeroDuration ) { rcps_job_successor_add( job, m_taskmap.key( static_cast( n ) ), type ); } else { // Add a dummy job to represent the lag struct rcps_job *dummy = addJob( r->lag().toString(), r->lag().seconds() / m_timeunit ); rcps_job_successor_add( job, dummy, type ); int t = type == SUCCESSOR_FINISH_FINISH ? type : SUCCESSOR_FINISH_START; rcps_job_successor_add( dummy, m_taskmap.key( static_cast( n ) ), t ); } } } void KPlatoRCPSScheduler::addDependenciesBackward( struct rcps_job *job, KPlato::Task *task ) { if ( task->dependParentNodes().isEmpty() && task->parentProxyRelations().isEmpty() ) { rcps_job_successor_add( job, m_jobend, SUCCESSOR_FINISH_START ); //debugPlan<"<dependChildNodes().isEmpty() && task->childProxyRelations().isEmpty() ) { rcps_job_successor_add( m_jobstart, job, SUCCESSOR_FINISH_START ); //debugPlan<"<dependParentNodes() ) { Node *n = r->parent(); if ( n == 0 || n->type() == Node::Type_Summarytask ) { continue; } int type = SUCCESSOR_FINISH_START; switch ( r->type() ) { case Relation::FinishStart: type = SUCCESSOR_FINISH_START; break; case Relation::FinishFinish: type = SUCCESSOR_FINISH_FINISH; break; case Relation::StartStart: type = SUCCESSOR_START_START; break; } if ( r->lag() == Duration::zeroDuration ) { rcps_job_successor_add( job, m_taskmap.key( static_cast( n ) ), type ); //debugPlan<"<( n ) ) )<lag().toString(), r->lag().seconds() / m_timeunit ); rcps_job_successor_add( job, dummy, type ); debugPlan<"<<"dummy lag"<( n ) ), t ); //debugPlan<<"dummy lag"<<"->"<( n ) ) )<parentProxyRelations() ) { Node *n = r->parent(); if ( n == 0 || n->type() == Node::Type_Summarytask ) { continue; } int type = SUCCESSOR_FINISH_START; switch ( r->type() ) { case Relation::FinishStart: type = SUCCESSOR_FINISH_START; break; case Relation::FinishFinish: type = SUCCESSOR_FINISH_FINISH; break; case Relation::StartStart: type = SUCCESSOR_START_START; break; } if ( r->lag() == Duration::zeroDuration ) { rcps_job_successor_add( job, m_taskmap.key( static_cast( n ) ), type ); //debugPlan<"<( n ) ) )<lag().toString(), r->lag().seconds() / m_timeunit ); rcps_job_successor_add( job, dummy, type ); debugPlan<"<<"dummy lag"<( n ) ), t ); //debugPlan<<"dummy lag"<<"->"<( n ) ) )< ::const_iterator it = m_taskmap.constBegin(); for ( ; it != m_taskmap.constEnd(); ++it ) { if ( m_backward ) { addDependenciesBackward( it.key(), it.value() ); } else { addDependenciesForward( it.key(), it.value() ); } } } void KPlatoRCPSScheduler::addRequests() { debugPlan; QMap ::const_iterator it = m_taskmap.constBegin(); for ( ; it != m_taskmap.constEnd(); ++it ) { addRequest( it.key(), it.value() ); } } void KPlatoRCPSScheduler::addRequest( rcps_job *job, Task *task ) { debugPlan; struct rcps_mode *mode = rcps_mode_new(); rcps_mode_add( job, mode ); // add a weight callback argument struct KPlatoRCPSScheduler::weight_info *wi = new KPlatoRCPSScheduler::weight_info; wi->self = this; wi->task = task; wi->targettime = 0; wi->isEndJob = false; wi->finish = 0; rcps_mode_set_weight_cbarg( mode, wi ); m_weight_info_list[ job ] = wi; if ( task->constraint() != Node::FixedInterval ) { if ( task->type() == Node::Type_Milestone || task->estimate() == 0 || ( m_recalculate && task->completion().isFinished() ) ) { rcps_mode_setduration(mode, 0); return; } if ( task->estimate()->type() == Estimate::Type_Duration && task->estimate()->calendar() == 0 ) { // Fixed duration, no duration callback needed rcps_mode_setduration(mode, task->estimate()->value( Estimate::Use_Expected, m_usePert ).seconds() / m_timeunit ); return; } } /* set the argument for the duration callback */ struct KPlatoRCPSScheduler::duration_info *info = new KPlatoRCPSScheduler::duration_info; info->self = this; info->calls = 0; info->task = task; if ( m_recalculate && task->completion().isStarted() ) { info->estimate = task->completion().remainingEffort(); } else { info->estimate = task->estimate()->value( Estimate::Use_Expected, m_usePert ); } info->requests = task->requests().resourceRequests(); // returns team members (not team resource itself) info->estimatetype = task->estimate()->type(); rcps_mode_set_cbarg( mode, info ); m_duration_info_list[ job ] = info; foreach ( ResourceRequest *rr, info->requests ) { Resource *r = rr->resource(); if ( r->type() == Resource::Type_Team ) { warnPlan<<"There should not be any request to a team resource:"<name(); continue; } struct rcps_request *req = rcps_request_new(); rcps_request_add( mode, req ); m_requestmap[ req ] = rr; struct rcps_alternative *alt = rcps_alternative_new(); rcps_alternative_setresource( alt, m_resourcemap.key( r ) ); rcps_alternative_setamount( alt, (double)rr->units() * 100 / r->units() ); rcps_alternative_add( req, alt ); } } void KPlatoRCPSScheduler::setConstraints() { for ( QMap::ConstIterator it = m_taskmap.constBegin(); it != m_taskmap.constEnd(); ++it ) { Task *task = it.value(); struct rcps_job *job = it.key(); struct weight_info *wi = m_weight_info_list.value( job ); struct duration_info *di = m_duration_info_list.value( job ); switch ( task->constraint() ) { case Node::MustStartOn: case Node::StartNotEarlier: wi->targettime = toRcpsTime( task->constraintStartTime() ); if ( m_backward ) { int d = 0; if ( di ) { // as m_backward == true, DURATION_BACKWARD in rcps means forward in plan d = duration( DURATION_BACKWARD, wi->targettime, 0, di ); } wi->targettime -= d; } rcps_job_setearliest_start( job, wi->targettime ); task->currentSchedule()->logDebug( QString( "%2 %3 %4: %5 (rcps=%6)") .arg( task->constraintToString() ) .arg( m_backward?"backward":"forward") .arg( task->constraintStartTime().toString() ) .arg( fromRcpsTime( wi->targettime ).toString() ) .arg( wi->targettime ) ); break; case Node::MustFinishOn: wi->targettime = toRcpsTime( task->constraintEndTime() ); if ( ! m_backward ) { int d = 0; if ( di ) { d = duration( DURATION_BACKWARD, wi->targettime, 0, di ); } rcps_job_setearliest_start( job, wi->targettime - d ); } break; case Node::FinishNotLater: wi->targettime = toRcpsTime( task->constraintEndTime() ); if ( m_backward ) { rcps_job_setearliest_start( job, wi->targettime ); } break; case Node::FixedInterval: wi->targettime = m_backward ? toRcpsTime( task->constraintEndTime() ) : toRcpsTime( task->constraintStartTime() ); rcps_job_setearliest_start( job, wi->targettime ); break; default: break; } } } void KPlatoRCPSScheduler::setWeights() { for ( QMap::ConstIterator it = m_taskmap.constBegin(); it != m_taskmap.constEnd(); ++it ) { Task *task = it.value(); struct rcps_job *job = it.key(); if ( m_backward ) { switch ( task->constraint() ) { case Node::ASAP: rcps_job_setweight( job, WEIGHT_ALAP ); break; case Node::ALAP: rcps_job_setweight( job, WEIGHT_ASAP ); break; case Node::StartNotEarlier: rcps_job_setweight( job, WEIGHT_CONSTRAINT ); break; case Node::MustStartOn: rcps_job_setweight( job, WEIGHT_CONSTRAINT ); break; case Node::FinishNotLater: rcps_job_setearliest_start( job, toRcpsTime( task->constraintEndTime() ) ); rcps_job_setweight( job, WEIGHT_CONSTRAINT ); break; case Node::MustFinishOn: rcps_job_setearliest_start( job, toRcpsTime( task->constraintEndTime() ) ); rcps_job_setweight( job, WEIGHT_CONSTRAINT ); break; case Node::FixedInterval: rcps_job_setearliest_start( job, toRcpsTime( task->constraintEndTime() ) ); rcps_job_setweight( job, WEIGHT_CONSTRAINT ); break; default: rcps_job_setweight( job, WEIGHT_ASAP ); break; } } else { switch ( task->constraint() ) { case Node::ASAP: rcps_job_setweight( job, WEIGHT_ASAP ); break; case Node::ALAP: rcps_job_setweight( job, WEIGHT_ALAP ); break; case Node::StartNotEarlier: rcps_job_setearliest_start( job, toRcpsTime( task->constraintStartTime() ) ); rcps_job_setweight( job, WEIGHT_CONSTRAINT ); break; case Node::MustStartOn: rcps_job_setearliest_start( job, toRcpsTime( task->constraintStartTime() ) ); rcps_job_setweight( job, WEIGHT_CONSTRAINT ); break; case Node::FinishNotLater: rcps_job_setweight( job, WEIGHT_CONSTRAINT ); break; case Node::MustFinishOn: rcps_job_setweight( job, WEIGHT_CONSTRAINT ); break; case Node::FixedInterval: rcps_job_setearliest_start( job, toRcpsTime( task->constraintStartTime() ) ); rcps_job_setweight( job, WEIGHT_CONSTRAINT ); break; default: rcps_job_setweight( job, WEIGHT_ASAP ); break; } } } } diff --git a/src/plugins/schedulers/tj/PlanTJPlugin.cpp b/src/plugins/schedulers/tj/PlanTJPlugin.cpp index 5cb69b17..bcad5ab6 100644 --- a/src/plugins/schedulers/tj/PlanTJPlugin.cpp +++ b/src/plugins/schedulers/tj/PlanTJPlugin.cpp @@ -1,166 +1,166 @@ /* This file is part of the KDE project * Copyright (C) 2009, 2011 Dag Andersen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "PlanTJPlugin.h" #include "kptschedulerplugin_macros.h" #include "PlanTJScheduler.h" #include "kptproject.h" #include "kptschedule.h" #include "kptdebug.h" #include #include #ifndef PLAN_NOPLUGIN PLAN_SCHEDULERPLUGIN_EXPORT(PlanTJPlugin, "plantjscheduler.json") #endif using namespace KPlato; PlanTJPlugin::PlanTJPlugin( QObject * parent, const QVariantList & ) : KPlato::SchedulerPlugin(parent) { m_granularities << (long unsigned int) 5 * 60 * 1000 << (long unsigned int) 15 * 60 * 1000 << (long unsigned int) 30 * 60 * 1000 << (long unsigned int) 60 * 60 * 1000; } PlanTJPlugin::~PlanTJPlugin() { } QString PlanTJPlugin::description() const { return i18nc( "@info:whatsthis", "TaskJuggler Scheduler" "This is a slightly modified version of the scheduler used in TaskJuggler." " It has been enhanced to handle resource units." "Scheduling backwards is simulated by scheduling all tasks as late as possible." "Plan does not utilize all of its functionality." ); } int PlanTJPlugin::capabilities() const { return SchedulerPlugin::AvoidOverbooking | SchedulerPlugin::ScheduleForward | SchedulerPlugin::ScheduleBackward; } ulong PlanTJPlugin::currentGranularity() const { ulong v = m_granularities.value( m_granularity ); return qMax( v, (ulong)300000 ); // minimum 5 min } void PlanTJPlugin::calculate( KPlato::Project &project, KPlato::ScheduleManager *sm, bool nothread ) { foreach ( SchedulerThread *j, m_jobs ) { if ( j->manager() == sm ) { return; } } sm->setScheduling( true ); PlanTJScheduler *job = new PlanTJScheduler( &project, sm, currentGranularity() ); m_jobs << job; - connect(job, SIGNAL(jobFinished(SchedulerThread*)), SLOT(slotFinished(SchedulerThread*))); + connect(job, SIGNAL(jobFinished(KPlato::SchedulerThread*)), SLOT(slotFinished(KPlato::SchedulerThread*))); project.changed( sm ); -// connect(this, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*)), &project, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*))); -// connect(this, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*)), &project, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*))); +// connect(this, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*)), &project, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*))); +// connect(this, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*)), &project, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*))); connect(job, SIGNAL(maxProgressChanged(int)), sm, SLOT(setMaxProgress(int))); connect(job, SIGNAL(progressChanged(int)), sm, SLOT(setProgress(int))); if ( nothread ) { job->doRun(); } else { job->start(); } } void PlanTJPlugin::stopAllCalculations() { foreach ( SchedulerThread *s, m_jobs ) { stopCalculation( s ); } } void PlanTJPlugin::stopCalculation( SchedulerThread *sch ) { if ( sch ) { //FIXME: this should just call stopScheduling() and let the job finish "normally" disconnect( sch, SIGNAL(jobFinished(PlanTJScheduler*)), this, SLOT(slotFinished(PlanTJScheduler*)) ); sch->stopScheduling(); // wait max 20 seconds. sch->mainManager()->setCalculationResult( ScheduleManager::CalculationStopped ); if ( ! sch->wait( 20000 ) ) { sch->deleteLater(); m_jobs.removeAt( m_jobs.indexOf( sch ) ); } else { slotFinished( sch ); } } } void PlanTJPlugin::slotStarted( SchedulerThread */*job*/ ) { // debugPlan<<"PlanTJPlugin::slotStarted:"; } void PlanTJPlugin::slotFinished( SchedulerThread *j ) { PlanTJScheduler *job = static_cast( j ); Project *mp = job->mainProject(); ScheduleManager *sm = job->mainManager(); //debugPlan<<"PlanTJPlugin::slotFinished:"<isStopped(); if ( job->isStopped() ) { sm->setCalculationResult( ScheduleManager::CalculationCanceled ); } else { updateLog( job ); if ( job->result > 0 ) { sm->setCalculationResult( ScheduleManager::CalculationError ); } else { Project *tp = job->project(); ScheduleManager *tm = job->manager(); updateProject( tp, tm, mp, sm ); sm->setCalculationResult( ScheduleManager::CalculationDone ); } } sm->setScheduling( false ); m_jobs.removeAt( m_jobs.indexOf( job ) ); if ( m_jobs.isEmpty() ) { m_synctimer.stop(); } emit sigCalculationFinished( mp, sm ); - disconnect(this, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*)), mp, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*))); - disconnect(this, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*)), mp, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*))); + disconnect(this, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*)), mp, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*))); + disconnect(this, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*)), mp, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*))); job->deleteLater(); } #include "PlanTJPlugin.moc" diff --git a/src/plugins/schedulers/tj/PlanTJPlugin.h b/src/plugins/schedulers/tj/PlanTJPlugin.h index cbedf502..46c1a1c0 100644 --- a/src/plugins/schedulers/tj/PlanTJPlugin.h +++ b/src/plugins/schedulers/tj/PlanTJPlugin.h @@ -1,70 +1,70 @@ /* This file is part of the KDE project * Copyright (C) 2009 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 PLANTJPLUGIN_H #define PLANTJPLUGIN_H #include "plantj_export.h" #include "kptschedulerplugin.h" #include namespace KPlato { class Project; class ScheduleManager; class Schedule; } using namespace KPlato; class PLANTJ_EXPORT PlanTJPlugin : public SchedulerPlugin { Q_OBJECT public: PlanTJPlugin( QObject * parent, const QVariantList & ); ~PlanTJPlugin(); virtual QString description() const; virtual int capabilities() const; /// Calculate the project virtual void calculate( Project &project, ScheduleManager *sm, bool nothread = false ); /// Return the scheduling granularity in milliseconds ulong currentGranularity() const; Q_SIGNALS: - void sigCalculationStarted(Project*, ScheduleManager*); - void sigCalculationFinished(Project*, ScheduleManager*); + void sigCalculationStarted(KPlato::Project*, KPlato::ScheduleManager*); + void sigCalculationFinished(KPlato::Project*, KPlato::ScheduleManager*); public Q_SLOTS: void stopAllCalculations(); - void stopCalculation( SchedulerThread *sch ); + void stopCalculation(KPlato::SchedulerThread *sch); protected Q_SLOTS: - void slotStarted( SchedulerThread *job ); - void slotFinished( SchedulerThread *job ); + void slotStarted(KPlato::SchedulerThread *job); + void slotFinished(KPlato::SchedulerThread *job); }; #endif // PLANTJPLUGIN_H diff --git a/src/plugins/schedulers/tj/PlanTJScheduler.cpp b/src/plugins/schedulers/tj/PlanTJScheduler.cpp index c106e91f..7eacbb31 100644 --- a/src/plugins/schedulers/tj/PlanTJScheduler.cpp +++ b/src/plugins/schedulers/tj/PlanTJScheduler.cpp @@ -1,916 +1,916 @@ /* This file is part of the KDE project * Copyright (C) 2009, 2010, 2011, 2012 Dag Andersen * Copyright (C) 2016 Dag Andersen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "PlanTJScheduler.h" #include "kptproject.h" #include "kptschedule.h" #include "kptresource.h" #include "kpttask.h" #include "kptrelation.h" #include "kptduration.h" #include "kptcalendar.h" #include "kptdebug.h" #include "taskjuggler/taskjuggler.h" #include "taskjuggler/Project.h" #include "taskjuggler/Scenario.h" #include "taskjuggler/Resource.h" #include "taskjuggler/Task.h" #include "taskjuggler/Interval.h" #include "taskjuggler/Allocation.h" #include "taskjuggler/Utility.h" #include "taskjuggler/UsageLimits.h" #include "taskjuggler/CoreAttributes.h" #include "taskjuggler/TjMessageHandler.h" #include "taskjuggler/debug.h" #include #include #include #include #include #include #include #include #define PROGRESS_MAX_VALUE 100 PlanTJScheduler::PlanTJScheduler( Project *project, ScheduleManager *sm, ulong granularity, QObject *parent ) : SchedulerThread( project, sm, parent ), result( -1 ), m_schedule( 0 ), m_recalculate( false ), m_usePert( false ), m_backward( false ), m_granularity( granularity ) { TJ::TJMH.reset(); connect(&TJ::TJMH, SIGNAL(message(int,QString,TJ::CoreAttributes*)), this, SLOT(slotMessage(int,QString,TJ::CoreAttributes*))); - connect(this, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*)), project, SIGNAL(sigCalculationStarted(Project*,ScheduleManager*))); + connect(this, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*)), project, SIGNAL(sigCalculationStarted(KPlato::Project*,KPlato::ScheduleManager*))); emit sigCalculationStarted( project, sm ); - connect( this, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*)), project, SIGNAL(sigCalculationFinished(Project*,ScheduleManager*)) ); + connect( this, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*)), project, SIGNAL(sigCalculationFinished(KPlato::Project*,KPlato::ScheduleManager*)) ); } PlanTJScheduler::~PlanTJScheduler() { delete m_tjProject; } void PlanTJScheduler::slotMessage( int type, const QString &msg, TJ::CoreAttributes *object ) { // debugPlan<<"PlanTJScheduler::slotMessage:"<getType() == CA_Task && m_taskmap.contains( static_cast( object ) ) ) { log = Schedule::Log( static_cast( m_taskmap[ static_cast( object ) ] ), type, msg ); } else if ( object && object->getType() == CA_Resource && m_resourcemap.contains( static_cast( object ) ) ) { log = Schedule::Log( 0, m_resourcemap[ static_cast( object ) ], type, msg ); } else if ( object && ! object->getName().isEmpty() ) { log = Schedule::Log( static_cast( m_project ), type, QString( "%1: %2" ).arg(object->getName() ).arg( msg ) ); } else { log = Schedule::Log( static_cast( m_project ), type, msg ); } slotAddLog( log ); } void PlanTJScheduler::run() { if ( m_haltScheduling ) { deleteLater(); return; } if ( m_stopScheduling ) { return; } setMaxProgress( PROGRESS_MAX_VALUE ); { // mutex --> m_projectMutex.lock(); m_managerMutex.lock(); m_project = new Project(); loadProject( m_project, m_pdoc ); m_project->setName( "Schedule: " + m_project->name() ); //Debug m_project->stopcalculation = false; m_manager = m_project->scheduleManager( m_mainmanagerId ); Q_CHECK_PTR( m_manager ); Q_ASSERT( m_manager->expected() ); Q_ASSERT( m_manager != m_mainmanager ); Q_ASSERT( m_manager->scheduleId() == m_mainmanager->scheduleId() ); Q_ASSERT( m_manager->expected() != m_mainmanager->expected() ); m_manager->setName( "Schedule: " + m_manager->name() ); //Debug m_schedule = m_manager->expected(); bool x = connect(m_manager, SIGNAL(sigLogAdded(Schedule::Log)), this, SLOT(slotAddLog(Schedule::Log))); Q_ASSERT( x ); Q_UNUSED( x ); m_project->initiateCalculation( *m_schedule ); m_project->initiateCalculationLists( *m_schedule ); m_usePert = m_manager->usePert(); m_recalculate = m_manager->recalculate(); if ( m_recalculate ) { m_backward = false; } else { m_backward = m_manager->schedulingDirection(); } m_project->setCurrentSchedule( m_manager->expected()->id() ); m_schedule->setPhaseName( 0, xi18nc( "@info/plain" , "Init" ) ); QLocale locale; KFormat format(locale); if ( ! m_backward ) { logDebug( m_project, 0, QString( "Schedule project using TJ Scheduler, starting at %1, granularity %2" ).arg( QDateTime::currentDateTime().toString() ).arg( format.formatDuration( m_granularity ) ), 0 ); if ( m_recalculate ) { logInfo( m_project, 0, xi18nc( "@info/plain" , "Re-calculate project from start time: %1", locale.toString(m_project->constraintStartTime(), QLocale::ShortFormat) ), 0 ); } else { logInfo( m_project, 0, xi18nc( "@info/plain" , "Schedule project from start time: %1", locale.toString(m_project->constraintStartTime(), QLocale::ShortFormat) ), 0 ); } logInfo( m_project, 0, xi18nc( "@info/plain" , "Project target finish time: %1", locale.toString(m_project->constraintEndTime(), QLocale::ShortFormat) ), 0 ); } else { logDebug( m_project, 0, QString( "Schedule project backward using TJ Scheduler, starting at %1, granularity %2" ).arg( locale.toString(QDateTime::currentDateTime(), QLocale::ShortFormat) ).arg( format.formatDuration( m_granularity ) ), 0 ); logInfo( m_project, 0, xi18nc( "@info/plain" , "Schedule project from end time: %1", locale.toString(m_project->constraintEndTime(), QLocale::ShortFormat) ), 0 ); } m_managerMutex.unlock(); m_projectMutex.unlock(); } // <--- mutex setProgress( 2 ); if ( ! kplatoToTJ() ) { result = 1; setProgress( PROGRESS_MAX_VALUE ); return; } setMaxProgress( PROGRESS_MAX_VALUE ); connect(m_tjProject, SIGNAL(updateProgressBar(int,int)), this, SLOT(setProgress(int))); m_schedule->setPhaseName( 1, xi18nc( "@info/plain" , "Schedule" ) ); logInfo( m_project, 0, "Start scheduling", 1 ); bool r = solve(); if ( ! r ) { debugPlan<<"Scheduling failed"; result = 2; logError( m_project, 0, xi18nc( "@info/plain" , "Failed to schedule project" ) ); setProgress( PROGRESS_MAX_VALUE ); return; } if ( m_haltScheduling ) { debugPlan<<"Scheduling halted"; logInfo( m_project, 0, "Scheduling halted" ); deleteLater(); return; } m_schedule->setPhaseName( 2, xi18nc( "@info/plain" , "Update" ) ); logInfo( m_project, 0, "Scheduling finished, update project", 2 ); if ( ! kplatoFromTJ() ) { logError( m_project, 0, "Project update failed" ); } setProgress( PROGRESS_MAX_VALUE ); m_schedule->setPhaseName( 3, xi18nc( "@info/plain" , "Finish" ) ); } bool PlanTJScheduler::check() { DebugCtrl.setDebugMode( 0 ); DebugCtrl.setDebugLevel( 1000 ); return m_tjProject->pass2( true ); } bool PlanTJScheduler::solve() { debugPlan<<"PlanTJScheduler::solve()"; TJ::Scenario *sc = m_tjProject->getScenario( 0 ); if ( ! sc ) { logError( m_project, 0, xi18nc( "@info/plain" , "Failed to find scenario to schedule" ) ); return false; } DebugCtrl.setDebugLevel(0); DebugCtrl.setDebugMode(PSDEBUG+TSDEBUG+RSDEBUG+PADEBUG); return m_tjProject->scheduleScenario( sc ); } bool PlanTJScheduler::kplatoToTJ() { m_tjProject = new TJ::Project(); m_tjProject->setScheduleGranularity( m_granularity / 1000 ); m_tjProject->getScenario( 0 )->setMinSlackRate( 0.0 ); // Do not calculate critical path m_tjProject->setNow( m_project->constraintStartTime().toTime_t() ); m_tjProject->setStart( m_project->constraintStartTime().toTime_t() ); m_tjProject->setEnd( m_project->constraintEndTime().toTime_t() ); m_tjProject->setDailyWorkingHours( m_project->standardWorktime()->day() ); // Set working days for the project, it is used for tasks with a length specification // FIXME: Plan has task specific calendars for this estimate type KPlato::Calendar *cal = m_project->defaultCalendar(); if ( ! cal ) { m_project->calendars().value( 0 ); } if ( cal ) { int days[ 7 ] = { Qt::Sunday, Qt::Monday, Qt::Tuesday, Qt::Wednesday, Qt::Thursday, Qt::Friday, Qt::Saturday }; for ( int i = 0; i < 7; ++i ) { CalendarDay *d = 0; for ( Calendar *c = cal; c; c = c->parentCal() ) { QTime t; t.start(); d = c->weekday( days[ i ] ); Q_ASSERT( d ); if ( d == 0 || d->state() != CalendarDay::Undefined ) { break; } } if ( d && d->state() == CalendarDay::Working ) { QList lst; foreach ( const TimeInterval *ti, d->timeIntervals() ) { TJ::Interval *tji = new TJ::Interval( toTJInterval( ti->startTime(), ti->endTime(),tjGranularity() ) ); lst << tji; } m_tjProject->setWorkingHours( i, lst ); qDeleteAll( lst ); } } } addTasks(); setConstraints(); addDependencies(); addRequests(); addStartEndJob(); if (result != -1) { return false; } return check(); } void PlanTJScheduler::addStartEndJob() { TJ::Task *start = new TJ::Task( m_tjProject, "TJ::StartJob", "TJ::StartJob", 0, QString(), 0); start->setMilestone( true ); if ( ! m_backward ) { start->setSpecifiedStart( 0, m_tjProject->getStart() ); start->setPriority( 999 ); } else { // backwards: insert a new ms before start and make start an ALAP to push all other jobs ALAP TJ::Task *bs = new TJ::Task( m_tjProject, "TJ::StartJob-B", "TJ::StartJob-B", 0, QString(), 0); bs->setMilestone( true ); bs->setSpecifiedStart( 0, m_tjProject->getStart() ); bs->setPriority( 999 ); bs->addPrecedes( start->getId() ); start->addDepends( bs->getId() ); start->setScheduling( TJ::Task::ALAP ); } TJ::Task *end = new TJ::Task( m_tjProject, "TJ::EndJob", "TJ::EndJob", 0, QString(), 0); end->setMilestone( true ); if ( m_backward ) { end->setSpecifiedEnd( 0, m_tjProject->getEnd() - 1 ); end->setScheduling( TJ::Task::ALAP ); } for ( QMap::ConstIterator it = m_taskmap.constBegin(); it != m_taskmap.constEnd(); ++it ) { if ( it.value()->isStartNode() ) { it.key()->addDepends( start->getId() ); // logDebug( m_project, 0, QString( "'%1' depends on: '%2'" ).arg( it.key()->getName() ).arg( start->getName() ) ); if ( start->getScheduling() == TJ::Task::ALAP ) { start->addPrecedes( it.key()->getId() ); // logDebug( m_project, 0, QString( "'%1' precedes: '%2'" ).arg( start->getName() ).arg( it.key()->getName() ) ); } } if ( it.value()->isEndNode() ) { end->addDepends( it.key()->getId() ); if ( it.key()->getScheduling() == TJ::Task::ALAP ) { it.key()->addPrecedes( end->getId() ); } } } } // static int PlanTJScheduler::toTJDayOfWeek( int day ) { return day == 7 ? 0 : day; } // static DateTime PlanTJScheduler::fromTime_t( time_t t, const QTimeZone &tz ) { return DateTime ( QDateTime::fromTime_t( t ).toTimeZone( tz ) ); } time_t PlanTJScheduler::toTJTime_t( const QDateTime &dt, ulong granularity ) { int secs = QTime( 0, 0, 0 ).secsTo( dt.time() ); secs -= secs % granularity; return QDateTime( dt.date(), QTime( 0, 0, 0 ).addSecs( secs ), dt.timeZone() ).toTime_t(); } // static AppointmentInterval PlanTJScheduler::fromTJInterval( const TJ::Interval &tji, const QTimeZone &tz ) { AppointmentInterval a( fromTime_t( tji.getStart(), tz ), fromTime_t( tji.getEnd(), tz ).addSecs( 1 ) ); return a; } // static TJ::Interval PlanTJScheduler::toTJInterval( const QDateTime &start, const QDateTime &end, ulong granularity ) { int secs = QTime( 0, 0, 0 ).secsTo( start.time() ); secs -= secs % granularity; QDateTime s( start.date(), QTime( 0, 0, 0 ).addSecs( secs ), start.timeZone() ); secs = QTime( 0, 0, 0 ).secsTo( end.time() ); secs -= secs % granularity; QDateTime e( end.date(), QTime( 0, 0, 0 ).addSecs( secs ), end.timeZone() ); TJ::Interval ti( s.toTime_t(), e.addSecs( -1 ).toTime_t() ); return ti; } // static TJ::Interval PlanTJScheduler::toTJInterval( const QTime &start, const QTime &end, ulong granularity ) { int secs = QTime( 0, 0, 0 ).secsTo( start ); time_t s = secs - ( secs % granularity ); secs = ( end == QTime( 0, 0, 0 ) ) ? 86399 : QTime( 0, 0, 0 ).secsTo( end ); time_t e = secs - ( secs % granularity ) - 1; TJ::Interval ti( s, e ); return ti; } ulong PlanTJScheduler::tjGranularity() const { return m_tjProject->getScheduleGranularity(); } bool PlanTJScheduler::kplatoFromTJ() { MainSchedule *cs = static_cast( m_project->currentSchedule() ); QDateTime start; QDateTime end; for ( QMap::ConstIterator it = m_taskmap.constBegin(); it != m_taskmap.constEnd(); ++it ) { if ( ! taskFromTJ( it.key(), it.value() ) ) { return false; } if ( ! start.isValid() || it.value()->startTime() < start ) { start = it.value()->startTime(); } if ( ! end.isValid() || it.value()->endTime() > end ) { end = it.value()->endTime(); } } m_project->setStartTime( start.isValid() ? start : m_project->constraintStartTime() ); m_project->setEndTime( end.isValid() ? end : m_project->constraintEndTime() ); adjustSummaryTasks( m_schedule->summaryTasks() ); foreach ( Task *task, m_taskmap ) { calcPertValues( task ); } m_project->calcCriticalPathList( m_schedule ); // calculate positive float foreach ( Task* t, m_taskmap ) { if ( ! t->inCriticalPath() && t->isStartNode() ) { calcPositiveFloat( t ); } } QLocale locale; logInfo( m_project, 0, xi18nc( "@info/plain" , "Project scheduled to start at %1 and finish at %2", locale.toString(m_project->startTime(), QLocale::ShortFormat), locale.toString(m_project->endTime(), QLocale::ShortFormat) ) ); if ( m_manager ) { logDebug( m_project, 0, QString( "Project scheduling finished at %1" ).arg( locale.toString(QDateTime::currentDateTime(), QLocale::ShortFormat) ) ); m_project->finishCalculation( *m_manager ); m_manager->scheduleChanged( cs ); } return true; } bool PlanTJScheduler::taskFromTJ( TJ::Task *job, Task *task ) { if ( m_haltScheduling || m_manager == 0 ) { return true; } Schedule *cs = task->currentSchedule(); Q_ASSERT( cs ); QTimeZone tz = m_project->timeZone(); debugPlan<<"taskFromTJ:"<name()<id()<getStart( 0 ); if ( s < m_tjProject->getStart() || s > m_tjProject->getEnd() ) { m_project->currentSchedule()->setSchedulingError( true ); cs->setSchedulingError( true ); s = m_tjProject->getStart(); } time_t e = job->getEnd( 0 ); if ( job->isMilestone() ) { Q_ASSERT( s = (e + 1)); e = s - 1; } else if ( e <= s || e > m_tjProject->getEnd() ) { m_project->currentSchedule()->setSchedulingError( true ); cs->setSchedulingError( true ); e = s + (8*60*60); } task->setStartTime( fromTime_t( s, tz ) ); task->setEndTime( fromTime_t( e + 1, tz ) ); task->setDuration( task->endTime() - task->startTime() ); debugPlan<startTime()<<"-- "<endTime(); if ( ! task->startTime().isValid() ) { logError( task, 0, xi18nc( "@info/plain", "Invalid start time" ) ); return false; } if ( ! task->endTime().isValid() ) { logError( task, 0, xi18nc( "@info/plain", "Invalid end time" ) ); return false; } if ( m_project->startTime() > task->startTime() ) { m_project->setStartTime( task->startTime() ); } if ( task->endTime() > m_project->endTime() ) { m_project->setEndTime( task->endTime() ); } foreach ( TJ::CoreAttributes *a, job->getBookedResources( 0 ) ) { TJ::Resource *r = static_cast( a ); Resource *res = m_resourcemap[ r ]; const QVector lst = r->getBookedIntervals( 0, job ); foreach ( const TJ::Interval &tji, lst ) { AppointmentInterval ai = fromTJInterval( tji, tz ); double load = res->type() == Resource::Type_Material ? res->units() : ai.load() * r->getEfficiency(); res->addAppointment( cs, ai.startTime(), ai.endTime(), load ); logDebug( task, 0, '\'' + res->name() + "' added appointment: " + ai.startTime().toString( Qt::ISODate ) + " - " + ai.endTime().toString( Qt::ISODate ) ); } } cs->setScheduled( true ); QLocale locale; if ( task->type() == Node::Type_Milestone ) { logInfo( task, 0, xi18nc( "@info/plain" , "Scheduled milestone: %1", locale.toString(task->startTime(), QLocale::ShortFormat) ) ); } else { logInfo( task, 0, xi18nc( "@info/plain" , "Scheduled task: %1 - %2", locale.toString(task->startTime(), QLocale::ShortFormat), locale.toString(task->endTime(), QLocale::ShortFormat) ) ); } return true; } void PlanTJScheduler::adjustSummaryTasks( const QList &nodes ) { foreach ( Node *n, nodes ) { adjustSummaryTasks( n->childNodeIterator() ); if ( n->parentNode()->type() == Node::Type_Summarytask ) { DateTime pt = n->parentNode()->startTime(); DateTime nt = n->startTime(); if ( ! pt.isValid() || pt > nt ) { n->parentNode()->setStartTime( nt ); } pt = n->parentNode()->endTime(); nt = n->endTime(); if ( ! pt.isValid() || pt < nt ) { n->parentNode()->setEndTime( nt ); } } } } Duration PlanTJScheduler::calcPositiveFloat( Task *task ) { if ( task->positiveFloat() != 0 ) { return task->positiveFloat(); } Duration x; if ( task->dependChildNodes().isEmpty() && task->childProxyRelations().isEmpty() ) { x = m_project->endTime() - task->endTime(); } else { foreach ( const Relation *r, task->dependChildNodes() + task->childProxyRelations() ) { if ( ! r->child()->inCriticalPath() ) { Duration f = calcPositiveFloat( static_cast( r->child() ) ); if ( x == 0 || f < x ) { x = f; } } } } Duration totfloat = task->freeFloat() + x; task->setPositiveFloat( totfloat ); return totfloat; } void PlanTJScheduler::calcPertValues( Task *t ) { switch ( t->constraint() ) { case Node::MustStartOn: if ( t->constraintStartTime() != t->startTime() ) { t->setNegativeFloat( t->startTime() - t->constraintStartTime() ); } break; case Node::StartNotEarlier: if ( t->startTime() < t->constraintStartTime() ) { t->setNegativeFloat( t->constraintStartTime() - t->startTime() ); } break; case Node::MustFinishOn: if ( t->constraintEndTime() != t->endTime() ) { t->setNegativeFloat( t->endTime() - t->constraintEndTime() ); } break; case Node::FinishNotLater: if ( t->endTime() > t->constraintEndTime() ) { t->setNegativeFloat( t->endTime() - t->constraintEndTime() ); } break; case Node::FixedInterval: if ( t->constraintStartTime() != t->startTime() ) { t->setNegativeFloat( t->startTime() - t->constraintStartTime() ); } else if ( t->endTime() != t->constraintEndTime() ) { t->setNegativeFloat( t->endTime() - t->constraintEndTime() ); } break; default: break; } if ( t->negativeFloat() != 0 ) { t->currentSchedule()->setConstraintError( true ); m_project->currentSchedule()->setSchedulingError( true ); logError( t, 0, i18nc( "1=type of constraint", "%1: Failed to meet constraint. Negative float=%2", t->constraintToString( true ), t->negativeFloat().toString( Duration::Format_i18nHour ) ) ); } debugPlan<name()<startTime()<endTime(); Duration negativefloat; foreach ( const Relation *r, t->dependParentNodes() + t->parentProxyRelations() ) { if ( r->parent()->endTime() + r->lag() > t->startTime() ) { Duration f = r->parent()->endTime() + r->lag() - t->startTime(); if ( f > negativefloat ) { negativefloat = f; } } } if ( negativefloat > 0 ) { t->currentSchedule()->setSchedulingError( true ); m_project->currentSchedule()->setSchedulingError( true ); logError( t, 0, xi18nc( "@info/plain", "Failed to meet dependency. Negative float=%1", negativefloat.toString( Duration::Format_i18nHour ) ) ); if ( t->negativeFloat() < negativefloat ) { t->setNegativeFloat( negativefloat ); } } Duration freefloat; foreach ( const Relation *r, t->dependChildNodes() + t->childProxyRelations() ) { if ( t->endTime() + r->lag() < r->child()->startTime() ) { Duration f = r->child()->startTime() - r->lag() - t->endTime(); if ( f > 0 && ( freefloat == 0 || freefloat > f ) ) { freefloat = f; } } } t->setFreeFloat( freefloat ); } bool PlanTJScheduler::exists( QList &lst, CalendarDay *day ) { foreach ( CalendarDay *d, lst ) { if ( d->date() == day->date() && day->state() != CalendarDay::Undefined && d->state() != CalendarDay::Undefined ) { return true; } } return false; } TJ::Resource *PlanTJScheduler::addResource( KPlato::Resource *r) { if ( m_resourcemap.values().contains( r ) ) { debugPlan<name()<<"already exist"; return m_resourcemap.key( r ); } TJ::Resource *res = new TJ::Resource( m_tjProject, r->id(), r->name(), 0 ); if ( r->type() == Resource::Type_Material ) { res->setEfficiency( 0.0 ); } else { res->setEfficiency( (double)(r->units()) / 100. ); } Calendar *cal = r->calendar(); Q_ASSERT(cal); DateTime start = qMax( r->availableFrom(), m_project->constraintStartTime() ); DateTime end = m_project->constraintEndTime(); if ( r->availableUntil().isValid() && end > r->availableUntil() ) { end = r->availableUntil(); } AppointmentIntervalList lst = cal->workIntervals( start, end, 1.0 ); // qDebug()<name()<::const_iterator mapend = lst.map().constEnd(); QMultiMap::const_iterator it = lst.map().constBegin(); TJ::Shift *shift = new TJ::Shift( m_tjProject, r->id(), r->name(), 0, QString(), 0 ); for ( ; it != mapend; ++it ) { shift->addWorkingInterval( toTJInterval( it.value().startTime(), it.value().endTime(), m_granularity/1000 ) ); } res->addShift( toTJInterval( start, end, m_granularity/1000 ), shift ); m_resourcemap[res] = r; logDebug( m_project, 0, "Added resource: " + r->name() ); /* QListIterator it = res->getVacationListIterator(); while ( it.hasNext() ) { TJ::Interval *i = it.next(); logDebug( m_project, 0, "Vacation: " + TJ::time2ISO( i->getStart() ) + " - " + TJ::time2ISO( i->getEnd() ) ); }*/ return res; } TJ::Task *PlanTJScheduler::addTask( KPlato::Task *task, TJ::Task *parent ) { /* if ( m_backward && task->isStartNode() ) { Relation *r = new Relation( m_backwardTask, task ); m_project->addRelation( r ); }*/ TJ::Task *t = new TJ::Task(m_tjProject, task->id(), task->name(), parent, QString(), 0); m_taskmap[ t ] = task; // logDebug( m_project, 0, "Added task: " + task->name() ); addWorkingTime( task, t ); return t; } void PlanTJScheduler::addWorkingTime( KPlato::Task *task, TJ::Task *job ) { if ( task->type() != Node::Type_Task || task->estimate()->type() != Estimate::Type_Duration || ! task->estimate()->calendar() ) { return; } int id = 0; Calendar *cal = task->estimate()->calendar(); DateTime start = m_project->constraintStartTime(); DateTime end = m_project->constraintEndTime(); AppointmentIntervalList lst = cal->workIntervals( start, end, 1.0 ); QMultiMap::const_iterator mapend = lst.map().constEnd(); QMultiMap::const_iterator it = lst.map().constBegin(); TJ::Shift *shift = new TJ::Shift( m_tjProject, task->id() + QString( "-%1" ).arg( ++id ), task->name(), 0, QString(), 0 ); for ( ; it != mapend; ++it ) { shift->addWorkingInterval(toTJInterval(it.value().startTime(), it.value().endTime(), m_granularity/1000)); } job->addShift(toTJInterval(start, end, m_granularity/1000), shift); } void PlanTJScheduler::addTasks() { debugPlan; QList list = m_project->allNodes(); for (int i = 0; i < list.count(); ++i) { Node *n = list.at(i); TJ::Task *parent = 0; switch ( n->type() ) { case Node::Type_Summarytask: m_schedule->insertSummaryTask( n ); break; case Node::Type_Task: case Node::Type_Milestone: switch ( n->constraint() ) { case Node::StartNotEarlier: parent = addStartNotEarlier( n ); break; case Node::FinishNotLater: parent = addFinishNotLater( n ); break; } addTask( static_cast( n ), parent ); break; default: break; } } } void PlanTJScheduler::addDepends( const Relation *rel ) { TJ::Task *child = m_tjProject->getTask( rel->child()->id() ); TJ::TaskDependency *d = child->addDepends( rel->parent()->id() ); d->setGapDuration( 0, rel->lag().seconds() ); } void PlanTJScheduler::addPrecedes( const Relation *rel ) { TJ::Task *parent = m_tjProject->getTask( rel->parent()->id() ); TJ::TaskDependency *d = parent->addPrecedes( rel->child()->id() ); d->setGapDuration( 0, rel->lag().seconds() ); } void PlanTJScheduler::addDependencies( KPlato::Task *task ) { foreach ( Relation *r, task->dependParentNodes() + task->parentProxyRelations() ) { Node *n = r->parent(); if ( n == 0 || n->type() == Node::Type_Summarytask ) { continue; } switch ( r->type() ) { case Relation::FinishStart: break; case Relation::FinishFinish: case Relation::StartStart: warnPlan<<"Dependency type not handled. Using FinishStart."; logWarning( task, 0, xi18nc( "@info/plain" , "Dependency type '%1' not handled. Using FinishStart.", r->typeToString( true ) ) ); break; } switch ( task->constraint() ) { case Node::ASAP: case Node::ALAP: addPrecedes( r ); addDepends( r ); break; case Node::MustStartOn: case Node::StartNotEarlier: addPrecedes( r ); if ( task->constraintStartTime() < m_project->constraintStartTime() ) { addDepends( r ); } break; case Node::MustFinishOn: case Node::FinishNotLater: addDepends( r ); if ( task->constraintEndTime() < m_project->constraintEndTime() ) { addPrecedes( r ); } break; case Node::FixedInterval: break; } } } void PlanTJScheduler::addDependencies() { foreach ( Task *t, m_taskmap ) { addDependencies( t ); } } void PlanTJScheduler::setConstraints() { QMap ::const_iterator it = m_taskmap.constBegin(); for ( ; it != m_taskmap.constEnd(); ++it ) { setConstraint( it.key(), it.value() ); } } void PlanTJScheduler::setConstraint( TJ::Task *job, KPlato::Task *task ) { switch ( task->constraint() ) { case Node::ASAP: if ( ! job->isMilestone() ) { job->setScheduling( m_backward ? TJ::Task::ALAP : TJ::Task::ASAP ); } break; case Node::ALAP: job->setScheduling( TJ::Task::ALAP); break; case Node::MustStartOn: if ( task->constraintStartTime() >= m_project->constraintStartTime() ) { job->setPriority( 600 ); job->setSpecifiedStart( 0, task->constraintStartTime().toTime_t() ); logDebug( task, 0, QString( "MSO: set specified start: %1").arg( TJ::time2ISO( task->constraintStartTime().toTime_t() ) ) ); } else { logWarning( task, 0, xi18nc( "@info/plain", "%1: Invalid start constraint", task->constraintToString( true ) ) ); } break; case Node::StartNotEarlier: { break; } case Node::MustFinishOn: if ( task->constraintEndTime() <= m_project->constraintEndTime() ) { job->setPriority( 600 ); job->setScheduling( TJ::Task::ALAP ); job->setSpecifiedEnd( 0, task->constraintEndTime().toTime_t() - 1 ); logDebug( task, 0, QString( "MFO: set specified end: %1").arg( TJ::time2ISO( task->constraintEndTime().toTime_t() ) ) ); } else { logWarning( task, 0, xi18nc( "@info/plain", "%1: Invalid end constraint", task->constraintToString( true ) ) ); } break; case Node::FinishNotLater: { break; } case Node::FixedInterval: { job->setPriority( 700 ); TJ::Interval i( toTJInterval( task->constraintStartTime(), task->constraintEndTime(), tjGranularity() ) ); job->setSpecifiedPeriod( 0, i ); // estimate not allowed job->setDuration( 0, 0.0 ); job->setLength( 0, 0.0 ); job->setEffort( 0, 0.0 ); logDebug( task, 0, QString( "FI: set specified: %1 - %2 -> %3 - %4 (%5)") .arg( TJ::time2ISO( task->constraintStartTime().toTime_t() ) ) .arg( TJ::time2ISO( task->constraintEndTime().toTime_t() ) ) .arg( TJ::time2ISO( i.getStart() ) ) .arg( TJ::time2ISO( i.getEnd() ) ) .arg( tjGranularity() ) ); break; } default: logWarning( task, 0, xi18nc( "@info/plain", "Unhandled time constraint type" ) ); break; } } TJ::Task *PlanTJScheduler::addStartNotEarlier( Node *task ) { DateTime time = task->constraintStartTime(); if ( task->estimate()->type() == Estimate::Type_Duration && task->estimate()->calendar() != 0 ) { Calendar *cal = task->estimate()->calendar(); if ( cal != m_project->defaultCalendar() && cal != m_project->calendars().value( 0 ) ) { logWarning( task, 0, xi18nc( "@info/plain", "Could not use the correct calendar for calculation of task duration" ) ); } else { time = cal->firstAvailableAfter( time, m_project->constraintEndTime() ); } } TJ::Task *p = new TJ::Task( m_tjProject, QString("%1-sne").arg( m_tjProject->taskCount() + 1 ), task->name() + "-sne", 0, QString(), 0 ); p->setSpecifiedStart( 0, toTJTime_t( time, tjGranularity() ) ); p->setSpecifiedEnd( 0, m_tjProject->getEnd() - 1 ); qDebug()<<"PlanTJScheduler::addStartNotEarlier:"<constraintEndTime(); if ( task->estimate()->type() == Estimate::Type_Duration && task->estimate()->calendar() != 0 ) { Calendar *cal = task->estimate()->calendar(); if ( cal != m_project->defaultCalendar() && cal != m_project->calendars().value( 0 ) ) { logWarning( task, 0, xi18nc( "@info/plain", "Could not use the correct calendar for calculation of task duration" ) ); } else { time = cal->firstAvailableBefore( time, m_project->constraintStartTime() ); } } TJ::Task *p = new TJ::Task( m_tjProject, QString("%1-fnl").arg( m_tjProject->taskCount() + 1 ), task->name() + "-fnl", 0, QString(), 0 ); p->setSpecifiedEnd( 0, toTJTime_t( time, tjGranularity() ) - 1 ); p->setSpecifiedStart( 0, m_tjProject->getStart() ); return p; } void PlanTJScheduler::addRequests() { debugPlan; QMap ::const_iterator it = m_taskmap.constBegin(); for ( ; it != m_taskmap.constEnd(); ++it ) { addRequest( it.key(), it.value() ); } } void PlanTJScheduler::addRequest( TJ::Task *job, Task *task ) { debugPlan; if ( task->type() == Node::Type_Milestone || task->estimate() == 0 || ( m_recalculate && task->completion().isFinished() ) ) { job->setMilestone( true ); job->setDuration( 0, 0.0 ); return; } // Note: FI tasks can never have an estimate set (duration, length or effort) if ( task->constraint() != Node::FixedInterval ) { if ( task->estimate()->type() == Estimate::Type_Duration && task->estimate()->calendar() == 0 ) { job->setDuration( 0, task->estimate()->value( Estimate::Use_Expected, m_usePert ).toDouble( Duration::Unit_d ) ); return; } if ( task->estimate()->type() == Estimate::Type_Duration && task->estimate()->calendar() != 0 ) { job->setLength( 0, task->estimate()->value( Estimate::Use_Expected, m_usePert ).toDouble( Duration::Unit_d ) * 24.0 / m_tjProject->getDailyWorkingHours() ); return; } if ( m_recalculate && task->completion().isStarted() ) { job->setEffort( 0, task->completion().remainingEffort().toDouble( Duration::Unit_d ) ); } else { Estimate *estimate = task->estimate(); double e = estimate->scale( estimate->value( Estimate::Use_Expected, m_usePert ), Duration::Unit_d, estimate->scales() ); job->setEffort( 0, e ); } } if ( task->requests().isEmpty() ) { return; } foreach ( ResourceRequest *rr, task->requests().resourceRequests( true /*resolveTeam*/ ) ) { if (!rr->resource()->calendar()) { result = 1; // stops scheduling logError(task, 0, i18n("No working hours defined for resource: %1",rr->resource()->name())); continue; // may happen if no calendar is set, and no default calendar } TJ::Resource *tjr = addResource( rr->resource() ); TJ::Allocation *a = new TJ::Allocation(); a->setSelectionMode( TJ::Allocation::order ); if ( rr->units() != 100 ) { TJ::UsageLimits *l = new TJ::UsageLimits(); l->setDailyUnits( rr->units() ); a->setLimits( l ); } a->addCandidate( tjr ); job->addAllocation( a ); logDebug( task, 0, "Added resource candidate: " + rr->resource()->name() ); foreach ( Resource *r, rr->requiredResources() ) { TJ::Resource *tr = addResource( r ); a->addRequiredResource( tjr, tr ); logDebug( task, 0, "Added required resource: " + r->name() ); } } } diff --git a/src/plugins/schedulers/tj/PlanTJScheduler.h b/src/plugins/schedulers/tj/PlanTJScheduler.h index fcf8d2a0..07542c87 100644 --- a/src/plugins/schedulers/tj/PlanTJScheduler.h +++ b/src/plugins/schedulers/tj/PlanTJScheduler.h @@ -1,138 +1,138 @@ /* This file is part of the KDE project * Copyright (C) 2009 Dag Andersen * Copyright (C) 2011 Dag Andersen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef PLANTJSCHEDULER_H #define PLANTJSCHEDULER_H #include "plantj_export.h" #include "kptschedulerplugin.h" #include "kptdatetime.h" #include #include #include #include class QDateTime; namespace TJ { class Project; class Task; class Resource; class Interval; class CoreAttributes; } namespace KPlato { class Project; class ScheduleManager; class Schedule; class MainSchedule; class Resource; class Task; class Node; class Relation; } using namespace KPlato; class PlanTJScheduler : public KPlato::SchedulerThread { Q_OBJECT private: public: PlanTJScheduler( Project *project, ScheduleManager *sm, ulong granularity, QObject *parent = 0 ); ~PlanTJScheduler(); bool check(); bool solve(); int result; /// Fill project data into TJ structure bool kplatoToTJ(); /// Fetch project data from TJ structure bool kplatoFromTJ(); Q_SIGNALS: - void sigCalculationStarted( Project*, ScheduleManager* ); - void sigCalculationFinished( Project*, ScheduleManager* ); + void sigCalculationStarted(KPlato::Project*, KPlato::ScheduleManager*); + void sigCalculationFinished(KPlato::Project*, KPlato::ScheduleManager*); const char* taskname(); public Q_SLOTS: void slotMessage( int type, const QString &msg, TJ::CoreAttributes *object ); protected: void run(); void adjustSummaryTasks( const QList &nodes ); TJ::Resource *addResource( KPlato::Resource *resource ); void addTasks(); void addWorkingTime( KPlato::Task *task, TJ::Task *job ); TJ::Task *addTask( KPlato::Task *task , TJ::Task *parent = 0 ); void addDependencies(); void addPrecedes( const Relation *rel ); void addDepends( const Relation *rel ); void addDependencies( Task *task ); void setConstraints(); void setConstraint( TJ::Task *job, KPlato::Task *task ); TJ::Task *addStartNotEarlier( Node *task ); TJ::Task *addFinishNotLater( Node *task ); void addRequests(); void addRequest( TJ::Task *job, Task *task ); void addStartEndJob(); bool taskFromTJ( TJ::Task *job, Task *task ); void calcPertValues( Task *task ); Duration calcPositiveFloat( Task *task ); static bool exists( QList &lst, CalendarDay *day ); static int toTJDayOfWeek( int day ); static DateTime fromTime_t( time_t, const QTimeZone &tz ); static time_t toTJTime_t( const QDateTime &dt, ulong granularity ); AppointmentInterval fromTJInterval( const TJ::Interval &tji, const QTimeZone &tz ); static TJ::Interval toTJInterval( const QDateTime &start, const QDateTime &end, ulong tjGranularity ); static TJ::Interval toTJInterval( const QTime &start, const QTime &end, ulong tjGranularity ); private: ulong tjGranularity() const; private: MainSchedule *m_schedule; bool m_recalculate; bool m_usePert; bool m_backward; TJ::Project *m_tjProject; // Task *m_backwardTask; QMap m_taskmap; QMap m_resourcemap; ulong m_granularity; }; #endif // PLANTJSCHEDULER_H diff --git a/src/workpackage/part.cpp b/src/workpackage/part.cpp index 67e4e78c..3adfaf61 100644 --- a/src/workpackage/part.cpp +++ b/src/workpackage/part.cpp @@ -1,841 +1,841 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999, 2000 Torben Weis Copyright (C) 2004 - 2009 Dag Andersen Copyright (C) 2006 Raphael Langerhorst Copyright (C) 2007 Thorsten Zachmann Copyright (C) 2007 - 2009, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "part.h" #include "view.h" #include "factory.h" #include "mainwindow.h" #include "workpackage.h" #include "KPlatoXmlLoader.h" //NB! #include "kptglobal.h" #include "kptnode.h" #include "kptproject.h" #include "kpttask.h" #include "kptdocuments.h" #include "kptcommand.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 "debugarea.h" using namespace KPlato; namespace KPlatoWork { //------------------------------- DocumentChild::DocumentChild( WorkPackage *parent) : QObject( parent ), m_doc( 0 ), m_type( Type_Unknown ), m_copy( false ), m_process( 0 ), m_editor( 0 ), m_editormodified( false ), m_filemodified( false ), m_fileSystemWatcher(new QFileSystemWatcher(this)) { } // DocumentChild::DocumentChild( KParts::ReadWritePart *editor, const QUrl &url, const Document *doc, Part *parent) // : KoDocumentChild( parent ), // m_doc( doc ), // m_type( Type_Unknown ), // m_copy( true ), // m_process( 0 ), // m_editor( editor ), // m_editormodified( false ), // m_filemodified( false ) // { // setFileInfo( url ); // if ( dynamic_cast( editor ) ) { // debugPlanWork<<"Creating Calligra doc"; // m_type = Type_Calligra; // connect( static_cast( editor ), SIGNAL(modified(bool)), this, SLOT(setModified(bool)) ); // } else { // debugPlanWork<<"Creating KParts doc"; // m_type = Type_KParts; // slotUpdateModified(); // } // } DocumentChild::~DocumentChild() { debugPlanWork; disconnect(m_fileSystemWatcher, SIGNAL(fileChanged(QString)), this, SLOT(slotDirty(QString))); m_fileSystemWatcher->removePath( filePath() ); if ( m_type == Type_Calligra || m_type == Type_KParts ) { delete m_editor; } } WorkPackage *DocumentChild::parentPackage() const { return static_cast( parent() ); } void DocumentChild::setFileInfo( const QUrl &url ) { m_fileinfo.setFile( url.path() ); //debugPlanWork<addPath( filePath() ); } void DocumentChild::setModified( bool mod ) { debugPlanWork<isModified() != m_editormodified ) ) { setModified( m_editor->isModified() ); } QTimer::singleShot( 500, this, SLOT(slotUpdateModified()) ); } bool DocumentChild::setDoc( const Document *doc ) { Q_ASSERT ( m_doc == 0 ); if ( isOpen() ) { KMessageBox::error( 0, i18n( "Document is already open:
%1", doc->url().url() ) ); return false; } m_doc = doc; QUrl url; if ( parentPackage()->newDocuments().contains( doc ) ) { url = parentPackage()->newDocuments().value( doc ); Q_ASSERT( url.isValid() ); parentPackage()->removeNewDocument( doc ); } else if ( doc->sendAs() == Document::SendAs_Copy ) { url = parentPackage()->extractFile( doc ); if ( url.url().isEmpty() ) { KMessageBox::error( 0, i18n( "Could not extract document from storage:
%1", doc->url().url() ) ); return false; } m_copy = true; } else { url = doc->url(); } if ( ! url.isValid() ) { KMessageBox::error( 0, i18n( "Invalid URL:
%1", url.url() ) ); return false; } setFileInfo( url ); return true; } bool DocumentChild::openDoc( const Document *doc, KoStore *store ) { Q_ASSERT ( m_doc == 0 ); if ( isOpen() ) { KMessageBox::error( 0, i18n( "Document is already open:
%1", doc->url().path() ) ); return false; } m_doc = doc; QUrl url; if ( doc->sendAs() == Document::SendAs_Copy ) { url = parentPackage()->extractFile( doc, store ); if ( url.url().isEmpty() ) { KMessageBox::error( 0, i18n( "Could not extract document from storage:
%1", doc->url().path() ) ); return false; } m_copy = true; } else { url = doc->url(); } if ( ! url.isValid() ) { KMessageBox::error( 0, i18n( "Invalid URL:
%1", url.url() ) ); return false; } setFileInfo( url ); return true; } bool DocumentChild::editDoc() { Q_ASSERT( m_doc != 0 ); debugPlanWork<<"file:"< %1", m_doc->url().path() ) ); return false; } if ( ! m_fileinfo.exists() ) { KMessageBox::error( 0, i18n( "File does not exist:
%1", fileName() ) ); return false; } QUrl filename = QUrl::fromLocalFile( filePath() ); const QMimeType mimetype = QMimeDatabase().mimeTypeForUrl( filename ); KService::Ptr service = KMimeTypeTrader::self()->preferredService( mimetype.name() ); bool editing = startProcess( service, filename ); if ( editing ) { m_type = Type_Other; // FIXME: try to be more specific } return editing; } bool DocumentChild::startProcess( KService::Ptr service, const QUrl &url ) { QStringList args; QList files; if ( url.isValid() ) { files << url; } if ( service ) { KIO::DesktopExecParser parser(*service, files); parser.setUrlsAreTempFiles(false); args = parser.resultingArguments(); } else { QList list; QPointer dlg = new KOpenWithDialog( list, i18n("Edit with:"), QString(), 0 ); if ( dlg->exec() == QDialog::Accepted && dlg ){ args << dlg->text(); } if ( args.isEmpty() ) { debugPlanWork<<"No executable selected"; return false; } args << url.url(); delete dlg; } debugPlanWork<setProgram( args ); connect( m_process, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(slotEditFinished(int,QProcess::ExitStatus)) ); connect( m_process, SIGNAL(error(QProcess::ProcessError)), SLOT(slotEditError(QProcess::ProcessError)) ); m_process->start(); //debugPlanWork<pid()<program(); return true; } bool DocumentChild::isModified() const { return m_editormodified; } bool DocumentChild::isFileModified() const { return m_filemodified; } void DocumentChild::slotEditFinished( int /*par*/, QProcess::ExitStatus ) { //debugPlanWork<deleteLater(); m_process = 0; } else debugPlanWork<<"Error="<removePath( filePath() ); bool ok = false; bool wasmod = m_filemodified; if ( m_type == Type_Calligra || m_type == Type_KParts ) { if ( m_editor->isModified() ) { ok = m_editor->save(); // hmmmm } else { ok = true; } } else if ( m_type == Type_Other ) { if ( isOpen() ) { warnPlanWork<<"External editor open"; } ok = true; } else { errorPlanWork<<"Unknown document type"; } if ( ok ) { debugPlanWork<<"Add to store:"<addLocalFile( filePath(), fileName() ); m_filemodified = false; if ( wasmod != m_filemodified ) { emit fileModified( m_filemodified ); } } m_fileSystemWatcher->addPath( filePath() ); return ok; } //------------------------------------ Part::Part( QWidget *parentWidget, QObject *parent, const QVariantList & /*args*/ ) : KParts::ReadWritePart( parent ), m_xmlLoader(), m_modified( false ), m_loadingFromProjectStore( false ), m_undostack( new KUndo2QStack( this ) ) { debugPlanWork; setComponentData( *Factory::aboutData() ); if ( isReadWrite() ) { setXMLFile( "calligraplanwork.rc" ); } else { setXMLFile( "calligraplanwork_readonly.rc" ); } View *v = new View( this, parentWidget, actionCollection() ); setWidget( v ); - connect( v, SIGNAL(viewDocument(Document*)), SLOT(viewWorkpackageDocument(Document*)) ); + connect( v, SIGNAL(viewDocument(KPlato::Document*)), SLOT(viewWorkpackageDocument(KPlato::Document*)) ); loadWorkPackages(); connect( m_undostack, SIGNAL(cleanChanged(bool)), SLOT(setDocumentClean(bool)) ); } Part::~Part() { debugPlanWork; // m_config.save(); qDeleteAll( m_packageMap ); } void Part::addCommand( KUndo2Command *cmd ) { if ( cmd ) { m_undostack->push( cmd ); } } bool Part::setWorkPackage( WorkPackage *wp, KoStore *store ) { //debugPlanWork; QString id = wp->id(); if ( m_packageMap.contains( id ) ) { if ( KMessageBox::warningYesNo( 0, i18n("

The work package already exists in the projects store.

" "

Project: %1
Task: %2

" "

Do you want to update the existing package with data from the new?

", wp->project()->name(), wp->node()->name()) ) == KMessageBox::No ) { delete wp; return false; } m_packageMap[ id ]->merge( this, wp, store ); delete wp; return true; } wp->setFilePath( m_loadingFromProjectStore ? wp->fileName( this ) : localFilePath() ); m_packageMap[ id ] = wp; if ( ! m_loadingFromProjectStore ) { wp->saveToProjects( this ); } connect( wp->project(), SIGNAL(projectChanged()), wp, SLOT(projectChanged()) ); connect ( wp, SIGNAL(modified(bool)), this, SLOT(setModified(bool)) ); emit workPackageAdded( wp, indexOf( wp ) ); - connect(wp, SIGNAL(saveWorkPackage(WorkPackage*)), SLOT(saveWorkPackage(WorkPackage*))); + connect(wp, SIGNAL(saveWorkPackage(KPlatoWork::WorkPackage*)), SLOT(saveWorkPackage(KPlatoWork::WorkPackage*))); return true; } void Part::removeWorkPackage( Node *node, MacroCommand *m ) { //debugPlanWork<name(); WorkPackage *wp = findWorkPackage( node ); if ( wp == 0 ) { KMessageBox::error( 0, i18n("Remove failed. Cannot find work package") ); return; } PackageRemoveCmd *cmd = new PackageRemoveCmd( this, wp, kundo2_i18n( "Remove work package" ) ); if ( m ) { m->addCommand( cmd ); } else { addCommand( cmd ); } } void Part::removeWorkPackages( const QList &nodes ) { //debugPlanWork<name(); MacroCommand *m = new MacroCommand( kundo2_i18np( "Remove work package", "Remove work packages", nodes.count() ) ); foreach ( Node *n, nodes ) { removeWorkPackage( n, m ); } if ( m->isEmpty() ) { delete m; } else { addCommand( m ); } } void Part::removeWorkPackage( WorkPackage *wp ) { //debugPlanWork; int row = indexOf( wp ); if ( row >= 0 ) { m_packageMap.remove( m_packageMap.keys().at( row ) ); emit workPackageRemoved( wp, row ); } } void Part::addWorkPackage( WorkPackage *wp ) { //debugPlanWork; QString id = wp->id(); Q_ASSERT( ! m_packageMap.contains( id ) ); m_packageMap[ id ] = wp; emit workPackageAdded( wp, indexOf( wp ) ); } bool Part::loadWorkPackages() { m_loadingFromProjectStore = true; const QStringList lst = KoResourcePaths::findAllResources( "projects", "*.planwork", KoResourcePaths::Recursive | KoResourcePaths::NoDuplicates ); //debugPlanWork<%1" , file ) ); } } m_loadingFromProjectStore = false; return true; } bool Part::loadNativeFormatFromStore(const QString& file) { debugPlanWork<bad()) { KMessageBox::error( 0, i18n("Not a valid work package file:
%1", file) ); delete store; QApplication::restoreOverrideCursor(); return false; } const bool success = loadNativeFormatFromStoreInternal(store); delete store; return success; } bool Part::loadNativeFormatFromStoreInternal(KoStore * store) { if (store->hasFile("root")) { KoXmlDocument doc; bool ok = loadAndParse(store, "root", doc); if (ok) { ok = loadXML(doc, store); } if (!ok) { QApplication::restoreOverrideCursor(); return false; } } else { errorPlanWork << "ERROR: No maindoc.xml" << endl; KMessageBox::error( 0, i18n("Invalid document. The document does not contain 'maindoc.xml'.") ); QApplication::restoreOverrideCursor(); return false; } // if (store->hasFile("documentinfo.xml")) { // KoXmlDocument doc; // if (oldLoadAndParse(store, "documentinfo.xml", doc)) { // d->m_docInfo->load(doc); // } // } else { // //debugPlanWork <<"cannot open document info"; // delete d->m_docInfo; // d->m_docInfo = new KoDocumentInfo(this); // } bool res = completeLoading(store); QApplication::restoreOverrideCursor(); return res; } bool Part::loadAndParse(KoStore* store, const QString& filename, KoXmlDocument& doc) { //debugPlanWork <<"Trying to open" << filename; if (!store->open(filename)) { warnPlanWork << "Entry " << filename << " not found!"; KMessageBox::error( 0, i18n("Failed to open file: %1", filename) ); return false; } // Error variables for QDomDocument::setContent QString errorMsg; int errorLine, errorColumn; bool ok = doc.setContent(store->device(), &errorMsg, &errorLine, &errorColumn); store->close(); if (!ok) { errorPlanWork << "Parsing error in " << filename << "! Aborting!" << endl << " In line: " << errorLine << ", column: " << errorColumn << endl << " Error message: " << errorMsg; KMessageBox::error( 0, i18n("Parsing error in file '%1' at line %2, column %3
Error message: %4", filename , errorLine, errorColumn , QCoreApplication::translate("QXml", errorMsg.toUtf8(), 0) ) ); return false; } return true; } bool Part::loadXML( const KoXmlDocument &document, KoStore* store ) { debugPlanWork; QString value; KoXmlElement plan = document.documentElement(); // Check if this is the right app value = plan.attribute( "mime", QString() ); if ( value.isEmpty() ) { errorPlanWork << "No mime type specified!" << endl; KMessageBox::error( 0, i18n( "Invalid document. No mimetype specified." ) ); return false; } else if ( value == "application/x-vnd.kde.kplato.work" ) { return loadKPlatoXML( document, store ); } else if ( value != "application/x-vnd.kde.plan.work" ) { errorPlanWork << "Unknown mime type " << value; KMessageBox::error( 0, i18n( "Invalid document. Expected mimetype application/x-vnd.kde.plan.work, got %1", value ) ); return false; } QString syntaxVersion = plan.attribute( "version", PLANWORK_FILE_SYNTAX_VERSION ); m_xmlLoader.setWorkVersion( syntaxVersion ); if ( syntaxVersion > PLANWORK_FILE_SYNTAX_VERSION ) { KMessageBox::ButtonCode ret = KMessageBox::warningContinueCancel( 0, i18n( "This document is a newer version than supported by PlanWork (syntax version: %1)
" "Opening it in this version of PlanWork will lose some information.", syntaxVersion ), i18n( "File-Format Mismatch" ), KGuiItem( i18n( "Continue" ) ) ); if ( ret == KMessageBox::Cancel ) { return false; } } m_xmlLoader.setVersion( plan.attribute( "plan-version", PLAN_FILE_SYNTAX_VERSION ) ); m_xmlLoader.startLoad(); WorkPackage *wp = new WorkPackage( m_loadingFromProjectStore ); wp->loadXML( plan, m_xmlLoader ); m_xmlLoader.stopLoad(); if ( ! setWorkPackage( wp, store ) ) { // rejected, so nothing changed... return true; } emit changed(); return true; } bool Part::loadKPlatoXML( const KoXmlDocument &document, KoStore* ) { debugPlanWork; QString value; KoXmlElement plan = document.documentElement(); // Check if this is the right app value = plan.attribute( "mime", QString() ); if ( value.isEmpty() ) { errorPlanWork << "No mime type specified!" << endl; KMessageBox::error( 0, i18n( "Invalid document. No mimetype specified." ) ); return false; } else if ( value != "application/x-vnd.kde.kplato.work" ) { errorPlanWork << "Unknown mime type " << value; KMessageBox::error( 0, i18n( "Invalid document. Expected mimetype application/x-vnd.kde.kplato.work, got %1", value ) ); return false; } QString syntaxVersion = plan.attribute( "version", KPLATOWORK_MAX_FILE_SYNTAX_VERSION ); m_xmlLoader.setWorkVersion( syntaxVersion ); if ( syntaxVersion > KPLATOWORK_MAX_FILE_SYNTAX_VERSION ) { KMessageBox::ButtonCode ret = KMessageBox::warningContinueCancel( 0, i18n( "This document is a newer version than supported by PlanWork (syntax version: %1)
" "Opening it in this version of PlanWork will lose some information.", syntaxVersion ), i18n( "File-Format Mismatch" ), KGuiItem( i18n( "Continue" ) ) ); if ( ret == KMessageBox::Cancel ) { return false; } } m_xmlLoader.setMimetype( value ); m_xmlLoader.setVersion( plan.attribute( "kplato-version", KPLATO_MAX_FILE_SYNTAX_VERSION ) ); m_xmlLoader.startLoad(); WorkPackage *wp = new WorkPackage( m_loadingFromProjectStore ); wp->loadKPlatoXML( plan, m_xmlLoader ); m_xmlLoader.stopLoad(); if ( ! setWorkPackage( wp ) ) { // rejected, so nothing changed... return true; } emit changed(); return true; } bool Part::completeLoading( KoStore * ) { return true; } QUrl Part::extractFile( const Document *doc ) { WorkPackage *wp = findWorkPackage( doc ); return wp == 0 ? QUrl() : wp->extractFile( doc ); } int Part::docType( const Document *doc ) const { DocumentChild *ch = findChild( doc ); if ( ch == 0 ) { return DocumentChild::Type_Unknown; } return ch->type(); } DocumentChild *Part::findChild( const Document *doc ) const { foreach ( const WorkPackage *wp, m_packageMap ) { DocumentChild *c = wp->findChild( doc ); if ( c ) { return c; } } return 0; } WorkPackage *Part::findWorkPackage( const Document *doc ) const { foreach ( const WorkPackage *wp, m_packageMap ) { if ( wp->contains( doc ) ) { return const_cast( wp ); } } return 0; } WorkPackage *Part::findWorkPackage( const DocumentChild *child ) const { foreach ( const WorkPackage *wp, m_packageMap ) { if ( wp->contains( child ) ) { return const_cast( wp ); } } return 0; } WorkPackage *Part::findWorkPackage( const Node *node ) const { return m_packageMap.value( node->projectNode()->id() + node->id() ); } bool Part::editWorkpackageDocument( const Document *doc ) { //debugPlanWork<url(); // start in any suitable application return editOtherDocument( doc ); } bool Part::editOtherDocument( const Document *doc ) { Q_ASSERT( doc != 0 ); //debugPlanWork<url(); WorkPackage *wp = findWorkPackage( doc ); if ( wp == 0 ) { KMessageBox::error( 0, i18n( "Edit failed. Cannot find a work package." ) ); return false; } return wp->addChild( this, doc ); } void Part::viewWorkpackageDocument( Document *doc ) { debugPlanWork<sendAs() == Document::SendAs_Copy ) { filename = extractFile( doc ); } else { filename = doc->url(); } // open for view viewDocument( filename ); } bool Part::removeDocument( Document *doc ) { if ( doc == 0 ) { return false; } WorkPackage *wp = findWorkPackage( doc ); if ( wp == 0 ) { return false; } return wp->removeDocument( this, doc ); } bool Part::viewDocument( const QUrl &filename ) { debugPlanWork<<"url:"<isModified() ) { saveWorkPackage( wp ); } } m_undostack->setClean(); } void Part::saveWorkPackage( WorkPackage *wp ) { wp->saveToProjects( this ); } bool Part::saveWorkPackages( bool silent ) { debugPlanWork<saveToProjects( this ); } m_undostack->setClean(); return true; } bool Part::completeSaving( KoStore */*store*/ ) { return true; } QDomDocument Part::saveXML() { debugPlanWork; return QDomDocument(); } bool Part::queryClose() { debugPlanWork; QList modifiedList; foreach ( WorkPackage *wp, m_packageMap ) { switch ( wp->queryClose( this ) ) { case KMessageBox::No: modifiedList << wp; break; case KMessageBox::Cancel: debugPlanWork<<"Cancel"; return false; } } // closeEvent calls queryClose so modified must be reset or else wps are queried all over again foreach ( WorkPackage *wp, modifiedList ) { wp->setModified( false ); } setModified( false ); return true; } bool Part::openFile() { debugPlanWork< Copyright (C) 2004 - 2009 Dag Andersen Copyright (C) 2006 Raphael Langerhorst Copyright (C) 2007 Thorsten Zachmann Copyright (C) 2007 - 2009 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 KPLATOWORK_PART_H #define KPLATOWORK_PART_H #include "planwork_export.h" #include "kptxmlloaderobject.h" #include #include #include #include #include class KUndo2QStack; class KoStore; class KProcess; class QFileSystemWatcher; namespace KPlato { class Project; class Document; class MacroCommand; } using namespace KPlato; /// The main namespace for KPlato WorkPackage Handler namespace KPlatoWork { class Part; class WorkPackage; /** * DocumentChild stores info about documents opened for editing. * Editors can be KParts, Calligra or Other. */ class DocumentChild : public QObject { Q_OBJECT public: // The type of document this child handles enum DocType { Type_Unknown = 0, Type_Calligra, Type_KParts, Type_Other }; explicit DocumentChild( WorkPackage *parent ); // DocumentChild( KParts::ReadWritePart *editor, const QUrl &url, const Document *doc, Part *parent); ~DocumentChild(); WorkPackage *parentPackage() const; const Document *doc() const { return m_doc; } /// Set document, return true if ok, false if failure bool setDoc( const Document *doc ); /// Open @p doc from @p store bool openDoc( const Document *doc, KoStore *store ); /// Open document for editing, return true if ok, false if failure bool editDoc(); bool isOpen() const { return m_process != 0; } bool isModified() const; bool isFileModified() const; QString fileName() const { return m_fileinfo.fileName(); } QString filePath() const { return m_fileinfo.canonicalFilePath(); } void setFileInfo( const QUrl &url ); const QFileInfo &fileInfo() const { return m_fileinfo; } QUrl url() const { return QUrl::fromLocalFile( filePath() ); } KParts::ReadWritePart *editor() const { return m_editor; } bool startProcess( KService::Ptr service, const QUrl &url = QUrl() ); int type() const { return m_type; } void setType( int type ) { m_type = type; } bool saveToStore( KoStore *store ); Q_SIGNALS: void modified( bool ); void fileModified( bool ); public Q_SLOTS: void setModified( bool mod ); protected Q_SLOTS: void slotEditFinished( int, QProcess::ExitStatus ); void slotEditError( QProcess::ProcessError status ); void slotDirty( const QString &file ); void slotUpdateModified(); protected: const Document *m_doc; int m_type; bool m_copy; KProcess *m_process; // Used if m_type == Type_Other; KParts::ReadWritePart *m_editor; // 0 if m_type == Type_Other QFileInfo m_fileinfo; bool m_editormodified; bool m_filemodified; QFileSystemWatcher *m_fileSystemWatcher; }; /** This part handles work packages. A work package file consists of a Project node and one Task node along with scheduling information and assigned resources. */ class PLANWORK_EXPORT Part : public KParts::ReadWritePart { Q_OBJECT public: explicit Part( QWidget *parentWidget, QObject *parent, const QVariantList & /*args*/ = QVariantList() ); ~Part(); int docType( const Document *doc ) const; bool loadWorkPackages(); virtual bool loadXML( const KoXmlDocument &document, KoStore *store ); virtual QDomDocument saveXML(); bool saveAs( const QUrl &url ); /// Check if we have documents open for editing before saving virtual bool completeSaving( KoStore* store ); /// Extract document file from the store to disk QUrl extractFile( const Document *doc ); //Config &config() { return m_config; } /// Open Calligra document for editing // DocumentChild *openCalligraDocument( KMimeType::Ptr mimetype, const Document *doc ); /// Open KParts document for editing // DocumentChild *openKPartsDocument( KService::Ptr service, const Document *doc ); /// Open document for editing, return true if ok, false if failure bool editWorkpackageDocument( const Document *doc ); /// Open document for editing, return true if ok, false if failure bool editOtherDocument( const Document *doc ); /// Remove the document @p doc from its workpackage bool removeDocument( Document *doc ); /// Remove the child document // void removeChildDocument( DocumentChild *child ); /// Find the child that handles document @p doc DocumentChild *findChild( const Document *doc ) const; /// Add @p child document to work package @p wp // void addChild( WorkPackage *wp, DocumentChild *child ); /// Number of workpackages int workPackageCount() const { return m_packageMap.count(); } /// Work package at index WorkPackage *workPackage( int index ) const { return m_packageMap.values().value( index ); } /// Work package containing node WorkPackage *workPackage( Node *node ) const { return m_packageMap.value( node->projectNode()->id() + node->id() ); } int indexOf( WorkPackage *package ) const { return m_packageMap.values().indexOf( package ); } void addWorkPackage( WorkPackage *wp ); void removeWorkPackage( WorkPackage *wp ); void removeWorkPackage( Node *node, MacroCommand *m = 0 ); void removeWorkPackages( const QList &nodes ); /// Find the work package that handles document @p doc WorkPackage *findWorkPackage( const Document *doc ) const; /// Find the work package that handles document child @p child WorkPackage *findWorkPackage( const DocumentChild *child ) const; /// Find the work package that handles @p node WorkPackage *findWorkPackage( const Node *node ) const; /// Save all work packages bool saveWorkPackages( bool silent ); Node *node() const; bool queryClose(); bool openFile(); bool saveFile(); KUndo2QStack *undoStack() const { return m_undostack; } int commandIndex() const { return m_undostack->index(); } public Q_SLOTS: /** * Called by the undo stack when the document is saved or all changes has been undone * @param clean if the document's undo stack is clean or not */ virtual void setDocumentClean(bool clean); virtual void setModified( bool mod ); void saveModifiedWorkPackages(); - void saveWorkPackage( WorkPackage *wp ); + void saveWorkPackage(KPlatoWork::WorkPackage *wp ); void addCommand( KUndo2Command *cmd ); - void viewWorkpackageDocument( Document *doc ); + void viewWorkpackageDocument(KPlato::Document *doc); Q_SIGNALS: void changed(); - void workPackageAdded( WorkPackage *package, int index ); - void workPackageRemoved( WorkPackage *wp, int index ); + void workPackageAdded(KPlatoWork::WorkPackage *package, int index ); + void workPackageRemoved(KPlatoWork::WorkPackage *wp, int index ); void captionChanged( const QString&, bool ); protected: /// Load the old kplato format bool loadKPlatoXML( const KoXmlDocument &document, KoStore *store ); /// Adds work package @p wp to the list of workpackages. /// If it already exists, the user is asked if it shall be merged with the existing one. bool setWorkPackage( WorkPackage *wp, KoStore *store = 0 ); bool completeLoading( KoStore *store ); bool loadAndParse(KoStore* store, const QString& filename, KoXmlDocument& doc); bool loadNativeFormatFromStore(const QString& file); bool loadNativeFormatFromStoreInternal(KoStore * store); bool viewDocument( const QUrl &filename ); private: XMLLoaderObject m_xmlLoader; //Config m_config; QMap m_packageMap; bool m_modified; bool m_loadingFromProjectStore; KUndo2QStack *m_undostack; }; } //KPlatoWork namespace #endif diff --git a/src/workpackage/taskworkpackagemodel.cpp b/src/workpackage/taskworkpackagemodel.cpp index b51ffaca..f7750c2e 100644 --- a/src/workpackage/taskworkpackagemodel.cpp +++ b/src/workpackage/taskworkpackagemodel.cpp @@ -1,708 +1,708 @@ /* This file is part of the KDE project Copyright (C) 2009, 2011, 2012 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "taskworkpackagemodel.h" #include "part.h" #include "workpackage.h" #include "kptglobal.h" #include "kptresource.h" #include "kptproject.h" #include "kpttask.h" #include "kptcommand.h" #include "kptitemmodelbase.h" #include "kpttaskcompletedelegate.h" #include #include #include #include #include #include "debugarea.h" using namespace KPlato; namespace KPlatoWork { TaskWorkPackageModel::TaskWorkPackageModel( Part *part, QObject *parent ) : ItemModelBase( parent ), m_part( part ) { - connect( part, SIGNAL(workPackageAdded(WorkPackage*,int)), this, SLOT(addWorkPackage(WorkPackage*,int)) ); - connect( part, SIGNAL(workPackageRemoved(WorkPackage*,int)), this, SLOT(removeWorkPackage(WorkPackage*,int)) ); + connect( part, SIGNAL(workPackageAdded(KPlato::WorkPackage*,int)), this, SLOT(addWorkPackage(KPlato::WorkPackage*,int)) ); + connect( part, SIGNAL(workPackageRemoved(KPlato::WorkPackage*,int)), this, SLOT(removeWorkPackage(KPlato::WorkPackage*,int)) ); } Qt::ItemFlags TaskWorkPackageModel::flags( const QModelIndex &index ) const { Qt::ItemFlags flags = QAbstractItemModel::flags( index ); flags &= ~( Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled ); Node *n = nodeForIndex( index ); if ( n == 0 ) { return flags; } if ( n->type() != Node::Type_Task && n->type() != Node::Type_Milestone ) { return flags; } Task *t = static_cast( n ); if ( ! t->completion().isStarted() ) { switch ( index.column() ) { case NodeActualStart: flags |= Qt::ItemIsEditable; break; case NodeCompleted: flags |= Qt::ItemIsEditable; break; default: break; } } else if ( ! t->completion().isFinished() ) { // task is running switch ( index.column() ) { case NodeActualFinish: case NodeCompleted: case NodeRemainingEffort: case NodeActualEffort: flags |= Qt::ItemIsEditable; break; default: break; } } return flags; } void TaskWorkPackageModel::slotNodeToBeInserted( Node *parent, int row ) { //debugPlanWork<name()<<"; "<parentNode()->name()<<"-->"<name(); endInsertRows(); } void TaskWorkPackageModel::slotNodeToBeRemoved( Node *node ) { //debugPlanWork<name(); int row = indexForNode( node ).row(); beginRemoveRows( indexForNode( node->parentNode() ), row, row ); } void TaskWorkPackageModel::slotNodeRemoved( Node */*node*/ ) { //debugPlanWork<name(); endRemoveRows(); } void TaskWorkPackageModel::slotNodeChanged( Node *node ) { if ( node == 0 || node->type() == Node::Type_Project ) { return; } int row = indexForNode( node ).row(); debugPlanWork<name()<parentNode() ), createIndex( row, columnCount()-1, node->parentNode() ) ); } void TaskWorkPackageModel::slotDocumentAdded( Node *node, Document */*doc*/, int row ) { QModelIndex parent = indexForNode( node ); if ( parent.isValid() ) { beginInsertRows( parent, row, row ); endInsertRows(); } } void TaskWorkPackageModel::slotDocumentRemoved( Node *node, Document */*doc*/, int row ) { QModelIndex parent = indexForNode( node ); if ( parent.isValid() ) { beginRemoveRows( parent, row, row ); endRemoveRows(); } } void TaskWorkPackageModel::slotDocumentChanged( Node *node, Document */*doc*/, int row ) { QModelIndex parent = indexForNode( node ); if ( parent.isValid() ) { emit dataChanged( index( row, 0, parent ), index( row, columnCount( parent ), parent ) ); } } void TaskWorkPackageModel::addWorkPackage( WorkPackage *package, int row ) { beginInsertRows( QModelIndex(), row, row ); Project *project = package->project(); endInsertRows(); if ( project ) { - connect( project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - connect( project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); - connect( project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); + connect( project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*)) ); + connect( project, SIGNAL(nodeToBeAdded(KPlato::Node*,int)), this, SLOT(slotNodeToBeInserted(KPlato::Node*,int)) ); + connect( project, SIGNAL(nodeToBeRemoved(KPlato::Node*)), this, SLOT(slotNodeToBeRemoved(KPlato::Node*)) ); - connect( project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); - connect( project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); + connect( project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeInserted(KPlato::Node*)) ); + connect( project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*)) ); - connect(project, SIGNAL(documentAdded(Node*,Document*,int)), this, SLOT(slotDocumentAdded(Node*,Document*,int))); - connect(project, SIGNAL(documentRemoved(Node*,Document*,int)), this, SLOT(slotDocumentRemoved(Node*,Document*,int))); - connect(project, SIGNAL(documentChanged(Node*,Document*,int)), this, SLOT(slotDocumentChanged(Node*,Document*,int))); + connect(project, SIGNAL(documentAdded(KPlato::Node*,KPlato::Document*,int)), this, SLOT(slotDocumentAdded(KPlato::Node*,KPlato::Document*,int))); + connect(project, SIGNAL(documentRemoved(KPlato::Node*,KPlato::Document*,int)), this, SLOT(slotDocumentRemoved(KPlato::Node*,KPlato::Document*,int))); + connect(project, SIGNAL(documentChanged(KPlato::Node*,KPlato::Document*,int)), this, SLOT(slotDocumentChanged(KPlato::Node*,KPlato::Document*,int))); } } void TaskWorkPackageModel::removeWorkPackage( WorkPackage *package, int row ) { beginRemoveRows( QModelIndex(), row, row ); Project *project = package->project(); debugPlanWork<project(); if ( project ) { - disconnect( project, SIGNAL(nodeChanged(Node*)), this, SLOT(slotNodeChanged(Node*)) ); - disconnect( project, SIGNAL(nodeToBeAdded(Node*,int)), this, SLOT(slotNodeToBeInserted(Node*,int)) ); - disconnect( project, SIGNAL(nodeToBeRemoved(Node*)), this, SLOT(slotNodeToBeRemoved(Node*)) ); + disconnect( project, SIGNAL(nodeChanged(KPlato::Node*)), this, SLOT(slotNodeChanged(KPlato::Node*)) ); + disconnect( project, SIGNAL(nodeToBeAdded(KPlato::Node*,int)), this, SLOT(slotNodeToBeInserted(KPlato::Node*,int)) ); + disconnect( project, SIGNAL(nodeToBeRemoved(KPlato::Node*)), this, SLOT(slotNodeToBeRemoved(KPlato::Node*)) ); - disconnect( project, SIGNAL(nodeAdded(Node*)), this, SLOT(slotNodeInserted(Node*)) ); - disconnect( project, SIGNAL(nodeRemoved(Node*)), this, SLOT(slotNodeRemoved(Node*)) ); + disconnect( project, SIGNAL(nodeAdded(KPlato::Node*)), this, SLOT(slotNodeInserted(KPlato::Node*)) ); + disconnect( project, SIGNAL(nodeRemoved(KPlato::Node*)), this, SLOT(slotNodeRemoved(KPlato::Node*)) ); - disconnect(project, SIGNAL(documentAdded(Node*,Document*,int)), this, SLOT(slotDocumentAdded(Node*,Document*,int))); - disconnect(project, SIGNAL(documentRemoved(Node*,Document*,int)), this, SLOT(slotDocumentRemoved(Node*,Document*,int))); - disconnect(project, SIGNAL(documentChanged(Node*,Document*,int)), this, SLOT(slotDocumentChanged(Node*,Document*,int))); + disconnect(project, SIGNAL(documentAdded(KPlato::Node*,KPlato::Document*,int)), this, SLOT(slotDocumentAdded(KPlato::Node*,KPlato::Document*,int))); + disconnect(project, SIGNAL(documentRemoved(KPlato::Node*,KPlato::Document*,int)), this, SLOT(slotDocumentRemoved(KPlato::Node*,KPlato::Document*,int))); + disconnect(project, SIGNAL(documentChanged(KPlato::Node*,KPlato::Document*,int)), this, SLOT(slotDocumentChanged(KPlato::Node*,KPlato::Document*,int))); } endRemoveRows(); } QVariant TaskWorkPackageModel::name( const Resource *r, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return r->name(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant TaskWorkPackageModel::email( const Resource *r, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: return r->email(); case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant TaskWorkPackageModel::projectName( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: { const Node *proj = node->projectNode(); return proj == 0 ? QVariant() : proj->name(); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } QVariant TaskWorkPackageModel::projectManager( const Node *node, int role ) const { switch ( role ) { case Qt::DisplayRole: case Qt::EditRole: case Qt::ToolTipRole: { const Node *proj = node->projectNode(); return proj == 0 ? QVariant() : proj->leader(); } case Qt::StatusTipRole: case Qt::WhatsThisRole: return QVariant(); } return QVariant(); } int TaskWorkPackageModel::rowCount( const QModelIndex &parent ) const { if ( ! parent.isValid() ) { //debugPlanWork<workPackageCount(); return m_part->workPackageCount(); // == no of nodes (1 node pr wp) } Node *n = nodeForIndex( parent ); if ( n ) { //debugPlanWork<documents().count(); return n->documents().count(); } //debugPlanWork<plannedEffort( CURRENTSCHEDULE, ECCT_EffortWork ); return v.format(); } default: break; } return QVariant(); } QVariant TaskWorkPackageModel::status( Node *n, int role ) const { return m_nodemodel.status( n, role ); } QVariant TaskWorkPackageModel::nodeData( Node *n, int column, int role ) const { if ( role >= Qt::UserRole ) { // debugPlanWork<name()<type() ) { case Node::Type_Task: return KGantt::TypeTask; default: break; } case KGantt::StartTimeRole: debugPlanWork<name()<<"start:"<startTime(); return m_nodemodel.data( n, NodeModel::NodeStartTime, Qt::EditRole ); case KGantt::EndTimeRole: debugPlanWork<name()<<"end:"<endTime(); return m_nodemodel.data( n, NodeModel::NodeEndTime, Qt::EditRole ); default: break; } } switch ( column ) { case NodeName: return m_nodemodel.data( n, NodeModel::NodeName, role ); case NodeType: return m_nodemodel.data( n, NodeModel::NodeType, role ); case NodeResponsible: return m_nodemodel.data( n, NodeModel::NodeResponsible, role ); case NodeDescription: return m_nodemodel.data( n, NodeModel::NodeDescription, role ); // After scheduling case NodeStartTime: return m_nodemodel.data( n, NodeModel::NodeStartTime, role ); case NodeEndTime: return m_nodemodel.data( n, NodeModel::NodeEndTime, role ); case NodeAssignments: return m_nodemodel.data( n, NodeModel::NodeAssignments, role ); // Completion case NodeCompleted: return m_nodemodel.data( n, NodeModel::NodeCompleted, role ); case NodeActualEffort: return m_nodemodel.data( n, NodeModel::NodeActualEffort, role ); case NodeRemainingEffort: return m_nodemodel.data( n, NodeModel::NodeRemainingEffort, role ); case NodePlannedEffort: return plannedEffort( n, role ); case NodeActualStart: return actualStart( n, role ); case NodeStarted: return m_nodemodel.data( n, NodeModel::NodeStarted, role ); case NodeActualFinish: return actualFinish( n, role ); case NodeFinished: return m_nodemodel.data( n, NodeModel::NodeFinished, role ); case NodeStatus: return status( n, role ); case NodeStatusNote: return m_nodemodel.data( n, NodeModel::NodeStatusNote, role ); case ProjectName: return projectName( n, role ); case ProjectManager: return projectManager( n, role ); default: //debugPlanWork<<"Invalid column number: "<url().fileName()<name(); case NodeType: return doc->typeToString( doc->type(), true ); case NodeStatusNote: return doc->status(); default: return ""; } } else if ( role == Qt::ToolTipRole ) { switch ( column ) { case NodeName: return doc->typeToString( doc->type(), true ); default: break; } } return QVariant(); } bool TaskWorkPackageModel::setCompletion( Node *node, const QVariant &value, int role ) { if ( role != Qt::EditRole ) { return false; } if ( node->type() == Node::Type_Task ) { Completion &c = static_cast( node )->completion(); QDate date = qMax( c.entryDate(), QDate::currentDate() ); QDateTime dt( date, QTime::currentTime() ); // xgettext: no-c-format MacroCommand *m = new MacroCommand( kundo2_i18n( "Modify completion" ) ); if ( ! c.isStarted() ) { m->addCommand( new ModifyCompletionStartedCmd( c, true ) ); m->addCommand( new ModifyCompletionStartTimeCmd( c, dt ) ); } m->addCommand( new ModifyCompletionPercentFinishedCmd( c, date, value.toInt() ) ); if ( value.toInt() == 100 ) { m->addCommand( new ModifyCompletionFinishedCmd( c, true ) ); m->addCommand( new ModifyCompletionFinishTimeCmd( c, dt ) ); } bool newentry = c.entryDate() < date; emit executeCommand( m ); // also adds a new entry if necessary if ( newentry ) { // new entry so calculate used/remaining based on completion Duration planned = static_cast( node )->plannedEffort( m_nodemodel.id() ); Duration actual = ( planned * value.toInt() ) / 100; debugPlanWork<execute(); m->addCommand( cmd ); cmd = new ModifyCompletionRemainingEffortCmd( c, date, planned - actual ); cmd->execute(); m->addCommand( cmd ); } else if ( c.isFinished() && c.remainingEffort() != 0 ) { ModifyCompletionRemainingEffortCmd *cmd = new ModifyCompletionRemainingEffortCmd( c, date, Duration::zeroDuration ); cmd->execute(); m->addCommand( cmd ); } return true; } if ( node->type() == Node::Type_Milestone ) { Completion &c = static_cast( node )->completion(); if ( value.toInt() > 0 ) { QDateTime dt = QDateTime::currentDateTime(); QDate date = dt.date(); MacroCommand *m = new MacroCommand( kundo2_i18n( "Set finished" ) ); m->addCommand( new ModifyCompletionStartedCmd( c, true ) ); m->addCommand( new ModifyCompletionStartTimeCmd( c, dt ) ); m->addCommand( new ModifyCompletionFinishedCmd( c, true ) ); m->addCommand( new ModifyCompletionFinishTimeCmd( c, dt ) ); m->addCommand( new ModifyCompletionPercentFinishedCmd( c, date, 100 ) ); emit executeCommand( m ); // also adds a new entry if necessary return true; } return false; } return false; } bool TaskWorkPackageModel::setRemainingEffort( Node *node, const QVariant &value, int role ) { if ( role == Qt::EditRole && node->type() == Node::Type_Task ) { Task *t = static_cast( node ); double d( value.toList()[0].toDouble() ); Duration::Unit unit = static_cast( value.toList()[1].toInt() ); Duration dur( d, unit ); emit executeCommand( new ModifyCompletionRemainingEffortCmd( t->completion(), QDate::currentDate(), dur, kundo2_i18n( "Modify remaining effort" ) ) ); return true; } return false; } bool TaskWorkPackageModel::setActualEffort( Node *node, const QVariant &value, int role ) { if ( role == Qt::EditRole && node->type() == Node::Type_Task ) { Task *t = static_cast( node ); double d( value.toList()[0].toDouble() ); Duration::Unit unit = static_cast( value.toList()[1].toInt() ); Duration dur( d, unit ); emit executeCommand( new ModifyCompletionActualEffortCmd( t->completion(), QDate::currentDate(), dur, kundo2_i18n( "Modify actual effort" ) ) ); return true; } return false; } bool TaskWorkPackageModel::setStartedTime( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { Task *t = qobject_cast( node ); if ( t == 0 ) { return false; } MacroCommand *m = new MacroCommand( kundo2_noi18n(headerData( NodeModel::NodeActualStart, Qt::Horizontal, Qt::DisplayRole ).toString()) ); //FIXME: proper description when string freeze is lifted if ( ! t->completion().isStarted() ) { m->addCommand( new ModifyCompletionStartedCmd( t->completion(), true ) ); } m->addCommand( new ModifyCompletionStartTimeCmd( t->completion(), value.toDateTime() ) ); if ( t->type() == Node::Type_Milestone ) { m->addCommand( new ModifyCompletionFinishedCmd( t->completion(), true ) ); m->addCommand( new ModifyCompletionFinishTimeCmd( t->completion(), value.toDateTime() ) ); if ( t->completion().percentFinished() < 100 ) { Completion::Entry *e = new Completion::Entry( 100, Duration::zeroDuration, Duration::zeroDuration ); m->addCommand( new AddCompletionEntryCmd( t->completion(), value.toDate(), e ) ); } } emit executeCommand( m ); return true; } } return false; } bool TaskWorkPackageModel::setFinishedTime( Node *node, const QVariant &value, int role ) { switch ( role ) { case Qt::EditRole: { Task *t = qobject_cast( node ); if ( t == 0 ) { return false; } MacroCommand *m = new MacroCommand( kundo2_noi18n(headerData( NodeModel::NodeActualFinish, Qt::Horizontal, Qt::DisplayRole ).toString()) ); //FIXME: proper description when string freeze is lifted if ( ! t->completion().isFinished() ) { m->addCommand( new ModifyCompletionFinishedCmd( t->completion(), true ) ); if ( t->completion().percentFinished() < 100 ) { QDate lastdate = t->completion().entryDate(); if ( ! lastdate.isValid() || lastdate < value.toDate() ) { Completion::Entry *e = new Completion::Entry( 100, Duration::zeroDuration, Duration::zeroDuration ); m->addCommand( new AddCompletionEntryCmd( t->completion(), value.toDate(), e ) ); } else { Completion::Entry *e = new Completion::Entry( *( t->completion().entry( lastdate ) ) ); e->percentFinished = 100; m->addCommand( new ModifyCompletionEntryCmd( t->completion(), lastdate, e ) ); } } } m->addCommand( new ModifyCompletionFinishTimeCmd( t->completion(), value.toDateTime() ) ); if ( t->type() == Node::Type_Milestone ) { m->addCommand( new ModifyCompletionStartedCmd( t->completion(), true ) ); m->addCommand( new ModifyCompletionStartTimeCmd( t->completion(), value.toDateTime() ) ); } emit executeCommand( m ); return true; } } return false; } bool TaskWorkPackageModel::setData( const QModelIndex &index, const QVariant &value, int role ) { if ( ! index.isValid() ) { return ItemModelBase::setData( index, value, role ); } switch ( index.column() ) { case NodeCompleted: return setCompletion( nodeForIndex( index ), value, role ); case NodeRemainingEffort: return setRemainingEffort( nodeForIndex( index ), value, role ); case NodeActualEffort: return setActualEffort( nodeForIndex( index ), value, role ); case NodeActualStart: return setStartedTime( nodeForIndex( index ), value, role ); case NodeActualFinish: return setFinishedTime( nodeForIndex( index ), value, role ); default: break; } return false; } QVariant TaskWorkPackageModel::headerData( int section, Qt::Orientation orientation, int role ) const { if ( orientation == Qt::Vertical ) { return section; } if ( role == Qt::DisplayRole ) { switch ( section ) { case NodeName: return i18n( "Name" ); case NodeType: return i18n( "Type" ); case NodeResponsible: return i18n( "Responsible" ); case NodeDescription: return i18n( "Description" ); // After scheduling case NodeStartTime: return i18n( "Planned Start" ); case NodeEndTime: return i18n( "Planned Finish" ); case NodeAssignments: return i18n( "Resource Assignments" ); // Completion case NodeCompleted: return i18n( "Completion" ); case NodeActualEffort: return i18n( "Actual Effort" ); case NodeRemainingEffort: return i18n( "Remaining Effort" ); case NodePlannedEffort: return i18n( "Planned Effort" ); case NodeActualStart: return i18n( "Actual Start" ); case NodeStarted: return i18n( "Started" ); case NodeActualFinish: return i18n( "Actual Finish" ); case NodeFinished: return i18n( "Finished" ); case NodeStatus: return i18nc( "@title:column", "Status" ); case NodeStatusNote: return i18n( "Note" ); case ProjectName: return i18n( "Project Name" ); case ProjectManager: return i18n( "Project Manager" ); default: //debugPlanWork<<"Invalid column number: "<node()->name(); return wp->node(); } return 0; } Document *TaskWorkPackageModel::documentForIndex( const QModelIndex &index ) const { if ( index.isValid() ) { Node *parent = ptrToNode( index ); if ( parent && index.row() < parent->documents().count() ) { //debugPlanWork<name(); return parent->documents().value( index.row() ); } } return 0; } QModelIndex TaskWorkPackageModel::indexForNode( Node *node ) const { WorkPackage *p = m_part->workPackage( node ); if ( p == 0 ) { return QModelIndex(); } return createIndex( m_part->indexOf( p ), 0, p ); } WorkPackage *TaskWorkPackageModel::workPackage( int index ) const { return m_part->workPackage( index ); } QAbstractItemDelegate *TaskWorkPackageModel::createDelegate( int column, QWidget *parent ) const { switch ( column ) { case NodeCompleted: return new TaskCompleteDelegate( parent ); case NodeRemainingEffort: return new DurationSpinBoxDelegate( parent ); case NodeActualEffort: return new DurationSpinBoxDelegate( parent ); case NodeActualStart: return new DateTimeCalendarDelegate( parent ); case NodeActualFinish: return new DateTimeCalendarDelegate( parent ); default: break; } return 0; } WorkPackage *TaskWorkPackageModel::ptrToWorkPackage( const QModelIndex &idx ) const { return qobject_cast( static_cast( idx.internalPointer() ) ); } Node *TaskWorkPackageModel::ptrToNode( const QModelIndex &idx ) const { return qobject_cast( static_cast( idx.internalPointer() ) ); } bool TaskWorkPackageModel::isNode( const QModelIndex &idx ) const { // a node index: ptr is WorkPackage* return qobject_cast( static_cast( idx.internalPointer() ) ) != 0; } bool TaskWorkPackageModel::isDocument( const QModelIndex &idx ) const { // a document index: ptr is Node* return qobject_cast( static_cast( idx.internalPointer() ) ) != 0; } } //namespace KPlato diff --git a/src/workpackage/taskworkpackagemodel.h b/src/workpackage/taskworkpackagemodel.h index fdd853a0..356a341e 100644 --- a/src/workpackage/taskworkpackagemodel.h +++ b/src/workpackage/taskworkpackagemodel.h @@ -1,176 +1,176 @@ /* This file is part of the KDE project Copyright (C) 2009, 2011 Dag Andersen This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef TASKWORKPACKAGEMODEL_H #define TASKWORKPACKAGEMODEL_H #include "planwork_export.h" #include "kptitemmodelbase.h" #include "kptnodeitemmodel.h" #include "kptschedule.h" #include class QModelIndex; class QAbstractItemDelegate; namespace KPlato { class Project; class Node; class Resource; class Document; } using namespace KPlato; /// The main namespace namespace KPlatoWork { class Part; class WorkPackage; /** * The TaskWorkPackageModel class gives access to workpackage status * for the resources assigned to the task in this package. * * The model stores a nodes parentNode() in the index's internalPointer(). */ class PLANWORK_EXPORT TaskWorkPackageModel : public ItemModelBase { Q_OBJECT Q_ENUMS( Properties ) public: explicit TaskWorkPackageModel( Part *part, QObject *parent = 0 ); ~TaskWorkPackageModel() {} enum Properties { NodeName = 0, NodeType, NodeResponsible, NodeDescription, // After scheduling NodeStartTime, NodeEndTime, NodeAssignments, // Completion NodeCompleted, NodeActualEffort, NodeRemainingEffort, NodePlannedEffort, NodeActualStart, NodeStarted, NodeActualFinish, NodeFinished, NodeStatus, NodeStatusNote, ProjectName, ProjectManager }; const QMetaEnum columnMap() const { return metaObject()->enumerator( metaObject()->indexOfEnumerator("Properties") ); } WorkPackage *workPackage( int index ) const; virtual Qt::ItemFlags flags( const QModelIndex &index ) const; virtual QModelIndex parent( const QModelIndex &index ) const; virtual QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const; virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const; virtual bool setData( const QModelIndex & index, const QVariant & value, int role = Qt::EditRole ); QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const; virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const; virtual int columnCount( const QModelIndex &index = QModelIndex() ) const; Node *nodeForIndex( const QModelIndex &index ) const; QModelIndex indexForNode( Node *node ) const; QAbstractItemDelegate *createDelegate( int column, QWidget *parent ) const; Document *documentForIndex( const QModelIndex &idx ) const; WorkPackage *ptrToWorkPackage( const QModelIndex &idx ) const; Node *ptrToNode( const QModelIndex &idx ) const; bool isNode( const QModelIndex &idx ) const; bool isDocument( const QModelIndex &idx ) const; public Q_SLOTS: - void addWorkPackage( WorkPackage *package, int row ); - void removeWorkPackage( WorkPackage *package, int row ); + void addWorkPackage(KPlatoWork::WorkPackage *package, int row); + void removeWorkPackage(KPlatoWork::WorkPackage *package, int row); protected Q_SLOTS: - void slotNodeChanged( Node* ); - void slotNodeToBeInserted( Node *node, int row ); - void slotNodeInserted( Node *node ); - void slotNodeToBeRemoved( Node *node ); - void slotNodeRemoved( Node *node ); - - void slotDocumentAdded( Node *node, Document *doc, int index ); - void slotDocumentRemoved( Node *node, Document *doc, int index ); - void slotDocumentChanged( Node *node, Document *doc, int index ); + void slotNodeChanged(KPlato::Node*); + void slotNodeToBeInserted(KPlato::Node *node, int row ); + void slotNodeInserted(KPlato::Node *node ); + void slotNodeToBeRemoved(KPlato::Node *node ); + void slotNodeRemoved(KPlato::Node *node ); + + void slotDocumentAdded(KPlato::Node *node, KPlato::Document *doc, int index ); + void slotDocumentRemoved(KPlato::Node *node, KPlato::Document *doc, int index ); + void slotDocumentChanged(KPlato::Node *node, KPlato::Document *doc, int index ); protected: QVariant nodeData( Node *node, int column, int role ) const; QVariant documentData( Document *doc, int column, int role ) const; QVariant name( const Resource *r, int role ) const; QVariant email( const Resource *r, int role ) const; QVariant sendStatus( const Resource *r, int role ) const; QVariant sendTime( const Resource *r, int role ) const; QVariant responseType( const Resource *r, int role ) const; QVariant requiredTime( const Resource *r, int role ) const; QVariant responseStatus( const Resource *r, int role ) const; QVariant responseTime( const Resource *r, int role ) const; QVariant lastAction( const Resource *r, int role ) const; QVariant projectName( const Node *n, int role ) const; QVariant projectManager( const Node *n, int role ) const; bool setCompletion( Node *node, const QVariant &value, int role ); bool setRemainingEffort( Node *node, const QVariant &value, int role ); bool setActualEffort( Node *node, const QVariant &value, int role ); bool setStartedTime( Node *node, const QVariant &value, int role ); bool setFinishedTime( Node *node, const QVariant &value, int role ); QVariant actualStart( Node *n, int role ) const; QVariant actualFinish( Node *n, int role ) const; QVariant plannedEffort( Node *n, int role ) const; QVariant status( Node *n, int role ) const; private: NodeModel m_nodemodel; Part *m_part; }; } //namespace KPlato #endif //WORKPACKAGEMODEL_H diff --git a/src/workpackage/taskworkpackageview.h b/src/workpackage/taskworkpackageview.h index be036988..2f9151f9 100644 --- a/src/workpackage/taskworkpackageview.h +++ b/src/workpackage/taskworkpackageview.h @@ -1,260 +1,260 @@ /* This file is part of the KDE project Copyright (C) 2007 - 2009 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 TASKWORKPACKAGEVIEW_H #define TASKWORKPACKAGEVIEW_H #include "planwork_export.h" #include "kptitemmodelbase.h" #include "kptviewbase.h" #include "kptganttview.h" #include #include class QItemSelection; namespace KPlato { class Project; class Node; class Document; } using namespace KPlato; namespace KPlatoWork { class Part; class WorkPackage; class TaskWorkPackageModel; class PLANWORK_EXPORT TaskWorkPackageTreeView : public DoubleTreeViewBase { Q_OBJECT public: TaskWorkPackageTreeView( Part *part, QWidget *parent ); //void setSelectionModel( QItemSelectionModel *selectionModel ); TaskWorkPackageModel *itemModel() const; Project *project() const; void setProject( Project *project ); Document *currentDocument() const; Node *currentNode() const; QList selectedNodes() const; Q_SIGNALS: void sectionsMoved(); protected Q_SLOTS: void slotActivated( const QModelIndex &index ); void setSortOrder( int col, Qt::SortOrder order ); protected: void dragMoveEvent(QDragMoveEvent *event); }; class PLANWORK_EXPORT AbstractView : public QWidget, public ViewActionLists { Q_OBJECT public: AbstractView( Part *part, QWidget *parent ); /// reimplement virtual void updateReadWrite( bool readwrite ); /// reimplement virtual Node *currentNode() const; /// reimplement virtual Document *currentDocument() const; /// reimplement virtual QList selectedNodes() const; /// Loads context info into this view. Reimplement. virtual bool loadContext(); /// Save context info from this view. Reimplement. virtual void saveContext(); /// reimplement virtual KoPrintJob *createPrintJob(); Q_SIGNALS: void requestPopupMenu( const QString& name, const QPoint &pos ); void selectionChanged(); protected Q_SLOTS: /// Builds menu from action list virtual void slotHeaderContextMenuRequested( const QPoint &pos ); /// Reimplement if you have index specific context menu, standard calls slotHeaderContextMenuRequested() void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); /// Should not need to be reimplemented - virtual void slotContextMenuRequested( Node *node, const QPoint& pos ); + virtual void slotContextMenuRequested(KPlato::Node *node, const QPoint& pos); /// Should not need to be reimplemented - virtual void slotContextMenuRequested( Document *doc, const QPoint& pos ); + virtual void slotContextMenuRequested(KPlato::Document *doc, const QPoint& pos); /// Calls saveContext(), connect to this to have configuration saved virtual void sectionsMoved(); protected: Part *m_part; }; class PLANWORK_EXPORT TaskWorkPackageView : public AbstractView { Q_OBJECT public: TaskWorkPackageView( Part *part, QWidget *parent ); void setupGui(); TaskWorkPackageModel *itemModel() const { return m_view->itemModel(); } void updateReadWrite( bool readwrite ); Node *currentNode() const; Document *currentDocument() const; QList selectedNodes() const; /// Loads context info into this view. Reimplement. virtual bool loadContext(); /// Save context info from this view. Reimplement. virtual void saveContext(); using AbstractView::slotContextMenuRequested; protected Q_SLOTS: void slotOptions(); void slotSplitView(); void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); void slotSelectionChanged( const QModelIndexList &lst ); protected: void updateActionsEnabled( bool on ); private: TaskWorkPackageTreeView *m_view; }; //------------- class GanttItemDelegate : public KPlato::GanttItemDelegate { Q_OBJECT public: enum Brushes { Brush_Normal, Brush_Late, Brush_NotScheduled, Brush_Finished, Brush_NotReadyToStart, Brush_ReadyToStart }; explicit GanttItemDelegate(QObject *parent = 0); void paintGanttItem( QPainter* painter, const KGantt::StyleOptionGanttItem& opt, const QModelIndex& idx ); QString toolTip( const QModelIndex &idx ) const; protected: bool showStatus; QMap m_brushes; }; class GanttView : public KPlato::GanttViewBase { Q_OBJECT public: GanttView( Part *part, QWidget *parent ); ~GanttView(); TaskWorkPackageModel *itemModel() const; void setProject( Project *project ); Project *project() const { return m_project; } GanttItemDelegate *delegate() const { return m_ganttdelegate; } QList selectedNodes() const; Node *currentNode() const; /// Loads context info into this view. Reimplement. virtual bool loadContext( const KoXmlElement &context ); /// Save context info from this view. Reimplement. virtual void saveContext( QDomElement &context ) const; Q_SIGNALS: void headerContextMenuRequested( const QPoint& ); void contextMenuRequested( const QModelIndex&, const QPoint& ); void selectionChanged( const QModelIndexList& ); void sectionsMoved(); protected Q_SLOTS: void slotSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected ); void slotRowsInserted( const QModelIndex &parent, int start, int end ); void slotRowsRemoved( const QModelIndex &parent, int start, int end ); void updateDateTimeGrid( WorkPackage *wp ); protected: Part *m_part; Project *m_project; GanttItemDelegate *m_ganttdelegate; TaskWorkPackageModel *m_itemmodel; KGantt::TreeViewRowController *m_rowController; }; class PLANWORK_EXPORT TaskWPGanttView : public AbstractView { Q_OBJECT public: TaskWPGanttView( Part *part, QWidget *parent ); void setupGui(); TaskWorkPackageModel *itemModel() const { return m_view->itemModel(); } Node *currentNode() const; QList selectedNodes() const; /// Loads context info into this view. Reimplement. virtual bool loadContext(); /// Save context info from this view. Reimplement. virtual void saveContext(); using AbstractView::slotContextMenuRequested; protected Q_SLOTS: void slotContextMenuRequested( const QModelIndex &index, const QPoint& pos ); void slotSelectionChanged( const QModelIndexList &lst ); void slotOptions(); private: GanttView *m_view; }; } //namespace KPlatoWork #endif diff --git a/src/workpackage/workpackage.h b/src/workpackage/workpackage.h index 19688229..686bb3e1 100644 --- a/src/workpackage/workpackage.h +++ b/src/workpackage/workpackage.h @@ -1,214 +1,214 @@ /* This file is part of the KDE project Copyright (C) 2009 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 KPLATOWORK_WORKPACKAGE_H #define KPLATOWORK_WORKPACKAGE_H #include "kptxmlloaderobject.h" #include "kptcommand.h" #include "kpttask.h" #include #include #include class KoStore; class QDomDocument; namespace KPlato { class Project; class Document; class XMLLoaderObject; } using namespace KPlato; /// The main namespace for KPlato WorkPackage Handler namespace KPlatoWork { class Part; class WorkPackage; class DocumentChild; /** A work package consists of a Project node and one Task node along with scheduling information and assigned resources. */ class WorkPackage : public QObject { Q_OBJECT public: explicit WorkPackage(bool fromProjectStore); WorkPackage( Project *project, bool fromProjectStore ); ~WorkPackage(); DocumentChild *findChild( const Document *doc ) const; /// Called when loading a work package. Saves to Project store. /// Asks to save/overwrite if already there. /// Does nothing if opened from Projects store. void saveToProjects( Part *part ); bool contains( const DocumentChild* child ) const { return m_childdocs.contains( const_cast( child ) ); } QList childDocs() { return m_childdocs; } bool addChild( Part *part, const Document *doc ); void removeChild( DocumentChild *child ); bool contains( const Document *doc ) const; QString nodeId() const; /// Load the Plan work package document bool loadXML( const KoXmlElement &element, XMLLoaderObject &status ); /// Load the old KPlato work package file format bool loadKPlatoXML( const KoXmlElement &element, XMLLoaderObject &status ); QDomDocument saveXML(); bool saveNativeFormat( Part *part, const QString &path ); bool saveDocumentsToStore( KoStore *store ); bool completeSaving( KoStore *store ); Node *node() const; Task *task() const; Project *project() const { return m_project; } /// Remove document @p doc bool removeDocument( Part *part, Document *doc ); /// Set the file path to this package void setFilePath( const QString &name ) { m_filePath = name; } /// Return the file path to this package QString filePath() const { return m_filePath; } /// Construct file path to projects store QString fileName( const Part *part ) const; /// Remove work package file void removeFile(); /// Merge data from work package @p wp void merge( Part *part, const WorkPackage *wp, KoStore *store ); bool isModified() const; int queryClose( Part *part ); QUrl extractFile( const Document *doc ); QUrl extractFile( const Document *doc, KoStore *store ); QString id() const; bool isValid() const { return m_project && node(); } WorkPackageSettings &settings() { return m_settings; } void setSettings( const WorkPackageSettings &settings ); QMap newDocuments() const { return m_newdocs; } void removeNewDocument( const Document *doc ) { m_newdocs.remove( doc ); } Q_SIGNALS: void modified( bool ); - void saveWorkPackage( WorkPackage* ); + void saveWorkPackage(KPlatoWork::WorkPackage* ); public Q_SLOTS: void setModified( bool on ) { m_modified = on; } protected Q_SLOTS: void projectChanged(); void slotChildModified( bool mod ); protected: /// Copy file @p filename from old store @p from, to the new store @p to bool copyFile( KoStore *from, KoStore *to, const QString &filename ); bool saveToStream( QIODevice * dev ); void openNewDocument( const Document *doc, KoStore *store ); protected: Project *m_project; QString m_filePath; bool m_fromProjectStore; QList m_childdocs; QMap m_newdocs; // new documents that does not exists in the project store (yet) bool m_modified; WorkPackageSettings m_settings; ConfigBase m_config; }; //----------------------------- class PackageRemoveCmd : public NamedCommand { public: PackageRemoveCmd( Part *part, WorkPackage *value, const KUndo2MagicString &name = KUndo2MagicString() ); ~PackageRemoveCmd(); void execute(); void unexecute(); private: Part *m_part; WorkPackage *m_value; bool m_mine; }; //----------------------------- class ModifyPackageSettingsCmd : public NamedCommand { public: ModifyPackageSettingsCmd( WorkPackage *wp, WorkPackageSettings &value, const KUndo2MagicString &name = KUndo2MagicString() ); void execute(); void unexecute(); private: WorkPackage *m_wp; WorkPackageSettings m_value, m_oldvalue; }; //----------------------------- class CopySchedulesCmd : public NamedCommand { public: CopySchedulesCmd( const Project &fromProject, Project &toProject, const KUndo2MagicString &name = KUndo2MagicString() ); void execute(); void unexecute(); private: void load( const QString &doc ); void clean( const QDomDocument &doc ); void clearSchedules(); private: Project &m_project; QString m_olddoc; QString m_newdoc; }; } //KPlatoWork namespace #endif