From 44a89dc0ac7f44e1094488c8cc33bd6774fb5aac Mon Sep 17 00:00:00 2001 From: Trevor SANDY Date: Tue, 23 Apr 2019 12:09:08 +0200 Subject: [PATCH] Add Rebrickable.com and to HTML Part List lookup sites #239 --- builds/linux/obs/alldeps/PKGBUILD | 2 +- builds/linux/obs/alldeps/debian/changelog | 6 +- builds/linux/obs/alldeps/debian/lpub3d.dsc | 2 +- builds/linux/obs/alldeps/lpub3d.spec | 4 +- builds/utilities/ci/secure/.secrets.tar.enc | Bin 10256 -> 10256 bytes builds/utilities/version.info | 2 +- ldvlib/LDVQt/LDVHtmlInventory.cpp | 178 +++++++++-- ldvlib/LDVQt/LDVHtmlInventory.h | 115 +++---- ldvlib/LDVQt/LDVPartList.ui | 54 +++- ldvlib/LDVQt/LDVQt.pro | 4 +- ldvlib/LDVQt/LDVWidget.cpp | 229 ++++++++++++++ ldvlib/LDVQt/LDVWidget.h | 31 +- ldvlib/LDVQt/LDVWidgetDefaultKeys.h | 1 + ldvlib/LDVQt/LDVWidgetMessages.ini | 3 + ldvlib/LDVQt/LDViewPartList.cpp | 233 ++++++++------- ldvlib/LDVQt/LDViewPartList.h | 24 +- mainApp/annotations.cpp | 314 +++++++++++++++++++- mainApp/annotations.h | 10 + mainApp/docs/README.txt | 2 +- mainApp/docs/RELEASE_NOTES.html | 7 +- mainApp/extras/ldvMessages.ini | 3 + mainApp/lpub.cpp | 76 ++++- mainApp/lpub.h | 8 +- mainApp/lpub3d.qrc | 1 + mainApp/lpub_preferences.cpp | 45 ++- mainApp/lpub_preferences.h | 2 + mainApp/org.trevorsandy.lpub3d.appdata.xml | 2 +- mainApp/resources/editld2rbxref.png | Bin 0 -> 4717 bytes mainApp/version.h | 4 + 29 files changed, 1117 insertions(+), 245 deletions(-) create mode 100644 mainApp/resources/editld2rbxref.png 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 9cb0ec616c2d9c1f6fe8da395712763e199acc59..552e2776aec3dcbbfe28a9bb29a46044f22b64cf 100644 GIT binary patch literal 10256 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 WNQ8USi?y{> #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 0000000000000000000000000000000000000000..426acb9867a2c930c690a8af369bbf84594bd129 GIT binary patch literal 4717 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 literal 0 HcmV?d00001 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__