Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
0e185510cThis 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 "boardplanepropertiesdialog.h"
#include "../../project/cmd/cmdboardplaneedit.h"
#include "../../undostack.h"
#include "ui_boardplanepropertiesdialog.h"
#include <librepcb/core/project/board/board.h>
#include <librepcb/core/project/board/items/bi_plane.h>
#include <librepcb/core/project/circuit/circuit.h>
#include <librepcb/core/project/circuit/netsignal.h>
#include <librepcb/core/types/layer.h>
#include <librepcb/core/utils/toolbox.h>
#include <QtCore>
#include <QtWidgets>
/*******************************************************************************
* Namespace
******************************************************************************/
namespace librepcb {
namespace editor {
/*******************************************************************************
* Constructors / Destructor
******************************************************************************/
BoardPlanePropertiesDialog::BoardPlanePropertiesDialog(
Project& project, BI_Plane& plane, UndoStack& undoStack,
const LengthUnit& lengthUnit, const QString& settingsPrefix,
QWidget* parent) noexcept
: QDialog(parent),
mProject(project),
mPlane(plane),
mUi(new Ui::BoardPlanePropertiesDialog),
mUndoStack(undoStack) {
mUi->setupUi(this);
mUi->edtMinWidth->configure(lengthUnit, LengthEditBase::Steps::generic(),
settingsPrefix % "/min_width");
mUi->edtMinClearanceToCopper->configure(
lengthUnit, LengthEditBase::Steps::generic(),
settingsPrefix % "/min_copper_clearance");
mUi->edtMinClearanceToBoard->configure(
lengthUnit, LengthEditBase::Steps::generic(),
settingsPrefix % "/min_board_clearance");
mUi->edtMinClearanceToNpth->configure(lengthUnit,
LengthEditBase::Steps::generic(),
settingsPrefix % "/min_npth_clearance");
mUi->edtThermalGap->configure(lengthUnit, LengthEditBase::Steps::generic(),
settingsPrefix % "/thermal_gap");
mUi->edtThermalSpokeWidth->configure(lengthUnit,
LengthEditBase::Steps::generic(),
settingsPrefix % "/thermal_spoke");
mUi->pathEditorWidget->setLengthUnit(lengthUnit);
connect(mUi->buttonBox, &QDialogButtonBox::clicked, this,
&BoardPlanePropertiesDialog::buttonBoxClicked);
// net signal combobox
connect(
mUi->cbxNetSignal,
static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
this, [this](int index) {
const bool hasNet =
!mUi->cbxNetSignal->itemData(index).toString().isEmpty();
mUi->cbxConnectStyle->setEnabled(hasNet);
mUi->cbKeepIslands->setEnabled(hasNet);
});
QList<NetSignal*> netSignals = mPlane.getCircuit().getNetSignals().values();
Toolbox::sortNumeric(
netSignals,
[](const QCollator& cmp, const NetSignal* lhs, const NetSignal* rhs) {
return cmp(*lhs->getName(), *rhs->getName());
},
Qt::CaseInsensitive, false);
mUi->cbxNetSignal->addItem("[" % tr("None") % "]", QString());
foreach (NetSignal* netsignal, netSignals) {
mUi->cbxNetSignal->addItem(*netsignal->getName(),
netsignal->getUuid().toStr());
}
mUi->cbxNetSignal->setCurrentIndex(mUi->cbxNetSignal->findData(
mPlane.getNetSignal() ? mPlane.getNetSignal()->getUuid().toStr()
: QString()));
// layer combobox
mUi->cbxLayer->setLayers(mPlane.getBoard().getCopperLayers());
mUi->cbxLayer->setCurrentLayer(mPlane.getLayer());
// minimum width / clearance spinboxes
mUi->edtMinWidth->setValue(mPlane.getMinWidth());
mUi->edtMinClearanceToCopper->setValue(mPlane.getMinClearanceToCopper());
mUi->edtMinClearanceToBoard->setValue(mPlane.getMinClearanceToBoard());
mUi->edtMinClearanceToNpth->setValue(mPlane.getMinClearanceToNpth());
// connect style combobox
mUi->cbxConnectStyle->addItem(tr("None"),
static_cast<int>(BI_Plane::ConnectStyle::None));
mUi->cbxConnectStyle->addItem(
tr("Thermal Relief"),
static_cast<int>(BI_Plane::ConnectStyle::ThermalRelief));
mUi->cbxConnectStyle->addItem(
tr("Solid"), static_cast<int>(BI_Plane::ConnectStyle::Solid));
mUi->cbxConnectStyle->setCurrentIndex(mUi->cbxConnectStyle->findData(
static_cast<int>(mPlane.getConnectStyle())));
// thermal gap/width spinbox
mUi->edtThermalGap->setValue(mPlane.getThermalGap());
mUi->edtThermalSpokeWidth->setValue(mPlane.getThermalSpokeWidth());
// priority spinbox
mUi->spbPriority->setValue(mPlane.getPriority());
// checkboxes
mUi->cbKeepIslands->setChecked(mPlane.getKeepIslands());
mUi->cbxLock->setChecked(mPlane.isLocked());
// vertices
mUi->pathEditorWidget->setPath(mPlane.getOutline());
// Make sure the thermal spoke width is >= minimum plane width.
connect(mUi->edtMinWidth, &UnsignedLengthEdit::valueChanged, this,
[this](const UnsignedLength& value) {
if (value > 0) {
mUi->edtThermalSpokeWidth->clipToMinimum(PositiveLength(*value));
}
});
connect(mUi->edtThermalSpokeWidth, &PositiveLengthEdit::valueChanged, this,
[this](const PositiveLength& value) {
mUi->edtMinWidth->clipToMaximum(positiveToUnsigned(value));
});
}
BoardPlanePropertiesDialog::~BoardPlanePropertiesDialog() noexcept {
mUi.reset();
}
/*******************************************************************************
* Private Methods
******************************************************************************/
void BoardPlanePropertiesDialog::buttonBoxClicked(
QAbstractButton* button) noexcept {
switch (mUi->buttonBox->buttonRole(button)) {
case QDialogButtonBox::ApplyRole:
applyChanges();
break;
case QDialogButtonBox::AcceptRole:
if (applyChanges()) {
accept();
}
break;
case QDialogButtonBox::RejectRole:
reject();
break;
default:
Q_ASSERT(false);
break;
}
}
bool BoardPlanePropertiesDialog::applyChanges() noexcept {
try {
std::unique_ptr<CmdBoardPlaneEdit> cmd(new CmdBoardPlaneEdit(mPlane));
// net signal
const std::optional<Uuid> netSignalUuid =
Uuid::tryFromString(mUi->cbxNetSignal->currentData().toString());
if (!netSignalUuid) {
cmd->setNetSignal(nullptr);
} else if (NetSignal* netsignal =
mPlane.getCircuit().getNetSignals().value(*netSignalUuid)) {
cmd->setNetSignal(netsignal);
} else {
qWarning() << "No valid netsignal selected in plane properties dialog!";
}
// layer
if (auto layer = mUi->cbxLayer->getCurrentLayer()) {
cmd->setLayer(*layer, false); // can throw
}
// min width/clearances
cmd->setMinWidth(mUi->edtMinWidth->getValue());
cmd->setMinClearanceToCopper(mUi->edtMinClearanceToCopper->getValue());
cmd->setMinClearanceToBoard(mUi->edtMinClearanceToBoard->getValue());
cmd->setMinClearanceToNpth(mUi->edtMinClearanceToNpth->getValue());
// connect style
cmd->setConnectStyle(static_cast<BI_Plane::ConnectStyle>(
mUi->cbxConnectStyle->currentData().toInt()));
// thermal gap & spoke width spinbox
cmd->setThermalGap(mUi->edtThermalGap->getValue());
cmd->setThermalSpokeWidth(mUi->edtThermalSpokeWidth->getValue());
// priority
cmd->setPriority(mUi->spbPriority->value());
// booleans
cmd->setKeepIslands(mUi->cbKeepIslands->isChecked());
cmd->setLocked(mUi->cbxLock->isChecked());
// vertices
cmd->setOutline(mUi->pathEditorWidget->getPath(), false); // can throw
// apply changes
mUndoStack.execCmd(cmd.release());
return true;
} catch (const Exception& e) {
QMessageBox::critical(this, tr("Error"), e.getMsg());
return false;
}
}
/*******************************************************************************
* End of File
******************************************************************************/
} // namespace editor
} // namespace librepcb