Loading files
c730ec352This 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/>.
*/
#ifndef LIBREPCB_EDITOR_BOARDCLIPBOARDDATA_H
#define LIBREPCB_EDITOR_BOARDCLIPBOARDDATA_H
/*******************************************************************************
* Includes
******************************************************************************/
#include <librepcb/core/attribute/attribute.h>
#include <librepcb/core/geometry/junction.h>
#include <librepcb/core/geometry/trace.h>
#include <librepcb/core/geometry/via.h>
#include <librepcb/core/project/board/boardholedata.h>
#include <librepcb/core/project/board/boardpaddata.h>
#include <librepcb/core/project/board/boardpolygondata.h>
#include <librepcb/core/project/board/boardstroketextdata.h>
#include <librepcb/core/project/board/boardzonedata.h>
#include <librepcb/core/project/board/items/bi_plane.h>
#include <librepcb/core/project/circuit/circuit.h>
#include <librepcb/core/serialization/serializableobjectlist.h>
#include <librepcb/core/types/point.h>
#include <librepcb/core/types/uuid.h>
#include <librepcb/core/utils/signalslot.h>
#include <QtCore>
#include <QtWidgets>
#include <memory>
/*******************************************************************************
* Namespace / Forward Declarations
******************************************************************************/
namespace librepcb {
class Layer;
class TransactionalDirectory;
class TransactionalFileSystem;
namespace editor {
/*******************************************************************************
* Class BoardClipboardData
******************************************************************************/
/**
* @brief The BoardClipboardData class
*/
class BoardClipboardData final {
public:
// Types
struct Device {
static constexpr const char* tagname = "device";
Uuid componentUuid;
Uuid libDeviceUuid;
Uuid libFootprintUuid;
Point position;
Angle rotation;
bool mirrored;
bool locked;
bool glue;
AttributeList attributes;
QList<BoardStrokeTextData> strokeTexts;
Signal<Device> onEdited; ///< Dummy event, not used
Device(const Uuid& componentUuid, const Uuid& libDeviceUuid,
const Uuid& libFootprintUuid, const Point& position,
const Angle& rotation, bool mirrored, bool locked, bool glue,
const AttributeList& attributes,
const QList<BoardStrokeTextData>& strokeTexts)
: componentUuid(componentUuid),
libDeviceUuid(libDeviceUuid),
libFootprintUuid(libFootprintUuid),
position(position),
rotation(rotation),
mirrored(mirrored),
locked(locked),
glue(glue),
attributes(attributes),
strokeTexts(strokeTexts),
onEdited(*this) {}
explicit Device(const SExpression& node)
: componentUuid(deserialize<Uuid>(node.getChild("@0"))),
libDeviceUuid(deserialize<Uuid>(node.getChild("lib_device/@0"))),
libFootprintUuid(deserialize<Uuid>(node.getChild("lib_footprint/@0"))),
position(node.getChild("position")),
rotation(deserialize<Angle>(node.getChild("rotation/@0"))),
mirrored(deserialize<bool>(node.getChild("flip/@0"))),
locked(deserialize<bool>(node.getChild("lock/@0"))),
glue(deserialize<bool>(node.getChild("glue/@0"))),
attributes(node),
strokeTexts(),
onEdited(*this) {
foreach (const SExpression* child, node.getChildren("stroke_text")) {
strokeTexts.append(BoardStrokeTextData(*child));
}
}
void serialize(SExpression& root) const {
root.appendChild(componentUuid);
root.ensureLineBreak();
root.appendChild("lib_device", libDeviceUuid);
root.ensureLineBreak();
root.appendChild("lib_footprint", libFootprintUuid);
root.ensureLineBreak();
position.serialize(root.appendList("position"));
root.appendChild("rotation", rotation);
root.appendChild("flip", mirrored);
root.appendChild("lock", locked);
root.appendChild("glue", glue);
root.ensureLineBreak();
attributes.serialize(root);
foreach (const BoardStrokeTextData& strokeText, strokeTexts) {
root.ensureLineBreak();
strokeText.serialize(root.appendList("stroke_text"));
}
root.ensureLineBreak();
}
bool operator!=(const Device& rhs) noexcept {
return (componentUuid != rhs.componentUuid) ||
(libDeviceUuid != rhs.libDeviceUuid) ||
(libFootprintUuid != rhs.libFootprintUuid) ||
(position != rhs.position) || (rotation != rhs.rotation) ||
(mirrored != rhs.mirrored) || (locked != rhs.locked) ||
(glue != rhs.glue) || (attributes != rhs.attributes) ||
(strokeTexts != rhs.strokeTexts);
}
};
struct NetSegment {
static constexpr const char* tagname = "netsegment";
std::optional<CircuitIdentifier> netName;
BoardPadDataList pads;
ViaList vias;
JunctionList junctions;
TraceList traces;
Signal<NetSegment> onEdited; ///< Dummy event, not used
explicit NetSegment(const std::optional<CircuitIdentifier>& netName)
: netName(netName),
pads(),
vias(),
junctions(),
traces(),
onEdited(*this) {}
explicit NetSegment(const SExpression& node)
: netName(deserialize<std::optional<CircuitIdentifier>>(
node.getChild("net/@0"))),
pads(node),
vias(node),
junctions(node),
traces(node),
onEdited(*this) {}
void serialize(SExpression& root) const {
root.ensureLineBreak();
root.appendChild("net", netName);
root.ensureLineBreak();
pads.serialize(root);
root.ensureLineBreak();
vias.serialize(root);
root.ensureLineBreak();
junctions.serialize(root);
root.ensureLineBreak();
traces.serialize(root);
root.ensureLineBreak();
}
bool operator!=(const NetSegment& rhs) noexcept {
return (netName != rhs.netName) || (pads != rhs.pads) ||
(vias != rhs.vias) || (junctions != rhs.junctions) ||
(traces != rhs.traces);
}
};
struct Plane {
static constexpr const char* tagname = "plane";
Uuid uuid;
const Layer* layer;
std::optional<CircuitIdentifier> netSignalName;
Path outline;
UnsignedLength minWidth;
UnsignedLength minClearanceToCopper;
UnsignedLength minClearanceToBoard;
UnsignedLength minClearanceToNpth;
bool keepIslands;
int priority;
BI_Plane::ConnectStyle connectStyle;
PositiveLength thermalGap;
PositiveLength thermalSpokeWidth;
bool locked;
Signal<Plane> onEdited; ///< Dummy event, not used
Plane(const Uuid& uuid, const Layer& layer,
const std::optional<CircuitIdentifier>& netSignalName,
const Path& outline, const UnsignedLength& minWidth,
const UnsignedLength& minClearanceToCopper,
const UnsignedLength& minClearanceToBoard,
const UnsignedLength& minClearanceToNpth, bool keepIslands,
int priority, BI_Plane::ConnectStyle connectStyle,
const PositiveLength& thermalGap,
const PositiveLength& thermalSpokeWidth, bool locked)
: uuid(uuid),
layer(&layer),
netSignalName(netSignalName),
outline(outline),
minWidth(minWidth),
minClearanceToCopper(minClearanceToCopper),
minClearanceToBoard(minClearanceToBoard),
minClearanceToNpth(minClearanceToNpth),
keepIslands(keepIslands),
priority(priority),
connectStyle(connectStyle),
thermalGap(thermalGap),
thermalSpokeWidth(thermalSpokeWidth),
locked(locked),
onEdited(*this) {}
explicit Plane(const SExpression& node)
: uuid(deserialize<Uuid>(node.getChild("@0"))),
layer(deserialize<const Layer*>(node.getChild("layer/@0"))),
netSignalName(deserialize<std::optional<CircuitIdentifier>>(
node.getChild("net/@0"))),
outline(node),
minWidth(deserialize<UnsignedLength>(node.getChild("min_width/@0"))),
minClearanceToCopper(deserialize<UnsignedLength>(
node.getChild("min_copper_clearance/@0"))),
minClearanceToBoard(deserialize<UnsignedLength>(
node.getChild("min_board_clearance/@0"))),
minClearanceToNpth(deserialize<UnsignedLength>(
node.getChild("min_npth_clearance/@0"))),
keepIslands(deserialize<bool>(node.getChild("keep_islands/@0"))),
priority(deserialize<int>(node.getChild("priority/@0"))),
connectStyle(deserialize<BI_Plane::ConnectStyle>(
node.getChild("connect_style/@0"))),
thermalGap(
deserialize<PositiveLength>(node.getChild("thermal_gap/@0"))),
thermalSpokeWidth(
deserialize<PositiveLength>(node.getChild("thermal_spoke/@0"))),
locked(deserialize<bool>(node.getChild("lock/@0"))),
onEdited(*this) {}
void serialize(SExpression& root) const {
root.appendChild(uuid);
root.appendChild("layer", *layer);
root.ensureLineBreak();
root.appendChild("net", netSignalName);
root.appendChild("priority", priority);
root.appendChild("min_width", minWidth);
root.ensureLineBreak();
root.appendChild("min_copper_clearance", minClearanceToCopper);
root.appendChild("min_board_clearance", minClearanceToBoard);
root.appendChild("min_npth_clearance", minClearanceToNpth);
root.ensureLineBreak();
root.appendChild("connect_style", connectStyle);
root.appendChild("thermal_gap", thermalGap);
root.appendChild("thermal_spoke", thermalSpokeWidth);
root.ensureLineBreak();
root.appendChild("keep_islands", keepIslands);
root.appendChild("lock", locked);
root.ensureLineBreak();
outline.serialize(root);
root.ensureLineBreak();
}
bool operator!=(const Plane& rhs) noexcept {
return (uuid != rhs.uuid) || (layer != rhs.layer) ||
(netSignalName != rhs.netSignalName) || (outline != rhs.outline) ||
(minWidth != rhs.minWidth) ||
(minClearanceToCopper != rhs.minClearanceToCopper) ||
(minClearanceToBoard != rhs.minClearanceToBoard) ||
(minClearanceToNpth != rhs.minClearanceToNpth) ||
(keepIslands != rhs.keepIslands) || (priority != rhs.priority) ||
(connectStyle != rhs.connectStyle) ||
(thermalGap != rhs.thermalGap) ||
(thermalSpokeWidth != rhs.thermalSpokeWidth) ||
(locked != rhs.locked);
}
};
// Constructors / Destructor
BoardClipboardData() = delete;
BoardClipboardData(const BoardClipboardData& other) = delete;
BoardClipboardData(const Uuid& boardUuid, const Point& cursorPos) noexcept;
explicit BoardClipboardData(const QByteArray& mimeData);
~BoardClipboardData() noexcept;
// Getters
bool isEmpty() const noexcept;
std::unique_ptr<TransactionalDirectory> getDirectory(
const QString& path = "") noexcept;
const Uuid& getBoardUuid() const noexcept { return mBoardUuid; }
const Point& getCursorPos() const noexcept { return mCursorPos; }
SerializableObjectList<Device, Device>& getDevices() noexcept {
return mDevices;
}
SerializableObjectList<NetSegment, NetSegment>& getNetSegments() noexcept {
return mNetSegments;
}
SerializableObjectList<Plane, Plane>& getPlanes() noexcept { return mPlanes; }
QList<BoardZoneData>& getZones() noexcept { return mZones; }
QList<BoardPolygonData>& getPolygons() noexcept { return mPolygons; }
QList<BoardStrokeTextData>& getStrokeTexts() noexcept { return mStrokeTexts; }
QList<BoardHoleData>& getHoles() noexcept { return mHoles; }
QMap<std::pair<Uuid, Uuid>, Point>& getPadPositions() noexcept {
return mPadPositions;
}
// General Methods
std::unique_ptr<QMimeData> toMimeData() const;
static std::unique_ptr<BoardClipboardData> fromMimeData(
const QMimeData* mime);
static bool isValid(const QMimeData* mime) noexcept;
// Operator Overloadings
BoardClipboardData& operator=(const BoardClipboardData& rhs) = delete;
private: // Methods
static QString getMimeType() noexcept;
private: // Data
std::shared_ptr<TransactionalFileSystem> mFileSystem;
Uuid mBoardUuid;
Point mCursorPos;
SerializableObjectList<Device, Device> mDevices;
SerializableObjectList<NetSegment, NetSegment> mNetSegments;
SerializableObjectList<Plane, Plane> mPlanes;
QList<BoardZoneData> mZones;
QList<BoardPolygonData> mPolygons;
QList<BoardStrokeTextData> mStrokeTexts;
QList<BoardHoleData> mHoles;
QMap<std::pair<Uuid, Uuid>, Point> mPadPositions;
};
/*******************************************************************************
* End of File
******************************************************************************/
} // namespace editor
} // namespace librepcb
#endif