1 #include "DownloadOSM.h"
2
3 #include "MainWindow.h"
4 #include "MapView.h"
5 #include "Coord.h"
6 #include "ImportGPX.h"
7 #include "ImportExportGdal.h"
8 #include "ImportOSM.h"
9 #include "Document.h"
10 #include "Layer.h"
11 #include "Feature.h"
12 #include "TrackSegment.h"
13 #include "SlippyMapWidget.h"
14 #include "MerkaartorPreferences.h"
15 #include "OsmLink.h"
16
17 #include "IProgressWindow.h"
18
19 #include <ui_DownloadMapDialog.h>
20
21 #include <QBuffer>
22 #include <QTimer>
23 #include <QComboBox>
24 #include <QMessageBox>
25 #include <QProgressBar>
26 #include <QLabel>
27 #include <QProgressDialog>
28 #include <QStatusBar>
29 #include <QInputDialog>
30
31 /* DOWNLOADER */
32
Downloader(const QString & aUser,const QString & aPwd)33 Downloader::Downloader(const QString& aUser, const QString& aPwd)
34 : User(aUser), Password(aPwd),
35 currentReply(0),Error(false), AnimatorLabel(0), AnimatorBar(0), AnimationTimer(0)
36 {
37 //IdAuth = Request.setUser(User.toUtf8(), Password.toUtf8());
38 connect(&netManager,SIGNAL(finished(QNetworkReply*)),this,SLOT(on_requestFinished(QNetworkReply*)));
39 connect(&netManager,SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this,SLOT(on_authenticationRequired(QNetworkReply*,QAuthenticator*)));
40 }
41
42
animate()43 void Downloader::animate()
44 {
45 if (AnimatorBar && AnimationTimer)
46 AnimatorBar->setValue((AnimatorBar->value()+1) % AnimatorBar->maximum());
47 }
48
setAnimator(QProgressDialog * anAnimator,QLabel * anAnimatorLabel,QProgressBar * anAnimatorBar,bool anAnimate)49 void Downloader::setAnimator(QProgressDialog *anAnimator, QLabel* anAnimatorLabel, QProgressBar* anAnimatorBar, bool anAnimate)
50 {
51 delete AnimationTimer;
52
53 AnimatorLabel = anAnimatorLabel;
54 AnimatorBar = anAnimatorBar;
55 if (AnimatorBar && anAnimate)
56 {
57 AnimationTimer = new QTimer(this);
58 connect(AnimationTimer,SIGNAL(timeout()),this,SLOT(animate()));
59 }
60 if (AnimatorBar)
61 {
62 AnimatorBar->setValue(0);
63 if (anAnimator)
64 connect(anAnimator,SIGNAL(canceled()),this,SLOT(on_Cancel_clicked()));
65 qApp->processEvents();
66 }
67 }
68
on_Cancel_clicked()69 void Downloader::on_Cancel_clicked()
70 {
71 Error = true;
72 if (Loop.isRunning())
73 Loop.exit(QDialog::Rejected);
74 }
75
76 #include "QTextBrowser"
77
go(const QUrl & url)78 bool Downloader::go(const QUrl& url) {
79 return request("GET", url, QString());
80 }
81
request(const QString & theMethod,const QUrl & url,const QString & theData)82 bool Downloader::request(const QString& theMethod, const QUrl& url, const QString& theData) {
83 if (Error) return false;
84
85 qDebug() << "Downloader::request:" << url;
86
87 netManager.setProxy(M_PREFS->getProxy(url));
88 QNetworkRequest req(url);
89
90 req.setRawHeader(QByteArray("Content-Type"), QByteArray("text/xml"));
91 req.setRawHeader(QByteArray("User-Agent"), USER_AGENT.toLatin1());
92
93 QByteArray dataArray(theData.toUtf8());
94 QBuffer dataBuffer(&dataArray);
95 currentReply = netManager.sendCustomRequest(req, theMethod.toLatin1(), &dataBuffer);
96
97 if (AnimationTimer) {
98 AnimationTimer->start(200);
99 connect(currentReply,SIGNAL(downloadProgress(qint64, qint64)), this,SLOT(progress(qint64, qint64)));
100 }
101
102 if (Loop.exec() == QDialog::Rejected)
103 return false;
104
105 if (AnimationTimer)
106 SAFE_DELETE(AnimationTimer);
107
108 /* Test for redirections */
109 QVariant redir = currentReply->attribute(QNetworkRequest::RedirectionTargetAttribute);
110 if (redir.isValid()) {
111 LocationText = redir.toString();
112 if (!LocationText.isEmpty()) {
113 QUrl newUrl(LocationText);
114 return request(theMethod, newUrl, theData);
115 }
116 }
117
118 /* We will log the error, but reporting shall be done at the call site. */
119 if (currentReply->error()) {
120 qDebug() << "Downloader::request: received response with code"
121 << currentReply->error() << ", message" << currentReply->errorString();
122 }
123
124
125 /* Read the data */
126 Content = currentReply->readAll();
127 Result = currentReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
128 ResultText = currentReply->errorString();
129 ErrorText = currentReply->rawHeader("Error");
130 return !Error;
131 }
132
on_authenticationRequired(QNetworkReply * reply,QAuthenticator * auth)133 void Downloader::on_authenticationRequired( QNetworkReply *reply, QAuthenticator *auth) {
134 static QNetworkReply *lastReply = NULL;
135
136 /* Only provide authentication the first time we see this reply, to avoid
137 * infinite loop providing the same credentials. */
138 if (lastReply != reply) {
139 lastReply = reply;
140 qDebug() << "Downloader authentication required and provided.";
141 auth->setUser(User);
142 auth->setPassword(Password);
143 }
144 }
145
content()146 QByteArray& Downloader::content()
147 {
148 return Content;
149 }
150
on_requestFinished(QNetworkReply * reply)151 void Downloader::on_requestFinished( QNetworkReply *reply)
152 {
153 if (reply->error())
154 Error = true;
155 if ( (reply == currentReply) && Loop.isRunning() )
156 Loop.exit(QDialog::Accepted);
157 }
158
progress(qint64 done,qint64 total)159 void Downloader::progress(qint64 done, qint64 total)
160 {
161 if (AnimatorLabel && AnimatorBar)
162 {
163 if (done < 10240)
164 AnimatorLabel->setText(tr("Downloading from OSM (%n bytes)", "", done));
165 else
166 AnimatorLabel->setText(tr("Downloading from OSM (%n kBytes)", "", (done/1024)));
167 if (AnimationTimer && total != 0)
168 {
169 SAFE_DELETE(AnimationTimer);
170 AnimatorBar->setMaximum(total);
171 }
172 if (!AnimationTimer && AnimatorBar)
173 AnimatorBar->setValue(done);
174 }
175 }
176
resultCode()177 int Downloader::resultCode()
178 {
179 return Result;
180 }
181
resultText()182 const QString &Downloader::resultText()
183 {
184 return ResultText;
185 }
186
errorText()187 const QString &Downloader::errorText()
188 {
189 return ErrorText;
190 }
191
locationText()192 const QString &Downloader::locationText()
193 {
194 return LocationText;
195 }
196
getURLToOpenChangeSet()197 QString Downloader::getURLToOpenChangeSet()
198 {
199 return QString("/changeset/create");
200 }
201
getURLToCloseChangeSet(const QString & Id)202 QString Downloader::getURLToCloseChangeSet(const QString& Id)
203 {
204 return QString("/changeset/%1/close").arg(Id);
205 }
206
getURLToUploadDiff(QString changesetId)207 QString Downloader::getURLToUploadDiff(QString changesetId)
208 {
209 return QString("/changeset/%1/upload").arg(changesetId);
210 }
211
getURLToFetch(const QString & What)212 QString Downloader::getURLToFetch(const QString &What)
213 {
214 QString URL = QString("/%1?%2=");
215 return URL.arg(What).arg(What);
216 }
217
getURLToFetchFull(IFeature::FId id)218 QString Downloader::getURLToFetchFull(IFeature::FId id)
219 {
220 QString type;
221 QString URL;
222 if (id.type & IFeature::Point) {
223 type = "node";
224 URL = QString("/%1/%2");
225 } else {
226 if (id.type & IFeature::LineString)
227 type = "way";
228 if (id.type & IFeature::OsmRelation)
229 type = "relation";
230 URL = QString("/%1/%2/full");
231 }
232
233 return URL.arg(type).arg(id.numId);
234 }
235
getURLToFetchFull(Feature * aFeature)236 QString Downloader::getURLToFetchFull(Feature* aFeature)
237 {
238 return getURLToFetchFull(aFeature->id());
239 }
240
getURLToFetch(const QString & What,const QString & Id)241 QString Downloader::getURLToFetch(const QString &What, const QString& Id)
242 {
243 QString URL = QString("/%1/%2");
244 return URL.arg(What).arg(Id);
245 }
246
getURLToCreate(const QString & What)247 QString Downloader::getURLToCreate(const QString &What)
248 {
249 QString URL = QString("/%1/create");
250 return URL.arg(What);
251 }
252
getURLToUpdate(const QString & What,const QString & Id)253 QString Downloader::getURLToUpdate(const QString &What, const QString& Id)
254 {
255 QString URL = QString("/%1/%2");
256 return URL.arg(What).arg(Id);
257 }
258
getURLToDelete(const QString & What,const QString & Id)259 QString Downloader::getURLToDelete(const QString &What, const QString& Id)
260 {
261 QString URL = QString("/%1/%2");
262 return URL.arg(What).arg(Id);
263 }
264
getURLToMap()265 QString Downloader::getURLToMap()
266 {
267 QString URL("/map?bbox=%1,%2,%3,%4");
268 return URL;
269 }
270
getURLToTrackPoints()271 QString Downloader::getURLToTrackPoints()
272 {
273 QString URL = QString("/trackpoints?bbox=%1,%2,%3,%4&page=%5");
274 return URL;
275 }
276
downloadOSM(QWidget * aParent,const QUrl & theUrl,const QString & aUser,const QString & aPassword,Document * theDocument,Layer * theLayer)277 bool downloadOSM(QWidget* aParent, const QUrl& theUrl, const QString& aUser, const QString& aPassword, Document* theDocument, Layer* theLayer)
278 {
279 Downloader Rcv(aUser, aPassword);
280
281 IProgressWindow* aProgressWindow = dynamic_cast<IProgressWindow*>(aParent);
282 if (aProgressWindow) {
283
284 QProgressDialog* dlg = aProgressWindow->getProgressDialog();
285 if (dlg) {
286 dlg->setWindowTitle(QApplication::translate("Downloader","Downloading..."));
287 dlg->setWindowFlags(dlg->windowFlags() & ~Qt::WindowContextHelpButtonHint);
288 dlg->setWindowFlags(dlg->windowFlags() | Qt::MSWindowsFixedSizeDialogHint);
289 }
290
291 QProgressBar* Bar = aProgressWindow->getProgressBar();
292 Bar->setTextVisible(false);
293 Bar->setMaximum(11);
294
295 QLabel* Lbl = aProgressWindow->getProgressLabel();
296 Lbl->setText(QApplication::translate("Downloader","Downloading from OSM (connecting)"));
297
298 if (dlg)
299 dlg->show();
300
301 Rcv.setAnimator(dlg, Lbl, Bar, true);
302 }
303 if (!Rcv.go(theUrl))
304 {
305 #ifndef _MOBILE
306 /** TODO: Let the caller set the cursor. */
307 aParent->setCursor(QCursor(Qt::ArrowCursor));
308 #endif
309 }
310 int x = Rcv.resultCode();
311 qDebug() << "DownloadOSM: Received OSM API response code:" << x << ", processing.";
312
313 /** We will parse the error codes and display the appropriate messages. */
314 switch (x)
315 {
316 case 200:
317 qDebug() << "DownloadOSM: Response OK, processing.";
318 break;
319 case 301:
320 case 302:
321 case 307: {
322 QString aWeb = Rcv.locationText();
323 if (!aWeb.isEmpty()) {
324 QUrl aURL(aWeb);
325 return downloadOSM(aParent, aURL, aUser, aPassword, theDocument, theLayer);
326 } else {
327 QString msg = QApplication::translate("Downloader","Unexpected http status code (%1)\nServer message is '%2'").arg(x).arg(Rcv.resultText());
328 if (!Rcv.errorText().isEmpty())
329 msg += QApplication::translate("Downloader", "\nAPI message is '%1'").arg(Rcv.errorText());
330 QMessageBox::warning(aParent,QApplication::translate("Downloader","Download failed"), msg);
331 return false;
332 }
333 break;
334 }
335 case 401:
336 QMessageBox::warning(aParent,QApplication::translate("Downloader","Download failed"),QApplication::translate("Downloader","Username/password invalid"));
337 return false;
338 default:
339 QString msg = QApplication::translate("Downloader","Unexpected http status code (%1)\nServer message is '%2'").arg(x).arg(Rcv.resultText());
340 if (!Rcv.errorText().isEmpty())
341 msg += QApplication::translate("Downloader", "\nAPI message is '%1'").arg(Rcv.errorText());
342 QMessageBox::warning(aParent,QApplication::translate("Downloader","Download failed"), msg);
343 return false;
344 }
345 Downloader Down(aUser, aPassword);
346 bool OK = importOSM(aParent, Rcv.content(), theDocument, theLayer, &Down);
347 return OK;
348 }
349
downloadOSM(QWidget * aParent,const QString & aWeb,const QString & aUser,const QString & aPassword,const CoordBox & aBox,Document * theDocument,Layer * theLayer)350 bool downloadOSM(QWidget* aParent, const QString& aWeb, const QString& aUser, const QString& aPassword, const CoordBox& aBox , Document* theDocument, Layer* theLayer)
351 {
352 if (checkForConflicts(theDocument))
353 {
354 QMessageBox::warning(aParent,QApplication::translate("Downloader","Unresolved conflicts"), QApplication::translate("Downloader","Please resolve existing conflicts first"));
355 return false;
356 }
357 Downloader Rcv(aUser, aPassword);
358 QString URL = Rcv.getURLToMap();
359
360 if ((fabs(aBox.bottomLeft().x()) < 180.0 && fabs(aBox.topRight().x()) > 180.0)
361 || (fabs(aBox.bottomLeft().x()) > 180.0 && fabs(aBox.topRight().x()) < 180.0)) {
362 /* Check for +-180 meridian, and split query in two if necessary */
363 int sign = (aBox.bottomLeft().x() > 0) ? 1 : -1;
364 CoordBox q1 = aBox, q2 = aBox;
365 if (aBox.bottomLeft().x() > 0) {
366 q1.setRight(180*sign);
367 q2.setLeft(-180*sign);
368 q2.setRight(q2.right()-360);
369 } else {
370 q1.setLeft(180*sign);
371 q2.setRight(-180*sign);
372 q2.setLeft(q2.left()+360);
373 }
374 return downloadOSM(aParent, aWeb, aUser, aPassword, q1, theDocument, theLayer)
375 && downloadOSM(aParent, aWeb, aUser, aPassword, q2, theDocument, theLayer);
376
377 } else {
378 /* Normal code path */
379 URL = URL.arg(aBox.bottomLeft().x(), 0, 'f').arg(aBox.bottomLeft().y(), 0, 'f').arg(aBox.topRight().x(), 0, 'f').arg(aBox.topRight().y(), 0, 'f');
380 QUrl theUrl(aWeb+URL);
381 return downloadOSM(aParent, theUrl, aUser, aPassword, theDocument, theLayer);
382 }
383 }
384
downloadTracksFromOSM(QWidget * Main,const QString & aWeb,const QString & aUser,const QString & aPassword,const CoordBox & aBox,Document * theDocument)385 bool downloadTracksFromOSM(QWidget* Main, const QString& aWeb, const QString& aUser, const QString& aPassword, const CoordBox& aBox , Document* theDocument)
386 {
387 Downloader theDownloader(aUser, aPassword);
388 QList<TrackLayer*> theTracklayers;
389 //TrackMapLayer* trackLayer = new TrackMapLayer(QApplication::translate("Downloader","Downloaded tracks"));
390 //theDocument->add(trackLayer);
391
392 IProgressWindow* aProgressWindow = dynamic_cast<IProgressWindow*>(Main);
393 if (!aProgressWindow)
394 return false;
395
396 QProgressDialog* dlg = aProgressWindow->getProgressDialog();
397 dlg->setWindowTitle(QApplication::translate("Downloader","Parsing..."));
398
399 QProgressBar* Bar = aProgressWindow->getProgressBar();
400 Bar->setTextVisible(false);
401 Bar->setMaximum(11);
402
403 QLabel* Lbl = aProgressWindow->getProgressLabel();
404 Lbl->setText(QApplication::translate("Downloader","Parsing XML"));
405
406 if (dlg)
407 dlg->show();
408
409 theDownloader.setAnimator(dlg,Lbl,Bar,true);
410 for (int Page=0; ;++Page)
411 {
412 Lbl->setText(QApplication::translate("Downloader","Downloading trackpoints %1-%2").arg(Page*5000+1).arg(Page*5000+5000));
413 QString URL = theDownloader.getURLToTrackPoints();
414 URL = URL.arg(aBox.bottomLeft().x()).
415 arg(aBox.bottomLeft().y()).
416 arg(aBox.topRight().x()).
417 arg(aBox.topRight().y()).
418 arg(Page);
419 QUrl theUrl(aWeb+URL);
420 if (!theDownloader.go(theUrl))
421 return false;
422 if (theDownloader.resultCode() != 200)
423 return false;
424 int Before = theTracklayers.size();
425 QByteArray Ar(theDownloader.content());
426 bool OK = ImportGPX::import(Main, Ar, theDocument, theTracklayers, ImportGPX::Option::MakeSegmented | ImportGPX::Option::DetectAnonymizedSegments);
427 if (!OK)
428 return false;
429 if (Before == theTracklayers.size())
430 break;
431 }
432 return true;
433 }
434
435
checkForConflicts(Document * theDocument)436 bool checkForConflicts(Document* theDocument)
437 {
438 for (FeatureIterator it(theDocument); !it.isEnd(); ++it) {
439 if (it.get()->lastUpdated() == Feature::OSMServerConflict)
440 return true;
441 }
442 return false;
443 }
444
downloadFeatures(MainWindow * Main,const QList<Feature * > & aDownloadList,Document * theDocument)445 bool downloadFeatures(MainWindow* Main, const QList<Feature*>& aDownloadList , Document* theDocument)
446 {
447 QList<IFeature::FId> list;
448 foreach (Feature* F, aDownloadList) {
449 list << F->id();
450 }
451
452 bool ok = downloadFeatures(Main, list, theDocument, NULL);
453
454 return ok;
455 }
456
downloadFeature(MainWindow * Main,const IFeature::FId & id,Document * theDocument,Layer * theLayer)457 bool downloadFeature(MainWindow* Main, const IFeature::FId& id, Document* theDocument, Layer* theLayer)
458 {
459 QList<IFeature::FId> list;
460 list << id;
461 bool ok = downloadFeatures(Main, list, theDocument, theLayer);
462
463 return ok;
464 }
465
downloadFeatures(MainWindow * Main,const QList<IFeature::FId> & idList,Document * theDocument,Layer * theLayer)466 bool downloadFeatures(MainWindow* Main, const QList<IFeature::FId>& idList , Document* theDocument, Layer* theLayer)
467 {
468 if (!theLayer) {
469 if (!theDocument->getLastDownloadLayer()) {
470 theLayer = new DrawingLayer(QApplication::translate("Downloader","%1 download").arg(QDateTime::currentDateTime().toString(Qt::ISODate)));
471 theDocument->add(theLayer);
472 } else
473 theLayer = (Layer*)theDocument->getLastDownloadLayer();
474 }
475
476 QString osmWebsite, osmUser, osmPwd;
477
478 osmWebsite = M_PREFS->getOsmApiUrl();
479 osmUser = M_PREFS->getOsmUser();
480 osmPwd = M_PREFS->getOsmPassword();
481
482 if (Main)
483 Main->view()->setUpdatesEnabled(false);
484
485 bool OK = true;
486 Downloader Rcv(osmUser, osmPwd);
487
488 for (int i=0; i<idList.size(); ++i) {
489 QString URL = Rcv.getURLToFetchFull(idList[i]);
490 QUrl theUrl(osmWebsite+URL);
491
492 downloadOSM(Main, theUrl, osmUser, osmPwd, theDocument, theLayer);
493 }
494
495 if (Main)
496 Main->view()->setUpdatesEnabled(true);
497 if (OK)
498 {
499 if (Main)
500 Main->invalidateView();
501 } else
502 {
503 if (theLayer != theDocument->getLastDownloadLayer()) {
504 theDocument->remove(theLayer);
505 delete theLayer;
506 }
507 }
508 return OK;
509 }
510
downloadMapdust(MainWindow * Main,const CoordBox & aBox,Document * theDocument,SpecialLayer * theLayer)511 bool downloadMapdust(MainWindow* Main, const CoordBox& aBox, Document* theDocument, SpecialLayer* theLayer)
512 {
513 QUrl url;
514
515 url.setUrl(M_PREFS->getMapdustUrl());
516
517 if (Main)
518 Main->view()->setUpdatesEnabled(false);
519
520 Downloader theDownloader("", "");
521
522 SpecialLayer* trackLayer = theLayer;
523 if (!trackLayer) {
524 trackLayer = new SpecialLayer(QApplication::translate("Downloader","MapDust"), Layer::MapDustLayer);
525 trackLayer->setUploadable(false);
526 theDocument->add(trackLayer);
527 }
528
529 IProgressWindow* aProgressWindow = dynamic_cast<IProgressWindow*>(Main);
530 if (!aProgressWindow)
531 return false;
532
533 QProgressDialog* dlg = aProgressWindow->getProgressDialog();
534 dlg->setWindowTitle(QApplication::translate("Downloader","Parsing..."));
535
536 QProgressBar* Bar = aProgressWindow->getProgressBar();
537 Bar->setTextVisible(false);
538 Bar->setMaximum(11);
539
540 QLabel* Lbl = aProgressWindow->getProgressLabel();
541 Lbl->setText(QApplication::translate("Downloader","Parsing XML"));
542
543 if (dlg)
544 dlg->show();
545
546 theDownloader.setAnimator(dlg,Lbl,Bar,true);
547 Lbl->setText(QApplication::translate("Downloader","Downloading points"));
548
549 #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
550 QUrlQuery theQuery(url);
551 #define theQuery theQuery
552 #else
553 #define theQuery url
554 #endif
555 theQuery.addQueryItem("t", COORD2STRING(aBox.topRight().y()));
556 theQuery.addQueryItem("l", COORD2STRING(aBox.bottomLeft().x()));
557 theQuery.addQueryItem("b", COORD2STRING(aBox.bottomLeft().y()));
558 theQuery.addQueryItem("r", COORD2STRING(aBox.topRight().x()));
559 #if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
560 url.setQuery(theQuery);
561 #endif
562 #undef theQuery
563
564 if (!theDownloader.go(url))
565 return false;
566 if (theDownloader.resultCode() != 200)
567 return false;
568 QByteArray Ar(theDownloader.content());
569 ImportExportGdal gdal(theDocument);
570 bool OK = gdal.import(trackLayer, Ar, false);
571
572 if (Main)
573 Main->view()->setUpdatesEnabled(true);
574 if (OK) {
575 if (Main)
576 Main->invalidateView();
577 }
578 return OK;
579 }
580
downloadMoreOSM(MainWindow * Main,const CoordBox & aBox,Document * theDocument)581 bool downloadMoreOSM(MainWindow* Main, const CoordBox& aBox , Document* theDocument)
582 {
583 Layer* theLayer;
584 if (!theDocument->getLastDownloadLayer()) {
585 theLayer = new DrawingLayer(QApplication::translate("Downloader","%1 download").arg(QDateTime::currentDateTime().toString(Qt::ISODate)));
586 theDocument->add(theLayer);
587 } else
588 theLayer = (Layer*)theDocument->getLastDownloadLayer();
589
590 QString osmWebsite, osmUser, osmPwd;
591
592 osmWebsite = M_PREFS->getOsmApiUrl();
593 osmUser = M_PREFS->getOsmUser();
594 osmPwd = M_PREFS->getOsmPassword();
595 qDebug() << "Requesting more from " << osmWebsite;
596
597 Main->view()->setUpdatesEnabled(false);
598
599 bool OK = true;
600 OK = downloadOSM(Main,osmWebsite,osmUser,osmPwd,aBox,theDocument,theLayer);
601 Main->view()->setUpdatesEnabled(true);
602 if (OK)
603 {
604 theDocument->setLastDownloadLayer(theLayer);
605 theDocument->addDownloadBox(theLayer, aBox);
606 // Don't jump around on Download More
607 // aParent->view()->projection().setViewport(aBox,aParent->view()->rect());
608 Main->invalidateView();
609 } else
610 {
611 if (theLayer != theDocument->getLastDownloadLayer()) {
612 theDocument->remove(theLayer);
613 delete theLayer;
614 }
615 }
616 return OK;
617 }
618
downloadOSM(MainWindow * Main,const CoordBox & aBox,Document * theDocument)619 bool downloadOSM(MainWindow* Main, const CoordBox& aBox , Document* theDocument)
620 {
621 QString osmWebsite, osmUser, osmPwd;
622 static bool DownloadRaw = false;
623
624 QDialog * dlg = new QDialog(Main);
625
626 osmWebsite = M_PREFS->getOsmApiUrl();
627 osmUser = M_PREFS->getOsmUser();
628 osmPwd = M_PREFS->getOsmPassword();
629
630 Ui::DownloadMapDialog ui;
631 ui.setupUi(dlg);
632 SlippyMapWidget* SlippyMap = new SlippyMapWidget(ui.groupBox);
633 #ifndef _MOBILE
634 SlippyMap->setMinimumHeight(256);
635 #endif
636 CoordBox Clip(aBox);
637 SlippyMap->setViewportArea(Clip);
638 ui.verticalLayout->addWidget(SlippyMap);
639 QObject::connect(SlippyMap, SIGNAL(redraw()), ui.FromMap, SLOT(toggle()));
640 BookmarkListIterator i(*(M_PREFS->getBookmarks()));
641 while (i.hasNext()) {
642 i.next();
643 if (i.value().deleted == false)
644 ui.Bookmarks->addItem(i.key());
645 }
646 ui.edXapiUrl->setText(QString("*[bbox=%1,%2,%3,%4]").arg(aBox.bottomLeft().x(), 0, 'f').arg(aBox.bottomLeft().y(), 0, 'f').arg(aBox.topRight().x(), 0, 'f').arg(aBox.topRight().y(), 0, 'f'));
647 ui.IncludeTracks->setChecked(DownloadRaw);
648 ui.ResolveRelations->setChecked(M_PREFS->getResolveRelations());
649 bool OK = true, retry = true, directAPI = false;
650 QString directUrl;
651 while (retry) {
652 retry = false;
653 #ifdef _MOBILE
654 dlg->setWindowState(Qt::WindowMaximized);
655 #endif
656 if (dlg->exec() == QDialog::Accepted)
657 {
658 DownloadRaw = false;
659 if (ui.FromBookmark->isChecked())
660 {
661 Clip = M_PREFS->getBookmarks()->value(ui.Bookmarks->currentText()).Coordinates;
662 }
663 else if (ui.FromView->isChecked())
664 {
665 Clip = aBox;
666 }
667 else if (ui.FromLink->isChecked()) {
668 QString link = ui.Link->text();
669
670 if (link.contains("/api/")) {
671 directAPI=true;
672 directUrl = link;
673 } else if (link.contains("/browse/")) {
674 QString tag("/browse/");
675 int ix = link.lastIndexOf(tag) + tag.length();
676 directUrl = M_PREFS->getOsmApiUrl();
677 if (!directUrl.endsWith("/")) directUrl += "/";
678 directUrl += link.right(link.length() - ix);
679 if (!directUrl.endsWith("/")) directUrl += "/";
680 directUrl += "full";
681 directAPI=true;
682 } else if (link.startsWith("way") || link.startsWith("node") || link.startsWith("relation")) {
683 directUrl = M_PREFS->getOsmApiUrl();
684 if (!directUrl.endsWith("/")) directUrl += "/";
685 directUrl += link;
686 directAPI=true;
687 } else {
688 OsmLink ol(link);
689 Clip = ol.getCoordBox();
690 if (Clip.isNull() || Clip.isEmpty())
691 retry = true;
692 }
693 }
694 else if (ui.FromXapi->isChecked())
695 {
696 directAPI = true;
697 directUrl = M_PREFS->getXapiUrl();
698 //if (!directUrl.endsWith("/")) directUrl += "/";
699 directUrl += ui.edXapiUrl->text();
700 }
701 else if (ui.FromMap->isChecked())
702 {
703 QRectF R(SlippyMap->selectedArea());
704 Clip = CoordBox(Coord(R.x(), R.y()), Coord(R.x()+R.width(), R.y()+R.height()));
705 }
706 if (retry) continue;
707 Main->view()->setUpdatesEnabled(false);
708 Layer* theLayer = new DrawingLayer(QApplication::translate("Downloader","%1 download").arg(QDateTime::currentDateTime().toString(Qt::ISODate)));
709 theDocument->add(theLayer);
710 M_PREFS->setResolveRelations(ui.ResolveRelations->isChecked());
711 if (directAPI) {
712 if (ui.FromXapi->isChecked())
713 theLayer->setUploadable(false);
714 OK = downloadOSM(Main,QUrl(QUrl::fromEncoded(directUrl.toLatin1())),osmUser,osmPwd,theDocument,theLayer);
715 }
716 else
717 OK = downloadOSM(Main,osmWebsite,osmUser,osmPwd,Clip,theDocument,theLayer);
718 if (OK && ui.IncludeTracks->isChecked())
719 OK = downloadTracksFromOSM(Main,osmWebsite,osmUser,osmPwd, Clip,theDocument);
720 Main->view()->setUpdatesEnabled(true);
721 if (OK)
722 {
723 theDocument->setLastDownloadLayer(theLayer);
724 theDocument->addDownloadBox(theLayer, Clip);
725 #ifndef _MOBILE
726 if (directAPI)
727 Main->on_viewZoomAllAction_triggered();
728 else
729 #endif
730 Main->view()->setViewport(Clip,Main->view()->rect());
731 Main->invalidateView();
732 } else {
733 retry = true;
734 theDocument->remove(theLayer);
735 SAFE_DELETE(theLayer);
736 }
737 }
738 }
739 delete dlg;
740 return OK;
741 }
742
743