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 | |
35 | class QDomDocument; |
36 | class KLocale; |
37 | |
38 | namespace KPlato |
39 | { |
40 | |
41 | class SchedulerThread; |
42 | class Project; |
43 | class ScheduleManager; |
44 | class Node; |
45 | class 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 | */ |
64 | class KPLATOKERNEL_EXPORT SchedulerPlugin : public QObject |
65 | { |
66 | Q_OBJECT |
67 | public: |
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 () const; |
77 | /// Comment is normally set by the plugin loader, from Comment in the desktop file |
78 | void ( 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 | |
112 | protected slots: |
113 | virtual void slotSyncData(); |
114 | |
115 | protected: |
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 | |
125 | private: |
126 | class Private; |
127 | Private *d; |
128 | |
129 | protected: |
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 | */ |
154 | class KPLATOKERNEL_EXPORT SchedulerThread : public QThread |
155 | { |
156 | Q_OBJECT |
157 | public: |
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 | |
195 | signals: |
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 | |
206 | public slots: |
207 | /// Stop scheduling. Result may still be used. |
208 | virtual void stopScheduling(); |
209 | /// Halt scheduling. Discard result. |
210 | virtual void haltScheduling(); |
211 | |
212 | |
213 | protected 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 | |
222 | protected: |
223 | /// Re-implement to do the job |
224 | virtual void run() {} |
225 | |
226 | protected: |
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 | |