diff --git a/builds/linux/obs/alldeps/PKGBUILD b/builds/linux/obs/alldeps/PKGBUILD index 3b792e8ea..7b3538a65 100644 --- a/builds/linux/obs/alldeps/PKGBUILD +++ b/builds/linux/obs/alldeps/PKGBUILD @@ -2,7 +2,7 @@ # Last Update: March 23, 2019 # Copyright (c) 2017 - 2019 by Trevor SANDY pkgname=lpub3d -pkgver=2.3.10.1231 +pkgver=2.3.10.1232 pkgrel=1 pkgdesc="An LDraw Building Instruction Editor" url="https://github.com/trevorsandy/lpub3d.git" diff --git a/builds/linux/obs/alldeps/debian/changelog b/builds/linux/obs/alldeps/debian/changelog index 42dc1a15c..1d7c19497 100644 --- a/builds/linux/obs/alldeps/debian/changelog +++ b/builds/linux/obs/alldeps/debian/changelog @@ -1,5 +1,5 @@ -lpub3d (2.3.10.1231) debian; urgency=medium +lpub3d (2.3.10.1232) debian; urgency=medium - * LPub3D version 2.3.10.1.1231_20190423 for Linux + * LPub3D version 2.3.10.1.1232_20190423 for Linux - -- Trevor SANDY Tue, 23 Apr 2019 12:07:42 +0200 + -- Trevor SANDY Tue, 23 Apr 2019 12:09:09 +0200 diff --git a/builds/linux/obs/alldeps/debian/lpub3d.dsc b/builds/linux/obs/alldeps/debian/lpub3d.dsc index cc4c1582b..728cec976 100644 --- a/builds/linux/obs/alldeps/debian/lpub3d.dsc +++ b/builds/linux/obs/alldeps/debian/lpub3d.dsc @@ -2,7 +2,7 @@ Format: 1.0 Source: lpub3d Binary: lpub3d Architecture: any -Version: 2.3.10.1231 +Version: 2.3.10.1232 Maintainer: Trevor SANDY Homepage: https://trevorsandy.github.io/lpub3d/ Standards-Version: 3.9.7 diff --git a/builds/linux/obs/alldeps/lpub3d.spec b/builds/linux/obs/alldeps/lpub3d.spec index 319c7f71d..651bc4707 100644 --- a/builds/linux/obs/alldeps/lpub3d.spec +++ b/builds/linux/obs/alldeps/lpub3d.spec @@ -118,7 +118,7 @@ BuildRequires: fdupes Summary: An LDraw Building Instruction Editor Name: lpub3d Icon: lpub3d.xpm -Version: 2.3.10.1231 +Version: 2.3.10.1232 Release: %{?dist} URL: https://trevorsandy.github.io/lpub3d Vendor: Trevor SANDY @@ -717,5 +717,5 @@ update-mime-database /usr/share/mime >/dev/null || true update-desktop-database || true %endif -* Tue Apr 23 2019 - trevor.dot.sandy.at.gmail.dot.com 2.3.10.1231 +* Tue Apr 23 2019 - trevor.dot.sandy.at.gmail.dot.com 2.3.10.1232 - LPub3D Linux package (rpm) release diff --git a/builds/utilities/ci/secure/.secrets.tar.enc b/builds/utilities/ci/secure/.secrets.tar.enc index 9cb0ec616..552e2776a 100644 Binary files a/builds/utilities/ci/secure/.secrets.tar.enc and b/builds/utilities/ci/secure/.secrets.tar.enc differ diff --git a/builds/utilities/version.info b/builds/utilities/version.info index 8d926cd36..0e8127ad9 100755 --- a/builds/utilities/version.info +++ b/builds/utilities/version.info @@ -1 +1 @@ -2 3 10 1 1231 956fd56 +2 3 10 1 1232 614e913 diff --git a/ldvlib/LDVQt/LDVHtmlInventory.cpp b/ldvlib/LDVQt/LDVHtmlInventory.cpp index 42d381992..dd0c8ed8b 100644 --- a/ldvlib/LDVQt/LDVHtmlInventory.cpp +++ b/ldvlib/LDVQt/LDVHtmlInventory.cpp @@ -16,7 +16,8 @@ #include #include -#include +#include "LDVWidget.h" +#include "LDVWidgetDefaultKeys.h" #include "messageboxresizable.h" #include "annotations.h" #include "paths.h" @@ -31,6 +32,7 @@ #define SNAPSHOT_WIDTH_DEFAULT 400 #define SNAPSHOT_HEIGHT_DEFAULT 300 +#define REBRICKABLE_KEY_DEFAULT "" const char *LDVHtmlInventory::sm_style = "\ body\n\ @@ -77,6 +79,7 @@ th\n\ border-bottom: 1px solid #000000;\n\ border-right: 1px solid #00558A;\n\ padding: 4px 8px;\n\ + white-space: nowrap;\n\ }\n\ \n\ th.title\n\ @@ -496,7 +499,7 @@ function sort(columnClassName, tableId) {\n\ };\n\ "; -LDVHtmlInventory::LDVHtmlInventory(void) : +LDVHtmlInventory::LDVHtmlInventory() : m_prefs(new LDPreferences), m_viewPoint(nullptr) { @@ -519,9 +522,9 @@ LDVHtmlInventory::LDVHtmlInventory(void) : m_columnOrder.push_back((LDVPartListColumn)columnOrder[i]); } - Meta meta; + Meta meta; // use BOM element setting bool bl = meta.LPub.bom.partElements.bricklinkElements.value(); - m_lookupDefault = bl ? LookUp::Bricklink : LookUp::Peeron; + m_lookupDefault = bl ? LookUp::Bricklink : LookUp::Rebrickable; m_elementDefault = bl ? ElementSrc::BL : ElementSrc::LEGO; } @@ -609,6 +612,8 @@ bool LDVHtmlInventory::generateHtml( int invalidElements = 0; int uniqueElements = 0; + QStringList partList; + IntVector uniqueColors; for (i = 0; i < uniqueParts; i++) { @@ -616,11 +621,12 @@ bool LDVHtmlInventory::generateHtml( const IntVector &colors = partCount.getColors(); int elements = (int)colors.size(); uniqueElements += elements; + QString ldPartId(QFileInfo(QString::fromStdString(partCount.getFilename())).baseName()); + partList.append(ldPartId); for (j = 0; j < elements; j++) { bool bl = m_lookupSite == LookUp::Bricklink; QString ldColorId(QString::number(colors[j])); - QString ldPartId(QFileInfo(QString::fromStdString(partCount.getFilename())).baseName()); QString elementId = Annotations::getBLElement( ldColorId, ldPartId, bl ? ElementSrc::BL:ElementSrc::LEGO); @@ -631,6 +637,13 @@ bool LDVHtmlInventory::generateHtml( } } + if (getLookupSite() == LookUp::Rebrickable && + partList.size() && + m_modelWidget) { + m_modelWidget->doSetRebrickableColors(); + m_modelWidget->doSetRebrickableParts(partList.join(",")); + } + ProgressDialog->setMaximum(uniqueParts); writeHeader(file); @@ -700,6 +713,11 @@ void LDVHtmlInventory::setSnapshotHeightFlag(int value) setOtherSetting(m_snapshotHeight, value, SAVE_HEIGHT_KEY, true); } +void LDVHtmlInventory::setRebrickableKeyFlag(std::string value) +{ + setOtherSetting(m_rebrickableKey, value, PARTS_LIST_REBRICKABLE_KEY_KEY, true); +} + bool LDVHtmlInventory::getGeneratePdfFlag() { m_generatePdf = getBoolSetting(PARTS_LIST_GENERATE_PDF_KEY); @@ -730,6 +748,12 @@ int LDVHtmlInventory::getSnapshotHeightFlag() return m_snapshotHeight; } +std::string LDVHtmlInventory::getRebrickableKeyFlag() +{ + m_rebrickableKey = getStringSetting(PARTS_LIST_REBRICKABLE_KEY_KEY,REBRICKABLE_KEY_DEFAULT); + return m_rebrickableKey; +} + void LDVHtmlInventory::loadOtherSettings(void) { getGeneratePdfFlag(); @@ -737,6 +761,7 @@ void LDVHtmlInventory::loadOtherSettings(void) getElementSourceFlag(); getSnapshotWidthFlag(); getSnapshotHeightFlag(); + getRebrickableKeyFlag(); LongVector columnOrder; columnOrder.push_back(1); // Part columnOrder.push_back(3); // Color @@ -745,8 +770,11 @@ void LDVHtmlInventory::loadOtherSettings(void) m_prefs->setInvColumnOrder(columnOrder); } -void LDVHtmlInventory::setOtherSetting(bool &setting, bool value, const char *key, - bool commit) +void LDVHtmlInventory::setOtherSetting( + bool &setting, + bool value, + const char *key, + bool commit) { if (setting != value) { @@ -759,8 +787,11 @@ void LDVHtmlInventory::setOtherSetting(bool &setting, bool value, const char *ke } } -void LDVHtmlInventory::setOtherSetting(int &setting, int value, const char *key, - bool commit) +void LDVHtmlInventory::setOtherSetting( + int &setting, + int value, + const char *key, + bool commit) { if (setting != value) { @@ -772,6 +803,32 @@ void LDVHtmlInventory::setOtherSetting(int &setting, int value, const char *key, } } +void LDVHtmlInventory::setOtherSetting( + std::string &setting, + const std::string &value, + const char *key, + bool commit, + bool isPath /*= false*/) +{ + if (setting != value) + { + setting = value; + if (commit) + { + if (isPath) + { + TCUserDefaults::setPathForKey(value.c_str(), key, + true /*!m_globalSettings[key]*/); + } + else + { + TCUserDefaults::setStringForKey(value.c_str(), key, + true /*!m_globalSettings[key]*/); + } + } + } +} + bool LDVHtmlInventory::getBoolSetting(const char *key, bool defaultValue) { return TCUserDefaults::longForKey(key, (long)defaultValue, @@ -784,6 +841,32 @@ int LDVHtmlInventory::getIntSetting(const char *key, int defaultValue) true /*!m_globalSettings[key]*/); } +std::string LDVHtmlInventory::getStringSetting( + const char *key, + const char *defaultValue /*= NULL*/, + bool isPath /*= false*/) +{ + char *tmpString; + std::string result; + + if (isPath) + { + tmpString = TCUserDefaults::pathForKey(key, defaultValue, + true /*!m_globalSettings[key]*/); + } + else + { + tmpString = TCUserDefaults::stringForKey(key, defaultValue, + true /*!m_globalSettings[key]*/); + } + if (tmpString) + { + result = tmpString; + delete[] tmpString; + } + return result; +} + // *** Settings Flags End *** FILE *LDVHtmlInventory::safeOpenCssFile(const std::string &cssFilename, @@ -995,7 +1078,6 @@ void LDVHtmlInventory::writePartCell( std::string partName = partCount.getFilename(); size_t nDotSpot = partName.find('.'); int r, g, b, a; - bool bl = m_lookupSite == LookUp::Bricklink; bool element = true; palette->getRGBA(colorInfo, r, g, b, a); @@ -1011,25 +1093,74 @@ void LDVHtmlInventory::writePartCell( className = " class=\"image\""; } - if (bl) { - QString elementId = Annotations::getBLElement( - QString::number(colorNumber), - QString::fromStdString(partName), - ElementSrc::BL); + std::string viewOnString; + + QString elementId; + if (getLookupSite() != LookUp::Peeron) { + elementId = Annotations::getBLElement( + QString::number(colorNumber), + QString::fromStdString(partName), + ElementSrc::BL); element = !elementId.isEmpty(); + } + switch (m_lookupSite) + { + case LookUp::Bricklink: + { QStringList elementParts = elementId.split("-"); fprintf(file, " " - "", - className.c_str(), - element ? elementParts.at(0).toLatin1().constData() : "0000", - element ? elementParts.at(1).toLatin1().constData() : "00"); - } else { + "", + className.c_str(), + element ? elementParts.at(0).toLatin1().constData() : "0000", + element ? elementParts.at(1).toLatin1().constData() : "00"); + + viewOnString = lsUtf8(element ? "PLViewOnBricklink" : "PLVInvalidElement"); + } + break; + case LookUp::Rebrickable: + { + int rebricableColor = colorNumber /*m_modelWidget->doGetRebrickableColor(colorNumber)*/; + + std::string rebricablePartUrl = m_modelWidget->doGetRebrickablePartURL(partName); + + fprintf(file, " " + "", + className.c_str(), + rebricablePartUrl.c_str(), + rebricableColor); + + viewOnString = lsUtf8(element ? "PLViewOnRebrickable" : "PLVInvalidElement"); + } + break; + case LookUp::Peeron: fprintf(file, " " - "", - className.c_str(), partName.c_str()); + "", + className.c_str(), partName.c_str()); + + viewOnString = lsUtf8("PLViewOnPeeron"); + break; + case LookUp::PTracker: + { + if (partCount.getModel()->isOfficial()) { + fprintf(file, " " + "", + className.c_str(), partCount.getFilename()); + + viewOnString = lsUtf8("PLViewOnLDrawPartTracker"); + } else { + fprintf(file, " " + "", + className.c_str(), partCount.getFilename()); + + viewOnString = lsUtf8("PLViewOnLDrawUnOffPartTracker"); + } + } + break; + default: + break; } QString localPartPath = QDir::toNativeSeparators(QString("%1/%2_%3_%4.png") @@ -1039,8 +1170,7 @@ void LDVHtmlInventory::writePartCell( .arg(QString::fromStdString(m_partListKey))); fprintf(file, "\"%s\"", - lsUtf8(bl ? element ? "PLViewOnBricklink" : "PLVInvalidElement" : "PLViewOnPeeron"), - lsUtf8(bl ? element ? "PLViewOnBricklink" : "PLVInvalidElement" : "PLViewOnPeeron"), + viewOnString.c_str(), viewOnString.c_str(), localPartPath.toLatin1().constData()); fprintf(file, "\n"); diff --git a/ldvlib/LDVQt/LDVHtmlInventory.h b/ldvlib/LDVQt/LDVHtmlInventory.h index 94baf705e..8180df2aa 100644 --- a/ldvlib/LDVQt/LDVHtmlInventory.h +++ b/ldvlib/LDVQt/LDVHtmlInventory.h @@ -12,16 +12,17 @@ class LDLPalette; class LDPreferences; class LDrawModelViewer; class LDViewPoint; +class LDVWidget; typedef enum { - LDVPLCFirst = 1, - LDVPLCPart = LDVPLCFirst, - LDVPLCDescription, - LDVPLCColor, - LDVPLCElement, - LDVPLCQuantity, - LDVPLCLast = LDVPLCQuantity + LDVPLCFirst = 1, + LDVPLCPart = LDVPLCFirst, + LDVPLCDescription, + LDVPLCColor, + LDVPLCElement, + LDVPLCQuantity, + LDVPLCLast = LDVPLCQuantity } LDVPartListColumn; typedef std::vector LDVPartListColumnVector; @@ -29,9 +30,13 @@ typedef std::map LDVPartListColumnBoolMap; class LDVHtmlInventory : public TCObject { + public: LDVHtmlInventory(void); + enum LookUp { Bricklink, Peeron, Rebrickable, PTracker }; + enum ElementSrc { BL, LEGO }; + void setShowModelFlag(bool value); bool getShowModelFlag(void) { return m_showModel; } void setExternalCssFlag(bool value); @@ -44,15 +49,15 @@ class LDVHtmlInventory : public TCObject bool getShowFileFlag(void) { return m_showFile; } void setShowTotalFlag(bool value); bool getShowTotalFlag(void) { return m_showTotal; } - void setPartListKey(const char *value) { m_partListKey = value; } - void setUserDefinedSnapshot(const char *value) { m_userDefinedSnapshot = value; } - const char *getUserDefinedSnapshot(void) { return m_userDefinedSnapshot.c_str(); } + void setPartListKey(const char *value) { m_partListKey = value; } + void setUserDefinedSnapshot(const char *value) { m_userDefinedSnapshot = value; } + const char *getUserDefinedSnapshot(void) { return m_userDefinedSnapshot.c_str(); } const LDVPartListColumnVector &getColumnOrder(void) const { return m_columnOrder; } - void setColumnOrder(const LDVPartListColumnVector &value); + void setColumnOrder(const LDVPartListColumnVector &value); const char *getLastSavePath(void) { return m_lastSavePath.c_str(); } const char *getSnapshotPath(void) const; bool isColumnEnabled(LDVPartListColumn column); @@ -67,34 +72,36 @@ class LDVHtmlInventory : public TCObject static const char *getColumnName(LDVPartListColumn column); static CUCSTR getColumnNameUC(LDVPartListColumn column); - + void setGeneratePdfFlag(bool value); - void setLookupSiteFlag(int value); - void setElementSourceFlag(int value); - void setSnapshotWidthFlag(int value); - void setSnapshotHeightFlag(int value); - - bool getGeneratePdfFlag(void); - int getLookupSiteFlag(void); - int getElementSourceFlag(void); - int getSnapshotWidthFlag(void); - int getSnapshotHeightFlag(void); - + void setLookupSiteFlag(int value); + void setElementSourceFlag(int value); + void setSnapshotWidthFlag(int value); + void setSnapshotHeightFlag(int value); + void setRebrickableKeyFlag(std::string value); + + bool getGeneratePdfFlag(void); + int getLookupSiteFlag(void); + int getElementSourceFlag(void); + int getSnapshotWidthFlag(void); + int getSnapshotHeightFlag(void); + std::string getRebrickableKeyFlag(void); + void loadOtherSettings(void); - enum LookUp { Bricklink, Peeron }; - enum ElementSrc { BL, LEGO }; + void setModelWidget(LDVWidget *modelWidget) {m_modelWidget = modelWidget; } - bool getLookupSite(void) { return m_lookupSite; } + int getLookupSite(void) { return m_lookupSite; } + std::string getRebrickableKey(void) { return m_rebrickableKey; } protected: virtual ~LDVHtmlInventory(void); virtual void dealloc(void); void writeHeader(FILE *file); void writeFooter(FILE *file); - void writeTableHeader(FILE *file, int totalParts, - int invalidElements, int uniqueElements, - int uniqueParts, int uniqueColors); + void writeTableHeader(FILE *file, int totalParts, + int invalidElements, int uniqueElements, + int uniqueParts, int uniqueColors); void writeTableFooter(FILE *file); void writePartRow(FILE *file, const LDPartCount &partCount, LDLPalette *palette, const LDLColorInfo &colorInfo, int colorNumber); @@ -108,33 +115,38 @@ class LDVHtmlInventory : public TCObject void writeDescriptionCell(FILE *file, const LDPartCount &partCount); void writeColorCell(FILE *file, LDLPalette *palette, const LDLColorInfo &colorInfo, int colorNumber); - void writeElementCell(FILE *file, const LDPartCount &partCount, + void writeElementCell(FILE *file, const LDPartCount &partCount, + int colorNumber); + void writeQuantityCell(FILE *file, const LDPartCount &partCount, int colorNumber); - void writeQuantityCell(FILE *file, const LDPartCount &partCount, - int colorNumber); void writeCell(FILE *file, LDVPartListColumn column, const LDPartCount &partCount, LDLPalette *palette, const LDLColorInfo &colorInfo, int colorNumber); void populateColumnMap(void); std::string getSnapshotFilename(void) const; - void setOtherSetting(bool &setting, bool value, const char *key, bool commit); - void setOtherSetting(int &setting, int value, const char *key, bool commit); - bool getBoolSetting(const char *key, bool defaultValue = false); - int getIntSetting(const char *key, int defaultValue); - + void setOtherSetting(bool &setting, bool value, const char *key, bool commit); + void setOtherSetting(int &setting, int value, const char *key, bool commit); + void setOtherSetting(std::string &setting, const std::string &value, + const char *key, bool commit, bool isPath = false); + bool getBoolSetting(const char *key, bool defaultValue = false); + int getIntSetting(const char *key, int defaultValue); + std::string getStringSetting(const char *key,const char *defaultValue = NULL, + bool isPath = false); + std::string m_modelName; + LDVWidget *m_modelWidget; LDPreferences *m_prefs; - LDViewPoint *m_viewPoint; - - bool m_generatePdf; - int m_lookupSite; - int m_elementSource; - int m_lookupDefault; - int m_elementDefault; - int m_snapshotWidth; - int m_snapshotHeight; - + LDViewPoint *m_viewPoint; + + bool m_generatePdf; + int m_lookupSite; + int m_elementSource; + int m_lookupDefault; + int m_elementDefault; + int m_snapshotWidth; + int m_snapshotHeight; + bool m_showModel; bool m_overwriteSnapshot; bool m_externalCss; @@ -143,16 +155,17 @@ class LDVHtmlInventory : public TCObject bool m_showTotal; std::string m_lastSavePath; std::string m_lastFilename; - std::string m_imageFilename; - std::string m_partListKey; - std::string m_userDefinedSnapshot; + std::string m_imageFilename; + std::string m_partListKey; + std::string m_userDefinedSnapshot; + std::string m_rebrickableKey; int m_columns; LDVPartListColumnVector m_columnOrder; LDVPartListColumnBoolMap m_columnMap; mutable std::string m_snapshotPath; static const char *sm_style; - static const char *sm_script; + static const char *sm_script; static const char *sm_cssHeader; static const char *sm_cssFilename; }; diff --git a/ldvlib/LDVQt/LDVPartList.ui b/ldvlib/LDVQt/LDVPartList.ui index acc23fc13..d2d7b9e83 100644 --- a/ldvlib/LDVQt/LDVPartList.ui +++ b/ldvlib/LDVQt/LDVPartList.ui @@ -8,7 +8,7 @@ 0 0 352 - 495 + 537 @@ -257,18 +257,18 @@ - + - + - Part lookup site: + Element source: - + - Select part lookup website + Select part element identification source @@ -277,7 +277,7 @@ - Peeron + LEGO @@ -285,18 +285,18 @@ - + - + - Element source: + Part lookup site: - + - Select part element identification source + Select part lookup website @@ -305,9 +305,37 @@ - LEGO + Peeron + + + + + Rebrickable + + + LDraw Part Tracker + + + + + + + + + + + + API Key + + + + + + + Enter your Rebrickable API Key or leave blank to use the LPub3D default key + diff --git a/ldvlib/LDVQt/LDVQt.pro b/ldvlib/LDVQt/LDVQt.pro index 43b2e0183..17b1b761c 100644 --- a/ldvlib/LDVQt/LDVQt.pro +++ b/ldvlib/LDVQt/LDVQt.pro @@ -1,6 +1,7 @@ TEMPLATE = lib QT += core QT += opengl +QT += network QT += widgets QT += gui CONFIG += thread @@ -15,7 +16,8 @@ INCLUDEPATH += . DEPENDPATH += ./include INCLUDEPATH += ./include INCLUDEPATH += ../WPngImage -INCLUDEPATH += ../../mainApp #../../lclib/common +INCLUDEPATH += ../../mainApp +INCLUDEPATH += ../../lclib/common INCLUDEPATH += ../../qslog macx: \ INCLUDEPATH += /usr/local/include diff --git a/ldvlib/LDVQt/LDVWidget.cpp b/ldvlib/LDVQt/LDVWidget.cpp index ded18e7a1..bd021305a 100644 --- a/ldvlib/LDVQt/LDVWidget.cpp +++ b/ldvlib/LDVQt/LDVWidget.cpp @@ -79,9 +79,11 @@ #include "messageboxresizable.h" #include "lpub_preferences.h" +#include "annotations.h" #include "lpubalert.h" #include "version.h" #include "paths.h" +#include "lc_http.h" #define PNG_IMAGE_TYPE_INDEX 1 #define WINDOW_WIDTH_DEFAULT 640 @@ -179,6 +181,13 @@ LDVWidget::~LDVWidget(void) TCAutoreleasePool::processReleases(); doneCurrent(); + + if (m_KeyListReply) + { + m_KeyListReply->abort(); + m_KeyListReply->deleteLater(); + } + ldvWidget = nullptr; } @@ -647,6 +656,24 @@ void LDVWidget::doPartList(void) if (partListKey) htmlInventory->setPartListKey(partListKey); + if (htmlInventory->getLookupSite() == LDVHtmlInventory::LookUp::Rebrickable) + { + // wire up downloads + m_HttpManager = new lcHttpManager(this); + + connect(m_HttpManager, SIGNAL(DownloadFinished(lcHttpReply*)), this, SLOT(DownloadFinished(lcHttpReply*))); + + // set API key + QString userKey = QString::fromStdString(htmlInventory->getRebrickableKey()); + if (userKey.isEmpty()) + doSetDefaultRebrickableKeys(); + else + doSetRebrickableKey(userKey); + + // set model widget + htmlInventory->setModelWidget(this); + } + QString initialDir = QString(ldPrefs->getInvLastSavePath()); if (initialDir.isEmpty()) { initialDir = QString(ldPrefs->getDefaultSaveDir(LDPreferences::SOPartsList, @@ -953,3 +980,205 @@ void LDVWidget::displayGLExtensions() } #endif } + +int LDVWidget::doGetRebrickableColor(const int LDrawColorID, bool alt) const +{ + QJsonDocument Document = QJsonDocument::fromJson(m_RebrickableColors); + QJsonObject Root = Document.object(); + QJsonArray Colors = Root["results"].toArray(); + for (const QJsonValue& Color : Colors) + { + // primary check + QJsonObject ColorObject = Color.toObject(); + int RBColorCode = ColorObject["id"].toInt(); + if (LDrawColorID == RBColorCode) { + emit lpubAlert->messageSig(LOG_INFO, QString("RBColorCode=%1 LDrawColorID=%2 ").arg(RBColorCode).arg(LDrawColorID)); + return RBColorCode; + } + // secondary check + QJsonArray ColorArray = ColorObject["external_ids"].toObject()["LDraw"].toObject()["ext_ids"].toArray(); + if (!ColorArray.isEmpty()) { + int LDColorCode = ColorArray.first().toInt(); + emit lpubAlert->messageSig(LOG_INFO, QString("RBColorCode=%1 LDColorCode=%2 ").arg(RBColorCode).arg(LDColorCode)); + if (LDrawColorID == LDColorCode) { + return RBColorCode; + } + } + } + // final check - if we get here, check cross-reference + int altColor = Annotations::getRBColorID(QString::number(LDrawColorID)); + if (!alt && altColor) + doGetRebrickableColor(altColor, true); + + return LDrawColorID; +} + +std::string LDVWidget::doGetRebrickablePartURL(const std::string &LDrawPartID, bool alt) const +{ + QJsonDocument Document = QJsonDocument::fromJson(m_RebrickableParts); + QJsonObject Root = Document.object(); + QJsonArray Parts = Root["results"].toArray(); + for (const QJsonValue& Part : Parts) + { + // primary check + QJsonObject PartObject = Part.toObject(); + QByteArray RBPartUrl = PartObject["part_url"].toString().toLatin1(); + QByteArray RBPartCode = PartObject["part_num"].toString().toLatin1(); + if (LDrawPartID == RBPartCode.toStdString()) { + emit lpubAlert->messageSig(LOG_INFO, QString("LDrawPartID=%1 RBPartCode=%2 RBPartUrl=%3 ") + .arg(QString::fromStdString(LDrawPartID)) + .arg(QString(RBPartCode)) + .arg(QString(RBPartUrl))); + return RBPartUrl.toStdString(); + } + // secondary check + QJsonArray PartIDArray = PartObject["external_ids"].toObject()["LDraw"].toArray(); + if (!PartIDArray.isEmpty()) { + for (int i = 0; i < PartIDArray.size(); i++){ + QByteArray LDPartCode = PartIDArray[i].toString().toLatin1(); + emit lpubAlert->messageSig(LOG_INFO, QString("LDPartCode=%1 RBPartCode=%2 RBPartUrl=%3 ") + .arg(QString(LDPartCode)) + .arg(QString(RBPartCode)) + .arg(QString(RBPartUrl))); + if (LDrawPartID == LDPartCode.toStdString()) { + return RBPartUrl.toStdString(); + } + } + } + } + // final check - if we get here, check cross-reference + std::string altPart = Annotations::getRBPartID(QString::fromStdString(LDrawPartID)).toStdString(); + if (!alt && !altPart.empty()) + doGetRebrickablePartURL(altPart, true); + + return std::string(""); +} + +void LDVWidget::DownloadFinished(lcHttpReply* Reply) +{ + if (Reply == m_KeyListReply) + { + if (!Reply->error()) + { + QJsonDocument Document = QJsonDocument::fromJson(Reply->readAll()); + QJsonObject Root = Document.object(); + + int Version = Root["Version"].toInt(); + + if (Version == 1) + { + QJsonArray Keys = Root["Keys"].toArray(); + + for (const QJsonValue& Key : Keys) + m_Keys.append(Key.toString()); + } + } + + if (m_Keys.isEmpty()) + { + emit lpubAlert->messageSig(LOG_ERROR, QString("%1").arg("Could not connect to server - no API Key specified.")); + close(); + } + + m_KeyListReply = nullptr; + } + else if (Reply == m_ColorsReply) + { + if (!Reply->error()) + m_RebrickableColors = Reply->readAll(); + else + emit lpubAlert->messageSig(LOG_ERROR, QString("%1").arg("Could not download Rebrickable colors.")); + + m_ColorsReply = nullptr; + } + else if (Reply == m_PartsReply) + { + if (!Reply->error()) + m_RebrickableParts = Reply->readAll(); + else + emit lpubAlert->messageSig(LOG_ERROR, QString("%1").arg("Could not download Rebrickable parts.")); + + m_PartsReply = nullptr; + } + + Reply->deleteLater(); +} + +void LDVWidget::doSetRebrickableParts(const QString &parts) +{ + QProgressDialog ProgressDialog(this); + ProgressDialog.setWindowTitle(tr("Rebrickable parts")); + ProgressDialog.setLabelText(tr("Retrieve Rebrickable part information from the server")); + ProgressDialog.setMaximum(0); + ProgressDialog.setMinimum(0); + ProgressDialog.setValue(0); +// ProgressDialog.show(); + + if (m_Keys.isEmpty()) + return; + + QString partNumbers = QString(parts).replace(",","% 2C"); + + int KeyIndex = m_Keys.size() > 1 ? QTime::currentTime().msec() % m_Keys.size() : 0 ; + + QString SearchUrl = QString("%1/parts/?part_nums=%2&key=%3") + .arg(VER_REBRICKABLE_API_URL) + .arg(partNumbers) + .arg(m_Keys[KeyIndex]).replace("% 2C","%2C"); + + m_PartsReply = m_HttpManager->DownloadFile(SearchUrl); + + while (m_PartsReply) + { + QApplication::processEvents(); + + if (ProgressDialog.wasCanceled()) + { + m_PartsReply->abort(); + m_PartsReply->deleteLater(); + m_PartsReply = nullptr; + return; + } + } +} + +void LDVWidget::doSetRebrickableColors() +{ + QProgressDialog ProgressDialog(this); + ProgressDialog.setWindowTitle(tr("Rebrickable colors")); + ProgressDialog.setLabelText(tr("Retrieving Rebrickable colors from the server")); + ProgressDialog.setMaximum(0); + ProgressDialog.setMinimum(0); + ProgressDialog.setValue(0); +// ProgressDialog.show(); + + if (m_Keys.isEmpty()) + return; + + int KeyIndex = m_Keys.size() > 1 ? QTime::currentTime().msec() % m_Keys.size() : 0 ; + + QString SearchUrl = QString("%1/colors/?key=%2") + .arg(VER_REBRICKABLE_API_URL) + .arg(m_Keys[KeyIndex]); + + m_ColorsReply = m_HttpManager->DownloadFile(SearchUrl); + + while (m_ColorsReply) + { + QApplication::processEvents(); + + if (ProgressDialog.wasCanceled()) + { + m_ColorsReply->abort(); + m_ColorsReply->deleteLater(); + m_ColorsReply = nullptr; + return; + } + } +} + +void LDVWidget::doSetDefaultRebrickableKeys() +{ + const char* defaultKeyUrl(VER_REBRICKABLE_KEYS_JSON_URL); + m_KeyListReply = m_HttpManager->DownloadFile(QLatin1String(defaultKeyUrl)); +} diff --git a/ldvlib/LDVQt/LDVWidget.h b/ldvlib/LDVQt/LDVWidget.h index f43e49f94..536e5613c 100644 --- a/ldvlib/LDVQt/LDVWidget.h +++ b/ldvlib/LDVQt/LDVWidget.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,9 @@ class LDVAlertHandler; class LDSnapshotTaker; class LDVHtmlInventory; +class lcHttpReply; +class lcHttpManager; + class LDVWidget : public QGLWidget, protected QGLFunctions { @@ -66,18 +70,29 @@ class LDVWidget : public QGLWidget, protected QGLFunctions bool doCommand(QStringList &arguments); + void doSetRebrickableColors(); + void doSetRebrickableParts(const QString &list); + void doSetDefaultRebrickableKeys(); + void doSetRebrickableKey(QString &key) { m_Keys.append(key); } + + int doGetRebrickableColor(const int ldrawColorID, bool = false) const; + std::string doGetRebrickablePartURL(const std::string &ldrawPartID, bool = false) const; + void doPartList(void); void doPartList(LDVHtmlInventory *htmlInventory, LDPartsList *partsList, - const char *filename); + const char *filename); bool saveImage(char *filename, int imageWidth, int imageHeight); bool grabImage(int &imageWidth, int &imageHeight); void setViewMode(LDInputHandler::ViewMode value, bool examineLatLong, - bool keepRightSideUp, bool saveSettings=true); + bool keepRightSideUp, bool saveSettings=true); void showDocument(QString &htmlFilename); signals: void loadBLCodesSig(); +public slots: + void DownloadFinished(lcHttpReply* Reply); + protected: bool setIniFile(void); bool setupPartList(void); @@ -111,11 +126,19 @@ class LDVWidget : public QGLWidget, protected QGLFunctions struct IniFile { - QString Title; - QString File; + QString Title; + QString File; }; IniFile iniFiles[NumIniFiles]; + lcHttpManager* m_HttpManager; + lcHttpReply* m_KeyListReply; + lcHttpReply* m_ColorsReply; + lcHttpReply* m_PartsReply; + QStringList m_Keys; + QByteArray m_RebrickableColors; + QByteArray m_RebrickableParts; + }; extern LDVWidget* ldvWidget; diff --git a/ldvlib/LDVQt/LDVWidgetDefaultKeys.h b/ldvlib/LDVQt/LDVWidgetDefaultKeys.h index cbc8ef9e9..92e869b51 100644 --- a/ldvlib/LDVQt/LDVWidgetDefaultKeys.h +++ b/ldvlib/LDVQt/LDVWidgetDefaultKeys.h @@ -6,6 +6,7 @@ #define PARTS_LIST_LOOKUP_SITE_KEY "PartsListLookupSite" #define PARTS_LIST_ELEMENT_SRURCE_KEY "PartsListElementSource" #define PARTS_LIST_GENERATE_PDF_KEY "PartsListPdf" +#define PARTS_LIST_REBRICKABLE_KEY_KEY "RebrickableKey" // Edges diff --git a/ldvlib/LDVQt/LDVWidgetMessages.ini b/ldvlib/LDVQt/LDVWidgetMessages.ini index eb2d7caa7..a7242f4d8 100644 --- a/ldvlib/LDVQt/LDVWidgetMessages.ini +++ b/ldvlib/LDVQt/LDVWidgetMessages.ini @@ -29,6 +29,9 @@ PLVInvalidElements = Invalid Elements: %d ; Additionally, if there isn't an image found for a particular part, it gets ; used instead of the image. PLViewOnBricklink =View on Bricklink.com +PLViewOnRebrickable =View on Rebrickable.com +PLViewOnLDrawPartTracker =View on LDraw.org Part Tracker Official Parts +PLViewOnLDrawUnOffPartTracker =View on LDraw.org Part Tracker Unofficial Parts PLVInvalidElement =Invalid Bricklink item number or color code ; The following two entries end up in HTML output. Make sure to leave the links ; intact. diff --git a/ldvlib/LDVQt/LDViewPartList.cpp b/ldvlib/LDVQt/LDViewPartList.cpp index 82da7c950..d20f38407 100644 --- a/ldvlib/LDVQt/LDViewPartList.cpp +++ b/ldvlib/LDVQt/LDViewPartList.cpp @@ -5,37 +5,40 @@ #include LDVPartList::LDVPartList(LDVWidget *modelWidget, LDVHtmlInventory *htmlInventory) - : QDialog(qobject_cast(modelWidget)), - LDVPartListPanel(), - m_modelViewer(modelWidget->getModelViewer() ? ((LDrawModelViewer*)modelWidget->getModelViewer()->retain()) : nullptr), - m_modelWidget(modelWidget), - m_htmlInventory(htmlInventory) + : QDialog(qobject_cast(modelWidget)), + LDVPartListPanel(), + m_modelViewer(modelWidget->getModelViewer() ? ((LDrawModelViewer*)modelWidget->getModelViewer()->retain()) : nullptr), + m_modelWidget(modelWidget), + m_htmlInventory(htmlInventory) { setupUi(this); - connect( upButton, SIGNAL( clicked() ), this, SLOT( doUp() ) ); - connect( downButton, SIGNAL( clicked() ), this, SLOT( doDown() ) ); - connect( okButton, SIGNAL( clicked() ), this, SLOT( doOk() ) ); - connect( cancelButton, SIGNAL( clicked() ), this, SLOT( doCancel() ) ); - connect( showModelButton, SIGNAL( clicked() ), this, SLOT( doShowModel() ) ); - connect( fieldOrderView, SIGNAL( currentItemChanged(QListWidgetItem *, QListWidgetItem *) ), this, SLOT( doHighlighted(QListWidgetItem *, QListWidgetItem *) ) ); - connect( preferencesButton, SIGNAL( clicked() ), this, SLOT( doShowPreferences() ) ); - connect( snapshotButton, SIGNAL( clicked() ), this, SLOT( doBrowseSnapshotFile() ) ); - connect( snapshotEdit, SIGNAL( editingFinished() ), this, SLOT(doUpdateSnapshotEdit() ) ); - - if (m_modelWidget && - m_htmlInventory->getLookupSite() == - LDVHtmlInventory::LookUp::Bricklink) - emit m_modelWidget->loadBLCodesSig(); - - QValidator *validator = new QIntValidator(10, 5000, this); - snapshotWidthEdit->setValidator(validator); - snapshotHeightEdit->setValidator(validator); - snapshotEdit->setValidator(new QRegExpValidator( - QRegExp("^.*\\.png$",Qt::CaseInsensitive), this)); + connect( upButton, SIGNAL( clicked() ), this, SLOT( doUp() ) ); + connect( downButton, SIGNAL( clicked() ), this, SLOT( doDown() ) ); + connect( okButton, SIGNAL( clicked() ), this, SLOT( doOk() ) ); + connect( cancelButton, SIGNAL( clicked() ), this, SLOT( doCancel() ) ); + connect( showModelButton, SIGNAL( clicked() ), this, SLOT( doShowModel() ) ); + connect( fieldOrderView, SIGNAL( currentItemChanged(QListWidgetItem *, QListWidgetItem *) ), this, SLOT( doHighlighted(QListWidgetItem *, QListWidgetItem *) ) ); + connect( preferencesButton, SIGNAL( clicked() ), this, SLOT( doShowPreferences() ) ); + connect( snapshotButton, SIGNAL( clicked() ), this, SLOT( doBrowseSnapshotFile() ) ); + connect( snapshotEdit, SIGNAL( editingFinished() ), this, SLOT(doUpdateSnapshotEdit() ) ); + connect( rebrickableKeyEdit, SIGNAL( editingFinished() ), this, SLOT(doUpdateRebrickableKey() ) ); + connect( partLookupSiteCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(doEnableRebrickableKeyEdit(int))); + + if (m_modelWidget) { + if (m_htmlInventory->getLookupSite() == + LDVHtmlInventory::LookUp::Bricklink) + emit m_modelWidget->loadBLCodesSig(); + } + + QValidator *validator = new QIntValidator(10, 5000, this); + snapshotWidthEdit->setValidator(validator); + snapshotHeightEdit->setValidator(validator); + snapshotEdit->setValidator(new QRegExpValidator( + QRegExp("^.*\\.png$",Qt::CaseInsensitive), this)); // fieldOrderView->header()->hide(); // fieldOrderView->setSorting(-1); - setMinimumSize(50,50); + setMinimumSize(50,50); } LDVPartList::~LDVPartList(void) @@ -44,29 +47,29 @@ LDVPartList::~LDVPartList(void) void LDVPartList::populateColumnList(void) { - const LDVPartListColumnVector &columnOrder = - m_htmlInventory->getColumnOrder(); + const LDVPartListColumnVector &columnOrder = + m_htmlInventory->getColumnOrder(); int i; fieldOrderView->clear(); for (i = 0; i < (int)columnOrder.size(); i++) { - LDVPartListColumn column = columnOrder[i]; - const char *name = LDVHtmlInventory::getColumnName(column); + LDVPartListColumn column = columnOrder[i]; + const char *name = LDVHtmlInventory::getColumnName(column); QListWidgetItem *item = new QListWidgetItem(name, fieldOrderView); item->setCheckState(m_htmlInventory->isColumnEnabled(column) ? Qt::Checked : Qt::Unchecked); item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); } - for (i = LDVPLCFirst; i <= LDVPLCLast; i++) - { - LDVPartListColumn column = (LDVPartListColumn)i; - if (!m_htmlInventory->isColumnEnabled(column)) - { - const char *name = LDVHtmlInventory::getColumnName(column); - QListWidgetItem *item = new QListWidgetItem(name, fieldOrderView); - item->setCheckState(m_htmlInventory->isColumnEnabled(column) ? Qt::Checked : Qt::Unchecked); - item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); - } - } + for (i = LDVPLCFirst; i <= LDVPLCLast; i++) + { + LDVPartListColumn column = (LDVPartListColumn)i; + if (!m_htmlInventory->isColumnEnabled(column)) + { + const char *name = LDVHtmlInventory::getColumnName(column); + QListWidgetItem *item = new QListWidgetItem(name, fieldOrderView); + item->setCheckState(m_htmlInventory->isColumnEnabled(column) ? Qt::Checked : Qt::Unchecked); + item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); + } + } } @@ -84,39 +87,41 @@ void LDVPartList::doOk() { int i,j; QListWidgetItem *item; - bool showmodel,openDocument; - LDVPartListColumnVector columnOrder; + bool showmodel,openDocument; + LDVPartListColumnVector columnOrder; m_htmlInventory->setExternalCssFlag(generateExternalSSButton->isChecked()); m_htmlInventory->setPartImagesFlag(showPartImageButton->isChecked()); - m_htmlInventory->setShowModelFlag(showmodel = showModelButton->isChecked()); + m_htmlInventory->setShowModelFlag(showmodel = showModelButton->isChecked()); if (showmodel) { m_htmlInventory->setOverwriteSnapshotFlag( overwriteExistingButton->isChecked()); - m_htmlInventory->setSnapshotWidthFlag( - snapshotWidthEdit->text().toInt()); - m_htmlInventory->setSnapshotHeightFlag( - snapshotHeightEdit->text().toInt()); - if (overwriteExistingButton->isChecked() && !(snapshotEdit->text().isEmpty())) - m_htmlInventory->setUserDefinedSnapshot(snapshotEdit->text().toLatin1().constData()); + m_htmlInventory->setSnapshotWidthFlag( + snapshotWidthEdit->text().toInt()); + m_htmlInventory->setSnapshotHeightFlag( + snapshotHeightEdit->text().toInt()); + if (overwriteExistingButton->isChecked() && !(snapshotEdit->text().isEmpty())) + m_htmlInventory->setUserDefinedSnapshot(snapshotEdit->text().toLatin1().constData()); + } + m_htmlInventory->setShowFileFlag(openDocument = showWebPageButton->isChecked()); + if (openDocument){ + m_htmlInventory->setGeneratePdfFlag(false); // not implemented } - m_htmlInventory->setShowFileFlag(openDocument = showWebPageButton->isChecked()); - if (openDocument){ - m_htmlInventory->setGeneratePdfFlag(false); // not implemented - } - m_htmlInventory->setLookupSiteFlag(partLookupSiteCombo->currentIndex()); - m_htmlInventory->setElementSourceFlag(elementSourceCombo->currentIndex()); + m_htmlInventory->setLookupSiteFlag(partLookupSiteCombo->currentIndex()); + m_htmlInventory->setElementSourceFlag(elementSourceCombo->currentIndex()); - for (item = fieldOrderView->item(j = 0) ; item && (j < (fieldOrderView->count())); + doUpdateRebrickableKey(); + + for (item = fieldOrderView->item(j = 0) ; item && (j < (fieldOrderView->count())); item = fieldOrderView->item(++j)) { - QListWidgetItem *item2 = (QListWidgetItem*)item; - for (i = LDVPLCFirst; i <= LDVPLCLast; i++) + QListWidgetItem *item2 = (QListWidgetItem*)item; + for (i = LDVPLCFirst; i <= LDVPLCLast; i++) { - LDVPartListColumn column = LDVPartListColumn(i); - const char *name = LDVHtmlInventory::getColumnName(column); - if (strcmp(name,item->text().toLatin1().constData())==0) + LDVPartListColumn column = LDVPartListColumn(i); + const char *name = LDVHtmlInventory::getColumnName(column); + if (strcmp(name,item->text().toLatin1().constData())==0) { if (item2->checkState() == Qt::Checked) { @@ -160,23 +165,27 @@ int LDVPartList::exec() { bool showmodel; populateColumnList(); - generateExternalSSButton->setChecked( + generateExternalSSButton->setChecked( m_htmlInventory->getExternalCssFlag()); - showPartImageButton->setChecked( + showPartImageButton->setChecked( m_htmlInventory->getPartImagesFlag()); - showModelButton->setChecked(showmodel = + showModelButton->setChecked(showmodel = m_htmlInventory->getShowModelFlag()); overwriteExistingButton->setChecked(showmodel ? m_htmlInventory->getOverwriteSnapshotFlag() : false); - showWebPageButton->setChecked(m_htmlInventory->getShowFileFlag()); - partLookupSiteCombo->setCurrentIndex( - m_htmlInventory->getLookupSiteFlag()); - elementSourceCombo->setCurrentIndex( - m_htmlInventory->getElementSourceFlag()); - snapshotWidthEdit->setText( - QString::number(m_htmlInventory->getSnapshotWidthFlag())); - snapshotHeightEdit->setText( - QString::number(m_htmlInventory->getSnapshotHeightFlag())); + showWebPageButton->setChecked(m_htmlInventory->getShowFileFlag()); + partLookupSiteCombo->setCurrentIndex( + m_htmlInventory->getLookupSiteFlag()); + elementSourceCombo->setCurrentIndex( + m_htmlInventory->getElementSourceFlag()); + snapshotWidthEdit->setText( + QString::number(m_htmlInventory->getSnapshotWidthFlag())); + snapshotHeightEdit->setText( + QString::number(m_htmlInventory->getSnapshotHeightFlag())); + rebrickableKeyEdit->setEnabled( + m_htmlInventory->getLookupSiteFlag() == LDVHtmlInventory::LookUp::Rebrickable); + rebrickableKeyEdit->setText( + QString::fromStdString(m_htmlInventory->getRebrickableKeyFlag())); doShowModel(); @@ -185,53 +194,65 @@ int LDVPartList::exec() void LDVPartList::doShowModel() { - bool show = showModelButton->isChecked(); + bool show = showModelButton->isChecked(); - overwriteExistingButton->setEnabled(show); - snapshotWidthEdit->setEnabled(show); - snapshotHeightEdit->setEnabled(show); - widthLabel->setEnabled(show); - heightLabel->setEnabled(show); - snapshotButton->setEnabled(show); - snapshotEdit->setEnabled(show); + overwriteExistingButton->setEnabled(show); + snapshotWidthEdit->setEnabled(show); + snapshotHeightEdit->setEnabled(show); + widthLabel->setEnabled(show); + heightLabel->setEnabled(show); + snapshotButton->setEnabled(show); + snapshotEdit->setEnabled(show); } void LDVPartList::doShowPreferences() { - LDVPreferences *preferences = new LDVPreferences(m_modelWidget); - if (preferences->exec() == QDialog::Accepted) - preferences->doOk(); - else - preferences->doCancel(); + LDVPreferences *preferences = new LDVPreferences(m_modelWidget); + if (preferences->exec() == QDialog::Accepted) + preferences->doOk(); + else + preferences->doCancel(); } void LDVPartList::doBrowseSnapshotFile() { - QString Result = QFileDialog::getOpenFileName(this, tr("Select Snapshot File"), snapshotEdit->text(), tr("Supported Image File (*.png);;PNG Files (*.png)")); - if (!Result.isEmpty()) { - doSetSnapshotFile(Result); - } + QString Result = QFileDialog::getOpenFileName(this, tr("Select Snapshot File"), snapshotEdit->text(), tr("Supported Image File (*.png);;PNG Files (*.png)")); + if (!Result.isEmpty()) { + doSetSnapshotFile(Result); + } } void LDVPartList::doUpdateSnapshotEdit() { - QString Result = snapshotEdit->text(); - if (!Result.isEmpty()) - doSetSnapshotFile(Result); + QString Result = snapshotEdit->text(); + if (!Result.isEmpty()) + doSetSnapshotFile(Result); } void LDVPartList::doSetSnapshotFile(QString &Result) { - preferencesButton->setEnabled(false); - snapshotEdit->setText(QDir::toNativeSeparators(Result)); - - QImage image(Result); - if (snapshotWidthEdit->text().toInt() != image.width()) { - m_htmlInventory->setSnapshotWidthFlag(image.width()); - snapshotWidthEdit->setText(QString::number(m_htmlInventory->getSnapshotWidthFlag())); - } - if (snapshotHeightEdit->text().toInt() != image.height()) { - m_htmlInventory->setSnapshotHeightFlag(image.height()); - snapshotHeightEdit->setText(QString::number(m_htmlInventory->getSnapshotHeightFlag())); - } + preferencesButton->setEnabled(false); + snapshotEdit->setText(QDir::toNativeSeparators(Result)); + + QImage image(Result); + if (snapshotWidthEdit->text().toInt() != image.width()) { + m_htmlInventory->setSnapshotWidthFlag(image.width()); + snapshotWidthEdit->setText(QString::number(m_htmlInventory->getSnapshotWidthFlag())); + } + if (snapshotHeightEdit->text().toInt() != image.height()) { + m_htmlInventory->setSnapshotHeightFlag(image.height()); + snapshotHeightEdit->setText(QString::number(m_htmlInventory->getSnapshotHeightFlag())); + } +} + +void LDVPartList::doUpdateRebrickableKey() +{ + QString Result = rebrickableKeyEdit->text(); + if (!Result.isEmpty() && Result != QString::fromStdString(m_htmlInventory->getRebrickableKeyFlag())) + m_htmlInventory->setRebrickableKeyFlag(Result.toStdString()); +} + +void LDVPartList::doEnableRebrickableKeyEdit(int index) +{ + rebrickableKeyEdit->setEnabled(index == LDVHtmlInventory::LookUp::Rebrickable); } diff --git a/ldvlib/LDVQt/LDViewPartList.h b/ldvlib/LDVQt/LDViewPartList.h index 84a73d0ad..86d49ce46 100644 --- a/ldvlib/LDVQt/LDViewPartList.h +++ b/ldvlib/LDVQt/LDViewPartList.h @@ -12,11 +12,11 @@ class LDVPartList : public QDialog , Ui::LDVPartListPanel { Q_OBJECT public: - LDVPartList(LDVWidget *modelWidget, LDVHtmlInventory *htmlInventory); - ~LDVPartList(void); - void populateColumnList(); + LDVPartList(LDVWidget *modelWidget, LDVHtmlInventory *htmlInventory); + ~LDVPartList(void); + void populateColumnList(); // QCheckListItem *description; - int exec(); + int exec(); public slots: void doOk(); @@ -25,15 +25,17 @@ public slots: void doDown(); void doHighlighted(QListWidgetItem * current, QListWidgetItem * previous ); void doShowModel(); - void doShowPreferences(); - void doBrowseSnapshotFile(); - void doUpdateSnapshotEdit(); + void doShowPreferences(); + void doBrowseSnapshotFile(); + void doUpdateSnapshotEdit(); + void doUpdateRebrickableKey(); + void doEnableRebrickableKeyEdit(int); protected: - void doSetSnapshotFile(QString &Result); + void doSetSnapshotFile(QString &Result); void doMoveColumn(int distance); - LDrawModelViewer *m_modelViewer; - LDVWidget *m_modelWidget; - LDVHtmlInventory *m_htmlInventory; + LDrawModelViewer *m_modelViewer; + LDVWidget *m_modelWidget; + LDVHtmlInventory *m_htmlInventory; }; #endif //__LDVIEWPARTLIST_H__ diff --git a/mainApp/annotations.cpp b/mainApp/annotations.cpp index c2e52e0c8..1af539e03 100644 --- a/mainApp/annotations.cpp +++ b/mainApp/annotations.cpp @@ -35,6 +35,9 @@ QHash Annotations::blColors; QHash Annotations::ld2blColorsXRef; QHash Annotations::ld2blCodesXRef; +QHash Annotations::ld2rbColorsXRef; +QHash Annotations::ld2rbCodesXRef; + void Annotations::loadLD2BLColorsXRef(QByteArray& Buffer){ /* # File: ld2blcolorsxref.lst @@ -672,6 +675,58 @@ void Annotations::loadDefaultAnnotationStyles(QByteArray& Buffer){ Buffer.append(VEXIQDefaultAnnotationStyles, sizeof(VEXIQDefaultAnnotationStyles)); } +void Annotations::loadLD2RBColorsXRef(QByteArray& Buffer){ +/* +# File: ld2rbcolorsxref.lst +# +# Tab-delmited LDConfig and Rebrickable Color code cross reference +# +# The Regular Expression used is: ^([^\t]+)\t+\s*([^\t]+).*$ +# +# 1. LDConfig Color ID: LDraw Color ID (Required) +# 2. Color ID: Rebrickable Color ID (Required) +# +*/ + const char LEGOLD2RBColorsXRef[] = { + "-1\t -1\n" + }; + + const char LD2RBColorsXRef[] = { + "no colors cross-references defined\n" + }; + + if (Preferences::validLDrawLibrary == LEGO_LIBRARY) + Buffer.append(LEGOLD2RBColorsXRef, sizeof(LEGOLD2RBColorsXRef)); + else + Buffer.append(LD2RBColorsXRef, sizeof(LD2RBColorsXRef)); +} + +void Annotations::loadLD2RBCodesXRef(QByteArray& Buffer){ +/* +# File: ld2rbcodesxref.lst +# +# Tab-delmited LDraw Design ID and Rebrickable Part ID cross reference +# +# The Regular Expression used is: ^([^\t]+)\t+\s*([^\t]+).*$ +# +# 1. Design ID: LDraw Part Number (Required) +# 2. Part ID: Rebrickable Part Number (Required) +# +*/ + const char LEGOLD2RBCodesXRef[] = { + "00000\t 00000\n" + }; + + const char LD2RBCodesXRef[] = { + "no code cross-references defined\n" + }; + + if (Preferences::validLDrawLibrary == LEGO_LIBRARY) + Buffer.append(LEGOLD2RBCodesXRef, sizeof(LEGOLD2RBCodesXRef)); + else + Buffer.append(LD2RBCodesXRef, sizeof(LD2RBCodesXRef)); +} + Annotations::Annotations() { returnString = QString(); @@ -996,6 +1051,126 @@ Annotations::Annotations() } } } + + // Rebrickable Codes + + if (ld2rbColorsXRef.size() == 0) { + QString ld2rbColorsXRefFile = Preferences::ld2rbColorsXRefFile; + QRegExp rx("^([^\\t]+)\\t+\\s*([^\\t]+).*$"); + if (!ld2rbColorsXRefFile.isEmpty()) { + QFile file(ld2rbColorsXRefFile); + if ( ! file.open(QFile::ReadOnly | QFile::Text)) { + QString message = QString("Failed to open ld2rbcolorsxref.lst file: %1:\n%2") + .arg(ld2rbColorsXRefFile) + .arg(file.errorString()); + if (Preferences::modeGUI){ + QMessageBox::warning(nullptr,QMessageBox::tr("LPub3D"),message); + } else { + logError() << message; + } + return; + } + QTextStream in(&file); + + // Load RegExp from file; + QRegExp rxin("^#\\sThe\\sRegular\\sExpression\\sused\\sis\\:[\\s](\\^.*)$"); + while ( ! in.atEnd()) { + QString sLine = in.readLine(0); + if (sLine.contains(rxin)) { + rx.setPattern(rxin.cap(1)); +// logDebug() << "LD2RB ColorsXRef RegExp Pattern: " << rxin.cap(1); + break; + } + } + + in.seek(0); + + // Load input values + while ( ! in.atEnd()) { + QString sLine = in.readLine(0); + if (sLine.contains(rx)) { + QString ldcolorid = rx.cap(1); + QString rbcolorid = rx.cap(2).trimmed(); + ld2rbColorsXRef[ldcolorid.toLower()] = rbcolorid; + } + } + } else { + ld2rbColorsXRef.clear(); + QByteArray Buffer; + loadLD2RBColorsXRef(Buffer); + QTextStream instream(Buffer); + for (QString sLine = instream.readLine(); !sLine.isNull(); sLine = instream.readLine()) + { + QChar comment = sLine.at(0); + if (comment == '#' || comment == ' ') + continue; + if (sLine.contains(rx)) { + QString ldcolorid = rx.cap(1); + QString rbcolorid = rx.cap(2).trimmed(); + ld2rbColorsXRef[ldcolorid.toLower()] = rbcolorid; + } + } + } + } + + if (ld2rbCodesXRef.size() == 0) { + QString ld2rbCodesXRefFile = Preferences::ld2rbCodesXRefFile; + QRegExp rx("^([^\\t]+)\\t+\\s*([^\\t]+).*$"); + if (!ld2rbCodesXRefFile.isEmpty()) { + QFile file(ld2rbCodesXRefFile); + if ( ! file.open(QFile::ReadOnly | QFile::Text)) { + QString message = QString("Failed to open ld2rbcodesxref.lst file: %1:\n%2") + .arg(ld2rbCodesXRefFile) + .arg(file.errorString()); + if (Preferences::modeGUI){ + QMessageBox::warning(nullptr,QMessageBox::tr("LPub3D"),message); + } else { + logError() << message; + } + return; + } + QTextStream in(&file); + + // Load RegExp from file; + QRegExp rxin("^#\\sThe\\sRegular\\sExpression\\sused\\sis\\:[\\s](\\^.*)$"); + while ( ! in.atEnd()) { + QString sLine = in.readLine(0); + if (sLine.contains(rxin)) { + rx.setPattern(rxin.cap(1)); +// logDebug() << "LD2RB CodesXRef RegExp Pattern: " << rxin.cap(1); + break; + } + } + + in.seek(0); + + // Load input values + while ( ! in.atEnd()) { + QString sLine = in.readLine(0); + if (sLine.contains(rx)) { + QString ldpartid = rx.cap(1); + QString rbitemid = rx.cap(2).trimmed(); + ld2rbCodesXRef[ldpartid.toLower()] = rbitemid; + } + } + } else { + ld2rbCodesXRef.clear(); + QByteArray Buffer; + loadLD2RBCodesXRef(Buffer); + QTextStream instream(Buffer); + for (QString sLine = instream.readLine(); !sLine.isNull(); sLine = instream.readLine()) + { + QChar comment = sLine.at(0); + if (comment == '#' || comment == ' ') + continue; + if (sLine.contains(rx)) { + QString ldpartid = rx.cap(1); + QString rbitemid = rx.cap(2).trimmed(); + ld2rbCodesXRef[ldpartid.toLower()] = rbitemid; + } + } + } + } } // key : blitemid+blcolorid @@ -1281,6 +1456,21 @@ const QString &Annotations::getBLElement(QString ldcolorid, QString ldpartid, in return returnString; } +const int &Annotations::getRBColorID(QString ldcolorid) +{ + returnInt = 0; + if (ld2rbColorsXRef.contains(ldcolorid.toLower())) + returnInt = ld2rbColorsXRef[ldcolorid.toLower()].toInt(); + return returnInt; +} + +const QString &Annotations::getRBPartID(QString ldpartid) +{ + if (ld2rbCodesXRef.contains(ldpartid.toLower())) + returnString = ld2rbCodesXRef[ldpartid.toLower()]; + return returnString; +} + bool Annotations::overwriteFile(const QString &file) { QFileInfo fileInfo(file); @@ -1563,7 +1753,7 @@ bool Annotations::exportLD2BLCodesXRefFile(){ { int counter = 1; QTextStream outstream(&file); - outstream << "# File:" << VER_LPUB3D_LD2BLCOLORSXREF_FILE << endl; + outstream << "# File:" << VER_LPUB3D_LD2BLCODESXREF_FILE << endl; outstream << "#" << endl; outstream << "# Tab-delmited LDraw Design ID and BrickLink Item Number cross reference" << endl; outstream << "#" << endl; @@ -1628,3 +1818,125 @@ bool Annotations::exportLD2BLCodesXRefFile(){ } return true; } + +bool Annotations::exportLD2RBColorsXRefFile(){ + QFile file(QString("%1/extras/%2").arg(Preferences::lpubDataPath,"/" VER_LPUB3D_LD2RBCOLORSXREF_FILE)); + + if (!overwriteFile(file.fileName())) + return true; + + if(file.open(QIODevice::WriteOnly | QIODevice::Text)) + { + int counter = 1; + QTextStream outstream(&file); + outstream << "# File:" << VER_LPUB3D_LD2RBCOLORSXREF_FILE << endl; + outstream << "#" << endl; + outstream << "# Tab-delmited LDConfig and Rebrickable Color code cross reference" << endl; + outstream << "#" << endl; + outstream << "# The Regular Expression used is: ^([^\\t]+)\\t+\\s*([^\\t]+).*$" << endl; + outstream << "#" << endl; + outstream << "# 1. LDConfig Color ID: LDraw Color ID (Required)" << endl; + outstream << "# 2. Color ID: Rebrickable Color ID (Required)" << endl; + outstream << "#" << endl; + outstream << "# This is one of two parameter files that support viewing parts on Rebrickable.com." << endl; + outstream << "#" << endl; + outstream << "# ld2rbcolorsxref.lst - Tab-delmited LDConfig and Rebrickable Color code cross reference" << endl; + outstream << "# ld2rbcodesxref.lst - Tab-delmited LDraw Design ID and Rebrickable Item Number cross reference" << endl; + outstream << "#" << endl; + outstream << "# Use ld2rbcolorsxref.lst to create cross-reference entries for LDConfig and Rebrickable Color IDs." << endl; + outstream << "#" << endl; + + QByteArray Buffer; + loadLD2RBColorsXRef(Buffer); + QTextStream instream(Buffer); + for (QString sLine = instream.readLine(); !sLine.isNull(); sLine = instream.readLine()) + { + outstream << sLine << endl; + counter++; + } + + file.close(); + QString message = QString("Finished Writing LDConfig and Rebrickable Color Code Entries, Processed %1 lines in file [%2]") + .arg(counter) + .arg(file.fileName()); + if (Preferences::modeGUI){ + QMessageBox::information(nullptr,QMessageBox::tr("LPub3D"),message); + } else { + logNotice() << message; + } + } + else + { + QString message = QString("Failed to open LDConfig and Rebrickable Color Code file: %1:\n%2") + .arg(file.fileName()) + .arg(file.errorString()); + if (Preferences::modeGUI){ + QMessageBox::warning(nullptr,QMessageBox::tr("LPub3D"),message); + } else { + logError() << message; + } + return false; + } + return true; +} + +bool Annotations::exportLD2RBCodesXRefFile(){ + QFile file(QString("%1/extras/%2").arg(Preferences::lpubDataPath,"/" VER_LPUB3D_LD2RBCODESXREF_FILE)); + + if (!overwriteFile(file.fileName())) + return true; + + if(file.open(QIODevice::WriteOnly | QIODevice::Text)) + { + int counter = 1; + QTextStream outstream(&file); + outstream << "# File:" << VER_LPUB3D_LD2RBCODESXREF_FILE << endl; + outstream << "#" << endl; + outstream << "# Tab-delmited LDraw Design ID and Rebrickable Part ID cross reference" << endl; + outstream << "#" << endl; + outstream << "# The Regular Expression used is: ^([^\\t]+)\\t+\\s*([^\\t]+).*$" << endl; + outstream << "#" << endl; + outstream << "# 1. Design ID: LDraw Part Number (Required)" << endl; + outstream << "# 2. Part ID: Rebrickable Part Number (Required)" << endl; + outstream << "#" << endl; + outstream << "# This is one of two parameter files that support viewing parts on Rebrickable.com." << endl; + outstream << "#" << endl; + outstream << "# ld2rbcolorsxref.lst - Tab-delmited LDConfig and Rebrickable Color code cross reference" << endl; + outstream << "# ld2rbcodesxref.lst - Tab-delmited LDraw Design ID and Rebrickable Item Number cross reference" << endl; + outstream << "#" << endl; + outstream << "# Use ld2rbcodesxref.lst to create cross-reference entries for LDraw Design ID and Rebrickable Parg ID." << endl; + outstream << "#" << endl; + + QByteArray Buffer; + loadLD2RBCodesXRef(Buffer); + QTextStream instream(Buffer); + for (QString sLine = instream.readLine(); !sLine.isNull(); sLine = instream.readLine()) + { + outstream << sLine << endl; + counter++; + } + + file.close(); + QString message = QString("Finished Writing LDraw Design ID and Rebrickable Part ID Entries, Processed %1 lines in file [%2]") + .arg(counter) + .arg(file.fileName()); + if (Preferences::modeGUI){ + QMessageBox::information(nullptr,QMessageBox::tr("LPub3D"),message); + } else { + logNotice() << message; + } + } + else + { + QString message = QString("Failed to open LDraw Design ID and Rebrickable Part ID file: %1:\n%2") + .arg(file.fileName()) + .arg(file.errorString()); + if (Preferences::modeGUI){ + QMessageBox::warning(nullptr,QMessageBox::tr("LPub3D"),message); + } else { + logError() << message; + } + return false; + } + return true; +} diff --git a/mainApp/annotations.h b/mainApp/annotations.h index df917b749..28f42cf4e 100644 --- a/mainApp/annotations.h +++ b/mainApp/annotations.h @@ -32,6 +32,9 @@ class Annotations { static QHash blColors; static QHash ld2blColorsXRef; static QHash ld2blCodesXRef; + + static QHash ld2rbColorsXRef; + static QHash ld2rbCodesXRef; public: Annotations(); static const QString &freeformAnnotation(QString part); @@ -46,6 +49,9 @@ class Annotations { static void loadLD2BLColorsXRef(QByteArray &Buffer); static void loadLD2BLCodesXRef(QByteArray &Buffer); + static void loadLD2RBColorsXRef(QByteArray &Buffer); + static void loadLD2RBCodesXRef(QByteArray &Buffer); + static bool loadBLCodes(); static bool loadBLCodes(QByteArray &Buffer); static bool loadLEGOElements(); @@ -55,10 +61,14 @@ class Annotations { static const QString &getBLElement(QString ldcolorid, QString ldpartid, int which = 0); + static const int &getRBColorID(QString blcolorid); + static const QString &getRBPartID(QString blpartid); static bool exportBLColorsFile(); static bool exportLD2BLColorsXRefFile(); static bool exportLD2BLCodesXRefFile(); + static bool exportLD2RBColorsXRefFile(); + static bool exportLD2RBCodesXRefFile(); static const QList getTitleAnnotations() { diff --git a/mainApp/docs/README.txt b/mainApp/docs/README.txt index e3bed7f38..cc2e6370a 100755 --- a/mainApp/docs/README.txt +++ b/mainApp/docs/README.txt @@ -1,4 +1,4 @@ -LPub3D 2.3.10.1.1231 (23 04 2019 12:07:42) +LPub3D 2.3.10.1.1232 (23 04 2019 12:09:09) Features, enhancements, fixes and changes ------------ diff --git a/mainApp/docs/RELEASE_NOTES.html b/mainApp/docs/RELEASE_NOTES.html index a9a9d04c9..a2658908c 100644 --- a/mainApp/docs/RELEASE_NOTES.html +++ b/mainApp/docs/RELEASE_NOTES.html @@ -9,7 +9,7 @@ - - + + +
-

