Files
leocad/common/lc_bricklink.cpp
T
Leonardo Zide 664cec006f Protect library directory and shared buffer access
Move the library directory and shared vertex/index buffer handles into the
protected source and rendering groups. Expose one GetBuffers accessor returning
const references to both buffers, and use structured binding in BindMesh while
preserving GL binding and uncached-mesh fallback behavior.

Add GetLibraryFilePath for mapping-file lookups and update the LXF and BrickLink
callers. Keep file opening and bundled-resource fallback in those callers so the
library only resolves the path and exposes no mutable directory state.

Validation: warning-free macOS Qt 6.10 Debug build, all 45 offscreen lifecycle
checks and diff whitespace checks pass. No remaining external field accesses
for the protected directory or buffers. GPU rendering was not tested.
2026-10-19 18:44:13 -07:00

131 lines
3.3 KiB
C++

#include "lc_global.h"
#include "lc_bricklink.h"
#include "lc_file.h"
#include "lc_library.h"
#include "lc_application.h"
#include "lc_string.h"
#include "lc_piecedata.h"
#include "lc_colors.h"
static QJsonDocument lcLoadBrickLinkMapping()
{
std::map<std::string, std::string> Remapping;
QFile File(lcGetPiecesLibrary()->GetLibraryFilePath(QLatin1String("ldraw2bl.txt")));
QByteArray Data;
if (File.open(QIODevice::ReadOnly))
Data = File.readAll();
else
{
QFile DefaultFile(":/resources/ldraw2bl.txt");
if (DefaultFile.open(QIODevice::ReadOnly))
Data = DefaultFile.readAll();
}
return QJsonDocument::fromJson(Data);
}
static std::string lcGetBrickLinkPart(const QJsonObject& PartMapping, const QString& LDrawPart)
{
QJsonObject::const_iterator PartIt = PartMapping.find(LDrawPart);
return (PartIt != PartMapping.end()) ? PartIt.value().toString().toStdString() : LDrawPart.toStdString();
}
static int lcGetBrickLinkColor(const QJsonObject& ColorMapping, int ColorIndex)
{
int ColorCode = gColorList[ColorIndex].Code;
QJsonObject::const_iterator ColorIt = ColorMapping.find(QString::number(ColorCode));
return (ColorIt != ColorMapping.end()) ? ColorIt.value().toString().toInt() : 0;
}
class lcBrickLinkItem
{
public:
lcBrickLinkItem(const std::string& id, int color, int count)
: mId(id), mColor(color), mCount(count)
{
}
void AddToCount(int count)
{
mCount += count;
}
std::string mId;
int mColor;
int mCount;
};
lcResult<void> lcExportBrickLink(const QString& SaveFileName, const lcPartsList& PartsList)
{
QJsonDocument Document = lcLoadBrickLinkMapping();
QJsonObject Root = Document.object();
QJsonObject PartMapping = Root["Parts"].toObject();
QJsonObject ColorMapping = Root["Colors"].toObject();
lcDiskFile BrickLinkFile(SaveFileName);
char Line[1024];
if (!BrickLinkFile.Open(QIODevice::WriteOnly))
return lcUnexpected(QObject::tr("Could not open file '%1' for writing.").arg(SaveFileName));
std::map<std::string, lcBrickLinkItem> Inventory;
BrickLinkFile.WriteLine("<INVENTORY>\n");
for (const auto& PartIt : PartsList)
{
const lcPieceData* PieceData = PartIt.first;
for (const auto& ColorIt : PartIt.second)
{
char FileName[LC_PIECE_NAME_LEN];
lcstrcpy(FileName, PieceData->mFileName);
char* Ext = strchr(FileName, '.');
if (Ext)
*Ext = 0;
std::string Remapped = lcGetBrickLinkPart(PartMapping, FileName);
int Color = lcGetBrickLinkColor(ColorMapping, ColorIt.first);
std::string key(Remapped);
key += "-" + std::to_string(Color);
auto iter = Inventory.find(key);
if (iter == Inventory.end())
{
Inventory.emplace(std::make_pair(key, lcBrickLinkItem(Remapped, Color, ColorIt.second)));
}
else
{
iter->second.AddToCount(ColorIt.second);
}
}
}
for (const auto& Item : Inventory)
{
BrickLinkFile.WriteLine(" <ITEM>\n");
BrickLinkFile.WriteLine(" <ITEMTYPE>P</ITEMTYPE>\n");
snprintf(Line, sizeof(Line), " <ITEMID>%s</ITEMID>\n", Item.second.mId.c_str());
BrickLinkFile.WriteLine(Line);
snprintf(Line, sizeof(Line), " <MINQTY>%d</MINQTY>\n", Item.second.mCount);
BrickLinkFile.WriteLine(Line);
if (Item.second.mColor)
{
snprintf(Line, sizeof(Line), " <COLOR>%d</COLOR>\n", Item.second.mColor);
BrickLinkFile.WriteLine(Line);
}
BrickLinkFile.WriteLine(" </ITEM>\n");
}
BrickLinkFile.WriteLine("</INVENTORY>\n");
return lcResult<void>();
}