Root/
1 | /* |
2 | * Copyright 2010-2011 Niels Kummerfeldt <niels.kummerfeldt@tu-harburg.de> |
3 | * |
4 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License as published by |
6 | * the Free Software Foundation; either version 2 of the License, or |
7 | * (at your option) any later version. |
8 | * |
9 | * This program is distributed in the hope that it will be useful, |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. |
13 | * |
14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write to the Free Software |
16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | * Boston, MA 02110-1301 USA |
18 | */ |
19 | |
20 | #include "downloadwidget.h" |
21 | |
22 | #include <cmath> |
23 | |
24 | #include <QtCore/QDebug> |
25 | #include <QtCore/QDir> |
26 | #include <QtCore/QFile> |
27 | #include <QtCore/QSettings> |
28 | #include <QtGui/QLayout> |
29 | #include <QtNetwork/QNetworkRequest> |
30 | |
31 | DownloadWidget::DownloadWidget(QWidget *parent) |
32 | : QWidget(parent), |
33 | m_manager(new QNetworkAccessManager(this)), |
34 | m_downloadMode(Tiles), |
35 | m_tabWidget(new QTabWidget(this)), |
36 | m_dlProgress(new QProgressBar(this)), |
37 | m_startButton(new QPushButton("&Start download", this)), |
38 | m_backButton(new QPushButton("&Back", this)), |
39 | m_startLevel(0), |
40 | m_dlRect(), |
41 | m_dlList(), |
42 | m_currentDownload(0), |
43 | m_prefix("OSM"), |
44 | m_up(new QLabel("N 0", this)), |
45 | m_left(new QLabel("E 0", this)), |
46 | m_right(new QLabel("E 0", this)), |
47 | m_bottom(new QLabel("N 0", this)), |
48 | m_levelSpinBox(new QSpinBox(this)), |
49 | m_prefixInput(new QLineEdit(this)), |
50 | m_skipExisting(new QCheckBox("S&kip already downloaded tiles", this)), |
51 | m_poiTypes(new QListWidget(this)), |
52 | m_makePOILayer(new QCheckBox("&Load file after download", this)), |
53 | m_destFilename(new QLineEdit(QDir::homePath()+"/pois.osm", this)), |
54 | m_packageList(new QListWidget(this)), |
55 | m_destDir(new QLineEdit(QDir::homePath(), this)) |
56 | { |
57 | QGridLayout *layout = new QGridLayout(this); |
58 | layout->setContentsMargins(0, 0, 0, 0); |
59 | layout->setRowStretch(0, 1); |
60 | |
61 | layout->addWidget(m_tabWidget, 0, 0, 1, 2); |
62 | |
63 | m_dlProgress->hide(); |
64 | layout->addWidget(m_dlProgress, 1, 0, 1, 2); |
65 | |
66 | m_startButton->setIcon(QIcon(":ok.png")); |
67 | connect(m_startButton, SIGNAL(clicked()), this, SLOT(startDownload())); |
68 | layout->addWidget(m_startButton, 2, 0); |
69 | |
70 | m_backButton->setIcon(QIcon(":cancel.png")); |
71 | connect(m_backButton, SIGNAL(clicked()), this, SIGNAL(back())); |
72 | layout->addWidget(m_backButton, 2, 1); |
73 | |
74 | QWidget *widget = new QWidget(this); |
75 | layout = new QGridLayout(widget); |
76 | layout->setContentsMargins(0, 0, 0, 0); |
77 | layout->setRowStretch(1, 1); |
78 | |
79 | m_up->setAlignment(Qt::AlignHCenter); |
80 | m_left->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); |
81 | m_right->setAlignment(Qt::AlignRight | Qt::AlignVCenter); |
82 | m_bottom->setAlignment(Qt::AlignHCenter); |
83 | layout->addWidget(m_up, 0, 0, 1, 4); |
84 | layout->addWidget(m_left, 1, 0); |
85 | layout->addWidget(m_right, 1, 3); |
86 | layout->addWidget(m_bottom, 2, 0, 1, 4); |
87 | |
88 | QLabel *label = new QLabel(this); |
89 | label->setFrameShape(QLabel::Box); |
90 | layout->addWidget(label, 1, 1, 1, 2); |
91 | |
92 | label = new QLabel("Download up to level:", this); |
93 | layout->addWidget(label, 3, 0, 1, 2); |
94 | |
95 | m_levelSpinBox->setRange(0, 18); |
96 | layout->addWidget(m_levelSpinBox, 3, 2, 1, 2); |
97 | |
98 | label = new QLabel("Download into directory:", this); |
99 | layout->addWidget(label, 4, 0, 1, 2); |
100 | |
101 | m_prefixInput->setText(m_prefix); |
102 | layout->addWidget(m_prefixInput, 4, 2, 1, 2); |
103 | |
104 | m_skipExisting->setChecked(false); |
105 | layout->addWidget(m_skipExisting, 5, 0, 1, 0); |
106 | |
107 | m_tabWidget->addTab(widget, "&Tiles"); |
108 | |
109 | widget = new QWidget(this); |
110 | layout = new QGridLayout(widget); |
111 | layout->setContentsMargins(0, 0, 0, 0); |
112 | layout->setRowStretch(0, 1); |
113 | |
114 | QSettings set(QDir::homePath()+"/Maps/nanomap.conf", QSettings::NativeFormat); |
115 | set.beginGroup("poi"); |
116 | QString iconPath = set.value("iconpath", "/usr/share/NanoMap/icons").toString(); |
117 | set.endGroup(); |
118 | QDir iconDir(iconPath); |
119 | QStringList icons = iconDir.entryList(QStringList() << "*.png"); |
120 | foreach (const QString &icon, icons) { |
121 | QString name = icon; |
122 | name.remove(".png"); |
123 | QListWidgetItem *item = new QListWidgetItem(QIcon(iconPath+"/"+icon), name); |
124 | m_poiTypes->addItem(item); |
125 | } |
126 | //m_poiTypes->setSelectionMode(QAbstractItemView::MultiSelection); |
127 | layout->addWidget(m_poiTypes, 0, 0, 1, 4); |
128 | |
129 | m_makePOILayer->setChecked(true); |
130 | layout->addWidget(m_makePOILayer , 1, 0, 1, 4); |
131 | |
132 | label = new QLabel("Save to:", this); |
133 | layout->addWidget(label , 2, 0); |
134 | |
135 | layout->addWidget(m_destFilename, 2, 1, 1, 3); |
136 | |
137 | m_tabWidget->addTab(widget, "&Points of Interest"); |
138 | |
139 | widget = new QWidget(this); |
140 | layout = new QGridLayout(widget); |
141 | layout->setContentsMargins(0, 0, 0, 0); |
142 | layout->setRowStretch(1, 1); |
143 | |
144 | label = new QLabel("This Page does not work yet!!!", this); |
145 | label->setAlignment(Qt::AlignCenter); |
146 | layout->addWidget(label, 0, 0, 1, 2); |
147 | |
148 | QPushButton *updateList = new QPushButton("Update list", this); |
149 | connect(updateList, SIGNAL(clicked()), this, SLOT(updateSourceList())); |
150 | layout->addWidget(updateList, 0, 2); |
151 | |
152 | layout->addWidget(m_packageList, 1, 0, 1, 3); |
153 | |
154 | label = new QLabel("Download into directory:", this); |
155 | layout->addWidget(label, 2, 0); |
156 | |
157 | layout->addWidget(m_destDir, 2, 1, 1, 2); |
158 | |
159 | m_tabWidget->addTab(widget, "&Routing data"); |
160 | |
161 | connect(m_manager, SIGNAL(finished(QNetworkReply*)), |
162 | this, SLOT(replyFinished(QNetworkReply*))); |
163 | |
164 | resize(320, 240); |
165 | } |
166 | |
167 | DownloadWidget::~DownloadWidget() |
168 | { |
169 | } |
170 | |
171 | void DownloadWidget::setStartLevel(int level) |
172 | { |
173 | if (level >= 17) { |
174 | level = 17; |
175 | } |
176 | m_startLevel = level + 1; |
177 | m_levelSpinBox->setMinimum(level + 1); |
178 | m_levelSpinBox->setValue(level + 1); |
179 | } |
180 | |
181 | void DownloadWidget::setDownloadRect(const QRectF &rect) |
182 | { |
183 | m_dlRect = rect; |
184 | m_up->setText(lat2string(rect.bottom())); |
185 | m_left->setText(lon2string(rect.left())); |
186 | m_right->setText(lon2string(rect.right())); |
187 | m_bottom->setText(lat2string(rect.top())); |
188 | } |
189 | |
190 | void DownloadWidget::startDownload() |
191 | { |
192 | switch (m_tabWidget->currentIndex()) { |
193 | case 0: |
194 | m_downloadMode = Tiles; |
195 | startDownloadTiles(); |
196 | break; |
197 | case 1: |
198 | m_downloadMode = POIs; |
199 | startDownloadPOIs(); |
200 | break; |
201 | case 2: |
202 | m_downloadMode = Packages; |
203 | startDownloadPackages(); |
204 | break; |
205 | } |
206 | } |
207 | |
208 | void DownloadWidget::replyFinished(QNetworkReply *reply) |
209 | { |
210 | switch (m_downloadMode) { |
211 | case Tiles: |
212 | replyFinishedTiles(reply); |
213 | break; |
214 | case Packages: |
215 | replyFinishedPackages(reply); |
216 | break; |
217 | case POIs: |
218 | replyFinishedPOIs(reply); |
219 | break; |
220 | case SourceList: |
221 | if (reply->error() == QNetworkReply::NoError) { |
222 | QStringList list = QString::fromUtf8(reply->readAll().constData()).split("\n"); |
223 | foreach (const QString &pkg, list) { |
224 | QListWidgetItem *item = new QListWidgetItem(pkg.section('@', 0, 0)); |
225 | item->setData(Qt::UserRole, QVariant(pkg.section('@', 1))); |
226 | m_packageList->addItem(item); |
227 | } |
228 | } |
229 | break; |
230 | } |
231 | reply->deleteLater(); |
232 | } |
233 | |
234 | void DownloadWidget::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) |
235 | { |
236 | m_dlProgress->setRange(0, bytesTotal); |
237 | m_dlProgress->setValue(bytesReceived); |
238 | } |
239 | |
240 | void DownloadWidget::saveDownload() |
241 | { |
242 | if (m_currentDownload->error() != QNetworkReply::NoError) { |
243 | return; |
244 | } |
245 | QString path = m_currentDownload->url().path().section("/", -2); |
246 | QByteArray a = m_currentDownload->readAll(); |
247 | |
248 | QFile file(m_destDir->text()+"/"+path); |
249 | if (file.open(QFile::WriteOnly)) { |
250 | file.write(a); |
251 | } |
252 | } |
253 | |
254 | void DownloadWidget::updateSourceList() |
255 | { |
256 | m_downloadMode = SourceList; |
257 | m_manager->get(QNetworkRequest(QUrl("http://host.domain.tld/path/source.list"))); |
258 | } |
259 | |
260 | void DownloadWidget::startDownloadTiles() |
261 | { |
262 | m_prefix = m_prefixInput->text(); |
263 | m_dlProgress->setValue(0); |
264 | for (int level = m_startLevel; level <= m_levelSpinBox->value(); ++level) { |
265 | int max = pow(2, level) - 1; |
266 | int minX = qBound(0, lon2tilex(m_dlRect.left(), level), max); |
267 | int minY = qBound(0, lat2tiley(m_dlRect.bottom(), level), max); |
268 | int maxX = qBound(0, lon2tilex(m_dlRect.right(), level), max); |
269 | int maxY = qBound(0, lat2tiley(m_dlRect.top(), level), max); |
270 | for (int x = minX; x <= maxX; ++x) { |
271 | for (int y = minY; y <= maxY; ++y) { |
272 | m_dlList << QString("http://tile.openstreetmap.org/%1/%2/%3.png").arg(level).arg(x).arg(y); |
273 | } |
274 | } |
275 | } |
276 | if (!m_dlList.isEmpty()) { |
277 | m_dlProgress->show(); |
278 | m_dlProgress->setRange(0, m_dlList.count()); |
279 | m_dlProgress->setFormat("%v / %m"); |
280 | m_tabWidget->setEnabled(false); |
281 | m_startButton->setEnabled(false); |
282 | m_backButton->setEnabled(false); |
283 | QUrl url(m_dlList.takeFirst()); |
284 | m_manager->get(QNetworkRequest(url)); |
285 | } |
286 | } |
287 | |
288 | void DownloadWidget::replyFinishedTiles(QNetworkReply *reply) |
289 | { |
290 | if (m_dlList.isEmpty()) { |
291 | m_dlProgress->hide(); |
292 | m_tabWidget->setEnabled(true); |
293 | m_startButton->setEnabled(true); |
294 | m_backButton->setEnabled(true); |
295 | } |
296 | if (reply->error() == QNetworkReply::NoError) { |
297 | QString path = reply->url().path(); |
298 | int level = path.section('/', 1, 1).toInt(); |
299 | int x = path.section('/', 2, 2).toInt(); |
300 | |
301 | QDir base(QDir::homePath()+"/Maps/"+m_prefix); |
302 | base.mkpath(QString("%1/%2").arg(level).arg(x)); |
303 | |
304 | QByteArray data = reply->readAll(); |
305 | if (!data.isEmpty()) { |
306 | QFile file(QDir::homePath()+"/Maps/"+m_prefix+path); |
307 | if (file.open(QFile::WriteOnly)) { |
308 | file.write(data); |
309 | } |
310 | } |
311 | while (!m_dlList.isEmpty()) { |
312 | QUrl url(m_dlList.takeFirst()); |
313 | if (QFile::exists(QDir::homePath()+"/Maps/"+m_prefix+url.path()) && |
314 | m_skipExisting->isChecked()) { |
315 | int n = m_dlProgress->value(); |
316 | m_dlProgress->setValue(n+1); |
317 | } else { |
318 | m_manager->get(QNetworkRequest(url)); |
319 | break; |
320 | } |
321 | } |
322 | int n = m_dlProgress->value(); |
323 | m_dlProgress->setValue(n+1); |
324 | } |
325 | } |
326 | |
327 | void DownloadWidget::startDownloadPOIs() |
328 | { |
329 | QListWidgetItem *item = m_poiTypes->currentItem(); |
330 | if (!item) { |
331 | return; |
332 | } |
333 | QString key = item->text().section("-", 0, 0); |
334 | QString value = item->text().section("-", 1); |
335 | QString keyValue = QString("[%1=%2]").arg(key, value); |
336 | QString bbox = QString("[bbox=%1,%2,%3,%4]").arg(m_dlRect.left()).arg(m_dlRect.top()) |
337 | .arg(m_dlRect.right()).arg(m_dlRect.bottom()); |
338 | |
339 | QString baseUrl("http://azure.openstreetmap.org/xapi/api/0.6/node"); |
340 | QUrl url(baseUrl+keyValue+bbox); |
341 | QNetworkReply *reply = m_manager->get(QNetworkRequest(url)); |
342 | connect(reply, SIGNAL(downloadProgress(qint64, qint64)), |
343 | this, SLOT(downloadProgress(qint64, qint64))); |
344 | |
345 | m_dlProgress->show(); |
346 | m_dlProgress->setValue(0); |
347 | m_dlProgress->setFormat("%p%"); |
348 | m_tabWidget->setEnabled(false); |
349 | m_startButton->setEnabled(false); |
350 | m_backButton->setEnabled(false); |
351 | } |
352 | |
353 | void DownloadWidget::replyFinishedPOIs(QNetworkReply *reply) |
354 | { |
355 | m_dlProgress->hide(); |
356 | m_tabWidget->setEnabled(true); |
357 | m_startButton->setEnabled(true); |
358 | m_backButton->setEnabled(true); |
359 | |
360 | if (reply->error() != QNetworkReply::NoError) { |
361 | return; |
362 | } |
363 | QByteArray data = reply->readAll(); |
364 | if (data.isEmpty()) { |
365 | return; |
366 | } |
367 | QFile file(m_destFilename->text()); |
368 | if (!file.open(QFile::WriteOnly)) { |
369 | return; |
370 | } |
371 | file.write(data); |
372 | file.close(); |
373 | |
374 | if (m_makePOILayer->isChecked()) { |
375 | emit loadFile(m_destFilename->text(), m_poiTypes->currentItem()->text().section("-", 1)); |
376 | } |
377 | } |
378 | |
379 | void DownloadWidget::startDownloadPackages() |
380 | { |
381 | QListWidgetItem *item = m_packageList->currentItem(); |
382 | if (!item) { |
383 | return; |
384 | } |
385 | |
386 | QString baseUrl = item->data(Qt::UserRole).toString(); |
387 | m_dlList << baseUrl+"Contraction Hierarchies_config"; |
388 | m_dlList << baseUrl+"Contraction Hierarchies_edges"; |
389 | m_dlList << baseUrl+"Contraction Hierarchies_names"; |
390 | m_dlList << baseUrl+"Contraction Hierarchies_paths"; |
391 | m_dlList << baseUrl+"Contraction Hierarchies_types"; |
392 | m_dlList << baseUrl+"GPSGrid_config"; |
393 | m_dlList << baseUrl+"GPSGrid_grid"; |
394 | m_dlList << baseUrl+"GPSGrid_index_1"; |
395 | m_dlList << baseUrl+"GPSGrid_index_2"; |
396 | m_dlList << baseUrl+"GPSGrid_index_3"; |
397 | m_dlList << baseUrl+"OSM Renderer_settings"; |
398 | m_dlList << baseUrl+"plugins.ini"; |
399 | m_dlList << baseUrl+"Unicode Tournament Trie_main"; |
400 | m_dlList << baseUrl+"Unicode Tournament Trie_sub"; |
401 | m_dlList << baseUrl+"Unicode Tournament Trie_ways"; |
402 | |
403 | m_currentDownload = m_manager->get(QNetworkRequest(QUrl(m_dlList.takeFirst()))); |
404 | connect(m_currentDownload, SIGNAL(downloadProgress(qint64, qint64)), |
405 | this, SLOT(downloadProgress(qint64, qint64))); |
406 | connect(m_currentDownload, SIGNAL(readReady()), |
407 | this, SLOT(saveDownload())); |
408 | |
409 | m_dlProgress->show(); |
410 | m_dlProgress->setValue(0); |
411 | m_dlProgress->setFormat("%p%"); |
412 | m_tabWidget->setEnabled(false); |
413 | m_startButton->setEnabled(false); |
414 | m_backButton->setEnabled(false); |
415 | } |
416 | |
417 | void DownloadWidget::replyFinishedPackages(QNetworkReply *reply) |
418 | { |
419 | Q_UNUSED(reply) |
420 | |
421 | if (m_dlList.isEmpty()) { |
422 | m_dlProgress->hide(); |
423 | m_tabWidget->setEnabled(true); |
424 | m_startButton->setEnabled(true); |
425 | m_backButton->setEnabled(true); |
426 | } else { |
427 | QUrl url(m_dlList.takeFirst()); |
428 | m_currentDownload = m_manager->get(QNetworkRequest(url)); |
429 | connect(m_currentDownload, SIGNAL(downloadProgress(qint64, qint64)), |
430 | this, SLOT(downloadProgress(qint64, qint64))); |
431 | connect(m_currentDownload, SIGNAL(readReady()), |
432 | this, SLOT(saveDownload())); |
433 | } |
434 | } |
435 | |
436 | QString DownloadWidget::lon2string(qreal lon) |
437 | { |
438 | QString result; |
439 | |
440 | if (lon < 0) { |
441 | result = "W "; |
442 | lon *= -1; |
443 | } else { |
444 | result = "E "; |
445 | } |
446 | result.append(QString::number(lon)); |
447 | |
448 | return result; |
449 | } |
450 | |
451 | QString DownloadWidget::lat2string(qreal lat) |
452 | { |
453 | QString result; |
454 | |
455 | if (lat < 0) { |
456 | result = "S "; |
457 | lat *= -1; |
458 | } else { |
459 | result = "N "; |
460 | } |
461 | result.append(QString::number(lat)); |
462 | |
463 | return result; |
464 | } |
465 | |
466 | int DownloadWidget::lon2tilex(qreal lon, int z) |
467 | { |
468 | return (int)(floor((lon + 180.0) / 360.0 * pow(2.0, z))); |
469 | } |
470 | |
471 | int DownloadWidget::lat2tiley(qreal lat, int z) |
472 | { |
473 | return (int)(floor((1.0 - log(tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * pow(2.0, z))); |
474 | } |
475 | |
476 |
Branches:
master