1 #include "operation.hpp"
2 
3 #include <string>
4 #include <vector>
5 
6 #include <QTimer>
7 
8 #include "../world/universalid.hpp"
9 
10 #include "stage.hpp"
11 
prepareStages()12 void CSMDoc::Operation::prepareStages()
13 {
14     mCurrentStage = mStages.begin();
15     mCurrentStep = 0;
16     mCurrentStepTotal = 0;
17     mTotalSteps = 0;
18     mError = false;
19 
20     for (std::vector<std::pair<Stage *, int> >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter)
21     {
22         iter->second = iter->first->setup();
23         mTotalSteps += iter->second;
24     }
25 }
26 
Operation(int type,bool ordered,bool finalAlways)27 CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways)
28 : mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()),
29   mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered),
30   mFinalAlways (finalAlways), mError(false), mConnected (false), mPrepared (false),
31   mDefaultSeverity (Message::Severity_Error)
32 {
33     mTimer = new QTimer (this);
34 }
35 
~Operation()36 CSMDoc::Operation::~Operation()
37 {
38     for (std::vector<std::pair<Stage *, int> >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter)
39         delete iter->first;
40 }
41 
run()42 void CSMDoc::Operation::run()
43 {
44     mTimer->stop();
45 
46     if (!mConnected)
47     {
48         connect (mTimer, SIGNAL (timeout()), this, SLOT (executeStage()));
49         mConnected = true;
50     }
51 
52     mPrepared = false;
53 
54     mTimer->start (0);
55 }
56 
appendStage(Stage * stage)57 void CSMDoc::Operation::appendStage (Stage *stage)
58 {
59     mStages.emplace_back (stage, 0);
60 }
61 
setDefaultSeverity(Message::Severity severity)62 void CSMDoc::Operation::setDefaultSeverity (Message::Severity severity)
63 {
64     mDefaultSeverity = severity;
65 }
66 
hasError() const67 bool CSMDoc::Operation::hasError() const
68 {
69     return mError;
70 }
71 
abort()72 void CSMDoc::Operation::abort()
73 {
74     if (!mTimer->isActive())
75         return;
76 
77     mError = true;
78 
79     if (mFinalAlways)
80     {
81         if (mStages.begin()!=mStages.end() && mCurrentStage!=--mStages.end())
82         {
83             mCurrentStep = 0;
84             mCurrentStage = --mStages.end();
85         }
86     }
87     else
88         mCurrentStage = mStages.end();
89 }
90 
executeStage()91 void CSMDoc::Operation::executeStage()
92 {
93     if (!mPrepared)
94     {
95         prepareStages();
96         mPrepared = true;
97     }
98 
99     Messages messages (mDefaultSeverity);
100 
101     while (mCurrentStage!=mStages.end())
102     {
103         if (mCurrentStep>=mCurrentStage->second)
104         {
105             mCurrentStep = 0;
106             ++mCurrentStage;
107         }
108         else
109         {
110             try
111             {
112                 mCurrentStage->first->perform (mCurrentStep++, messages);
113             }
114             catch (const std::exception& e)
115             {
116                 emit reportMessage (Message (CSMWorld::UniversalId(), e.what(), "", Message::Severity_SeriousError), mType);
117                 abort();
118             }
119 
120             ++mCurrentStepTotal;
121             break;
122         }
123     }
124 
125     emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType);
126 
127     for (Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter)
128         emit reportMessage (*iter, mType);
129 
130     if (mCurrentStage==mStages.end())
131         operationDone();
132 }
133 
operationDone()134 void CSMDoc::Operation::operationDone()
135 {
136     mTimer->stop();
137     emit done (mType, mError);
138 }
139