239 setAborted (false); |
239 setAborted (false); |
240 |
240 |
241 if (concurrent()) { |
241 if (concurrent()) { |
242 g_aborted = false; |
242 g_aborted = false; |
243 |
243 |
244 // Show a progress dialog if we're loading the main file here and move |
244 // Show a progress dialog if we're loading the main file here so we can |
245 // the actual work to a separate thread as this can be a rather intensive |
245 // show progress updates and keep the WM posted that we're still here. |
246 // operation and if we don't respond quickly enough, the program can be |
246 // Of course we cannot exec() the dialog because then the dialog would |
247 // deemed inresponsive.. which is a bad thing. |
247 // block. |
248 dlg = new OpenProgressDialog (g_win); |
248 dlg = new OpenProgressDialog (g_win); |
249 dlg->setNumLines (lines().size()); |
249 dlg->setNumLines (lines().size()); |
250 dlg->setModal (true); |
250 dlg->setModal (true); |
251 dlg->show(); |
251 dlg->show(); |
252 |
252 |
254 connect (this, SIGNAL (workDone()), dlg, SLOT (accept())); |
254 connect (this, SIGNAL (workDone()), dlg, SLOT (accept())); |
255 connect (dlg, SIGNAL (rejected()), this, SLOT (abort())); |
255 connect (dlg, SIGNAL (rejected()), this, SLOT (abort())); |
256 } else |
256 } else |
257 dlg = null; |
257 dlg = null; |
258 |
258 |
|
259 // Begin working |
259 work (0); |
260 work (0); |
260 } |
261 } |
261 |
262 |
262 // ============================================================================= |
263 // ============================================================================= |
263 // ----------------------------------------------------------------------------- |
264 // ----------------------------------------------------------------------------- |
264 void FileLoader::work (int i) { |
265 void FileLoader::work (int i) { |
|
266 // User wishes to abort, so stop here now. |
265 if (aborted()) { |
267 if (aborted()) { |
266 // We were flagged for abortion, so abort. |
|
267 for (LDObject* obj : m_objs) |
268 for (LDObject* obj : m_objs) |
268 delete obj; |
269 delete obj; |
269 |
270 |
270 m_objs.clear(); |
271 m_objs.clear(); |
271 setDone (true); |
272 setDone (true); |
272 return; |
273 return; |
273 } |
274 } |
274 |
275 |
|
276 // Parse up to 300 lines per iteration |
275 int max = i + 300; |
277 int max = i + 300; |
276 |
278 |
277 for (; i < max && i < (int) lines().size(); ++i) { |
279 for (; i < max && i < (int) lines().size(); ++i) { |
278 str line = lines()[i]; |
280 str line = lines()[i]; |
279 |
281 |
294 } |
296 } |
295 |
297 |
296 m_objs << obj; |
298 m_objs << obj; |
297 setProgress (i); |
299 setProgress (i); |
298 |
300 |
|
301 // If we have a dialog pointer, update the progress now |
299 if (concurrent()) |
302 if (concurrent()) |
300 dlg->updateProgress (i); |
303 dlg->updateProgress (i); |
301 } |
304 } |
302 |
305 |
|
306 // If we're done now, tell the environment we're done and stop. |
303 if (i >= ((int) lines().size()) - 1) { |
307 if (i >= ((int) lines().size()) - 1) { |
304 emit workDone(); |
308 emit workDone(); |
305 setDone (true); |
309 setDone (true); |
306 return; |
310 return; |
307 } |
311 } |
308 |
312 |
|
313 // Otherwise, continue, by recursing back. |
309 if (!done()) { |
314 if (!done()) { |
|
315 // If we have a dialog to show progress output to, we cannot just call |
|
316 // work() again immediately as the dialog needs some processor cycles as |
|
317 // well. Thus, take a detour through the event loop by using the |
|
318 // meta-object system. |
|
319 // |
|
320 // This terminates the loop here and control goes back to the function |
|
321 // which called the file loader. It will keep processing the event loop |
|
322 // until we're ready (see loadFileContents), thus the event loop will |
|
323 // eventually catch the invokation we throw here and send us back. Though |
|
324 // it's not technically recursion anymore, more like a for loop. :P |
310 if (concurrent()) |
325 if (concurrent()) |
311 QMetaObject::invokeMethod (this, "work", Qt::QueuedConnection, Q_ARG (int, i + 1)); |
326 QMetaObject::invokeMethod (this, "work", Qt::QueuedConnection, Q_ARG (int, i + 1)); |
312 else |
327 else |
313 work (i + 1); |
328 work (i + 1); |
314 } |
329 } |
342 loader->setWarningsPointer (numWarnings); |
357 loader->setWarningsPointer (numWarnings); |
343 loader->setLines (lines); |
358 loader->setLines (lines); |
344 loader->setConcurrent (g_loadingMainFile); |
359 loader->setConcurrent (g_loadingMainFile); |
345 loader->start(); |
360 loader->start(); |
346 |
361 |
|
362 // After start() returns, if the loader isn't done yet, it's delaying |
|
363 // its next iteration through the event loop. We need to catch this here |
|
364 // by telling the event loop to tick, which will tick the file loader again. |
|
365 // We keep doing this until the file loader is ready. |
347 while (loader->done() == false) |
366 while (loader->done() == false) |
348 qApp->processEvents(); |
367 qApp->processEvents(); |
349 |
368 |
350 // If we wanted the success value, supply that now |
369 // If we wanted the success value, supply that now |
351 if (ok) |
370 if (ok) |