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