Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzCore includes
Toshihiro Shimizu 890ddd
#include "tconst.h"
Toshihiro Shimizu 890ddd
#include "tundo.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzBase includes
Toshihiro Shimizu 890ddd
#include "tfxattributes.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzLib includes
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfx.h"
Toshihiro Shimizu 890ddd
#include "toonz/fxcommand.h"
Toshihiro Shimizu 890ddd
#include "toonz/fxdag.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheet.h"
Toshihiro Shimizu 890ddd
#include "toonz/tfxhandle.h"
Toshihiro Shimizu 890ddd
#include "toonz/tcolumnfxset.h"
Toshihiro Shimizu 890ddd
#include "toonz/txsheethandle.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/fxschematicscene.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// TnzQt includes
Toshihiro Shimizu 890ddd
#include "toonzqt/schematicnode.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/fxschematicnode.h"
Toshihiro Shimizu 890ddd
#include "toonzqt/selectioncommandids.h"
Toshihiro Shimizu 890ddd
#include "fxdata.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
// Qt includes
Toshihiro Shimizu 890ddd
#include <qapplication></qapplication>
Toshihiro Shimizu 890ddd
#include <qclipboard></qclipboard>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "toonzqt/fxselection.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
bool canGroup(TFx *fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TXsheetFx *xfx = dynamic_cast<txsheetfx *="">(fx);</txsheetfx>
Toshihiro Shimizu 890ddd
	TOutputFx *ofx = dynamic_cast<toutputfx *="">(fx);</toutputfx>
Toshihiro Shimizu 890ddd
	return (!xfx && !ofx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
// FxSelection
Toshihiro Shimizu 890ddd
//
Toshihiro Shimizu 890ddd
//=========================================================
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FxSelection::FxSelection()
Toshihiro Shimizu 890ddd
	: m_xshHandle(0), m_fxHandle(0), m_pastePosition(TConst::nowhere), m_schematicScene(0)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FxSelection::FxSelection(const FxSelection &src)
Toshihiro Shimizu 890ddd
	: m_selectedFxs(src.m_selectedFxs), m_selectedLinks(src.m_selectedLinks), m_xshHandle(src.m_xshHandle), m_fxHandle(src.m_fxHandle), m_selectedColIndexes(src.m_selectedColIndexes), m_pastePosition(TConst::nowhere), m_schematicScene(src.m_schematicScene)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
FxSelection::~FxSelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::enableCommands()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	enableCommand(this, MI_Clear, &FxSelection::deleteSelection);
Toshihiro Shimizu 890ddd
	enableCommand(this, MI_Cut, &FxSelection::cutSelection);
Toshihiro Shimizu 890ddd
	enableCommand(this, MI_Copy, &FxSelection::copySelection);
Toshihiro Shimizu 890ddd
	enableCommand(this, MI_Paste, &FxSelection::pasteSelection);
Toshihiro Shimizu 890ddd
	enableCommand(this, MI_Group, &FxSelection::groupSelection);
Toshihiro Shimizu 890ddd
	enableCommand(this, MI_Ungroup, &FxSelection::ungroupSelection);
Toshihiro Shimizu 890ddd
	enableCommand(this, MI_Collapse, &FxSelection::collapseSelection);
Toshihiro Shimizu 890ddd
	enableCommand(this, MI_ExplodeChild, &FxSelection::explodeChild);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TSelection *FxSelection::clone() const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(0);
Toshihiro Shimizu 890ddd
	return new FxSelection(*this);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::select(TFxP fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_selectedFxs.append(fx);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::select(int colIndex)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_selectedColIndexes.append(colIndex);
Toshihiro Shimizu 890ddd
	qSort(m_selectedColIndexes);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::unselect(int colIndex)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_selectedColIndexes.removeOne(colIndex);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::unselect(TFxP fx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int index = m_selectedFxs.indexOf(fx);
Toshihiro Shimizu 890ddd
	if (index >= 0)
Toshihiro Shimizu 890ddd
		m_selectedFxs.removeAt(index);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::select(SchematicLink *link)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (link->isLineShaped())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	Link boundingFxs = getBoundingFxs(link);
Toshihiro Shimizu 890ddd
	if (boundingFxs == Link())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	m_selectedLinks.append(boundingFxs);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::unselect(SchematicLink *link)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Link boundingFxs = getBoundingFxs(link);
Toshihiro Shimizu 890ddd
	int index = m_selectedLinks.indexOf(boundingFxs);
Toshihiro Shimizu 890ddd
	if (index >= 0)
Toshihiro Shimizu 890ddd
		m_selectedLinks.removeAt(index);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool FxSelection::isSelected(TFxP fx) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < m_selectedFxs.size(); i++) {
Toshihiro Shimizu 890ddd
		TFx *selectedFx = m_selectedFxs[i].getPointer();
Toshihiro Shimizu 890ddd
		TZeraryColumnFx *zfx = dynamic_cast<tzerarycolumnfx *="">(selectedFx);</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
		if (zfx && (fx.getPointer() == zfx || fx.getPointer() == zfx->getZeraryFx()))
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
		if (fx.getPointer() == selectedFx)
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool FxSelection::isSelected(int columnIndex) const
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return m_selectedColIndexes.contains(columnIndex);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool FxSelection::isSelected(SchematicLink *link)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Link boundingFxs = getBoundingFxs(link);
Toshihiro Shimizu 890ddd
	return m_selectedLinks.contains(boundingFxs);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::deleteSelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	std::list<tfxp, std::allocator<tfxp="">> fxList = m_selectedFxs.toStdList();</tfxp,>
Toshihiro Shimizu 890ddd
	TFxCommand::deleteSelection(fxList, m_selectedLinks.toStdList(), m_selectedColIndexes.toStdList(),
Toshihiro Shimizu 890ddd
								m_xshHandle, m_fxHandle);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::copySelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QClipboard *clipboard = QApplication::clipboard();
Toshihiro Shimizu 890ddd
	FxsData *fxsData = new FxsData();
Toshihiro Shimizu 890ddd
	fxsData->setFxs(m_selectedFxs, m_selectedLinks, m_selectedColIndexes, m_xshHandle->getXsheet());
Toshihiro Shimizu 890ddd
	clipboard->setMimeData(fxsData);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::cutSelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	copySelection();
Toshihiro Shimizu 890ddd
	deleteSelection();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::pasteSelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	/*--- Fxノードを1つだけ選択していた場合、Replace paste ---*/
Toshihiro Shimizu 890ddd
	if (m_selectedFxs.size() >= 1 && m_selectedLinks.size() == 0 && m_selectedColIndexes.isEmpty())
Toshihiro Shimizu 890ddd
		replacePasteSelection();
Toshihiro Shimizu 890ddd
	/*--- Linkを1つだけ選択していた場合、Insert paste ---*/
Toshihiro Shimizu 890ddd
	else if (m_selectedFxs.size() == 0 && m_selectedLinks.size() >= 1 && m_selectedColIndexes.isEmpty())
Toshihiro Shimizu 890ddd
		insertPasteSelection();
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		QClipboard *clipboard = QApplication::clipboard();
Toshihiro Shimizu 890ddd
		const FxsData *fxsData = dynamic_cast<const *="" fxsdata="">(clipboard->mimeData());</const>
Toshihiro Shimizu 890ddd
		if (!fxsData)
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
		QList<tfxp> fxs;</tfxp>
Toshihiro Shimizu 890ddd
		QMap<tfx *,="" int=""> zeraryFxColumnSize;</tfx>
Toshihiro Shimizu 890ddd
		QList<txshcolumnp> columns;</txshcolumnp>
Toshihiro Shimizu 890ddd
		fxsData->getFxs(fxs, zeraryFxColumnSize, columns);
Toshihiro Shimizu 890ddd
		if (fxs.isEmpty() && columns.isEmpty())
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		// in case of the paste command triggered from short cut key
Toshihiro Shimizu 890ddd
		if (m_pastePosition == TConst::nowhere && m_schematicScene) {
Toshihiro Shimizu 890ddd
			SchematicSceneViewer *ssv = dynamic_cast<schematicsceneviewer *="">(m_schematicScene->views().at(0));</schematicsceneviewer>
Toshihiro Shimizu 890ddd
			if (ssv)
Toshihiro Shimizu 890ddd
				m_pastePosition = TPointD(ssv->getOldScenePos().x(), ssv->getOldScenePos().y());
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFxCommand::pasteFxs(fxs.toStdList(), zeraryFxColumnSize.toStdMap(), columns.toStdList(), m_pastePosition, m_xshHandle, m_fxHandle);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (m_schematicScene) {
Toshihiro Shimizu 890ddd
			selectNone();
Toshihiro Shimizu 890ddd
			for (int i = 0; i < (int)fxs.size(); i++)
Toshihiro Shimizu 890ddd
				select(fxs[i]);
Toshihiro Shimizu 890ddd
			m_schematicScene->selectNodes(fxs);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	m_pastePosition = TConst::nowhere;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool FxSelection::insertPasteSelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QClipboard *clipboard = QApplication::clipboard();
Toshihiro Shimizu 890ddd
	const FxsData *fxsData = dynamic_cast<const *="" fxsdata="">(clipboard->mimeData());</const>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_pastePosition = TConst::nowhere;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!fxsData || !fxsData->isConnected())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_selectedLinks.isEmpty())
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Start an undo block and ensure it is appropriately destroyed
Toshihiro Shimizu 890ddd
	struct Auto {
Toshihiro Shimizu 890ddd
		bool m_destruct;
Toshihiro Shimizu 890ddd
		~Auto()
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			if (m_destruct)
Toshihiro Shimizu 890ddd
				TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} auto_ = {false};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	// Need to make a temporary copy of selected links. It's necessary since the selection will
Toshihiro Shimizu 890ddd
	// be updated (cleared) after each insertion.
Toshihiro Shimizu 890ddd
	QList<tfxcommand::link> selectedLinks(m_selectedLinks);</tfxcommand::link>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i, size = selectedLinks.size();
Toshihiro Shimizu 890ddd
	for (i = 0; i < size; ++i) {
Toshihiro Shimizu 890ddd
		// Clone the fxs to be inserted
Toshihiro Shimizu 890ddd
		QList<tfxp> fxs;</tfxp>
Toshihiro Shimizu 890ddd
		QMap<tfx *,="" int=""> zeraryFxColumnSize;</tfx>
Toshihiro Shimizu 890ddd
		QList<txshcolumnp> columns;</txshcolumnp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		fxsData->getFxs(fxs, zeraryFxColumnSize, columns);
Toshihiro Shimizu 890ddd
		if (fxs.empty() && columns.empty())
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!auto_.m_destruct)
Toshihiro Shimizu 890ddd
			auto_.m_destruct = true, TUndoManager::manager()->beginBlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFxCommand::insertPasteFxs(selectedLinks[i], fxs.toStdList(), zeraryFxColumnSize.toStdMap(),
Toshihiro Shimizu 890ddd
								   columns.toStdList(), m_xshHandle, m_fxHandle);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool FxSelection::addPasteSelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QClipboard *clipboard = QApplication::clipboard();
Toshihiro Shimizu 890ddd
	const FxsData *fxsData = dynamic_cast<const *="" fxsdata="">(clipboard->mimeData());</const>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_pastePosition = TConst::nowhere;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!fxsData || !fxsData->isConnected())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_selectedFxs.isEmpty())
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	struct Auto {
Toshihiro Shimizu 890ddd
		bool m_destruct;
Toshihiro Shimizu 890ddd
		~Auto()
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			if (m_destruct)
Toshihiro Shimizu 890ddd
				TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} auto_ = {false};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QList<tfxp> selectedFxs(m_selectedFxs);</tfxp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i, size = selectedFxs.size();
Toshihiro Shimizu 890ddd
	for (i = 0; i < size; ++i) {
Toshihiro Shimizu 890ddd
		// Clone the fxs to be inserted
Toshihiro Shimizu 890ddd
		QList<tfxp> fxs;</tfxp>
Toshihiro Shimizu 890ddd
		QMap<tfx *,="" int=""> zeraryFxColumnSize;</tfx>
Toshihiro Shimizu 890ddd
		QList<txshcolumnp> columns;</txshcolumnp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		fxsData->getFxs(fxs, zeraryFxColumnSize, columns);
Toshihiro Shimizu 890ddd
		if (fxs.empty() && columns.empty())
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!auto_.m_destruct)
Toshihiro Shimizu 890ddd
			auto_.m_destruct = true, TUndoManager::manager()->beginBlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFx *inFx = selectedFxs[i].getPointer();
Toshihiro Shimizu 890ddd
		TFxCommand::addPasteFxs(inFx, fxs.toStdList(), zeraryFxColumnSize.toStdMap(),
Toshihiro Shimizu 890ddd
								columns.toStdList(), m_xshHandle, m_fxHandle);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool FxSelection::replacePasteSelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	QClipboard *clipboard = QApplication::clipboard();
Toshihiro Shimizu 890ddd
	const FxsData *fxsData = dynamic_cast<const *="" fxsdata="">(clipboard->mimeData());</const>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	m_pastePosition = TConst::nowhere;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!fxsData || !fxsData->isConnected())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (m_selectedFxs.isEmpty())
Toshihiro Shimizu 890ddd
		return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	struct Auto {
Toshihiro Shimizu 890ddd
		bool m_destruct;
Toshihiro Shimizu 890ddd
		~Auto()
Toshihiro Shimizu 890ddd
		{
Toshihiro Shimizu 890ddd
			if (m_destruct)
Toshihiro Shimizu 890ddd
				TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} auto_ = {false};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QList<tfxp> selectedFxs(m_selectedFxs);</tfxp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	int i, size = selectedFxs.size();
Toshihiro Shimizu 890ddd
	for (i = 0; i < size; ++i) {
Toshihiro Shimizu 890ddd
		// Clone the fxs to be inserted
Toshihiro Shimizu 890ddd
		QList<tfxp> fxs;</tfxp>
Toshihiro Shimizu 890ddd
		QMap<tfx *,="" int=""> zeraryFxColumnSize;</tfx>
Toshihiro Shimizu 890ddd
		QList<txshcolumnp> columns;</txshcolumnp>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		fxsData->getFxs(fxs, zeraryFxColumnSize, columns);
Toshihiro Shimizu 890ddd
		if (fxs.empty() && columns.empty())
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!auto_.m_destruct)
Toshihiro Shimizu 890ddd
			auto_.m_destruct = true, TUndoManager::manager()->beginBlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFx *inFx = m_selectedFxs[i].getPointer();
Toshihiro Shimizu 890ddd
		TFxCommand::replacePasteFxs(inFx, fxs.toStdList(), zeraryFxColumnSize.toStdMap(),
Toshihiro Shimizu 890ddd
									columns.toStdList(), m_xshHandle, m_fxHandle);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return true;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::groupSelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_selectedFxs.size() <= 1)
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	TFxCommand::groupFxs(m_selectedFxs.toStdList(), m_xshHandle);
Toshihiro Shimizu 890ddd
	selectNone();
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::ungroupSelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (isEmpty())
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	QSet<int> idSet;</int>
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < m_selectedFxs.size(); i++) {
Toshihiro Shimizu 890ddd
		int groupId = m_selectedFxs[i]->getAttributes()->getGroupId();
Toshihiro Shimizu 890ddd
		if (groupId > 0)
Toshihiro Shimizu 890ddd
			idSet.insert(groupId);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->beginBlock();
Toshihiro Shimizu 890ddd
	QSet<int>::iterator it;</int>
Toshihiro Shimizu 890ddd
	for (it = idSet.begin(); it != idSet.end(); it++)
Toshihiro Shimizu 890ddd
		TFxCommand::ungroupFxs(*it, m_xshHandle);
Toshihiro Shimizu 890ddd
	TUndoManager::manager()->endBlock();
Toshihiro Shimizu 890ddd
	selectNone();
Toshihiro Shimizu 890ddd
	m_xshHandle->notifyXsheetChanged();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::collapseSelection()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_selectedFxs.isEmpty())