LPub3D 2.3.10.1.1231 (23 04 2019 12:07:42)

+

LPub3D 2.3.10.1.1232 (23 04 2019 12:09:09)


LPub3D version 2.3.10 addresses blocker fixes for HTML part list sorting
@@ -19,8 +19,9 @@

LPub3D 2.3.10.1.1231 (23 04 2019 12:07:42)

Features, enhancements, fixes and changes

Enhancement - Default placement selector for display submodel #237
Enhancement - Make display submodel instance count optional #236
Enhancement - Add Rebrickable.com to HTML Part List lookup sites #239
Enhancement - Default placement selector for display submodel #237
Enhancement - Make display submodel instance count optional #236
Fix - HTML Part List sort function broken #235
diff --git a/mainApp/extras/ldvMessages.ini b/mainApp/extras/ldvMessages.ini index 18fa45a58..9bfc7cc15 100644 --- a/mainApp/extras/ldvMessages.ini +++ b/mainApp/extras/ldvMessages.ini @@ -878,6 +878,9 @@ PLVInvalidElements = Invalid Elements: %d ; Additionally, if there isn't an image found for a particular part, it gets ; used instead of the image. PLViewOnBricklink =View on Bricklink.com +PLViewOnRebrickable =View on Rebrickable.com +PLViewOnLDrawPartTracker =View on LDraw.org Part Tracker Official Parts +PLViewOnLDrawUnOffPartTracker =View on LDraw.org Part Tracker Unofficial Parts PLVInvalidElement =Invalid Bricklink item number or color code ; The following two entries end up in HTML output. Make sure to leave the links ; intact. diff --git a/mainApp/lpub.cpp b/mainApp/lpub.cpp index 78c197666..ffdfe778f 100644 --- a/mainApp/lpub.cpp +++ b/mainApp/lpub.cpp @@ -1839,33 +1839,33 @@ void Gui::editPovrayConf() parmsWindow->show(); } -void Gui::editLD2BLCodesXRef() +void Gui::editAnnotationStyle() { - QFileInfo fileInfo(QString("%1/extras/%2").arg(Preferences::lpubDataPath,"/" VER_LPUB3D_LD2BLCODESXREF_FILE)); + QFileInfo fileInfo(QString("%1/extras/%2").arg(Preferences::lpubDataPath,Preferences::validAnnotationStyleFile)); if (!fileInfo.exists()) { - if (!Annotations::exportLD2BLCodesXRefFile()) { + if (!Annotations::exportAnnotationStyleFile()) { emit messageSig(LOG_ERROR, QString("Failed to export %1.").arg(fileInfo.absoluteFilePath())); return; } } displayParmsFile(fileInfo.absoluteFilePath()); - parmsWindow->setWindowTitle(tr("LDraw to Bricklink Design ID Cross-reference", - "Edit/add LDraw to Bricklink design ID cross-reference")); + parmsWindow->setWindowTitle(tr("Part Annotation Style reference", + "Edit/add Part Annotation Style reference")); parmsWindow->show(); } -void Gui::editAnnotationStyle() +void Gui::editLD2BLCodesXRef() { - QFileInfo fileInfo(QString("%1/extras/%2").arg(Preferences::lpubDataPath,Preferences::validAnnotationStyleFile)); + QFileInfo fileInfo(QString("%1/extras/%2").arg(Preferences::lpubDataPath,"/" VER_LPUB3D_LD2BLCODESXREF_FILE)); if (!fileInfo.exists()) { - if (!Annotations::exportAnnotationStyleFile()) { + if (!Annotations::exportLD2BLCodesXRefFile()) { emit messageSig(LOG_ERROR, QString("Failed to export %1.").arg(fileInfo.absoluteFilePath())); return; } } displayParmsFile(fileInfo.absoluteFilePath()); - parmsWindow->setWindowTitle(tr("Part Annotation Style reference", - "Edit/add Part Annotation Style reference")); + parmsWindow->setWindowTitle(tr("LDraw to Bricklink Design ID Cross-reference", + "Edit/add LDraw to Bricklink design ID cross-reference")); parmsWindow->show(); } @@ -1899,6 +1899,36 @@ void Gui::editBLColors() parmsWindow->show(); } +void Gui::editLD2RBCodesXRef() +{ + QFileInfo fileInfo(QString("%1/extras/%2").arg(Preferences::lpubDataPath,"/" VER_LPUB3D_LD2RBCODESXREF_FILE)); + if (!fileInfo.exists()) { + if (!Annotations::exportLD2RBCodesXRefFile()) { + emit messageSig(LOG_ERROR, QString("Failed to export %1.").arg(fileInfo.absoluteFilePath())); + return; + } + } + displayParmsFile(fileInfo.absoluteFilePath()); + parmsWindow->setWindowTitle(tr("LDraw to Rebrickable Design ID Cross-reference", + "Edit/add LDraw to Rebrickable design ID cross-reference")); + parmsWindow->show(); +} + +void Gui::editLD2RBColorsXRef() +{ + QFileInfo fileInfo(QString("%1/extras/%2").arg(Preferences::lpubDataPath,VER_LPUB3D_LD2RBCOLORSXREF_FILE)); + if (!fileInfo.exists()) { + if (!Annotations::exportLD2RBColorsXRefFile()) { + emit messageSig(LOG_ERROR, QString("Failed to export %1.").arg(fileInfo.absoluteFilePath())); + return; + } + } + displayParmsFile(fileInfo.absoluteFilePath()); + parmsWindow->setWindowTitle(tr("LDraw to Rebrickable Color Code cross-reference", + "Edit/add LDraw to Rebrickable Color Code cross-reference")); + parmsWindow->show(); +} + void Gui::editBLCodes() { QFileInfo fileInfo(QString("%1/extras/%2").arg(Preferences::lpubDataPath,VER_LPUB3D_BLCODES_FILE)); @@ -3563,18 +3593,26 @@ void Gui::createActions() editPovrayConfAct->setStatusTip(tr("Edit Raytracer (POV-Ray) file access configuration file")); connect(editPovrayConfAct, SIGNAL(triggered()), this, SLOT(editPovrayConf())); - editLD2BLCodesXRefAct = new QAction(QIcon(":/resources/editld2blxref.png"),tr("Edit LDraw to Bricklink Design ID reference"), this); - editLD2BLCodesXRefAct->setStatusTip(tr("Add/Edit LDraw to Bricklink Design ID reference")); - connect(editLD2BLCodesXRefAct, SIGNAL(triggered()), this, SLOT(editLD2BLCodesXRef())); - editAnnotationStyleAct = new QAction(QIcon(":/resources/editstyleref.png"),tr("Edit Part Annotation Style reference"), this); editAnnotationStyleAct->setStatusTip(tr("Add/edit LDraw Design ID, Part Annotation Style, Part Category reference")); connect(editAnnotationStyleAct, SIGNAL(triggered()), this, SLOT(editAnnotationStyle())); + editLD2BLCodesXRefAct = new QAction(QIcon(":/resources/editld2blxref.png"),tr("Edit LDraw to Bricklink Design ID reference"), this); + editLD2BLCodesXRefAct->setStatusTip(tr("Add/Edit LDraw to Bricklink Design ID reference")); + connect(editLD2BLCodesXRefAct, SIGNAL(triggered()), this, SLOT(editLD2BLCodesXRef())); + editLD2BLColorsXRefAct = new QAction(QIcon(":/resources/editld2blxref.png"),tr("Edit LDraw to Bricklink Color eference"), this); editLD2BLColorsXRefAct->setStatusTip(tr("Add/edit LDraw LDConfig to Bricklink Color ID reference")); connect(editLD2BLColorsXRefAct, SIGNAL(triggered()), this, SLOT(editLD2BLColorsXRef())); + editLD2RBCodesXRefAct = new QAction(QIcon(":/resources/editld2rbxref.png"),tr("Edit LDraw to Rebrickable Design ID reference"), this); + editLD2RBCodesXRefAct->setStatusTip(tr("Add/Edit LDraw to Rebrickable Design ID reference")); + connect(editLD2RBCodesXRefAct, SIGNAL(triggered()), this, SLOT(editLD2RBCodesXRef())); + + editLD2RBColorsXRefAct = new QAction(QIcon(":/resources/editld2rbxref.png"),tr("Edit LDraw to Rebrickable Color eference"), this); + editLD2RBColorsXRefAct->setStatusTip(tr("Add/edit LDraw LDConfig to Rebrickable Color ID reference")); + connect(editLD2RBColorsXRefAct, SIGNAL(triggered()), this, SLOT(editLD2RBColorsXRef())); + editBLColorsAct = new QAction(QIcon(":/resources/editld2blxref.png"),tr("Edit Bricklink Color reference"), this); editBLColorsAct->setStatusTip(tr("Add/edit Bricklink Color ID reference")); connect(editBLColorsAct, SIGNAL(triggered()), this, SLOT(editBLColors())); @@ -3682,9 +3720,11 @@ void Gui::enableActions() editLdviewPovIniAct->setEnabled(true); editPovrayIniAct->setEnabled(true); editPovrayConfAct->setEnabled(true); - editLD2BLCodesXRefAct->setEnabled(true); editAnnotationStyleAct->setEnabled(true); + editLD2BLCodesXRefAct->setEnabled(true); editLD2BLColorsXRefAct->setEnabled(true); + editLD2RBCodesXRefAct->setEnabled(true); + editLD2RBColorsXRefAct->setEnabled(true); editBLColorsAct->setEnabled(true); editBLCodesAct->setEnabled(true); editModelFileAct->setEnabled(true); @@ -3765,9 +3805,11 @@ void Gui::disableActions() editLdviewPovIniAct->setEnabled(false); editPovrayIniAct->setEnabled(false); editPovrayConfAct->setEnabled(false); - editLD2BLCodesXRefAct->setEnabled(false); editAnnotationStyleAct->setEnabled(false); + editLD2BLCodesXRefAct->setEnabled(false); editLD2BLColorsXRefAct->setEnabled(false); + editLD2RBCodesXRefAct->setEnabled(false); + editLD2RBColorsXRefAct->setEnabled(false); editBLColorsAct->setEnabled(false); editBLCodesAct->setEnabled(false); editModelFileAct->setEnabled(false); @@ -3977,6 +4019,8 @@ void Gui::createMenus() editorMenu->addAction(editAnnotationStyleAct); editorMenu->addAction(editLD2BLCodesXRefAct); editorMenu->addAction(editLD2BLColorsXRefAct); + editorMenu->addAction(editLD2RBCodesXRefAct); + editorMenu->addAction(editLD2RBColorsXRefAct); editorMenu->addAction(editBLColorsAct); editorMenu->addAction(editBLCodesAct); if (Preferences::ldrawiniFound){ diff --git a/mainApp/lpub.h b/mainApp/lpub.h index 7ad2a7b5b..0e9938360 100644 --- a/mainApp/lpub.h +++ b/mainApp/lpub.h @@ -1219,8 +1219,10 @@ private slots: void editPovrayIni(); void editPovrayConf(); void editLD2BLCodesXRef(); - void editAnnotationStyle(); void editLD2BLColorsXRef(); + void editLD2RBCodesXRef(); + void editLD2RBColorsXRef(); + void editAnnotationStyle(); void editBLColors(); void editBLCodes(); void generateCustomColourPartsList(bool prompt = true); @@ -1471,9 +1473,11 @@ private slots: QAction *editLdviewPovIniAct; QAction *editPovrayIniAct; QAction *editPovrayConfAct; - QAction *editLD2BLCodesXRefAct; QAction *editAnnotationStyleAct; + QAction *editLD2BLCodesXRefAct; QAction *editLD2BLColorsXRefAct; + QAction *editLD2RBCodesXRefAct; + QAction *editLD2RBColorsXRefAct; QAction *editBLColorsAct; QAction *editBLCodesAct; QAction *generateCustomColourPartsAct; diff --git a/mainApp/lpub3d.qrc b/mainApp/lpub3d.qrc index ad82e273f..37e6d0733 100644 --- a/mainApp/lpub3d.qrc +++ b/mainApp/lpub3d.qrc @@ -58,6 +58,7 @@ resources/deletepage.png resources/editdivider.png resources/editld2blxref.png + resources/editld2rbxref.png resources/editldraw.png resources/editldrawcolourparts.png resources/editfreeformannotations.png diff --git a/mainApp/lpub_preferences.cpp b/mainApp/lpub_preferences.cpp index 98ab98efe..5a7b6135b 100644 --- a/mainApp/lpub_preferences.cpp +++ b/mainApp/lpub_preferences.cpp @@ -137,6 +137,8 @@ QString Preferences::legoElementsFile = VER_LPUB3D_LEGOELEMENTS_FILE; QString Preferences::blColorsFile = VER_LPUB3D_BLCOLORS_FILE; QString Preferences::ld2blColorsXRefFile = VER_LPUB3D_LD2BLCOLORSXREF_FILE; QString Preferences::ld2blCodesXRefFile = VER_LPUB3D_LD2BLCODESXREF_FILE; +QString Preferences::ld2rbColorsXRefFile = VER_LPUB3D_LD2RBCOLORSXREF_FILE; +QString Preferences::ld2rbCodesXRefFile = VER_LPUB3D_LD2RBCODESXREF_FILE; bool Preferences::usingDefaultLibrary = true; bool Preferences::portableDistribution = false; @@ -2793,18 +2795,20 @@ void Preferences::setShowParseErrorsPreference(bool b) void Preferences::annotationPreferences() { - bool annoOk[8] = { true, true, true, true, true, true, true, true }; + bool annoOk[10] = { true, true, true, true, true, true, true, true, true, true }; QFileInfo annoInfo; QSettings Settings; titleAnnotationsFile = Settings.value(QString("%1/%2").arg(SETTINGS,"TitleAnnotationFile")).toString(); freeformAnnotationsFile = Settings.value(QString("%1/%2").arg(SETTINGS,"FreeFormAnnotationsFile")).toString(); annotationStyleFile = Settings.value(QString("%1/%2").arg(SETTINGS,"AnnotationStyleFile")).toString(); - blCodesFile = Settings.value(QString("%1/%2").arg(SETTINGS,"BLCodesFile")).toString(); + blCodesFile = Settings.value(QString("%1/%2").arg(SETTINGS,"BLCodesFile")).toString(); legoElementsFile = Settings.value(QString("%1/%2").arg(SETTINGS,"LEGOElementsFile")).toString(); blColorsFile = Settings.value(QString("%1/%2").arg(SETTINGS,"BLColorsFile")).toString(); ld2blColorsXRefFile = Settings.value(QString("%1/%2").arg(SETTINGS,"LD2BLColorsXRefFile")).toString(); ld2blCodesXRefFile = Settings.value(QString("%1/%2").arg(SETTINGS,"LD2BLCodesXRefFile")).toString(); + ld2rbColorsXRefFile = Settings.value(QString("%1/%2").arg(SETTINGS,"LD2RBColorsXRefFile")).toString(); + ld2rbCodesXRefFile = Settings.value(QString("%1/%2").arg(SETTINGS,"LD2RBCodesXRefFile")).toString(); annoInfo.setFile(titleAnnotationsFile); if (! annoInfo.exists()) { @@ -2854,8 +2858,21 @@ void Preferences::annotationPreferences() annoOk[7] = false; } + annoInfo.setFile(ld2rbColorsXRefFile); + if (! annoInfo.exists()) { + Settings.remove(QString("%1/%2").arg(SETTINGS,"LD2RBColorsXRefFile")); + annoOk[8] = false; + } + + annoInfo.setFile(ld2rbCodesXRefFile); + if (! annoInfo.exists()) { + Settings.remove(QString("%1/%2").arg(SETTINGS,"LD2RBCodesXRefFile")); + annoOk[9] = false; + } + if (annoOk[0] && annoOk[1] && annoOk[2] && annoOk[3] && - annoOk[4] && annoOk[5] && annoOk[6] && annoOk[7]) + annoOk[4] && annoOk[5] && annoOk[6] && annoOk[7] && + annoOk[8] && annoOk[9]) return; if (! annoOk[3]) { @@ -2913,6 +2930,28 @@ void Preferences::annotationPreferences() annoOk[7] = true; } + if (! annoOk[8]) { + ld2rbColorsXRefFile = QString("%1/extras/%2").arg(lpubDataPath,VER_LPUB3D_LD2RBCOLORSXREF_FILE); + annoInfo.setFile(ld2rbColorsXRefFile); + if (annoInfo.exists()) { + Settings.setValue(QString("%1/%2").arg(SETTINGS,"LD2RBColorsXRefFile"),ld2rbColorsXRefFile); + } else { + ld2rbColorsXRefFile = QString(); + } + annoOk[8] = true; + } + + if (! annoOk[9]) { + ld2rbCodesXRefFile = QString("%1/extras/%2").arg(lpubDataPath,VER_LPUB3D_LD2RBCODESXREF_FILE); + annoInfo.setFile(ld2rbCodesXRefFile); + if (annoInfo.exists()) { + Settings.setValue(QString("%1/%2").arg(SETTINGS,"LD2RBCodesXRefFile"),ld2rbCodesXRefFile); + } else { + ld2rbCodesXRefFile = QString(); + } + annoOk[9] = true; + } + if (annoOk[0] && annoOk[1] && annoOk[2]) return; diff --git a/mainApp/lpub_preferences.h b/mainApp/lpub_preferences.h index 223a8a20d..24a41e55f 100644 --- a/mainApp/lpub_preferences.h +++ b/mainApp/lpub_preferences.h @@ -150,6 +150,8 @@ class Preferences static QString blColorsFile; static QString ld2blColorsXRefFile; static QString ld2blCodesXRefFile; + static QString ld2rbColorsXRefFile; + static QString ld2rbCodesXRefFile; static QString fadeStepsColourKey; static QString ldrawSearchDirsKey; diff --git a/mainApp/org.trevorsandy.lpub3d.appdata.xml b/mainApp/org.trevorsandy.lpub3d.appdata.xml index aed2193de..4d7d7034c 100644 --- a/mainApp/org.trevorsandy.lpub3d.appdata.xml +++ b/mainApp/org.trevorsandy.lpub3d.appdata.xml @@ -68,7 +68,7 @@ lpub3d23 - +

