fw4spl
WorkerQt.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2017.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwGuiQt/WorkerQt.hpp"
8 
9 #include "fwGuiQt/App.hpp"
10 #include "fwGuiQt/util/FuncSlot.hpp"
11 
12 #include <fwRuntime/profile/Profile.hpp>
13 
14 #include <fwServices/registry/ActiveWorkers.hpp>
15 
16 #include <fwThread/Timer.hpp>
17 #include <fwThread/Worker.hpp>
18 
19 #include <QDir>
20 #include <QEvent>
21 #include <QFont>
22 #include <QPointer>
23 #include <QSharedPointer>
24 #include <QStringList>
25 #include <QTimer>
26 
27 #include <functional>
28 
29 namespace fwGuiQt
30 {
31 
32 class WorkerQtTask : public QEvent
33 {
34 public:
35  WorkerQtTask( const ::fwThread::Worker::TaskType& handler ) :
36  QEvent( static_cast< QEvent::Type >(s_WORKER_QT_TASK_EVENT_TYPE) ),
37  m_handler( handler )
38  {
39  SLM_ASSERT( "QApplication should be instantiated", qApp );
40  }
41 
42  ~WorkerQtTask()
43  {
44  m_handler();
45  }
46 
47  static const int s_WORKER_QT_TASK_EVENT_TYPE;
48 
49 protected:
50 
51  ::fwThread::Worker::TaskType m_handler;
52 };
53 
54 const int WorkerQtTask::s_WORKER_QT_TASK_EVENT_TYPE = QEvent::registerEventType();
55 
60 {
61 public:
62  WorkerQt();
63 
64  void init( int& argc, char** argv, bool guiEnabled = true );
65 
66  virtual ~WorkerQt();
67 
68  void stop();
69 
70  void post(TaskType handler);
71 
72  ::fwThread::Worker::FutureType getFuture();
73 
74  virtual ::fwThread::ThreadIdType getThreadId() const;
75 
76  virtual void processTasks();
77 
78  virtual void processTasks(PeriodType maxtime);
79 
80 protected:
81 
82  int m_argc;
83 
84  QSharedPointer< QApplication > m_app;
85 
86  SPTR(::fwThread::Timer) createTimer();
87 
89  WorkerQt( const WorkerQt& );
90 
92  WorkerQt& operator=( const WorkerQt& );
93 
94  ::fwThread::ThreadIdType m_threadId;
95 };
96 
97 //-----------------------------------------------------------------------------
98 
99 ::fwThread::Worker::sptr getQtWorker(int& argc, char** argv, bool guiEnabled)
100 {
101  SPTR(WorkerQt) workerQt = std::make_shared< WorkerQt >();
102  workerQt->init(argc, argv, guiEnabled);
103 
104  return workerQt;
105 }
106 
107 //-----------------------------------------------------------------------------
108 
113 {
114 public:
118  TimerQt();
119 
120  ~TimerQt();
121 
123  void start();
124 
126  void stop();
127 
129  void setDuration(TimeDurationType duration);
130 
132  bool isOneShot() const
133  {
134  ::fwCore::mt::ScopedLock lock(m_mutex);
135  return m_timerQt->isSingleShot();
136  }
137 
139  void setOneShot(bool oneShot)
140  {
141  ::fwCore::mt::ScopedLock lock(m_mutex);
142  m_timerQt->setSingleShot(oneShot);
143  }
144 
146  bool isRunning() const
147  {
148  ::fwCore::mt::ScopedLock lock(m_mutex);
149  return m_timerQt->isActive();
150  }
151 
152 protected Q_SLOTS:
153 
154  void call();
155 
156 protected:
157 
159  TimerQt( const TimerQt& );
160 
162  TimerQt& operator=( const TimerQt& );
163 
164  void updatedFunction();
165 
166  QPointer< QTimer > m_timerQt;
167 
168  QPointer< ::fwGuiQt::util::FuncSlot > m_qtFunc;
169 };
170 
171 //------------------------------------------------------------------------------
172 
173 // ---------- WorkerQt private implementation ----------
174 
175 WorkerQt::WorkerQt() :
176  m_argc(0),
177  m_app(nullptr),
178  m_threadId( ::fwThread::getCurrentThreadId() )
179 {
180 }
181 
182 //------------------------------------------------------------------------------
183 
184 void WorkerQt::init( int& argc, char** argv, bool guiEnabled )
185 {
186  OSLM_TRACE("Init Qt" << ::fwThread::getCurrentThreadId() <<" Start");
187 
188 #ifdef WIN32
189  QDir pluginDir("./bin/qt5/plugins");
190 #else
191  QDir pluginDir("./lib/qt5/plugins");
192 #endif
193  if (pluginDir.exists())
194  {
195  QCoreApplication::setLibraryPaths(QStringList(pluginDir.absolutePath()));
196  }
197 
198  m_argc = argc;
199  m_app = QSharedPointer< QApplication > ( new ::fwGuiQt::App( m_argc, argv, guiEnabled ) );
200 
201  OSLM_TRACE("Init Qt" << ::fwThread::getCurrentThreadId() <<" Finish");
202 }
203 
204 //------------------------------------------------------------------------------
205 
206 WorkerQt::~WorkerQt()
207 {
208  this->stop();
209 }
210 
211 //------------------------------------------------------------------------------
212 
213 ::fwThread::Worker::FutureType WorkerQt::getFuture()
214 {
215  if (!m_future.valid() )
216  {
217  SLM_ASSERT("WorkerQt loop shall be created and ran from main thread ",
218  !m_future.valid() && ::fwThread::getCurrentThreadId() == this->getThreadId() );
219 
220  std::packaged_task< ExitReturnType() > task( std::bind(&QApplication::exec) );
221 
222  std::future< ExitReturnType > ufuture = task.get_future();
223 
224  m_future = std::move(ufuture);
225 
226  task();
227  }
228 
229  return m_future;
230 }
231 
232 //------------------------------------------------------------------------------
233 
234 ::fwThread::ThreadIdType WorkerQt::getThreadId() const
235 {
236  return m_threadId;
237 }
238 
239 //------------------------------------------------------------------------------
240 
242 {
243  this->postTask<void>(&QApplication::quit).wait();
244 }
245 //------------------------------------------------------------------------------
246 
247 SPTR(::fwThread::Timer) WorkerQt::createTimer()
248 {
249  return std::make_shared< TimerQt >();
250 }
251 
252 //------------------------------------------------------------------------------
253 
254 void WorkerQt::post(TaskType handler)
255 {
256  QApplication::postEvent( qApp, new WorkerQtTask(handler) );
257 }
258 
259 //------------------------------------------------------------------------------
260 
262 {
263  QApplication::sendPostedEvents(0, ::fwGuiQt::WorkerQtTask::s_WORKER_QT_TASK_EVENT_TYPE);
264 }
265 
266 //------------------------------------------------------------------------------
267 
268 void WorkerQt::processTasks(PeriodType maxtime)
269 {
270  QCoreApplication::processEvents(QEventLoop::AllEvents, int(maxtime));
271 }
272 
273 // ---------- Timer private implementation ----------
274 
276  m_timerQt( new QTimer(qApp) )
277 {
278  m_qtFunc = new ::fwGuiQt::util::FuncSlot();
279  QObject::connect(m_timerQt, SIGNAL(timeout()), m_qtFunc, SLOT(trigger()));
280 }
281 
282 //------------------------------------------------------------------------------
283 
284 TimerQt::~TimerQt()
285 {
286  QObject::disconnect(m_timerQt, SIGNAL(timeout()), m_qtFunc, SLOT(trigger()));
287  delete m_qtFunc;
288  m_timerQt->stop();
289  delete m_timerQt;
290 }
291 
292 //------------------------------------------------------------------------------
293 
294 void TimerQt::setDuration(TimeDurationType duration)
295 {
296  ::fwCore::mt::ScopedLock lock(m_mutex);
297  m_timerQt->setInterval( static_cast<int>(
298  std::chrono::duration_cast< std::chrono::milliseconds >(duration).count())
299  );
300 }
301 
302 //------------------------------------------------------------------------------
303 
305 {
306  ::fwCore::mt::ScopedLock lock(m_mutex);
307  m_timerQt->start();
308 }
309 
310 //------------------------------------------------------------------------------
311 
313 {
314  ::fwCore::mt::ScopedLock lock(m_mutex);
315  m_timerQt->stop();
316 }
317 
318 //------------------------------------------------------------------------------
319 
320 void TimerQt::call()
321 {
322  m_function();
323 }
324 
325 //------------------------------------------------------------------------------
326 
328 {
329  m_qtFunc->setFunction(m_function);
330 }
331 
332 } //namespace fwGuiQt
333 
#define SPTR(_cls_)
void stop()
Stops the timer and cancel all pending operations.
Definition: WorkerQt.cpp:312
Private implementation of fwThread::Worker using boost::asio.
Definition: WorkerQt.cpp:59
void updatedFunction()
This method is triggered when Timer&#39;s function is changed.
Definition: WorkerQt.cpp:327
FWTHREAD_API ThreadIdType getCurrentThreadId()
Returns the current thread id.
Definition: Worker.cpp:14
virtual void processTasks()
Processes all worker pending tasks for the calling thread until there are no more tasks to process...
Definition: WorkerQt.cpp:261
#define OSLM_TRACE(message)
Definition: spyLog.hpp:230
The namespace fwGuiQt contains classes which provide the implementation of the Gui using Qt library...
Definition: WindowLevel.hpp:32
FunctionType m_function
Function object to execute each time the timer expires.
Definition: Timer.hpp:89
void post(TaskType handler)
Requests invocation of the given task handler and returns immediately.
Definition: WorkerQt.cpp:254
bool isOneShot() const
Returns if the timer mode is &#39;one shot&#39;.
Definition: WorkerQt.cpp:132
TimerQt()
Constructs a TimerQt from given io_service.
Definition: WorkerQt.cpp:275
::fwThread::Worker::FutureType getFuture()
Returns a std::shared_future associated with the execution of Worker&#39;s loop.
Definition: WorkerQt.cpp:213
void start()
Starts or restarts the timer.
Definition: WorkerQt.cpp:304
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
The Timer class provides single-shot or repetitive timers. A Timer triggers a function once after a d...
Definition: Timer.hpp:27
Private Timer implementation using Qt.
Definition: WorkerQt.cpp:112
void setOneShot(bool oneShot)
Sets timer mode.
Definition: WorkerQt.cpp:139
bool isRunning() const
Returns true if the timer is currently running.
Definition: WorkerQt.cpp:146
This class creates and manages a task loop. The default implementation create a loop in a new thread...
Definition: Worker.hpp:32
void setDuration(TimeDurationType duration)
Sets time duration.
Definition: WorkerQt.cpp:294
void stop()
Waits for the last task to be processed and stops the loop.
Definition: WorkerQt.cpp:241
virtual ::fwThread::ThreadIdType getThreadId() const
Returns the worker&#39;s thread id.
Definition: WorkerQt.cpp:234