Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
c74bd0883This file is pinned to the selected release. Download the original to open it in your design tool.
/*
* LibrePCB - Professional EDA for everyone!
* Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
* https://librepcb.org/
*
* 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/>.
*/
/*******************************************************************************
* Includes
******************************************************************************/
#include "cmdcombineallnetsignalsunderschematicnetpoint.h"
#include "cmdcombinenetsignals.h"
#include "cmdcombineschematicnetpoints.h"
#include "cmdremoveunusednetsignals.h"
#include <librepcb/core/common/scopeguard.h>
#include <librepcb/core/project/circuit/circuit.h>
#include <librepcb/core/project/circuit/cmd/cmdcompsiginstsetnetsignal.h>
#include <librepcb/core/project/circuit/cmd/cmdnetsignaledit.h>
#include <librepcb/core/project/circuit/componentsignalinstance.h>
#include <librepcb/core/project/circuit/netclass.h>
#include <librepcb/core/project/circuit/netsignal.h>
#include <librepcb/core/project/project.h>
#include <librepcb/core/project/schematic/cmd/cmdschematicnetlineadd.h>
#include <librepcb/core/project/schematic/cmd/cmdschematicnetlineremove.h>
#include <librepcb/core/project/schematic/cmd/cmdschematicnetpointadd.h>
#include <librepcb/core/project/schematic/cmd/cmdschematicnetpointedit.h>
#include <librepcb/core/project/schematic/items/si_netline.h>
#include <librepcb/core/project/schematic/items/si_netpoint.h>
#include <librepcb/core/project/schematic/items/si_symbolpin.h>
#include <librepcb/core/project/schematic/schematic.h>
#include <QtCore>
/*******************************************************************************
* Namespace
******************************************************************************/
namespace librepcb {
namespace editor {
/*******************************************************************************
* Constructors / Destructor
******************************************************************************/
CmdCombineAllNetSignalsUnderSchematicNetPoint::
CmdCombineAllNetSignalsUnderSchematicNetPoint(
SI_NetPoint& netpoint) noexcept
: UndoCommandGroup(tr("Combine Schematic Items")),
mCircuit(netpoint.getCircuit()),
mSchematic(netpoint.getSchematic()),
mNetPoint(netpoint),
mHasCombinedSomeItems(false) {
}
CmdCombineAllNetSignalsUnderSchematicNetPoint::
~CmdCombineAllNetSignalsUnderSchematicNetPoint() noexcept {
}
/*******************************************************************************
* Inherited from UndoCommand
******************************************************************************/
bool CmdCombineAllNetSignalsUnderSchematicNetPoint::performExecute() {
// if an error occurs, undo all already executed child commands
auto undoScopeGuard = scopeGuard([&]() { performUndo(); });
// TODO:
// - Add a more sophisticated algorithm to determine the resulting netsignal
// - Maybe a callback is required to let the user choose the resulting
// netsignal if
// the resulting netsignal cannot be determined automatically.
// get all netpoints, netlines and symbol pins under the netpoint
QList<SI_NetPoint*> netpointsUnderCursor =
mSchematic.getNetPointsAtScenePos(mNetPoint.getPosition());
QList<SI_NetLine*> netlinesUnderCursor =
mSchematic.getNetLinesAtScenePos(mNetPoint.getPosition());
QList<SI_SymbolPin*> pinsUnderCursor =
mSchematic.getPinsAtScenePos(mNetPoint.getPosition());
// get all other netsignals of the items under the netpoint
QList<NetSignal*> netSignalsUnderCursor;
QStringList forcedNetNames;
foreach (SI_NetPoint* netpoint, netpointsUnderCursor) {
if (!netSignalsUnderCursor.contains(&netpoint->getNetSignal())) {
netSignalsUnderCursor.append(&netpoint->getNetSignal());
}
}
foreach (SI_NetLine* netline, netlinesUnderCursor) {
if (!netSignalsUnderCursor.contains(&netline->getNetSignal())) {
netSignalsUnderCursor.append(&netline->getNetSignal());
}
}
foreach (SI_SymbolPin* pin, pinsUnderCursor) {
ComponentSignalInstance* cmpSig = pin->getComponentSignalInstance();
NetSignal* signal = pin->getCompSigInstNetSignal();
if ((signal) && (!netSignalsUnderCursor.contains(signal))) {
netSignalsUnderCursor.append(signal);
}
if ((cmpSig) && (cmpSig->isNetSignalNameForced())) {
if (!forcedNetNames.contains(cmpSig->getForcedNetSignalName())) {
forcedNetNames.append(cmpSig->getForcedNetSignalName());
}
}
}
foreach (NetSignal* netsignal, netSignalsUnderCursor) {
if ((netsignal->isNameForced()) &&
(!forcedNetNames.contains(netsignal->getName()))) {
forcedNetNames.append(netsignal->getName());
}
}
// check forced net names
QString nameOfResultingNetSignal;
if (forcedNetNames.count() == 0) {
nameOfResultingNetSignal = mNetPoint.getNetSignal().getName();
} else if (forcedNetNames.count() == 1) {
nameOfResultingNetSignal = forcedNetNames.first();
} else if (forcedNetNames.count() > 1) {
// TODO: what should we do here?
throw RuntimeError(__FILE__, __LINE__,
tr("There are multiple different nets with forced names "
"at this position."));
}
// determine resulting netsignal
NetSignal* resultingNetSignal =
mCircuit.getNetSignalByName(nameOfResultingNetSignal);
if (!resultingNetSignal) {
// rename current netsignal
CmdNetSignalEdit* cmd =
new CmdNetSignalEdit(mCircuit, mNetPoint.getNetSignal());
cmd->setName(nameOfResultingNetSignal, false);
execNewChildCmd(cmd); // can throw
resultingNetSignal = &mNetPoint.getNetSignal();
}
Q_ASSERT(resultingNetSignal);
// combine all netsignals together
foreach (NetSignal* netsignal, netSignalsUnderCursor) {
if (netsignal != resultingNetSignal) {
execNewChildCmd(
new CmdCombineNetSignals(mCircuit, *netsignal,
*resultingNetSignal)); // can throw
mHasCombinedSomeItems = true;
}
}
// combine all netpoints together
// TODO: does this work properly in any case?
foreach (SI_NetPoint* netpoint, netpointsUnderCursor) {
if (netpoint != &mNetPoint) {
execNewChildCmd(
new CmdCombineSchematicNetPoints(*netpoint, mNetPoint)); // can throw
mHasCombinedSomeItems = true;
}
}
// TODO: connect all pins under the cursor to the netpoint
if (pinsUnderCursor.count() == 1) {
SI_SymbolPin* pin = pinsUnderCursor.first();
if (mNetPoint.getSymbolPin() != pin) {
if (mNetPoint.getSymbolPin() == nullptr) {
// connect pin to netsignal
ComponentSignalInstance* cmpSig = pin->getComponentSignalInstance();
if (cmpSig->getNetSignal() != resultingNetSignal) {
// TODO: this does not work in all cases?!
execNewChildCmd(new CmdCompSigInstSetNetSignal(
*cmpSig, resultingNetSignal)); // can throw
}
// attach netpoint to pin
QList<SI_NetLine*> lines = mNetPoint.getLines();
foreach (SI_NetLine* line, lines) {
execNewChildCmd(new CmdSchematicNetLineRemove(*line)); // can throw
}
CmdSchematicNetPointEdit* cmd = new CmdSchematicNetPointEdit(mNetPoint);
cmd->setPinToAttach(pin);
execNewChildCmd(cmd); // can throw
foreach (SI_NetLine* line, lines) {
execNewChildCmd(new CmdSchematicNetLineAdd(*line)); // can throw
}
mHasCombinedSomeItems = true;
} else {
throw RuntimeError(__FILE__, __LINE__,
tr("Sorry, not yet implemented..."));
}
}
} else if (pinsUnderCursor.count() > 1) {
throw RuntimeError(__FILE__, __LINE__, tr("Sorry, not yet implemented..."));
}
/*foreach (SI_SymbolPin* pin, pinsUnderCursor) {
ComponentSignalInstance* cmpSig = pin->getComponentSignalInstance();
if (cmpSig) {
if (cmpSig->getNetSignal() != resultingNetSignal) {
// change netsignal of component signal
// TODO: this does not work in all cases!
execNewChildCmd(new CmdCompSigInstSetNetSignal(*cmpSig,
resultingNetSignal)); // can throw
}
if (pin->getNetPoint() != &mNetPoint) {
// connect netpoint to pin
if ((mNetPoint.getSymbolPin() == nullptr) ||
mNetPoint.getSymbolPin() == pin) { CmdSchematicNetPointEdit* cmd = new
CmdSchematicNetPointEdit(mNetPoint); cmd->setPinToAttach(pin);
execNewChildCmd(cmd); // can throw
} else {
// TODO: attach pin to netpoint
throw RuntimeError(__FILE__, __LINE__,
tr("Sorry, not yet implemented..."));
}
}
} else {
throw RuntimeError(__FILE__, __LINE__,
tr("There is at least one pin at this position cannot be connected
to a net."));
}
}*/
// split all lines under the cursor and connect them to the netpoint
// TODO: avoid adding duplicate netlines!
netlinesUnderCursor =
mSchematic.getNetLinesAtScenePos(mNetPoint.getPosition()); // important!
foreach (SI_NetLine* netline, netlinesUnderCursor) {
SI_NetPoint& p1 = netline->getStartPoint();
SI_NetPoint& p2 = netline->getEndPoint();
if ((p1 != mNetPoint) && (p2 != mNetPoint)) {
execNewChildCmd(new CmdSchematicNetLineRemove(*netline)); // can throw
execNewChildCmd(
new CmdSchematicNetLineAdd(mSchematic, p1, mNetPoint)); // can throw
execNewChildCmd(
new CmdSchematicNetLineAdd(mSchematic, mNetPoint, p2)); // can throw
mHasCombinedSomeItems = true;
}
}
if (getChildCount() > 0) {
// remove netsignals which are no longer required
execNewChildCmd(new CmdRemoveUnusedNetSignals(
mSchematic.getProject().getCircuit())); // can throw
}
undoScopeGuard.dismiss(); // no undo required
return (getChildCount() > 0);
}
/*******************************************************************************
* End of File
******************************************************************************/
} // namespace editor
} // namespace librepcb