LPub3D Linux AppImage package

diff --git a/mainApp/resources/editld2rbxref.png b/mainApp/resources/editld2rbxref.png new file mode 100644 index 000000000..426acb986 Binary files /dev/null and b/mainApp/resources/editld2rbxref.png differ diff --git a/mainApp/version.h b/mainApp/version.h index 907e519a2..58ddcd002 100755 --- a/mainApp/version.h +++ b/mainApp/version.h @@ -128,6 +128,8 @@ #define VER_LPUB3D_LEGOELEMENTS_FILE "legoelements.lst" #define VER_LPUB3D_LD2BLCOLORSXREF_FILE "ld2blcolorsxref.lst" #define VER_LPUB3D_LD2BLCODESXREF_FILE "ld2blcodesxref.lst" +#define VER_LPUB3D_LD2RBCOLORSXREF_FILE "ld2rbcolorsxref.lst" +#define VER_LPUB3D_LD2RBCODESXREF_FILE "ld2rbcodesxref.lst" #define VER_LPUB3D_BLCODES_DOWNLOAD_URL "https://trevorsandy.github.io/lpub3d/assets/resources/codes.txt" #define VER_LPUB3D_ONLINE_MANUAL_URL "https://sites.google.com/view/workingwithlpub3d/" @@ -143,6 +145,8 @@ #define VER_COMPANYDOMAIN_STR "https://trevorsandy.github.io/lpub3d/" #define VER_SOURCE_GITHUB_STR "https://github.com/trevorsandy/lpub3d/" +#define VER_REBRICKABLE_KEYS_JSON_URL VER_COMPANYDOMAIN_STR "assets/resources/rebrickablekeys.json" +#define VER_REBRICKABLE_API_URL "https://rebrickable.com/api/v3/lego" #ifdef __GNUC__ #ifdef __MINGW64__