Loading files
/*
* 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 "packagecheckmessages.h"
#include "../../geometry/stroketext.h"
#include "../../types/layer.h"
#include "footprint.h"
#include "packagepad.h"
/*******************************************************************************
* Namespace
******************************************************************************/
namespace librepcb {
/*******************************************************************************
* MsgDeprecatedAssemblyType
******************************************************************************/
MsgAmbiguousFootprintTags::MsgAmbiguousFootprintTags() noexcept
: RuleCheckMessage(
Severity::Hint, tr("Ambiguous footprint tags"),
tr("The package provides multiple footprints, but they don't specify "
"(enough) tags to make them uniquely identifiable just by their "
"tags. This is not a problem at all, but adding unique tags to the "
"footprints would make the automatic footprint selection of the "
"board editor more sophisticated."),
"ambiguous_footprint_tags") {
}
/*******************************************************************************
* MsgDeprecatedAssemblyType
******************************************************************************/
MsgDeprecatedAssemblyType::MsgDeprecatedAssemblyType() noexcept
: RuleCheckMessage(Severity::Hint, tr("Non-recommended assembly type"),
tr("The assembly type 'Auto-detect' is not recommended as "
"the detection might not be correct in every case. "
"It's safer to specify the assembly type manually."),
"auto_assembly_type") {
}
/*******************************************************************************
* MsgSuspiciousAssemblyType
******************************************************************************/
MsgSuspiciousAssemblyType::MsgSuspiciousAssemblyType() noexcept
: RuleCheckMessage(
Severity::Warning, tr("Suspicious assembly type"),
tr("The specified assembly type differs from the assembly type which "
"is auto-detected from the footprint contents. Double-check if the "
"specified assembly type is really correct."),
"suspicious_assembly_type") {
}
/*******************************************************************************
* MsgDuplicatePadName
******************************************************************************/
MsgDuplicatePadName::MsgDuplicatePadName(const PackagePad& pad) noexcept
: RuleCheckMessage(
Severity::Error, tr("Duplicate pad name: '%1'").arg(*pad.getName()),
tr("All package pads must have unique names, otherwise they cannot be "
"distinguished later in the device editor. If your part has several "
"leads with same functionality (e.g. multiple GND leads), you can "
"assign all these pads to the same component signal later in the "
"device editor.\n\nFor neutral packages (e.g. SOT23), pads should "
"be named only by numbers anyway, not by functionality (e.g. name "
"them '1', '2', '3' instead of 'D', 'G', 'S')."),
"duplicate_pad_name") {
mApproval->appendChild("name", *pad.getName());
}
/*******************************************************************************
* Class MsgFiducialClearanceLessThanStopMask
******************************************************************************/
MsgFiducialClearanceLessThanStopMask::MsgFiducialClearanceLessThanStopMask(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Small copper clearance on fiducial in '%1'")
.arg(*footprint->getNames().getDefaultValue()),
tr("The copper clearance of the fiducial pad is less than its stop "
"mask expansion, which is unusual. Typically the copper clearance "
"should be equal to or greater than the stop mask expansion to "
"avoid copper located within the stop mask opening."),
"fiducial_copper_clearance_less_than_stop_mask"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* Class MsgFiducialStopMaskNotSet
******************************************************************************/
MsgFiducialStopMaskNotSet::MsgFiducialStopMaskNotSet(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Stop mask not set on fiducial in '%1'")
.arg(*footprint->getNames().getDefaultValue()),
tr("The stop mask expansion of the fiducial pad is set to automatic, "
"which is unusual. Typically the stop mask expansion of fiducials "
"need to be manually set to a much larger value."),
"fiducial_stop_mask_not_set"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgHoleWithoutStopMask
******************************************************************************/
MsgHoleWithoutStopMask::MsgHoleWithoutStopMask(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const Hole> hole) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("No stop mask on %1 hole in '%2'",
"First placeholder is the hole diameter.")
.arg(hole->getDiameter()->toMmString() % "mm",
*footprint->getNames().getDefaultValue()),
tr("Non-plated holes should have a stop mask opening to avoid solder "
"resist flowing into the hole. An automatic stop mask opening can "
"be enabled in the hole properties."),
"hole_without_stop_mask"),
mFootprint(footprint),
mHole(hole) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("hole", hole->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgInvalidCustomPadOutline
******************************************************************************/
MsgInvalidCustomPadOutline::MsgInvalidCustomPadOutline(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad, const QString& pkgPadName) noexcept
: RuleCheckMessage(
Severity::Error,
tr("Invalid custom outline of pad '%1' in '%2'")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("The pad has set a custom outline which does not represent a valid "
"area. Either choose a different pad shape or specify a valid "
"custom outline."),
"invalid_custom_pad_outline"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgInvalidPadConnection
******************************************************************************/
MsgInvalidPadConnection::MsgInvalidPadConnection(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad) noexcept
: RuleCheckMessage(
Severity::Error,
tr("Invalid pad connection in '%1'")
.arg(*footprint->getNames().getDefaultValue()),
tr("A footprint pad is connected to a package pad which doesn't exist. "
"Check all pads for proper connections."),
"invalid_pad_connection"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgMinimumWidthViolation
******************************************************************************/
MsgMinimumWidthViolation::MsgMinimumWidthViolation(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const Polygon> polygon, const Length& minWidth) noexcept
: RuleCheckMessage(
Severity::Warning, getMessage(footprint, polygon->getLayer()),
tr("It is recommended that polygons on layer '%1' have a line width of "
"at least %2.")
.arg(polygon->getLayer().getNameTr())
.arg(QString::number(minWidth.toMm() * 1000) % "μm") %
" " % getDescriptionAppendix(),
"thin_line"),
mFootprint(footprint),
mPolygon(polygon) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("polygon", polygon->getUuid());
mApproval->ensureLineBreak();
}
MsgMinimumWidthViolation::MsgMinimumWidthViolation(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const Circle> circle, const Length& minWidth) noexcept
: RuleCheckMessage(
Severity::Warning, getMessage(footprint, circle->getLayer()),
tr("It is recommended that circles on layer '%1' have a line width of "
"at least %2.")
.arg(circle->getLayer().getNameTr())
.arg(QString::number(minWidth.toMm() * 1000) % "μm") %
" " % getDescriptionAppendix(),
"thin_line"),
mFootprint(footprint),
mCircle(circle) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("circle", circle->getUuid());
mApproval->ensureLineBreak();
}
MsgMinimumWidthViolation::MsgMinimumWidthViolation(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const StrokeText> text, const Length& minWidth) noexcept
: RuleCheckMessage(
Severity::Warning, getMessage(footprint, text->getLayer()),
tr("It is recommended that stroke texts on layer '%1' have a stroke "
"width of at least %2.")
.arg(text->getLayer().getNameTr())
.arg(QString::number(minWidth.toMm() * 1000) % "μm") %
" " % getDescriptionAppendix(),
"thin_line"),
mFootprint(footprint),
mStrokeText(text) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("text", text->getUuid());
mApproval->ensureLineBreak();
}
QString MsgMinimumWidthViolation::getMessage(
std::shared_ptr<const Footprint> footprint, const Layer& layer) noexcept {
return tr("Minimum width of '%1' in '%2'")
.arg(layer.getNameTr())
.arg(*footprint->getNames().getDefaultValue());
}
QString MsgMinimumWidthViolation::getDescriptionAppendix() noexcept {
return tr(
"Otherwise it could lead to manufacturing problems in some cases "
"(depending on board settings and/or the capabilities of the PCB "
"manufacturer).");
}
/*******************************************************************************
* MsgMissingCourtyard
******************************************************************************/
MsgMissingCourtyard::MsgMissingCourtyard(
std::shared_ptr<const Footprint> footprint) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Missing courtyard in footprint '%1'")
.arg(*footprint->getNames().getDefaultValue()),
tr("It is recommended to draw the package courtyard with a "
"single, closed, zero-width polygon or circle on "
"layer '%1'. This allows the DRC to warn if another device "
"is placed within the courtyard of this device (i.e. too close).")
.arg(Layer::topCourtyard().getNameTr()) %
"\n\n" %
tr("Often this is identical to the package outline but with a "
"small offset. If you're unsure, just ignore this message."),
"missing_courtyard"),
mFootprint(footprint) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgMissingFootprint
******************************************************************************/
MsgMissingFootprint::MsgMissingFootprint() noexcept
: RuleCheckMessage(
Severity::Error, tr("No footprint defined"),
tr("Every package must have at least one footprint, otherwise it can't "
"be added to a board."),
"missing_footprint") {
}
/*******************************************************************************
* MsgMissingFootprintModel
******************************************************************************/
MsgMissingFootprintModel::MsgMissingFootprintModel(
std::shared_ptr<const Footprint> footprint) noexcept
: RuleCheckMessage(
Severity::Hint,
tr("No 3D model defined for '%1'")
.arg(*footprint->getNames().getDefaultValue()),
tr("The footprint has no 3D model specified, so the package will be "
"missing in the 3D viewer and in 3D data exports. However, this has "
"no impact on the PCB production data."),
"missing_footprint_3d_model"),
mFootprint(footprint) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgMissingFootprintName
******************************************************************************/
MsgMissingFootprintName::MsgMissingFootprintName(
std::shared_ptr<const Footprint> footprint) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Missing text '%1' in footprint '%2'")
.arg("{{NAME}}", *footprint->getNames().getDefaultValue()),
tr("Most footprints should have a text element for the component's "
"name, otherwise you won't see that name on the PCB (e.g. on "
"silkscreen). There are only a few exceptions which don't need a "
"name (e.g. if the footprint is only a drawing), for those you can "
"ignore this message."),
"missing_name_text"),
mFootprint(footprint) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgMissingFootprintValue
******************************************************************************/
MsgMissingFootprintValue::MsgMissingFootprintValue(
std::shared_ptr<const Footprint> footprint) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Missing text '%1' in footprint '%2'")
.arg("{{VALUE}}", *footprint->getNames().getDefaultValue()),
tr("Most footprints should have a text element for the component's "
"value, otherwise you won't see that value on the PCB (e.g. on "
"silkscreen). There are only a few exceptions which don't need a "
"value (e.g. if the footprint is only a drawing), for those you can "
"ignore this message."),
"missing_value_text"),
mFootprint(footprint) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgMissingPackageOutline
******************************************************************************/
MsgMissingPackageOutline::MsgMissingPackageOutline(
std::shared_ptr<const Footprint> footprint) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Missing outline in footprint '%1'")
.arg(*footprint->getNames().getDefaultValue()),
tr("It is recommended to draw the package outline with a "
"single, closed, zero-width polygon or circle on "
"layer '%1'. This allows the DRC to warn if this device "
"is placed within the courtyard of another device (i.e. too close).")
.arg(Layer::topPackageOutlines().getNameTr()),
"missing_package_outline"),
mFootprint(footprint) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgFootprintOriginNotInCenter
******************************************************************************/
MsgFootprintOriginNotInCenter::MsgFootprintOriginNotInCenter(
std::shared_ptr<const Footprint> footprint, const Point& center) noexcept
: RuleCheckMessage(
Severity::Hint,
tr("Origin of '%1' not in center")
.arg(*footprint->getNames().getDefaultValue()),
tr("Generally the origin (0, 0) should be at the coordinate used for "
"pick&place which is typically in the center of the package body. "
"It should even be (more or less) <b>exactly</b> in the center, not "
"aligned to a grid (off-grid pads are fine).\n\nIt looks like this "
"rule is not followed in this footprint. However, for irregular "
"package shapes or other special cases this warning may not be "
"justified. In such cases, just approve it."),
"origin_not_in_center"),
mFootprint(footprint),
mCenter(center) {
}
/*******************************************************************************
* MsgOverlappingPads
******************************************************************************/
MsgOverlappingPads::MsgOverlappingPads(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad1, const QString& pkgPad1Name,
std::shared_ptr<const FootprintPad> pad2,
const QString& pkgPad2Name) noexcept
: RuleCheckMessage(
Severity::Error,
tr("Overlapping pads '%1' and '%2' in '%3'")
.arg(pkgPad1Name, pkgPad2Name,
*footprint->getNames().getDefaultValue()),
tr("The copper area of two pads overlap. This can lead to serious "
"issues with the design rule check and probably leads to a short "
"circuit in the board so this really needs to be fixed."),
"overlapping_pads"),
mFootprint(footprint),
mPad1(pad1),
mPad2(pad2) {
}
/*******************************************************************************
* MsgPadAnnularRingViolation
******************************************************************************/
MsgPadAnnularRingViolation::MsgPadAnnularRingViolation(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad, const QString& pkgPadName,
const Length& annularRing) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Annular ring of pad '%1' in '%2'")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("Pads should have at least %1 annular ring (copper around each pad "
"hole). Note that this value is just a general recommendation, the "
"exact value depends on the capabilities of the PCB manufacturer.")
.arg(QString::number(annularRing.toMm() * 1000) % "μm"),
"small_pad_annular_ring"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgPadClearanceViolation
******************************************************************************/
MsgPadClearanceViolation::MsgPadClearanceViolation(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad1, const QString& pkgPad1Name,
std::shared_ptr<const FootprintPad> pad2, const QString& pkgPad2Name,
const Length& clearance) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Clearance of pad '%1' to pad '%2' in '%3'")
.arg(pkgPad1Name, pkgPad2Name,
*footprint->getNames().getDefaultValue()),
tr("Pads must have at least %1 clearance between each other, as "
"configured in the package. Either increase the clearance between "
"those pads, or reduce the configured minimum clearance value if "
"you are sure the PCB manufacturer can reliably handle it.")
.arg(QString::number(clearance.toMm() * 1000) % "μm"),
"small_pad_clearance"),
mFootprint(footprint),
mPad1(pad1),
mPad2(pad2) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", std::min(pad1->getUuid(), pad2->getUuid()));
mApproval->ensureLineBreak();
mApproval->appendChild("pad", std::max(pad1->getUuid(), pad2->getUuid()));
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgPadHoleOutsideCopper
******************************************************************************/
MsgPadHoleOutsideCopper::MsgPadHoleOutsideCopper(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad, const QString& pkgPadName) noexcept
: RuleCheckMessage(
Severity::Error,
tr("Hole outside copper of pad '%1' in '%2'")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("All THT pad holes must be fully surrounded by copper, otherwise "
"they could lead to serious issues during the design rule check or "
"manufacturing process."),
"pad_hole_outside_copper"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgPadOriginOutsideCopper
******************************************************************************/
MsgPadOriginOutsideCopper::MsgPadOriginOutsideCopper(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad, const QString& pkgPadName) noexcept
: RuleCheckMessage(
Severity::Error,
tr("Invalid origin of pad '%1' in '%2'")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("The origin of each pad must be located within its copper area, "
"otherwise traces won't be connected properly.\n\n"
"For THT pads, the origin must be located within a drill "
"hole since on some layers the pad might only have a small annular "
"ring instead of the full pad shape."),
"pad_origin_outside_copper"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgPadOverlapsWithLegend
******************************************************************************/
MsgPadOverlapsWithLegend::MsgPadOverlapsWithLegend(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad, const QString& pkgPadName,
const Length& clearance) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Clearance of pad '%1' in '%2' to legend")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("Pads should have at least %1 clearance to drawings on the "
"legend because these drawings would be cropped during the "
"Gerber export when used as silkscreen.")
.arg(QString::number(clearance.toMm() * 1000) % "μm"),
"pad_overlaps_legend"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgPadStopMaskOff
******************************************************************************/
MsgPadStopMaskOff::MsgPadStopMaskOff(std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad,
const QString& pkgPadName) noexcept
: RuleCheckMessage(
Severity::Error,
tr("Solder resist on pad '%1' in '%2'")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("There's no stop mask opening enabled on the pad, so the copper "
"pad will be covered by solder resist and is thus not functional. "
"This is very unusual, you should double-check if this is really "
"what you want."),
"pad_stop_mask_off"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* Class MsgPadWithCopperClearance
******************************************************************************/
MsgPadWithCopperClearance::MsgPadWithCopperClearance(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad, const QString& pkgPadName) noexcept
: RuleCheckMessage(
Severity::Hint,
tr("Copper clearance >0 on pad '%1' in '%2'")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("There is a custom copper clearance enabled on the pad, which is "
"unusual for pads which do not represent a fiducial. Note that the "
"clearance value from the board design rules is applied to all pads "
"anyway, thus manual clearance values are usually not needed. If "
"this pad is a fiducial, make sure to set its function to the "
"corresponding value."),
"pad_with_copper_clearance"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgSmtPadWithSolderPaste
******************************************************************************/
MsgSmtPadWithSolderPaste::MsgSmtPadWithSolderPaste(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad, const QString& pkgPadName) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Solder paste on SMT pad '%1' in '%2'")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("The SMT pad has solder paste enabled, but its function indicates "
"that there's no lead to be soldered on it (e.g. a fiducial). "
"Usually solder paste is not desired on such special pads which "
"won't be soldered."),
"smt_pad_with_solder_paste"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgSmtPadWithoutSolderPaste
******************************************************************************/
MsgSmtPadWithoutSolderPaste::MsgSmtPadWithoutSolderPaste(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad, const QString& pkgPadName) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("No solder paste on SMT pad '%1' in '%2'")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("The SMT pad has no solder paste enabled, which is unusual since "
"without solder paste the pad cannot be reflow soldered. Only use "
"this if there's no lead to be soldered on that pad, or if you have "
"drawn a manual solder paste area."),
"smt_pad_without_solder_paste"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* Class MsgSuspiciousPadFunction
******************************************************************************/
MsgSuspiciousPadFunction::MsgSuspiciousPadFunction(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad, const QString& pkgPadName) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Suspicious function of pad '%1' in '%2'")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("The configured pad function does not match other properties of the "
"pad and thus looks suspicious. Possible reasons:\n\n"
" - Function is intended for THT pads but pad is SMT\n"
" - Function is intended for SMT pads but pad is THT\n"
" - Function is electrical but pad is not connected\n"
" - Function is fiducial but pad is connected"),
"suspicious_pad_function"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgThtPadWithSolderPaste
******************************************************************************/
MsgThtPadWithSolderPaste::MsgThtPadWithSolderPaste(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad, const QString& pkgPadName) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Solder paste on THT pad '%1' in '%2'")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("The THT pad has solder paste enabled, which is very unusual since "
"through-hole components are usually not reflow soldered. Also the "
"solder paste could flow into the pads hole, possibly causing "
"troubles during THT assembly. Double-check if this is really what "
"you want."),
"tht_pad_with_solder_paste"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* Class MsgUnspecifiedPadFunction
******************************************************************************/
MsgUnspecifiedPadFunction::MsgUnspecifiedPadFunction(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad, const QString& pkgPadName) noexcept
: RuleCheckMessage(
Severity::Hint,
tr("Unspecified function of pad '%1' in '%2'")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("The function of the pad is not specified, which could lead to "
"inaccurate or wrong data in exports (e.g. pick&place files). Also "
"the automatic checks can detect more potential issues if the "
"function is specified. Thus it's recommended to explicitly specify "
"the function of each pad.") %
"\n\n" %
tr("However, the image data of a PCB is not affected by the pad "
"function."),
"pad_function_unspecified"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgUnusedCustomPadOutline
******************************************************************************/
MsgUnusedCustomPadOutline::MsgUnusedCustomPadOutline(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const FootprintPad> pad, const QString& pkgPadName) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Unused custom outline of pad '%1' in '%2'")
.arg(pkgPadName, *footprint->getNames().getDefaultValue()),
tr("The pad has set a custom outline but it isn't used as the shape. "
"So it has no effect and should be removed to avoid confusion."),
"unused_custom_pad_outline"),
mFootprint(footprint),
mPad(pad) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("pad", pad->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgUselessZone
******************************************************************************/
MsgUselessZone::MsgUselessZone(std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const Zone> zone) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Useless keepout zone in '%2'")
.arg(*footprint->getNames().getDefaultValue()),
tr("The keepout zone has no layer or rule enabled so it has no effect. "
"Either correct its properties or remove it from the footprint."),
"useless_zone"),
mFootprint(footprint),
mZone(zone) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("zone", zone->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* MsgWrongFootprintTextLayer
******************************************************************************/
MsgWrongFootprintTextLayer::MsgWrongFootprintTextLayer(
std::shared_ptr<const Footprint> footprint,
std::shared_ptr<const StrokeText> text, const Layer& expectedLayer) noexcept
: RuleCheckMessage(
Severity::Warning,
tr("Layer of '%1' in '%2' is not '%3'")
.arg(text->getText(), *footprint->getNames().getDefaultValue(),
expectedLayer.getNameTr()),
tr("The text element '%1' should normally be on layer '%2'.")
.arg(text->getText(), expectedLayer.getNameTr()),
"unusual_text_layer"),
mFootprint(footprint),
mText(text),
mExpectedLayer(&expectedLayer) {
mApproval->ensureLineBreak();
mApproval->appendChild("footprint", footprint->getUuid());
mApproval->ensureLineBreak();
mApproval->appendChild("text", text->getUuid());
mApproval->ensureLineBreak();
}
/*******************************************************************************
* End of File
******************************************************************************/
} // namespace librepcb
ee84c48d4This file is pinned to the selected release. Download the original to open it in your design tool.