Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef __INTERRUPTABLE_ASYNC_WORKER__
00020 #define __INTERRUPTABLE_ASYNC_WORKER__
00021
00022 #ifdef _MSC_VER
00023 #include "msc_stdint.h"
00024 #else
00025 #include <stdint.h>
00026 #endif
00027 #include <boost/bind.hpp>
00028 #include "xap_App.h"
00029 #include "xap_DialogFactory.h"
00030 #include "AsyncWorker.h"
00031 #include "ap_Dialog_GenericProgress.h"
00032 #include "ServiceAccountHandler.h"
00033
00034 class InterruptedException {};
00035 class InternalErrorException {};
00036
00037 template <class T>
00038 class InterruptableAsyncWorker : public boost::enable_shared_from_this< InterruptableAsyncWorker<T> >
00039 {
00040 public:
00041 InterruptableAsyncWorker(boost::function<T ()> async_func)
00042 : m_async_func(async_func),
00043 m_worker_ptr(),
00044 m_pProgressDlg(NULL),
00045 m_progress(0),
00046 m_cancelled(false),
00047 m_finished(false),
00048 m_progressSynchronizerPtr(),
00049 m_result()
00050 {}
00051
00052 T run()
00053 {
00054 UT_DEBUGMSG(("InterruptableAsyncWorker::run()\n"));
00055
00056 m_worker_ptr.reset(new AsyncWorker<T>(m_async_func, boost::bind(&InterruptableAsyncWorker<T>::invoke_cb, InterruptableAsyncWorker<T>::shared_from_this(), _1)));
00057 m_progressSynchronizerPtr.reset(new Synchronizer(boost::bind(&InterruptableAsyncWorker<T>::_updateDialog, InterruptableAsyncWorker<T>::shared_from_this())));
00058
00059
00060 XAP_Frame* pFrame = XAP_App::getApp()->getLastFocussedFrame();
00061 if (!pFrame)
00062 throw InternalErrorException();
00063
00064 XAP_DialogFactory* pFactory = static_cast<XAP_DialogFactory *>(XAP_App::getApp()->getDialogFactory());
00065 if (!pFactory)
00066 throw InternalErrorException();
00067
00068 m_pProgressDlg = static_cast<AP_Dialog_GenericProgress*>(
00069 pFactory->requestDialog(ServiceAccountHandler::getDialogGenericProgressId())
00070 );
00071 m_pProgressDlg->setTitle("Retrieving Document");
00072 m_pProgressDlg->setInformation("Please wait while retrieving document...");
00073
00074
00075 m_worker_ptr->start();
00076
00077
00078 m_pProgressDlg->runModal(pFrame);
00079 UT_DEBUGMSG(("Progress dialog destroyed...\n"));
00080 m_cancelled = m_pProgressDlg->getAnswer() == AP_Dialog_GenericProgress::a_CANCEL;
00081 pFactory->releaseDialog(m_pProgressDlg);
00082 m_pProgressDlg = NULL;
00083 if (m_cancelled)
00084 throw InterruptedException();
00085 return m_result;
00086 }
00087
00088 bool cancelled()
00089 {
00090 return m_cancelled;
00091 }
00092
00093 void progress(uint32_t _progress)
00094 {
00095 UT_DEBUGMSG(("InterruptableAsyncWorker::_progress_cb() - %d\n", _progress));
00096 UT_return_if_fail(m_progressSynchronizerPtr);
00097
00098 if (_progress > 100)
00099 _progress = 100;
00100
00101 m_progress = _progress;
00102 m_progressSynchronizerPtr->signal();
00103 }
00104
00105
00106 void forceFinished()
00107 {
00108 m_finished = true;
00109 m_progressSynchronizerPtr->signal();
00110 }
00111
00112 private:
00113 void invoke_cb(T result)
00114 {
00115 UT_DEBUGMSG(("InterruptableAsyncWorker::invoke_cb()\n"));
00116 m_result = result;
00117
00118
00119 m_finished = true;
00120 m_progressSynchronizerPtr->signal();
00121 }
00122
00123 void _updateDialog()
00124 {
00125 UT_DEBUGMSG(("InterruptableAsyncWorker::_updateDialog()\n"));
00126 if (m_finished)
00127 {
00128 UT_DEBUGMSG(("We are finished, closing dialog...\n"));
00129 if (m_pProgressDlg)
00130 {
00131 m_pProgressDlg->close();
00132 }
00133 else
00134 {
00135 UT_DEBUGMSG(("Skipping dialog closure; it is destructed already\n"));
00136 }
00137 }
00138 else
00139 {
00140 UT_DEBUGMSG(("Setting progress value to %d%%\n", m_progress));
00141 if (m_pProgressDlg)
00142 {
00143 m_pProgressDlg->setProgress(m_progress);
00144 }
00145 else
00146 {
00147 UT_DEBUGMSG(("Skipping dialog progress update; it is destructed already\n"));
00148 }
00149 }
00150 }
00151
00152 boost::function<T ()> m_async_func;
00153 boost::shared_ptr< AsyncWorker<T> > m_worker_ptr;
00154
00155 AP_Dialog_GenericProgress* m_pProgressDlg;
00156 uint32_t m_progress;
00157 bool m_cancelled;
00158 bool m_finished;
00159 boost::shared_ptr<Synchronizer> m_progressSynchronizerPtr;
00160
00161 T m_result;
00162 };
00163
00164 #endif