#include <QMessageBox>
#include <QFileDialog>
#include <QInputDialog>
#include <QUiLoader>
#include <QMdiSubWindow>
#include <QMetaObject>
#include <QMetaMethod>
#include <QProcess>
#include <QTextBlock>
#include <QTextDocumentFragment>
#include <QTextTable>
#include <QScrollBar>
#include <QTimer>
#include <QPrinter>
#include <QDesktopServices>
#include <aboutwindow.h>
#include <ribbon.h>
#include <pimathbase.h>
#include <qad_locations.h>
#include "SH_designer.h"
#include "export_specification.h"
#include "SH_plugins_manager.h"

#define SHS_FILE_VERSION_HEADER  0xAB000000
#define SHS_FILE_VERSION_CURRENT 0x1


SHDesigner::SHDesigner(QWidget * parent): EMainWindow(parent), Ui::SHDesigner(), config(QAD::userPath(QAD::ltConfig, "SH_designer")) {
	setupUi(this);
	setRecentMenu(menuOpen_recent);
	actionEnable_resize->setText(tr("Enable\nresize"));
	SHCORE->sprocess.setBlockView(blockView);
	SHCORE->sprocess.setErrorsList(listErrors);
	SHCORE->dbgenerator.setBlockView(blockView);
	connect(&SHCORE->plugins_api, &SHDesignerAPI::newBlockRequest, this, [this](int block_id, QPoint pos, BlockItem ** ret){
		if (ret) *ret = nullptr;
		auto * nb = addBlock(block_id, SHDesignerCore::sDatabase, blockView->mapFromScene(pos));
		if (ret) *ret = nb;
	});
	connect(&SHCORE->plugins_api, &SHDesignerAPI::connectBlocksRequest, this, [this](int bus_id, QPoint p0, QPoint p1, BlockBusItem ** ret){
		if (ret) *ret = nullptr;
		BlockBusItem * bus = new BlockBusItem();
		bus->setBusType(bus_id);
		blockView->traceBus(p0, p1, bus);
		blockView->addItem(bus);
		if (ret) *ret = bus;
	});
	connect(&SHCORE->plugins_api, &SHDesignerAPI::sceneBlocksRequest, this, [this](QList<BlockItem *> * ret){
		if (ret) *ret = blockView->blocks();
	});
	connect(&SHCORE->plugins_api, &SHDesignerAPI::prepareBlockRequest, this, [](BlockItem * block){
		SHCORE->getStorage(block).prepareBlock(block);
	});

	draw_tools = new DrawTools(blockView);
	menuDraw->addActions(draw_tools->actionsForAdd());
	menuDraw->addSeparator();
	menuDraw->addActions(draw_tools->actionsForZ());
	QWidgetAction * wa = new QWidgetAction(menuDraw);
	wa->setDefaultWidget(draw_tools->propertyWidget());
	menuDraw->addSeparator();
	menuDraw->addAction(wa);
	connect(draw_tools, SIGNAL(itemCreated(QGraphicsItem*)), blockView, SLOT(addItem(QGraphicsItem*)));
	connect(draw_tools, SIGNAL(itemAddConfirm(QGraphicsItem*)), this, SLOT(addDecor(QGraphicsItem*)));
	connect(draw_tools, SIGNAL(itemEdited(QGraphicsItem*)), this, SLOT(decorChanged(QGraphicsItem*)));
	connect(draw_tools, SIGNAL(itemZChanged(QGraphicsItem*)), this, SLOT(decorZChanged(QGraphicsItem*)));

	Ribbon * ribbon = new Ribbon(this);
	//ribbon->setTabIconSize(QSize(32, 32));
	//ribbon->setIconSize(QSize(48, 48));
	preferences.piConfigWidget->setQPIConfig(&config);
	session.setFile(QAD::userPath(QAD::ltConfig, "session"));
	session.addEntry(this);
	session.addEntry(&database);
	session.addEntry(database.tabWidgetDB);
	session.addEntry(ribbon->tabWidget());
	session.addMainWidget(&block_properties);
	session.addMainWidget(&(block_properties.editor_dialog));
	session.addMainWidget(&bus_properties);
	session.addMainWidget(&(database.ext_db));
	session.addMainWidget(&plugins);
	//session.addEntry(&help);
	session.load();
	connect(actionAbout_Qt, SIGNAL(triggered(bool)), qApp, SLOT(aboutQt()));
	connect(SHCORE, SIGNAL(changed()), this, SLOT(reloadDB()));
	connect(SHCORE, SIGNAL(changedBlockPackets()), this, SLOT(selectionChanged()));
	connect(historyView, SIGNAL(commandExecute(const QByteArray &)), this, SLOT(loadScheme(const QByteArray &)));
	connect(historyView, SIGNAL(commandRequest(QByteArray &)), this, SLOT(saveScheme(QByteArray &)));
	connect(historyView, SIGNAL(changed()), this, SLOT(changed()));
	connect(blockView, SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
	connect(&block_properties, SIGNAL(editDatabaseBlock(int)), this, SLOT(editDatabaseBlock(int)));
	connect(&bus_properties, SIGNAL(editDatabaseBus(int)), this, SLOT(editDatabaseBus(int)));
	applyPreferences();
	historyView->registerAction(BlockItemBase::BlockAdd, "Block add", QImage(":/icons/format-add-block.png"));
	historyView->registerAction(BlockItemBase::BlockMove, "%count blocks moved", QImage(":/icons/format-move-block.png"));
	historyView->registerAction(BlockItemBase::BlockRemove, "%count blocks remove", QImage(":/icons/format-remove-block.png"));
	historyView->registerAction(BlockItemBase::BlockCopy, "%count blocks copy", QImage(":/icons/format-copy-block.png"));
	historyView->registerAction(BlockItemBase::BusAdd, "Bus add", QImage(":/icons/format-add-bus.png"));
	historyView->registerAction(BlockItemBase::BusRemove, "Bus remove", QImage(":/icons/edit-delete.png"));
	historyView->registerAction(BlockItemBase::BusPointAdd, "Bus point add", QImage(":/icons/format-add-point.png"));
	historyView->registerAction(BlockItemBase::BusPointMove, "Bus point move", QImage(":/icons/format-move-point.png"));
	historyView->registerAction(BlockItemBase::BusPointRemove, "Bus point remove", QImage(":/icons/format-remove-point.png"));
	historyView->registerAction(BlockItemBase::BusSegmentAdd, "Bus segment add");
	historyView->registerAction(BlockItemBase::BusSegmentMove, "Bus segment move", QImage(":/icons/format-move-segment.png"));
	historyView->registerAction(BlockItemBase::BusSegmentRemove, "Bus segment remove", QImage(":/icons/format-remove-segment.png"));
	historyView->registerAction(BlockItemBase::Paste, "%count items paste", QImage(":/icons/edit-paste.png"));
	historyView->registerAction(SchemeNew, "New scheme", QImage(":/icons/document-new.png"));
	historyView->registerAction(SchemeOpen, "Open scheme", QImage(":/icons/document-open.png"));
	historyView->registerAction(SchemePropertyChanged, "Project property changed", QImage(":/icons/format-edit-project.png"));
	historyView->registerAction(BlockPropertyChanged, "Block property changed", QImage(":/icons/format-edit-block.png"));
	historyView->registerAction(BusPropertyChanged, "Bus property changed", QImage(":/icons/format-edit-bus.png"));
	historyView->registerAction(DecorAdd, "Decor add", QImage(":/icons/decor-add.png"));
	historyView->registerAction(DecorEdit, "Decor changed", QImage(":/icons/decor-edit.png"));
	historyView->registerAction(DecorZChanged, "Decor Z-order changed", QImage(":/icons/decor-z.png"));
	historyView->addEntry(SchemeNew);
	propertiesProject->treeProps->hideColumn(1);
	propertiesProject->treeProps->headerItem()->setText(3, tr("Value"));
	SHCORE->reloadPlugins();
	setChanged(false);
	setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
	setCorner(Qt::BottomRightCorner, Qt::RightDockWidgetArea);
	reset();
}


SHDesigner::~SHDesigner() {
	//qDebug() << "~SHDesigner";
}


void SHDesigner::closeEvent(QCloseEvent * e) {
	EMainWindow::closeEvent(e);
	if (!e->isAccepted())
		return;
	session.save();
	session.clear();
	SHCORE->sprocess.setBlockView(0);
	SHCORE->sprocess.setErrorsList(0);
	SHCORE->dbgenerator.setBlockView(0);
	SHCORE->deleteEditors();
	RUNTIME->plugins_manager->localInterface().unloadPlugins();
	QApplication::closeAllWindows();
	//qDebug() << "close";
}


void SHDesigner::generateKey() {
	propertiesProject->blockSignals(true);
	PropertyStorage ps = propertiesProject->properties();
	if (ps.isPropertyExists("key"))
		ps.setPropertyValue("key", QString::number(randomi() % 10000).rightJustified(4, '0'));
	propertiesProject->setProperties(ps);
	SHCORE->project_properties = ps;
	propertiesProject->blockSignals(false);
	historyView->addEntry(SchemePropertyChanged);
}


void SHDesigner::editDatabaseBlock(int id) {
	on_actionEdit_database_triggered();
	database.tabWidgetDB->setCurrentIndex(3);
	database.tabDevices->showID(id);
}


void SHDesigner::editDatabaseBus(int id) {
	on_actionEdit_database_triggered();
	database.tabWidgetDB->setCurrentIndex(0);
	database.tabBuses->showID(id);
}


void SHDesigner::reset(bool full) {
	if (full) {
		if (!newProject()) return;
	}
	draw_tools->resetSizeTool();
	blockView->removeAll();
	
	QTimer::singleShot(0, this, SLOT(setTitle()));
	propertiesProject->clear();
	propertiesProject->addDefaultProperties();
	if (full) {
		file_name.clear();
		PropertyStorage pps = propertiesProject->properties();
		pps.setPropertyValue("name", SHCORE->current_project_name);
		propertiesProject->setProperties(pps);
	}
	generateKey();
	SHCORE->project_properties = propertiesProject->properties();
	historyView->clear(true);
	historyView->addEntry(SchemeNew);
	if (full) {
		save(SHCORE->currentProjectDir().filePath(SHCORE->current_project_name + ".shs"));
	}
	checkAllowEditDB();
	setChanged(false);
}


bool SHDesigner::load(const QString & path) {
	if (path.isEmpty()) return false;
	QFile f(path);
	if (!f.open(QIODevice::ReadOnly)) {
		QMessageBox::critical(this, "SH Designer", QString("Can`t open file \"%1\"!").arg(path));
		return false;
	}
	QFileInfo fi(f);
	PropertyStorage pprops;
	SHCORE->setCurrentProject(fi.absoluteDir().path());
	RUNTIME->shs_file = fi.dir().relativeFilePath(path);
	RUNTIME->shs_db_file = fi.dir().relativeFilePath(SHCORE->database().databaseName());

	QDataStream s(&f);
	uint v = schemeVersion(s);
	qDebug() << "load version" << v;
	switch (v) {
	case 0:
		{
		s.device()->seek(0);
		ChunkStream cs(s);
		while (!cs.atEnd()) {
			switch (cs.read()) {
			case 1: loadScheme_v0(cs.getData<QByteArray>()); break;
			case 2: blockView->setTransform(cs.getData<QTransform>()); break;
			case 3: blockView->centerOn(cs.getData<QPointF>()); break;
			case 4: pprops = cs.getData<PropertyStorage>(); break;
			}
		}
		SHCORE->actualizeProjectProperties(pprops);
		propertiesProject->blockSignals(true);
		propertiesProject->setProperties(pprops);
		propertiesProject->blockSignals(false);
		SHCORE->project_properties = propertiesProject->properties();
		} break;
	case SHS_FILE_VERSION_CURRENT:
		{
		ChunkStream cs(s);
		while (!cs.atEnd()) {
			switch (cs.read()) {
			case 1: loadScheme(cs.getData<QByteArray>()); break;
			case 2: blockView->setTransform(cs.getData<QTransform>()); break;
			case 3: blockView->centerOn(cs.getData<QPointF>()); break;
			}
		}
		} break;
	}

	historyView->clear(true);
	historyView->addEntry(SchemeOpen, 0, QString(" \"%1\"").arg(fi.baseName()));
	
	QTimer::singleShot(0, this, SLOT(setTitle()));
	setChanged(false);
	checkAllowEditDB();
	file_name = path;
	return true;
}


bool SHDesigner::save(const QString & path) {
	if (path == SHCORE->projectsDir().path()) {
		if (!newProject(propertiesProject->properties().propertyValueByName("name").toString())) return false;
		QMetaObject::invokeMethod(this, "saveFile", Qt::QueuedConnection, Q_ARG(QString, SHCORE->currentProjectDir().filePath(SHCORE->current_project_name) + ".shs"));
		return false;
	}
	QFileInfo fi(path);
	QString p = path;
	if (fi.suffix() != "shs")
		p += ".shs";
	QFile f(p);
	fi.setFile(f);
	f.open(QIODevice::WriteOnly);
	f.resize(0);
	
	ChunkStream cs;
	QByteArray ba;
	saveScheme(ba);
	cs.add(1, ba).add(2, blockView->transform()).add(3, blockView->mapToScene(blockView->viewport()->rect().center()));
	
	QDataStream s(&f);
	s << uint(SHS_FILE_VERSION_HEADER | SHS_FILE_VERSION_CURRENT) << cs.data();

	SHCORE->savePropertiesToFile(SHCORE->currentProjectDir().filePath("plugins.user"), RUNTIME->plugins_props_project);

	QTimer::singleShot(0, this, SLOT(setTitle()));
	checkAllowEditDB();
	setChanged(false);
	file_name = p;
	return true;
}


void SHDesigner::loadingSession(QPIConfig & conf) {
	setRecentFiles(conf.getValue("recent_files").toStringList());
}


void SHDesigner::savingSession(QPIConfig & conf) {
	conf.setValue("recent_files", recentFiles());
}


void SHDesigner::checkAllowEditDB() {
	bool ae = !SHCORE->current_project_name.isEmpty();
	actionEdit_database->setEnabled(ae);
}


bool SHDesigner::newProject(const QString & name) {
	bool ok = true;
	QString nn = QInputDialog::getText(this, "SH Designer", "Enter name for new project:", QLineEdit::Normal, name, &ok);
	if (!ok || nn.isEmpty()) return false;
	QDir td = SHCORE->projectsDir();
	if (td.cd(nn))
		if (td.exists()) {
			if (QMessageBox::question(this, "SH Designer", QString("Project \"%1\" already exists. Overwrite?").arg(nn),
									  QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Cancel)
				return false;
		}
	SHCORE->projectsDir().mkdir(nn);
	SHCORE->setCurrentProject(SHCORE->projectsDir().filePath(nn));
	return true;
}


BlockItem * SHDesigner::addBlock(int id, int source, QPoint pos) {
	BlockItem * nb = SHCORE->getStorage(source).src_blocks.value(id, 0);
	if (!nb) return nullptr;
	nb = nb->copy();
	blockView->setUniqueName(nb);
	QPointF qpos = quantize(blockView->mapToScene(pos) - QPointF(0, nb->height() / 2 - 5), blockView->gridStep());
	nb->setPos(qpos);
	nb->setData(SH_Block_ID, id);
	nb->setData(SH_Block_Source, source);
	SHCORE->getStorage(nb).prepareBlock(nb);
	blockView->addItem(nb);
	return nb;
}


void SHDesigner::setTitle() {
	setWindowTitle(QString("SH Designer - %1 (%2)[*]").arg(SHCORE->current_project_name, QFileInfo(file_name).fileName()));
}


void SHDesigner::loadScheme_v0(const QByteArray & data) {
	draw_tools->resetSizeTool();
	blockView->removeAll();
	blockView->blockSignals(true);
	blockView->load(data);
	blockView->blockSignals(false);
	on_blockView_changedScheme();
}


void SHDesigner::loadScheme(const QByteArray & data) {
	draw_tools->resetSizeTool();
	blockView->removeAll();
	blockView->blockSignals(true);
	propertiesProject->blockSignals(true);
	PropertyStorage pprops;
	ChunkStream cs(data);
	while (!cs.atEnd()) {
		switch (cs.read()) {
		case 1: blockView->load(cs.getData<QByteArray>()); break;
		case 2: pprops = cs.getData<PropertyStorage>(); break;
		}
	}
	SHCORE->actualizeProjectProperties(pprops);
	propertiesProject->setProperties(pprops);
	blockView->blockSignals(false);
	propertiesProject->blockSignals(false);
	SHCORE->project_properties = propertiesProject->properties();
	on_blockView_changedScheme();
}


void SHDesigner::saveScheme(QByteArray & data) {
	ChunkStream cs;
	cs.add(1, blockView->save()).add(2, propertiesProject->properties());
	data = cs.data();
}


int SHDesigner::schemeVersion(QDataStream & s) {
	s.setVersion(QDataStream::Qt_4_8);
	uint v = 0; s >> v;
	//qDebug() << "version" << v;
	if ((v & 0xFF000000) != SHS_FILE_VERSION_HEADER) return 0;
	return v & 0xFFFFFF;
}


#define CHECK_PREF(n, v) if (!config.isEntryExists(n)) config.setValue(n, v);

void SHDesigner::applyPreferences() {
	CHECK_PREF("projects dir", "$documents/SH_Designer/projects");
	CHECK_PREF("database dir", "SH_Databases");
	CHECK_PREF("default project properties", QStringList() << "name(s)" << "owner(s)" << "address(s)" << "key(s)");
	CHECK_PREF("default block properties", QStringList() << "id(n)" << "name(s)" << "comment(s)");
	CHECK_PREF("default bus properties", QStringList() << "name(s)" << "comment(s)" << "length(f)");
	CHECK_PREF("default pin properties", QStringList());
	CHECK_PREF("trace cross buses", true);
	CHECK_PREF("block animation", true);
	CHECK_PREF("view animation", true);
	CHECK_PREF("history limit", 64);
	SHCORE->setProjectsDir(config.getValue("projects dir", "$documents/SH_Designer/projects").toString());
	SHCORE->setDatabasesDir(config.getValue("database dir", "SH_Databases").toString());
	SHCORE->default_project_properties = SHCORE->parseDefaultProperties(config.getValue("default project properties").toStringList());
	SHCORE->default_block_properties = SHCORE->parseDefaultProperties(config.getValue("default block properties").toStringList());
	SHCORE->default_bus_properties = SHCORE->parseDefaultProperties(config.getValue("default bus properties").toStringList());
	SHCORE->default_pin_properties = SHCORE->parseDefaultProperties(config.getValue("default pin properties").toStringList());
	//SHCORE->actualizeProjectProperties(SHCORE->default_project_properties);
	blockView->setTraceConsiderBuses(!config.getValue("trace cross buses", true).toBool());
	blockView->setBlockAnimationEnabled(config.getValue("block animation", true).toBool());
	blockView->setNavigateAnimationEnabled(config.getValue("view animation", true).toBool());
	historyView->setLimit(config.getValue("history limit", 64).toInt());
	propertiesProject->setDefaultProperties(SHCORE->default_project_properties);
	if (file_name.isEmpty()) file_name = SHCORE->projectsDir().path();
}

#undef CHECK_PREF


void SHDesigner::reloadDB() {
	treeBlocks->clear();
	QMap<QString, QTreeWidgetItem * > groups;
	treeBlocks->setUpdatesEnabled(false);
	SHDatabaseStorage * storages[2] = {&(SHCORE->storage), &(SHCORE->storage_plugins)};
	for (int i = 0; i < 2; ++i) {
		auto it = storages[i]->block_types.makeIterator();
		while (it.next()) {
			if (it.value().name.isEmpty()) continue;
			int id = it.key();
			QString gn = it.value().group_name;
			QString name = it.value().name;
			if (i == 0) {
				name += QString(" (%2)").arg(it.value().vendor_name);
			} else {
				gn = "Plugins";
			}
			QTreeWidgetItem * ni = new QTreeWidgetItem(), * pi = groups.value(gn, 0);
			ni->setData(0, Qt::UserRole, id);
			ni->setData(0, Qt::UserRole+1, i);
			ni->setText(0, name);
			ni->setToolTip(0, it.value().description);
			if (!pi) {
				pi = new QTreeWidgetItem(QStringList() << gn);
				pi->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
				treeBlocks->addTopLevelItem(pi);
				groups[gn] = pi;
			}
			pi->addChild(ni);
		}
	}
	treeBlocks->expandAll();
	filterBlocks();
	auto pprops = propertiesProject->properties();
	SHCORE->actualizeProjectProperties(pprops);
	propertiesProject->setProperties(pprops);
	treeBlocks->setUpdatesEnabled(true);
	SHCORE->sprocess.checkForErrors();
}


void SHDesigner::filterBlocks() {
	QString f = lineFilterBlocks->text();
	for (int i = 0; i < treeBlocks->topLevelItemCount(); ++i) {
		QTreeWidgetItem * ti = treeBlocks->topLevelItem(i);
		bool hc = false;
		for (int j = 0; j < ti->childCount(); ++j) {
			QTreeWidgetItem * tj = ti->child(j);
			tj->setHidden(!(tj->text(0).contains(f, Qt::CaseInsensitive) ||
							tj->toolTip(0).contains(f, Qt::CaseInsensitive) ||
							tj->data(0, Qt::UserRole).toString().contains(f, Qt::CaseInsensitive)));
			if (!tj->isHidden())
				hc = true;
		}
		ti->setHidden(!hc);
	}
}


void SHDesigner::selectionChanged() {
	QList<QGraphicsItem*> sil = blockView->scene()->selectedItems();
	int sic = sil.size();
	bool hb = (sic > 0);
	actionRemove->setEnabled(hb);
	dockObject->widget()->setEnabled(sic == 1);
	if (sic == 1) {
		BlockItem * block = qgraphicsitem_cast<BlockItem * >(sil[0]);
		if (block) {
			SHS::Object o = SHCORE->dbgenerator.generateObject(block);
			o.swapIOFlags();
			objectTree->create(o);
		}
	}
}


void SHDesigner::on_actionPreferences_triggered() {
	preferences.piConfigWidget->setQPIConfig(&config);
	if (preferences.exec() == QDialog::Accepted)
		applyPreferences();
}


void SHDesigner::on_actionReload_triggered() {
	//load(form_path);
}


void SHDesigner::on_actionLoaded_Plugins_triggered() {
	plugins.exec();
	QAD::CursorOverrider curov;
	SHCORE->reloadPlugins();
}


void SHDesigner::on_actionReveal_all_triggered() {
	blockView->fitInView();
}


void SHDesigner::on_actionGenerate_specification_triggered() {
	QString p = QFileDialog::getSaveFileName(this, "Select file to save", spec_path, "MS Office document(*.doc)");
	if (p.isEmpty()) return;
	if (!p.endsWith(".doc")) p += ".doc";
	QFile file(p);
	if (!file.open(QIODevice::ReadWrite)) {
		QMessageBox::critical(this, "SH Designer", QString("Can`t open \"%1\"!").arg(p));
		return;
	}
	QApplication::setOverrideCursor(Qt::WaitCursor);
	spec_path = p;
	QByteArray doc = exportSpecification(blockView);
	file.resize(0);
	file.write(doc);
	QApplication::restoreOverrideCursor();
}


void SHDesigner::on_actionExport_to_PDF_triggered() {
	if (export_to_pdf.exec() != QDialog::Accepted) return;
	QString p = QFileDialog::getSaveFileName(this, "Select file to save", pdf_path, "Portable Document Format(*.pdf)");
	if (p.isEmpty()) return;
	if (!p.endsWith(".pdf")) p += ".pdf";
	QFile file(p);
	if (!file.open(QIODevice::ReadWrite)) {
		QMessageBox::critical(this, "SH Designer", QString("Can`t open \"%1\"!").arg(p));
		return;
	}
	QApplication::setOverrideCursor(Qt::WaitCursor);
	pdf_path = p;
	QPrinter printer;
	printer.setOutputFormat(QPrinter::PdfFormat);
	printer.setOutputFileName(p);
	printer.setPageSize(export_to_pdf.page_size);
	//printer.setOrientation(export_to_pdf.orientation);
	printer.setResolution(export_to_pdf.dpi);
	printer.setDocName(SHCORE->project_properties.propertyValueByName("name").toString());
	printer.setCreator("SH Designer");
	bool grid = blockView->isGridVisible();
	blockView->setGridVisible(export_to_pdf.checkGrid->isChecked());
	QPainter painter(&printer);
	blockView->render(&painter);
	QApplication::restoreOverrideCursor();
	blockView->setGridVisible(grid);
}


void SHDesigner::on_actionShow_project_in_file_manager_triggered() {
	QDesktopServices::openUrl(QUrl::fromLocalFile(SHCORE->projectsDir().filePath(SHCORE->current_project_name)));
}


void SHDesigner::on_actionAbout_SHS_triggered() {
	AboutWindow::show();
}


void SHDesigner::on_blockView_newBlockRequest(int id, int source, QPoint view_pos) {
	addBlock(id, source, view_pos);
}


void SHDesigner::on_blockView_changedScheme() {
	blockView->updateFileWatcher();
	SHCORE->sprocess.checkForErrors();
}


void SHDesigner::on_blockView_blockDoubleClicked(BlockItem * block) {
	if (block_properties.show(block) == QDialog::Rejected)
		return;
	blockView->reconnectAll();
	SHCORE->getStorage(block).prepareBlock(block);
	historyView->addEntry(BlockPropertyChanged);
	selectionChanged();
}


void SHDesigner::on_blockView_busDoubleClicked(BlockBusItem * bus) {
	if (bus_properties.show(bus) == QDialog::Rejected)
		return;
	blockView->reconnectAll();
	historyView->addEntry(BusPropertyChanged);
	selectionChanged();
}


void SHDesigner::on_blockView_schemeAction(BlockItemBase::Action action, QList<QGraphicsItem * > items) {
	historyView->addEntry(action, items.size());
}


void SHDesigner::on_propertiesProject_propertiesChanged() {
	SHCORE->project_properties = propertiesProject->properties();
	//qDebug() << "changed";
	//setChanged();
	checkAllowEditDB();
	historyView->addEntry(SchemePropertyChanged);
}