Toshihiro Shimizu 890ddd
		emit doCollapse(m_selectedFxs);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::explodeChild()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (!m_selectedFxs.isEmpty())
Toshihiro Shimizu 890ddd
		emit doExplodeChild(m_selectedFxs);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Link FxSelection::getBoundingFxs(SchematicLink *link)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Link boundingFxs;
Toshihiro Shimizu 890ddd
	if (link) {
Toshihiro Shimizu 890ddd
		SchematicPort *port = link->getStartPort();
Toshihiro Shimizu 890ddd
		if (!port)
Toshihiro Shimizu 890ddd
			return boundingFxs;
Toshihiro Shimizu 890ddd
		if (port->getType() == 201 || port->getType() == 202 || port->getType() == 203)
Toshihiro Shimizu 890ddd
			boundingFxs = getBoundingFxs(port, link->getOtherPort(port));
Toshihiro Shimizu 890ddd
		else if (port->getType() == 200 || port->getType() == 204)
Toshihiro Shimizu 890ddd
			boundingFxs = getBoundingFxs(link->getOtherPort(port), port);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return boundingFxs;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Link FxSelection::getBoundingFxs(SchematicPort *inputPort, SchematicPort *outputPort)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Link boundingFxs;
Toshihiro Shimizu 890ddd
	FxSchematicNode *inputNode = dynamic_cast<fxschematicnode *="">(outputPort->getNode());</fxschematicnode>
Toshihiro Shimizu 890ddd
	FxSchematicNode *outputNode = dynamic_cast<fxschematicnode *="">(inputPort->getNode());</fxschematicnode>
Toshihiro Shimizu 890ddd
	FxGroupNode *groupNode = dynamic_cast<fxgroupnode *="">(inputNode);</fxgroupnode>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!inputNode || !outputNode || (groupNode && groupNode->getOutputConnectionsCount() != 1))
