1 #include "lc_global.h"
2 #include "lc_setsdatabasedialog.h"
3 #include "ui_lc_setsdatabasedialog.h"
4 #include "lc_http.h"
5
lcSetsDatabaseDialog(QWidget * Parent)6 lcSetsDatabaseDialog::lcSetsDatabaseDialog(QWidget* Parent)
7 : QDialog(Parent),
8 ui(new Ui::lcSetsDatabaseDialog)
9 {
10 ui->setupUi(this);
11 ui->SearchEdit->installEventFilter(this);
12
13 mHttpManager = new lcHttpManager(this);
14
15 connect(ui->SetsTree, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(accept()));
16 connect(this, SIGNAL(finished(int)), this, SLOT(Finished(int)));
17 connect(mHttpManager, SIGNAL(DownloadFinished(lcHttpReply*)), this, SLOT(DownloadFinished(lcHttpReply*)));
18
19 mKeyListReply = mHttpManager->DownloadFile(QLatin1String("https://www.leocad.org/rebrickable.json"));
20 }
21
~lcSetsDatabaseDialog()22 lcSetsDatabaseDialog::~lcSetsDatabaseDialog()
23 {
24 delete ui;
25 }
26
GetSetName() const27 QString lcSetsDatabaseDialog::GetSetName() const
28 {
29 QTreeWidgetItem* Current = ui->SetsTree->currentItem();
30 return Current ? Current->text(0) : QString();
31 }
32
GetSetDescription() const33 QString lcSetsDatabaseDialog::GetSetDescription() const
34 {
35 QTreeWidgetItem* Current = ui->SetsTree->currentItem();
36 return Current ? Current->text(1) : QString();
37 }
38
eventFilter(QObject * Object,QEvent * Event)39 bool lcSetsDatabaseDialog::eventFilter(QObject* Object, QEvent* Event)
40 {
41 if (Event->type() == QEvent::KeyPress)
42 {
43 QKeyEvent* KeyEvent = static_cast<QKeyEvent*>(Event);
44
45 int Key = KeyEvent->key();
46 if (Key == Qt::Key_Return || Key == Qt::Key_Enter)
47 {
48 KeyEvent->accept();
49 on_SearchButton_clicked();
50 return true;
51 }
52 }
53
54 return QDialog::eventFilter(Object, Event);
55 }
56
accept()57 void lcSetsDatabaseDialog::accept()
58 {
59 QTreeWidgetItem* Current = ui->SetsTree->currentItem();
60 if (!Current)
61 {
62 QMessageBox::information(this, "LeoCAD", tr("Please select a set from the list."));
63 return;
64 }
65
66 QString SetNum = Current->text(0);
67
68 QProgressDialog ProgressDialog(this);
69 ProgressDialog.setWindowTitle(tr("Downloading"));
70 ProgressDialog.setLabelText(tr("Downloading set inventory"));
71 ProgressDialog.setMaximum(0);
72 ProgressDialog.setMinimum(0);
73 ProgressDialog.setValue(0);
74 ProgressDialog.show();
75
76 int KeyIndex = QTime::currentTime().msec() % mKeys.size();
77 QString DownloadUrl = QString("https://rebrickable.com/api/v3/lego/sets/%1/parts/?key=%2").arg(SetNum, mKeys[KeyIndex]);
78
79 mInventoryReply = mHttpManager->DownloadFile(DownloadUrl);
80
81 while (mInventoryReply)
82 {
83 QApplication::processEvents();
84
85 if (ProgressDialog.wasCanceled())
86 {
87 mInventoryReply->abort();
88 mInventoryReply->deleteLater();
89 mInventoryReply = nullptr;
90 return;
91 }
92 }
93
94 QDialog::accept();
95 }
96
Finished(int Result)97 void lcSetsDatabaseDialog::Finished(int Result)
98 {
99 Q_UNUSED(Result);
100
101 if (mKeyListReply)
102 {
103 mKeyListReply->abort();
104 mKeyListReply->deleteLater();
105 }
106 }
107
on_SearchButton_clicked()108 void lcSetsDatabaseDialog::on_SearchButton_clicked()
109 {
110 QString Keyword = ui->SearchEdit->text();
111
112 if (Keyword.isEmpty())
113 {
114 QMessageBox::information(this, "LeoCAD", tr("Keyword cannot be empty."));
115 return;
116 }
117
118 QProgressDialog ProgressDialog(this);
119 ProgressDialog.setWindowTitle(tr("Searching"));
120 ProgressDialog.setLabelText(tr("Connecting to server"));
121 ProgressDialog.setMaximum(0);
122 ProgressDialog.setMinimum(0);
123 ProgressDialog.setValue(0);
124 ProgressDialog.show();
125
126 while (mKeyListReply)
127 {
128 QApplication::processEvents();
129
130 if (ProgressDialog.wasCanceled())
131 return;
132 }
133
134 if (mKeys.isEmpty())
135 return;
136
137 int KeyIndex = QTime::currentTime().msec() % mKeys.size();
138 QString SearchUrl = QString("https://rebrickable.com/api/v3/lego/sets/?search=%1&key=%2").arg(Keyword, mKeys[KeyIndex]);
139
140 mSearchReply = mHttpManager->DownloadFile(SearchUrl);
141
142 while (mSearchReply)
143 {
144 QApplication::processEvents();
145
146 if (ProgressDialog.wasCanceled())
147 {
148 mSearchReply->abort();
149 mSearchReply->deleteLater();
150 mSearchReply = nullptr;
151 break;
152 }
153 }
154 }
155
DownloadFinished(lcHttpReply * Reply)156 void lcSetsDatabaseDialog::DownloadFinished(lcHttpReply* Reply)
157 {
158 if (Reply == mKeyListReply)
159 {
160 if (!Reply->error())
161 {
162 QJsonDocument Document = QJsonDocument::fromJson(Reply->readAll());
163 QJsonObject Root = Document.object();
164
165 int Version = Root["Version"].toInt();
166
167 if (Version == 1)
168 {
169 QJsonArray Keys = Root["Keys"].toArray();
170
171 for (const QJsonValue& Key : Keys)
172 mKeys.append(Key.toString());
173 }
174 }
175
176 if (mKeys.isEmpty())
177 {
178 QMessageBox::information(this, "LeoCAD", tr("Error connecting to server."));
179 close();
180 }
181
182 mKeyListReply = nullptr;
183 }
184 else if (Reply == mSearchReply)
185 {
186 QTreeWidget* SetsTree = ui->SetsTree;
187 SetsTree->clear();
188
189 if (!Reply->error())
190 {
191 QJsonDocument Document = QJsonDocument::fromJson(Reply->readAll());
192 QJsonObject Root = Document.object();
193
194 QJsonArray Sets = Root["results"].toArray();
195 for (const QJsonValue& Set : Sets)
196 {
197 QJsonObject SetObject = Set.toObject();
198 QStringList SetInfo;
199
200 SetInfo << SetObject["set_num"].toString();
201 SetInfo << SetObject["name"].toString();
202 SetInfo << QString::number(SetObject["year"].toInt());
203 SetInfo << QString::number(SetObject["num_parts"].toInt());
204
205 new QTreeWidgetItem(ui->SetsTree, SetInfo);
206 }
207
208 if (!Sets.isEmpty())
209 {
210 SetsTree->resizeColumnToContents(0);
211 SetsTree->resizeColumnToContents(1);
212 SetsTree->resizeColumnToContents(2);
213 SetsTree->resizeColumnToContents(3);
214 SetsTree->setCurrentItem(SetsTree->topLevelItem(0));
215 }
216 }
217
218 mSearchReply = nullptr;
219 }
220 else if (Reply == mInventoryReply)
221 {
222 if (!Reply->error())
223 mInventory = Reply->readAll();
224 else
225 QMessageBox::information(this, "LeoCAD", tr("Error downloading set inventory."));
226
227 mInventoryReply = nullptr;
228 }
229
230 Reply->deleteLater();
231 }
232