1/* This file is part of the KDE project
2 Copyright (C) 2009, 2010 Dag Andersen <danders@get2net.dk>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#ifndef KPTSCHEDULERPLUGIN_H
21#define KPTSCHEDULERPLUGIN_H
22
23#include "kplatokernel_export.h"
24
25#include "kptschedule.h"
26
27#include "KoXmlReader.h"
28
29#include <QObject>
30#include <QString>
31#include <QMutex>
32#include <QThread>
33#include <QTimer>
34
35class QDomDocument;
36class KLocale;
37
38namespace KPlato
39{
40
41class SchedulerThread;
42class Project;
43class ScheduleManager;
44class Node;
45class XMLLoaderObject;
46
47/**
48 SchedulerPlugin is the base class for project calculation plugins.
49
50 Sub-class SchedulerThread to do the actual calculation, then re-implement calculate()
51 to calculate the project, and slotFinished() to fetch the result into your project.
52
53 There is two ways to show progress:
54 <ul>
55 <li> Connect the SchedulerThread::maxProgressChanged() to ScheduleManager::setMaxProgress() and
56 and SchedulerThread::progressChanged() to ScheduleManager::setProgress().
57 Note that too many progress signals too often may choke the ui thread.
58 <li> Start the m_synctimer. This will fetch progress and log messages every 500 ms (by default).
59 </ul>
60
61 When the thread has finished scheduling, data can be fetched from its temporary project
62 into the real project by calling the updateProject() method.
63*/
64class KPLATOKERNEL_EXPORT SchedulerPlugin : public QObject
65{
66 Q_OBJECT
67public:
68 explicit SchedulerPlugin(QObject *parent);
69 virtual ~SchedulerPlugin();
70
71 /// Localized name
72 QString name() const;
73 /// Name is normally set by the plugin loader, from Name in the desktop file
74 void setName( const QString &name );
75 /// Localized comment
76 QString comment() const;
77 /// Comment is normally set by the plugin loader, from Comment in the desktop file
78 void setComment( const QString &name );
79 /// A more elaborate description suitable for use in what's this
80 virtual QString description() const { return QString(); }
81 /// The schedulers capabilities
82 enum Capabilities {
83 AvoidOverbooking = 1,
84 AllowOverbooking = 2,
85 ScheduleForward = 4,
86 ScheduleBackward = 8
87 };
88 /// Return the schedulers capabilities.
89 /// By default returns all capabilities
90 virtual int capabilities() const;
91 /// Stop calculation of the schedule @p sm. Current result may be used.
92 void stopCalculation( ScheduleManager *sm );
93 /// Terminate calculation of the schedule @p sm. No results will be available.
94 void haltCalculation( ScheduleManager *sm );
95
96 /// Stop calculation of the scheduling @p job. Current result may be used.
97 virtual void stopCalculation( SchedulerThread *job );
98 /// Terminate calculation of the scheduling @p job. No results will be available.
99 virtual void haltCalculation( SchedulerThread *job );
100
101 /// Calculate the project
102 virtual void calculate( Project &project, ScheduleManager *sm, bool nothread = false ) = 0;
103
104 /// Return the list of supported granularities
105 /// An empty list means granularity is not supported (the default)
106 QList<long unsigned int> granularities() const;
107 /// Return current index of supported granularities
108 int granularity() const;
109 /// Set current index of supported granularities
110 void setGranularity( int index );
111
112protected slots:
113 virtual void slotSyncData();
114
115protected:
116 void updateProject( const Project *tp, const ScheduleManager *tm, Project *mp, ScheduleManager *sm ) const;
117 void updateNode( const Node *tn, Node *mn, long sid, XMLLoaderObject &status ) const;
118 void updateResource( const KPlato::Resource *tr, Resource *r, XMLLoaderObject &status ) const;
119 void updateAppointments( const Project *tp, const ScheduleManager *tm, Project *mp, ScheduleManager *sm, XMLLoaderObject &status ) const;
120
121 void updateProgress();
122 void updateLog();
123 void updateLog( SchedulerThread *job );
124
125private:
126 class Private;
127 Private *d;
128
129protected:
130 QTimer m_synctimer;
131 QList<SchedulerThread*> m_jobs;
132
133 int m_granularity;
134 QList<long unsigned int> m_granularities;
135
136};
137
138/**
139 SchedulerThread is a basic class used to implement project calculation in a separate thread.
140 The scheduling thread is meant to run on a private copy of the project to avoid that the ui thread
141 changes the data while calculations are going on.
142
143 The constructor creates a KoXmlDocument m_pdoc of the project that can be used to
144 create a private project. This should be done in the reimplemented run() method.
145
146 When the calculations are done the signal jobFinished() is emitted. This can be used to
147 fetch data from the private calculated project into the actual project.
148
149 To track progress, the progress() method should be called from the ui thread with
150 an appropriate interval to avoid overload of the ui thread.
151 The progressChanged() signal may also be used but note that async signal handling are very slow
152 so it may affect the ui threads performance too much.
153*/
154class KPLATOKERNEL_EXPORT SchedulerThread : public QThread
155{
156 Q_OBJECT
157public:
158 SchedulerThread( Project *project, ScheduleManager *manager, QObject *parent );
159 ~SchedulerThread();
160
161 Project *mainProject() const { return m_mainproject; }
162 ScheduleManager *mainManager() const { return m_mainmanager; }
163
164 Project *project() const;
165 ScheduleManager *manager() const;
166
167 /// Run with no thread
168 void doRun();
169
170 /// The scheduling is stopping
171 bool isStopped() const { return m_stopScheduling; }
172 /// The scheduling is halting
173 bool isHalted() const { return m_haltScheduling; }
174
175 int maxProgress() const;
176 int progress() const;
177 QList<Schedule::Log> log();
178
179 QMap<int, QString> phaseNames() const;
180
181 /// Save the @p project into @p document
182 static void saveProject( Project *project, QDomDocument &document );
183 /// Load the @p project from @p document
184 static bool loadProject( Project *project, const KoXmlDocument &document );
185
186 ///Add a scheduling error log message
187 void logError( Node *n, Resource *r, const QString &msg, int phase = -1 );
188 ///Add a scheduling warning log message
189 void logWarning( Node *n, Resource *r, const QString &msg, int phase = -1 );
190 ///Add a scheduling information log message
191 void logInfo( Node *n, Resource *r, const QString &msg, int phase = -1 );
192 ///Add a scheduling debug log message
193 void logDebug( Node *n, Resource *r, const QString &msg, int phase = -1 );
194
195signals:
196 /// Job has started
197 void jobStarted( SchedulerThread *job );
198 /// Job is finished
199 void jobFinished( SchedulerThread *job );
200
201 /// Maximum progress value has changed
202 void maxProgressChanged( int value, ScheduleManager *sm = 0 );
203 /// Progress has changed
204 void progressChanged( int value, ScheduleManager *sm = 0 );
205
206public slots:
207 /// Stop scheduling. Result may still be used.
208 virtual void stopScheduling();
209 /// Halt scheduling. Discard result.
210 virtual void haltScheduling();
211
212
213protected slots:
214 virtual void slotStarted();
215 virtual void slotFinished();
216
217 void setMaxProgress( int );
218 void setProgress( int );
219
220 void slotAddLog( Schedule::Log log );
221
222protected:
223 /// Re-implement to do the job
224 virtual void run() {}
225
226protected:
227 /// The actual project to be calculated. Not accessed outside constructor.
228 Project *m_mainproject;
229 /// The actual schedule manager to be calculated. Not accessed outside constructor.
230 ScheduleManager *m_mainmanager;
231 /// The schedule manager identity
232 QString m_mainmanagerId;
233
234 /// The temporary project
235 Project *m_project;
236 mutable QMutex m_projectMutex;
237 /// The temporary schedule manager
238 ScheduleManager *m_manager;
239 mutable QMutex m_managerMutex;
240
241 bool m_stopScheduling; /// Stop asap, preliminary result may be used
242 bool m_haltScheduling; /// Stop and discrad result. Delete yourself.
243
244 KoXmlDocument m_pdoc;
245
246 int m_maxprogress;
247 mutable QMutex m_maxprogressMutex;
248 int m_progress;
249 mutable QMutex m_progressMutex;
250 QList<Schedule::Log> m_logs;
251 mutable QMutex m_logMutex;
252};
253
254} //namespace KPlato
255
256#endif
257