src/documentloader.cpp

changeset 980
4a95c6b06ebe
child 984
a7b6f987d269
equal deleted inserted replaced
979:880d3fe9ac7c 980:4a95c6b06ebe
1 /*
2 * LDForge: LDraw parts authoring CAD
3 * Copyright (C) 2013 - 2015 Teemu Piippo
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <QFile>
20 #include "documentloader.h"
21 #include "ldDocument.h"
22 #include "ldObject.h"
23 #include "mainwindow.h"
24 #include "dialogs/openprogressdialog.h"
25
26 DocumentLoader::DocumentLoader (bool onForeground, QObject *parent) :
27 QObject (parent),
28 m_warningCount (0),
29 m_isDone (false),
30 m_hasAborted (false),
31 m_isOnForeground (onForeground) {}
32
33 bool DocumentLoader::hasAborted()
34 {
35 return m_hasAborted;
36 }
37
38 bool DocumentLoader::isDone() const
39 {
40 return m_isDone;
41 }
42
43 int DocumentLoader::progress() const
44 {
45 return m_progress;
46 }
47
48 int DocumentLoader::warningCount() const
49 {
50 return m_warningCount;
51 }
52
53 bool DocumentLoader::isOnForeground() const
54 {
55 return m_isOnForeground;
56 }
57
58 const LDObjectList& DocumentLoader::objects() const
59 {
60 return m_objects;
61 }
62
63 void DocumentLoader::read (QIODevice* fp)
64 {
65 if (fp and fp->isOpen())
66 {
67 while (not fp->atEnd())
68 m_lines << QString::fromUtf8 (fp->readLine());
69 }
70 }
71
72 void DocumentLoader::start()
73 {
74 m_isDone = false;
75 m_progress = 0;
76 m_hasAborted = false;
77
78 if (isOnForeground())
79 {
80 // Show a progress dialog if we're loading the main ldDocument.here so we can show progress updates and keep the
81 // WM posted that we're still here.
82 m_progressDialog = new OpenProgressDialog (g_win);
83 m_progressDialog->setNumLines (m_lines.size());
84 m_progressDialog->setModal (true);
85 m_progressDialog->show();
86 connect (this, SIGNAL (workDone()), m_progressDialog, SLOT (accept()));
87 connect (m_progressDialog, SIGNAL (rejected()), this, SLOT (abort()));
88 }
89 else
90 m_progressDialog = null;
91
92 // Begin working
93 work (0);
94 }
95
96 void DocumentLoader::work (int i)
97 {
98 // User wishes to abort, so stop here now.
99 if (hasAborted())
100 {
101 for (LDObject* obj : m_objects)
102 obj->destroy();
103
104 m_objects.clear();
105 m_isDone = true;
106 return;
107 }
108
109 // Parse up to 200 lines per iteration
110 int max = i + 200;
111
112 for (; i < max and i < (int) m_lines.size(); ++i)
113 {
114 QString line = m_lines[i];
115
116 // Trim the trailing newline
117 while (line.endsWith ("\n") or line.endsWith ("\r"))
118 line.chop (1);
119
120 LDObject* obj = ParseLine (line);
121
122 // Check for parse errors and warn about them
123 if (obj->type() == OBJ_Error)
124 {
125 print ("Couldn't parse line #%1: %2", progress() + 1, static_cast<LDError*> (obj)->reason());
126 ++m_warningCount;
127 }
128
129 m_objects << obj;
130 }
131
132 m_progress = i;
133
134 if (m_progressDialog)
135 m_progressDialog->setProgress (i);
136
137 if (i >= m_lines.size() - 1)
138 {
139 emit workDone();
140 m_isDone = true;
141 }
142 else
143 {
144 // If we have a dialog to show progress output to, we cannot just call work() again immediately as the dialog
145 // needs to be updated as well. Thus, we take a detour through the event loop by using the meta-object system.
146 //
147 // This terminates the loop here and control goes back to the function which called the file loader. It will
148 // keep processing the event loop until we're ready (see loadFileContents), thus the event loop will eventually
149 // catch the invokation we throw here and send us back.
150 if (isOnForeground())
151 QMetaObject::invokeMethod (this, "work", Qt::QueuedConnection, Q_ARG (int, i));
152 else
153 work (i);
154 }
155 }
156
157 void DocumentLoader::abort()
158 {
159 m_hasAborted = true;
160 }

mercurial