Files
leocad/common/lc_setsdatabasedialog.cpp
T
Leonardo Zide 5f3bfbf9fa Use consistent message severities and simplify ordinary dialogs
Show recoverable rendering, export, library, and network failures as warnings.
Default Blender messages to Warning, keep renderer startup failures Critical,
and remove the duplicate Blender installation failure dialog.

Replace 28 ordinary Blender helper calls with QMessageBox statics while
retaining specialized dialogs with informative text, details, or update
preferences. Preserve confirmation buttons and defaults and suppress static
startup/export messages without a main window. Rename the failed-result
helper to ShowResultError and refresh catalog locations and retired strings.

Validation: Qt 6.10 debug build; catalog coverage for all 2,056 active messages
and existing translation preservation; git diff --check.
2026-10-22 12:29:30 -07:00

268 lines
6.6 KiB
C++

#include "lc_global.h"
#include "lc_setsdatabasedialog.h"
#include "ui_lc_setsdatabasedialog.h"
#include "lc_http.h"
#include "project.h"
lcSetsDatabaseDialog::lcSetsDatabaseDialog(QWidget* Parent)
: QDialog(Parent),
ui(new Ui::lcSetsDatabaseDialog)
{
ui->setupUi(this);
ui->SearchEdit->installEventFilter(this);
mHttpManager = new lcHttpManager(this);
connect(ui->SetsTree, &QTreeWidget::itemDoubleClicked, this, &lcSetsDatabaseDialog::accept);
connect(this, &QDialog::finished, this, &lcSetsDatabaseDialog::Finished);
connect(mHttpManager, &lcHttpManager::DownloadFinished, this, &lcSetsDatabaseDialog::DownloadFinished);
connect(ui->SearchButton, &QPushButton::clicked, this, &lcSetsDatabaseDialog::SearchButtonClicked);
mKeyListReply = mHttpManager->DownloadFile(QLatin1String("https://www.leocad.org/rebrickable.json"));
}
lcSetsDatabaseDialog::~lcSetsDatabaseDialog()
{
delete ui;
}
QString lcSetsDatabaseDialog::GetSetName() const
{
QTreeWidgetItem* Current = ui->SetsTree->currentItem();
return Current ? Current->text(0) : QString();
}
QString lcSetsDatabaseDialog::GetSetDescription() const
{
QTreeWidgetItem* Current = ui->SetsTree->currentItem();
return Current ? Current->text(1) : QString();
}
std::vector<lcSetInventoryItem> lcSetsDatabaseDialog::GetSetInventory() const
{
std::vector<lcSetInventoryItem> Inventory;
if (mInventory.isEmpty())
return Inventory;
QJsonDocument Document = QJsonDocument::fromJson(mInventory);
QJsonObject Root = Document.object();
const QJsonArray Parts = Root["results"].toArray();
for (const QJsonValue& Part : Parts)
{
QJsonObject PartObject = Part.toObject();
QByteArray PartID = PartObject["part"].toObject()["part_num"].toString().toLatin1();
QJsonArray PartIDArray = PartObject["part"].toObject()["external_ids"].toObject()["LDraw"].toArray();
if (!PartIDArray.isEmpty())
PartID = PartIDArray.first().toString().toLatin1();
int Quantity = PartObject["quantity"].toInt();
int ColorCode = 16;
QJsonArray ColorArray = PartObject["color"].toObject()["external_ids"].toObject()["LDraw"].toObject()["ext_ids"].toArray();
if (!ColorArray.isEmpty())
ColorCode = ColorArray.first().toInt();
Inventory.push_back({ PartID, Quantity, ColorCode });
}
return Inventory;
}
bool lcSetsDatabaseDialog::eventFilter(QObject* Object, QEvent* Event)
{
if (Event->type() == QEvent::KeyPress)
{
QKeyEvent* KeyEvent = static_cast<QKeyEvent*>(Event);
int Key = KeyEvent->key();
if (Key == Qt::Key_Return || Key == Qt::Key_Enter)
{
KeyEvent->accept();
SearchButtonClicked();
return true;
}
}
return QDialog::eventFilter(Object, Event);
}
void lcSetsDatabaseDialog::accept()
{
QTreeWidgetItem* Current = ui->SetsTree->currentItem();
if (!Current)
{
QMessageBox::information(this, tr("Set Inventory"), tr("Please select a set from the list."));
return;
}
QString SetNum = Current->text(0);
QProgressDialog ProgressDialog(this);
ProgressDialog.setWindowTitle(tr("Downloading"));
ProgressDialog.setLabelText(tr("Downloading set inventory"));
ProgressDialog.setMaximum(0);
ProgressDialog.setMinimum(0);
ProgressDialog.setValue(0);
ProgressDialog.show();
int KeyIndex = QTime::currentTime().msec() % mKeys.size();
QString DownloadUrl = QString("https://rebrickable.com/api/v3/lego/sets/%1/parts/?key=%2&page_size=1000").arg(SetNum, mKeys[KeyIndex]);
mInventoryReply = mHttpManager->DownloadFile(DownloadUrl);
while (mInventoryReply)
{
QApplication::processEvents();
if (ProgressDialog.wasCanceled())
{
mInventoryReply->abort();
mInventoryReply->deleteLater();
mInventoryReply = nullptr;
return;
}
}
QDialog::accept();
}
void lcSetsDatabaseDialog::Finished(int Result)
{
Q_UNUSED(Result);
if (mKeyListReply)
{
mKeyListReply->abort();
mKeyListReply->deleteLater();
}
}
void lcSetsDatabaseDialog::SearchButtonClicked()
{
QString Keyword = ui->SearchEdit->text();
if (Keyword.isEmpty())
{
QMessageBox::information(this, tr("Search Sets"), tr("Keyword cannot be empty."));
return;
}
QProgressDialog ProgressDialog(this);
ProgressDialog.setWindowTitle(tr("Searching"));
ProgressDialog.setLabelText(tr("Connecting to server"));
ProgressDialog.setMaximum(0);
ProgressDialog.setMinimum(0);
ProgressDialog.setValue(0);
ProgressDialog.show();
while (mKeyListReply)
{
QApplication::processEvents();
if (ProgressDialog.wasCanceled())
return;
}
if (mKeys.isEmpty())
return;
int KeyIndex = QTime::currentTime().msec() % mKeys.size();
QString SearchUrl = QString("https://rebrickable.com/api/v3/lego/sets/?search=%1&key=%2").arg(Keyword, mKeys[KeyIndex]);
mSearchReply = mHttpManager->DownloadFile(SearchUrl);
while (mSearchReply)
{
QApplication::processEvents();
if (ProgressDialog.wasCanceled())
{
mSearchReply->abort();
mSearchReply->deleteLater();
mSearchReply = nullptr;
break;
}
}
}
void lcSetsDatabaseDialog::DownloadFinished(lcHttpReply* Reply)
{
if (Reply == mKeyListReply)
{
if (!Reply->error())
{
QJsonDocument Document = QJsonDocument::fromJson(Reply->readAll());
QJsonObject Root = Document.object();
int Version = Root["Version"].toInt();
if (Version == 1)
{
const QJsonArray Keys = Root["Keys"].toArray();
for (const QJsonValue& Key : Keys)
mKeys.append(Key.toString());
}
}
if (mKeys.isEmpty())
{
QMessageBox::warning(this, tr("Connect to Sets Database"), tr("Error connecting to server."));
close();
}
mKeyListReply = nullptr;
}
else if (Reply == mSearchReply)
{
QTreeWidget* SetsTree = ui->SetsTree;
SetsTree->clear();
if (!Reply->error())
{
QJsonDocument Document = QJsonDocument::fromJson(Reply->readAll());
QJsonObject Root = Document.object();
const QJsonArray Sets = Root["results"].toArray();
for (const QJsonValue& Set : Sets)
{
QJsonObject SetObject = Set.toObject();
QStringList SetInfo;
SetInfo << SetObject["set_num"].toString();
SetInfo << SetObject["name"].toString();
SetInfo << QString::number(SetObject["year"].toInt());
SetInfo << QString::number(SetObject["num_parts"].toInt());
new QTreeWidgetItem(ui->SetsTree, SetInfo);
}
if (!Sets.isEmpty())
{
SetsTree->resizeColumnToContents(0);
SetsTree->resizeColumnToContents(1);
SetsTree->resizeColumnToContents(2);
SetsTree->resizeColumnToContents(3);
SetsTree->setCurrentItem(SetsTree->topLevelItem(0));
}
}
mSearchReply = nullptr;
}
else if (Reply == mInventoryReply)
{
if (!Reply->error())
mInventory = Reply->readAll();
else
QMessageBox::warning(this, tr("Download Set Inventory"), tr("Error downloading set inventory."));
mInventoryReply = nullptr;
}
Reply->deleteLater();
}