src/documentloader.cpp

Wed, 18 Nov 2015 19:05:22 +0200

author
Teemu Piippo <crimsondusk64@gmail.com>
date
Wed, 18 Nov 2015 19:05:22 +0200
changeset 1012
413ecd6b9801
parent 984
a7b6f987d269
child 1014
f0a8ecb6a357
child 1217
314e12e23c3a
permissions
-rw-r--r--

It worx again!

/*
 *  LDForge: LDraw parts authoring CAD
 *  Copyright (C) 2013 - 2015 Teemu Piippo
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <QFile>
#include "documentloader.h"
#include "ldDocument.h"
#include "ldObject.h"
#include "mainwindow.h"
#include "dialogs/openprogressdialog.h"

DocumentLoader::DocumentLoader (bool onForeground, QObject *parent) :
	QObject (parent),
	m_warningCount (0),
	m_isDone (false),
	m_hasAborted (false),
	m_isOnForeground (onForeground) {}

bool DocumentLoader::hasAborted()
{
	return m_hasAborted;
}

bool DocumentLoader::isDone() const
{
	return m_isDone;
}

int DocumentLoader::progress() const
{
	return m_progress;
}

int DocumentLoader::warningCount() const
{
	return m_warningCount;
}

bool DocumentLoader::isOnForeground() const
{
	return m_isOnForeground;
}

const LDObjectList& DocumentLoader::objects() const
{
	return m_objects;
}

void DocumentLoader::read (QIODevice* fp)
{
	if (fp and fp->isOpen())
	{
		while (not fp->atEnd())
			m_lines << QString::fromUtf8 (fp->readLine());
	}
}

void DocumentLoader::start()
{
	m_isDone = false;
	m_progress = 0;
	m_hasAborted = false;

	if (isOnForeground())
	{
		// Show a progress dialog if we're loading the main ldDocument.here so we can show progress updates and keep the
		// WM posted that we're still here.
		m_progressDialog = new OpenProgressDialog (g_win);
		m_progressDialog->setNumLines (m_lines.size());
		m_progressDialog->setModal (true);
		m_progressDialog->show();
		connect (this, SIGNAL (workDone()), m_progressDialog, SLOT (accept()));
		connect (m_progressDialog, SIGNAL (rejected()), this, SLOT (abort()));
	}
	else
		m_progressDialog = nullptr;

	// Begin working
	work (0);
}

void DocumentLoader::work (int i)
{
	// User wishes to abort, so stop here now.
	if (hasAborted())
	{
		for (LDObject* obj : m_objects)
			obj->destroy();

		m_objects.clear();
		m_isDone = true;
		return;
	}

	// Parse up to 200 lines per iteration
	int max = i + 200;

	for (; i < max and i < (int) m_lines.size(); ++i)
	{
		QString line = m_lines[i];

		// Trim the trailing newline
		while (line.endsWith ("\n") or line.endsWith ("\r"))
			line.chop (1);

		LDObject* obj = ParseLine (line);

		// Check for parse errors and warn about them
		if (obj->type() == OBJ_Error)
		{
			print ("Couldn't parse line #%1: %2", progress() + 1, static_cast<LDError*> (obj)->reason());
			++m_warningCount;
		}

		m_objects << obj;
	}

	m_progress = i;

	if (m_progressDialog)
		m_progressDialog->setProgress (i);

	if (i >= m_lines.size() - 1)
	{
		emit workDone();
		m_isDone = true;
	}
	else
	{
		// If we have a dialog to show progress output to, we cannot just call work() again immediately as the dialog
		// needs to be updated as well. Thus, we take a detour through the event loop by using the meta-object system.
		//
		// This terminates the loop here and control goes back to the function which called the file loader. It will
		// keep processing the event loop until we're ready (see loadFileContents), thus the event loop will eventually
		// catch the invokation we throw here and send us back.
		if (isOnForeground())
			QMetaObject::invokeMethod (this, "work", Qt::QueuedConnection, Q_ARG (int, i));
		else
			work (i);
	}
}

void DocumentLoader::abort()
{
	m_hasAborted = true;
}

mercurial