src/toolsets/filetoolset.cpp

Sun, 29 Jan 2017 15:05:14 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Sun, 29 Jan 2017 15:05:14 +0200
changeset 1073
a0a0d581309b
parent 1072
9ce9496427f2
child 1079
67c6e5d32e68
permissions
-rw-r--r--

Major overhaul of object→document relationship: added the Model class which models the object buffer. Each object is to be included in a model (an invariant that currently does not hold). A document is a subclass of a model. The LDObject is also now agnostic about selection, and the selection is now a set. A lot of things are probably broken now but it's a major step forward.
The LDObject::destroy method is also now gone. The model decides when objects are destroyed and calls the destructor directly. The end result removes a lot of cruft and adds structure to LDObject relations.

Notes:
- Inlining does not currently work (nothing simply gets inlined in)
- More work is required to ensure that each object actually goes into a model

/*
 *  LDForge: LDraw parts authoring CAD
 *  Copyright (C) 2013 - 2017 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 <QFileDialog>
#include <QMessageBox>
#include "../dialogs.h"
#include "../glRenderer.h"
#include "../ldDocument.h"
#include "../mainwindow.h"
#include "../partdownloader.h"
#include "../primitives.h"
#include "../dialogs/configdialog.h"
#include "../dialogs/ldrawpathdialog.h"
#include "../dialogs/newpartdialog.h"
#include "../dialogs/generateprimitivedialog.h"
#include "../documentmanager.h"
#include "filetoolset.h"
#include "ui_about.h"

FileToolset::FileToolset(MainWindow* parent)
    : Toolset(parent) {}

void FileToolset::newPart()
{
	NewPartDialog* dialog = new NewPartDialog {m_window};

	if (dialog->exec() == QDialog::Accepted)
	{
		m_window->createBlankDocument();
		dialog->fillHeader(currentDocument());
		m_window->doFullRefresh();
	}
}

void FileToolset::newFile()
{
	m_window->createBlankDocument();
}

void FileToolset::open()
{
	QString name = QFileDialog::getOpenFileName(m_window, "Open File", "", "LDraw files (*.dat *.ldr)");

	if (not name.isEmpty())
		m_documents->openMainModel (name);
}

void FileToolset::save()
{
	m_window->save(currentDocument(), false);
}

void FileToolset::saveAs()
{
	m_window->save(currentDocument(), true);
}

void FileToolset::saveAll()
{
	for (LDDocument* document : m_documents->allDocuments())
		m_window->save(document, false);
}

void FileToolset::close()
{
	if (currentDocument()->isSafeToClose())
		currentDocument()->close();
}

void FileToolset::closeAll()
{
	if (m_documents->isSafeToCloseAll())
		m_documents->clear();
}

void FileToolset::settings()
{
	(new ConfigDialog {m_window})->exec();
}

void FileToolset::setLDrawPath()
{
	LDrawPathDialog* dialog = new LDrawPathDialog {m_config->lDrawPath(), true};

	if (dialog->exec())
		m_config->setLDrawPath (dialog->path());
}

void FileToolset::exit()
{
	::exit(EXIT_SUCCESS);
}

void FileToolset::insertFrom()
{
	QString filePath = QFileDialog::getOpenFileName();
	int position = m_window->suggestInsertPoint();

	if (not filePath.isEmpty())
	{
		QFile file = {filePath};

		if (file.open(QIODevice::ReadOnly))
		{
			// TODO: shouldn't need to go to the document manager to parse a file
			Model model;
			m_documents->loadFileContents(&file, model, nullptr, nullptr);

			currentDocument()->clearSelection();

			for (LDObject* object : model.objects())
			{
				currentDocument()->insertObject (position, object);
				currentDocument()->addToSelection(object);
				m_window->renderer()->compileObject (object);
				position++;
			}

			m_window->refresh();
			m_window->scrollToSelection();
		}
		else
		{
			Critical(format("Couldn't open %1 (%2)", filePath, file.errorString()));
		}
	}
}

void FileToolset::exportTo()
{
	if (selectedObjects().isEmpty())
		return;

	QString filePath = QFileDialog::getSaveFileName();

	if (filePath.isEmpty())
		return;

	QFile file {filePath};

	if (file.open(QIODevice::WriteOnly | QIODevice::Text))
	{
		for (LDObject* obj : selectedObjects())
		{
			QString contents = obj->asText();
			QByteArray data = contents.toUtf8();
			file.write(data, countof(data));
			file.write("\r\n", 2);
		}
	}
	else
	{
		Critical(format("Unable to open %1 for writing (%2)", filePath, file.errorString()));
	}
}

void FileToolset::scanPrimitives()
{
	primitives()->startScan();
}

void FileToolset::openSubfiles()
{
	for (LDObject* object : selectedObjects())
	{
		LDSubfileReference* reference = dynamic_cast<LDSubfileReference*>(object);

		if (reference and reference->fileInfo()->isCache())
			reference->fileInfo()->openForEditing();
	}
}

void FileToolset::downloadFrom()
{
	PartDownloader* dialog = new PartDownloader {m_window};
	connect(dialog, &PartDownloader::primaryFileDownloaded, [&]()
	{
		m_window->changeDocument (dialog->primaryFile());
		m_window->doFullRefresh();
		m_window->renderer()->resetAngles();
	});
	dialog->exec();
}

void FileToolset::makePrimitive()
{
	GeneratePrimitiveDialog* dialog = new GeneratePrimitiveDialog {m_window};

	if (dialog->exec())
	{
		LDDocument* primitive = primitives()->generatePrimitive(dialog->primitiveModel());
		primitive->openForEditing();
		m_window->save(primitive, false);
	}
}

// These are not exactly file tools but I don't want to make another toolset just for 3 very small actions
void FileToolset::help()
{
	// Not yet implemented
}

void FileToolset::about()
{
	QDialog *dialog = new QDialog(m_window);
	Ui::AboutUI ui;
	ui.setupUi(dialog);
	ui.versionInfo->setText(APPNAME " " + QString (fullVersionString()));
	dialog->setWindowTitle(format(tr("About %1"), APPNAME));
	dialog->exec();
}

void FileToolset::aboutQt()
{
	QMessageBox::aboutQt (m_window);
}

mercurial