00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "controler.hh"
00026 using namespace std;
00027
00028 bool CControler::getUndoOnFile() const
00029 { return FUndoOnFile; }
00030
00031 void CControler::setUndoOnFile(bool ABool)
00032 {
00033 if (ABool!=FUndoOnFile)
00034 {
00035 emptyUndoRedo();
00036 FUndoOnFile = ABool;
00037 }
00038 }
00039
00040 int CControler::getNbMaxUndos() const
00041 {
00042 return FNbMaxUndos;
00043
00044 }
00045
00046 void CControler::setNbMaxUndos(int ANumber)
00047 {
00048 assert(ANumber==-1 || ANumber>=0);
00049
00050 if ( ANumber!=-1 && ANumber<FNbMaxUndos )
00051 {
00052 if (FActu != NULL)
00053 {
00054 FRedos.push_front(FActu);
00055 --FLastFileIndex;
00056 FActu = NULL;
00057 }
00058 emptyRedoList();
00059
00060 int nbToRemove = FUndos.size()-ANumber;
00061 for (int i=0; i<nbToRemove; ++i)
00062 {
00063 if (FUndoOnFile) remove(FUndos.back()->str().c_str());
00064 delete FUndos.back();
00065 FUndos.pop_back();
00066 }
00067 }
00068
00069 FNbMaxUndos = ANumber;
00070 saveLastUndoOnFile();
00071 }
00072
00073 bool CControler::undo(int AStep)
00074 {
00075 if (!canApplyOperation(COperation(OPERATION_UNDO_REDO)))
00076 return false;
00077
00078 if (!basicUndo(AStep))
00079 return false;
00080
00081 setMessage(string("Undo [") + getUndoRedoStatus() + "]");
00082 return true;
00083 }
00084
00085 bool CControler::redo(int AStep)
00086 {
00087 if (!canApplyOperation(COperation(OPERATION_UNDO_REDO)))
00088 return false;
00089
00090 if (!basicRedo(AStep))
00091 return false;
00092
00093 setMessage(string("Redo [") + getUndoRedoStatus() + "]");
00094 return true;
00095 }
00096
00097 void CControler::emptyUndoList()
00098 {
00099 while (!FUndos.empty())
00100 {
00101 if (FUndoOnFile) remove(FUndos.front()->str().c_str());
00102 delete FUndos.front();
00103 FUndos.pop_front();
00104 }
00105
00106 FLastFileIndex = 0;
00107 saveLastUndoOnFile();
00108 }
00109
00110 void CControler::emptyRedoList()
00111 {
00112 while (!FRedos.empty())
00113 {
00114 if (FUndoOnFile) remove(FRedos.front()->str().c_str());
00115 delete FRedos.front();
00116 FRedos.pop_front();
00117 }
00118 }
00119
00120 bool CControler::emptyUndoRedo()
00121 {
00122 if (FActu != NULL)
00123 {
00124 FRedos.push_front(FActu);
00125 FActu = NULL;
00126 }
00127
00128 emptyRedoList();
00129 emptyUndoList();
00130
00131 setMessage("Pile des undo / redo réinitialisée");
00132 return true;
00133 }
00134
00135 string CControler::getFilename(int AIndex) const
00136 {
00137 assert(AIndex >= 0);
00138
00139 char buffer[256];
00140 sprintf(buffer, "%s/.moka-undo-%d", FConfigDirectory.c_str(),AIndex);
00141 return buffer;
00142 }
00143
00144 int CControler::getNewFileIndex()
00145 {
00146 ++FLastFileIndex;
00147
00148 if ( FNbMaxUndos!=-1 )
00149 {
00150 while (FUndos.size() > (unsigned int)FNbMaxUndos)
00151 {
00152 ostringstream* os = FUndos.back();
00153 FUndos.pop_back();
00154 if (FUndoOnFile) remove(os->str().c_str());
00155 delete os;
00156 }
00157 }
00158
00159 return FLastFileIndex;
00160 }
00161
00162 ostringstream* CControler::saveModel()
00163 {
00164 return NULL;
00165 }
00166
00167 bool CControler::loadModel(ostringstream * )
00168 {
00169 return true;
00170 }
00171
00172 bool CControler::basicUndo(int AStep)
00173 {
00174 if (AStep == 0)
00175 return true;
00176
00177 if (AStep < 0)
00178 return basicRedo(-AStep);
00179
00180 if (FUndos.empty())
00181 return false;
00182
00183
00184 if (FActu == NULL)
00185 FActu = saveModel();
00186
00187
00188 FRedos.push_front(FActu);
00189
00190
00191 for (int i = 1; i < AStep && 1 < FUndos.size(); ++i)
00192 {
00193 FRedos.push_front(FUndos.front());
00194 FUndos.pop_front();
00195 --FLastFileIndex;
00196 }
00197
00198
00199 assert(! FUndos.empty());
00200 FActu = FUndos.front();
00201 FUndos.pop_front();
00202 --FLastFileIndex;
00203 loadModel(FActu);
00204
00205 saveLastUndoOnFile();
00206
00207 return true;
00208 }
00209
00210 bool CControler::basicRedo(int AStep)
00211 {
00212 if (AStep == 0)
00213 return true;
00214
00215 if (AStep < 0)
00216 return basicUndo(-AStep);
00217
00218 if (FRedos.empty())
00219 return false;
00220
00221 assert(FActu != NULL);
00222
00223
00224 FUndos.push_front(FActu);
00225
00226
00227 for (int i = 1; i < AStep && 1 < FUndos.size(); ++i)
00228 {
00229 FUndos.push_front(FRedos.front());
00230 ++FLastFileIndex;
00231 FRedos.pop_front();
00232 }
00233
00234
00235 assert(! FRedos.empty());
00236 FActu = FRedos.front();
00237 FRedos.pop_front();
00238 loadModel(FActu);
00239 ++FLastFileIndex;
00240
00241 saveLastUndoOnFile();
00242
00243 return true;
00244 }
00245
00246 void CControler::undoRedoPreSave()
00247 {
00248 basicPreSave();
00249 }
00250
00251 void CControler::undoRedoPostSaveOk()
00252 {
00253 basicPostSaveOk();
00254 FLastOperation = FCurrentOperation;
00255 }
00256
00257 void CControler::undoRedoPostSaveFailed()
00258 {
00259 basicPostSaveFailed();
00260 }
00261
00262 void CControler::basicPreSave()
00263 {
00264 if (FNbMaxUndos==0) return;
00265
00266 if ( FActu!=NULL )
00267 {
00268 if (FUndoOnFile) remove(FActu->str().c_str());
00269 delete FActu;
00270 --FLastFileIndex;
00271 }
00272
00273 FActu = saveModel();
00274 }
00275
00276 void CControler::basicPostSaveOk()
00277 {
00278 if (FNbMaxUndos==0) return;
00279
00280 assert( FActu!=NULL );
00281
00282
00283 FUndos.push_front(FActu);
00284 FActu = NULL;
00285
00286 emptyRedoList();
00287 saveLastUndoOnFile();
00288 }
00289
00290 void CControler::basicPostSaveFailed()
00291 {
00292 if (FNbMaxUndos==0) return;
00293
00294 assert(FActu != NULL);
00295 }
00296
00297 string CControler::getUndoRedoStatus() const
00298 {
00299 char result[256];
00300 sprintf(result, "%d * %d", FUndos.size(), FRedos.size());
00301 return result;
00302 }
00303
00304 bool CControler::existsFile(const string & AFilename)
00305 {
00306 FILE * f;
00307 f=fopen(AFilename.c_str(), "r");
00308
00309 if (f==NULL)
00310 return false;
00311
00312 fclose(f);
00313 return true;
00314 }
00315
00316 void CControler::saveLastUndoOnFile()
00317 {
00318 if (!FUndoOnFile) return;
00319
00320 char buffer[256];
00321 sprintf(buffer, "%s/.moka-last-undo-file", FConfigDirectory.c_str());
00322
00323 ofstream os;
00324 os.open(buffer);
00325
00326 if (os.is_open())
00327 {
00328 os<<FLastFileIndex<<endl;
00329 os.close();
00330 }
00331 }
00332
00333 void CControler::recupLastUndoFromFile()
00334 {
00335 if (!FUndoOnFile) return;
00336
00337 char buffer[256];
00338 sprintf(buffer, "%s/.moka-last-undo-file", FConfigDirectory.c_str());
00339
00340 ifstream is;
00341 is.open(buffer);
00342
00343 if (is.is_open())
00344 {
00345 is>>FLastFileIndex;
00346 is.close();
00347 }
00348 else
00349 {
00350 FLastFileIndex = 0;
00351 }
00352 }
00353
00354 void CControler::recupFromFiles()
00355 {
00356 recupLastUndoFromFile();
00357
00358 if (!FUndoOnFile || FNbMaxUndos==0 || FLastFileIndex==0) return;
00359
00360 string filename;
00361 int nbFilesRecup = 0;
00362
00363 int current = FLastFileIndex;
00364 bool undoFull = false;
00365 ostringstream * os;
00366
00367 filename = getFilename(current);
00368 while (existsFile(filename) && !undoFull)
00369 {
00370 os = new ostringstream;
00371 (*os)<<filename.c_str();
00372
00373 FUndos.push_back(os);
00374
00375 ++nbFilesRecup;
00376 if ( nbFilesRecup==FNbMaxUndos )
00377 undoFull = true;
00378
00379 --current;
00380 filename = getFilename(current);
00381 }
00382 }
00383