Toshihiro Shimizu 890ddd
		return boundingFxs;
Toshihiro Shimizu 890ddd
	if (dynamic_cast<txsheetfx *="">(outputNode->getFx())) {</txsheetfx>
Toshihiro Shimizu 890ddd
		if (!groupNode)
Toshihiro Shimizu 890ddd
			boundingFxs.m_inputFx = inputNode->getFx();
Toshihiro Shimizu 890ddd
		else {
Toshihiro Shimizu 890ddd
			TFxSet *terminals = m_xshHandle->getXsheet()->getFxDag()->getTerminalFxs();
Toshihiro Shimizu 890ddd
			QList<tfxp> roots = groupNode->getRootFxs();</tfxp>
Toshihiro Shimizu 890ddd
			int i;
Toshihiro Shimizu 890ddd
			for (i = 0; i < roots.size(); i++)
Toshihiro Shimizu 890ddd
				if (terminals->containsFx(roots[i].getPointer())) {
Toshihiro Shimizu 890ddd
					boundingFxs.m_inputFx = roots[i];
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		boundingFxs.m_outputFx = outputNode->getFx();
Toshihiro Shimizu 890ddd
		return boundingFxs;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (outputNode->isA(eGroupedFx)) {
Toshihiro Shimizu 890ddd
		//devo prima trovare l'effetto interno al gruppo al quale inputNode e' linkato.
Toshihiro Shimizu 890ddd
		FxGroupNode *groupNode = dynamic_cast<fxgroupnode *="">(outputNode);</fxgroupnode>
Toshihiro Shimizu 890ddd
		assert(groupNode);
Toshihiro Shimizu 890ddd
		QList<tfx *=""> fxs;</tfx>
Toshihiro Shimizu 890ddd
		TFx *inputFx = inputNode->getFx();
Toshihiro Shimizu 890ddd
		int i;
Toshihiro Shimizu 890ddd
		for (i = 0; i < inputFx->getOutputConnectionCount(); i++) {
Toshihiro Shimizu 890ddd
			TFx *outputFx = inputFx->getOutputConnection(i)->getOwnerFx();
Toshihiro Shimizu 890ddd
			if (!outputFx)
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			if (groupNode->contains(outputFx))
Toshihiro Shimizu 890ddd
				fxs.push_back(outputFx);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (fxs.size() != 1) //un nodo esterno al gruppo puo' essere linkato a piu' nodi interni al gruppo
Toshihiro Shimizu 890ddd
			return boundingFxs;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		TFx *outputFx = fxs[0];
Toshihiro Shimizu 890ddd
		//ho tovato l'effetto, ora devo trovare l'indice della porta a cui e' linkato l'effetto in input
Toshihiro Shimizu 890ddd
		for (i = 0; i < outputFx->getInputPortCount(); i++) {
Toshihiro Shimizu 890ddd
			TFxPort *inputPort = outputFx->getInputPort(i);
Toshihiro Shimizu 890ddd
			TFx *fx = inputPort->getFx();
Toshihiro Shimizu 890ddd
			if (fx == inputFx)
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (i >= outputFx->getInputPortCount())
Toshihiro Shimizu 890ddd
			return boundingFxs;
Toshihiro Shimizu 890ddd
		boundingFxs.m_inputFx = inputFx;
Toshihiro Shimizu 890ddd
		boundingFxs.m_outputFx = outputFx;
Toshihiro Shimizu 890ddd
		boundingFxs.m_index = i;
Toshihiro Shimizu 890ddd
		return boundingFxs;
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		bool found = false;
Toshihiro Shimizu 890ddd
		int i, index = -1;
Toshihiro Shimizu 890ddd
		for (i = 0; i < outputNode->getInputPortCount() && !found; i++) {
Toshihiro Shimizu 890ddd
			FxSchematicPort *inputAppPort = outputNode->getInputPort(i);
Toshihiro Shimizu 890ddd
			int j;
Toshihiro Shimizu 890ddd
			for (j = 0; j < inputAppPort->getLinkCount(); j++) {
Toshihiro Shimizu 890ddd
				FxSchematicNode *outputAppNode = dynamic_cast<fxschematicnode *="">(inputAppPort->getLinkedNode(j));</fxschematicnode>
Toshihiro Shimizu 890ddd
				if (!outputAppNode)
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
				FxSchematicPort *outputAppPort = outputAppNode->getOutputPort();
Toshihiro Shimizu 890ddd
				if (inputAppPort == inputPort && outputPort == outputAppPort) {
Toshihiro Shimizu 890ddd
					found = true;
Toshihiro Shimizu 890ddd
					index = i;
Toshihiro Shimizu 890ddd
					break;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
		if (index == -1)
Toshihiro Shimizu 890ddd
			return boundingFxs;
Toshihiro Shimizu 890ddd
		TFx *inputFx = inputNode->getFx();
Toshihiro Shimizu 890ddd
		TFx *outputFx = outputNode->getFx();
Toshihiro Shimizu 890ddd
		boundingFxs.m_inputFx = inputFx;
Toshihiro Shimizu 890ddd
		boundingFxs.m_outputFx = outputFx;
Toshihiro Shimizu 890ddd
		boundingFxs.m_index = index;
Toshihiro Shimizu 890ddd
		return boundingFxs;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool FxSelection::isConnected()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (m_selectedFxs.isEmpty())
Toshihiro Shimizu 890ddd
		return false;
Toshihiro Shimizu 890ddd
	QList<tfx *=""> visitedFxs;</tfx>
Toshihiro Shimizu 890ddd
	visitFx(m_selectedFxs.at(0).getPointer(), visitedFxs);
Toshihiro Shimizu 890ddd
	bool connected = true;
Toshihiro Shimizu 890ddd
	QList<tfxp>::const_iterator it;</tfxp>
Toshihiro Shimizu 890ddd
	TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
	TFxSet *internalFxs = xsh->getFxDag()->getInternalFxs();
Toshihiro Shimizu 890ddd
	for (it = m_selectedFxs.begin(); it != m_selectedFxs.end(); it++) {
Toshihiro Shimizu 890ddd
		TFx *selectedFx = it->getPointer();
Toshihiro Shimizu 890ddd
		TColumnFx *cfx = dynamic_cast<tcolumnfx *="">(selectedFx);</tcolumnfx>
Toshihiro Shimizu 890ddd
		if (!cfx && !internalFxs->containsFx(selectedFx))
Toshihiro Shimizu 890ddd
			return false;
Toshihiro Shimizu 890ddd
		TZeraryColumnFx *zfx = dynamic_cast<tzerarycolumnfx *="">(selectedFx);</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
		if (zfx)
Toshihiro Shimizu 890ddd
			selectedFx = zfx->getZeraryFx();
Toshihiro Shimizu 890ddd
		connected = connected && visitedFxs.contains(selectedFx);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return connected;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void FxSelection::visitFx(TFx *fx, QList<tfx *=""> &visitedFxs)</tfx>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (visitedFxs.contains(fx))
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	TZeraryColumnFx *zfx = dynamic_cast<tzerarycolumnfx *="">(fx);</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
	if (zfx)
Toshihiro Shimizu 890ddd
		fx = zfx->getZeraryFx();
Toshihiro Shimizu 890ddd
	if (!canGroup(fx))
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	visitedFxs.append(fx);
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < fx->getInputPortCount(); i++) {
Toshihiro Shimizu 890ddd
		TFx *inputFx = fx->getInputPort(i)->getFx();
Toshihiro Shimizu 890ddd
		TZeraryColumnFx *onputZFx = dynamic_cast<tzerarycolumnfx *="">(inputFx);</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
		if (onputZFx)
Toshihiro Shimizu 890ddd
			inputFx = onputZFx->getZeraryFx();
Toshihiro Shimizu 890ddd
		if (!inputFx)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		bool canBeGrouped = !inputFx->getAttributes()->isGrouped() ||
Toshihiro Shimizu 890ddd
							(inputFx->getAttributes()->getEditingGroupId() == fx->getAttributes()->getEditingGroupId());
Toshihiro Shimizu 890ddd
		if (!visitedFxs.contains(inputFx) && isSelected(inputFx) && canBeGrouped)
Toshihiro Shimizu 890ddd
			visitFx(inputFx, visitedFxs);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	if (zfx)
Toshihiro Shimizu 890ddd
		fx = zfx;
Toshihiro Shimizu 890ddd
	if (fx->isZerary() && !zfx) {
Toshihiro Shimizu 890ddd
		TXsheet *xsh = m_xshHandle->getXsheet();
Toshihiro Shimizu 890ddd
		int columnCount = xsh->getColumnCount();
Toshihiro Shimizu 890ddd
		int j;
Toshihiro Shimizu 890ddd
		for (j = 0; j < columnCount; j++) {
Toshihiro Shimizu 890ddd
			TZeraryColumnFx *zerary = dynamic_cast<tzerarycolumnfx *="">(xsh->getColumn(j)->getFx());</tzerarycolumnfx>
Toshihiro Shimizu 890ddd
			if (zerary && zerary->getZeraryFx() == fx) {
Toshihiro Shimizu 890ddd
				fx = zerary;
Toshihiro Shimizu 890ddd
				break;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	for (i = 0; i < fx->getOutputConnectionCount(); i++) {
Toshihiro Shimizu 890ddd
		TFx *outputFx = fx->getOutputConnection(i)->getOwnerFx();
Toshihiro Shimizu 890ddd
		if (!outputFx)
Toshihiro Shimizu 890ddd
			continue;
Toshihiro Shimizu 890ddd
		bool canBeGrouped = !outputFx->getAttributes()->isGrouped() ||
Toshihiro Shimizu 890ddd
							(outputFx->getAttributes()->getEditingGroupId() == fx->getAttributes()->getEditingGroupId());
Toshihiro Shimizu 890ddd
		if (!visitedFxs.contains(outputFx) && isSelected(outputFx) && canBeGrouped)
Toshihiro Shimizu 890ddd
			visitFx(outputFx, visitedFxs);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool FxSelection::areLinked(TFx *outFx, TFx *inFx)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	int i;
Toshihiro Shimizu 890ddd
	for (i = 0; i < outFx->getInputPortCount(); i++) {
Toshihiro Shimizu 890ddd
		TFx *inputFx = outFx->getInputPort(i)->getFx();
Toshihiro Shimizu 890ddd
		if (inFx == inputFx)
Toshihiro Shimizu 890ddd
			return true;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
	return false;
Toshihiro Shimizu 890ddd
}