wiview.cpp 20.3 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/***************************************************************************
                          wiview.cpp  -  K Desktop Planetarium
                             -------------------
    begin                : 2012/26/05
    copyright            : (C) 2012 by Samikshan Bairagya
    email                : samikshan@gmail.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

18

19
20
21
22
#include <QtQuick/QQuickView>
#include <QtQuick/QQuickItem>
#include <QStandardPaths>
#include <QGraphicsObject>
23
#include "wiview.h"
24
#include "skymap.h"
25
#include "dialogs/detaildialog.h"
26
#include <klocalizedcontext.h>
27
#include "kspaths.h"
28
29
#include "starobject.h"

30

31
32
33
34
35
36
37
#ifdef HAVE_INDI
#include <basedevice.h>
#include "indi/indilistener.h"
#include "indi/indistd.h"
#include "indi/driverinfo.h"
#endif

38

39
WIView::WIView(QWidget * parent, ObsConditions * obs) : QWidget(parent), m_Obs(obs), m_CurCategorySelected(-1)
40
{
41
42


43
    m_ModManager = new ModelManager(m_Obs);
44

45
    m_BaseView = new QQuickView();
46

47
    ///To use i18n() instead of qsTr() in qml/wiview.qml for translation
48
    //KDeclarative kd;
49
    // kd.setDeclarativeEngine(m_BaseView->engine());
50
51
    //kd.initialize();
    //kd.setupBindings();
52

53
    m_Ctxt = m_BaseView->rootContext();
54

55
56
57
    ///Use instead of KDeclarative
    m_Ctxt->setContextObject(new KLocalizedContext(m_BaseView));

58
    m_BaseView->setSource(QUrl::fromLocalFile(KSPaths::locate(QStandardPaths::AppDataLocation, "tools/whatsinteresting/qml/wiview.qml")));
59

60
    m_BaseObj = m_BaseView->rootObject();
61

62
    //soTypeTextObj = m_BaseObj->findChild<QObject *>("soTypeTextObj");
63

64
    m_ViewsRowObj = m_BaseObj->findChild<QQuickItem *>(QString("viewsRowObj"));
65
    connect(m_ViewsRowObj, SIGNAL(categorySelected(int)), this, SLOT(onCategorySelected(int)));
66

67
    m_SoListObj = m_BaseObj->findChild<QQuickItem *>("soListObj");
68
    connect(m_SoListObj, SIGNAL(soListItemClicked(int, QString, int)), this, SLOT(onSoListItemClicked(int, QString, int)));
69

70
    m_DetailsViewObj = m_BaseObj->findChild<QQuickItem *>("detailsViewObj");
71

72
    m_NextObj = m_BaseObj->findChild<QQuickItem *>("nextObj");
73
    connect(m_NextObj, SIGNAL(nextObjClicked()), this, SLOT(onNextObjClicked()));
74
    m_PrevObj = m_BaseObj->findChild<QQuickItem *>("prevObj");
75
    connect(m_PrevObj, SIGNAL(prevObjClicked()), this, SLOT(onPrevObjClicked()));
76

77
    m_SlewButtonObj = m_BaseObj->findChild<QQuickItem *>("slewButtonObj");
78
79
    connect(m_SlewButtonObj, SIGNAL(slewButtonClicked()), this, SLOT(onSlewButtonClicked()));

80
81
82
    m_SlewTelescopeButtonObj = m_BaseObj->findChild<QQuickItem *>("slewTelescopeButtonObj");
    connect(m_SlewTelescopeButtonObj, SIGNAL(slewTelescopeButtonClicked()), this, SLOT(onSlewTelescopeButtonClicked()));

83
    m_DetailsButtonObj = m_BaseObj->findChild<QQuickItem *>("detailsButtonObj");
84
85
    connect(m_DetailsButtonObj, SIGNAL(detailsButtonClicked()), this, SLOT(onDetailsButtonClicked()));

86
    QObject * settingsIconObj = m_BaseObj->findChild<QQuickItem *>("settingsIconObj");
87
88
    connect(settingsIconObj, SIGNAL(settingsIconClicked()), this, SLOT(onSettingsIconClicked()));

89
    QObject * reloadIconObj = m_BaseObj->findChild<QQuickItem *>("reloadIconObj");
90
91
    connect(reloadIconObj, SIGNAL(reloadIconClicked()), this, SLOT(onReloadIconClicked()));

92
    m_BaseView->setResizeMode(QQuickView::SizeRootObjectToView);
93
    m_BaseView->show();
94
95
}

Samikshan Bairagya's avatar
Samikshan Bairagya committed
96
97
WIView::~WIView()
{
98
    delete m_ModManager;
99
    delete m_CurSoItem;
Samikshan Bairagya's avatar
Samikshan Bairagya committed
100
}
101

102
void WIView::onCategorySelected(int type)
103
{
104
    m_CurCategorySelected = type;
105
    m_Ctxt->setContextProperty("soListModel", m_ModManager->returnModel(type));
106
}
107

108
void WIView::onSoListItemClicked(int type, QString typeName, int index)
109
{
Rafal Kulaga's avatar
Rafal Kulaga committed
110
    Q_UNUSED(typeName)
111
    Q_UNUSED(type)
Rafal Kulaga's avatar
Rafal Kulaga committed
112

113
    SkyObjItem * soitem = m_ModManager->returnModel(m_CurCategorySelected)->getSkyObjItem(index);
114

115
116
//    soTypeTextObj->setProperty("text", typeName);
//    soTypeTextObj->setProperty("visible", true);
117

118
//    soListObj->setProperty("visible", false);
119

120
    loadDetailsView(soitem, index);
121
122
}

123
void WIView::onNextObjClicked()
124
{
125
126
    int modelSize = m_ModManager->returnModel(m_CurCategorySelected)->rowCount();
    SkyObjItem * nextItem = m_ModManager->returnModel(m_CurCategorySelected)->getSkyObjItem((m_CurIndex+1)%modelSize);
127
    loadDetailsView(nextItem, (m_CurIndex+1)%modelSize);
Samikshan Bairagya's avatar
Samikshan Bairagya committed
128
}
129
130
131

void WIView::onPrevObjClicked()
{
132
133
    int modelSize = m_ModManager->returnModel(m_CurCategorySelected)->rowCount();
    SkyObjItem * prevItem = m_ModManager->returnModel(m_CurCategorySelected)->getSkyObjItem((m_CurIndex-1+modelSize)%modelSize);
134
135
    loadDetailsView(prevItem, (m_CurIndex-1+modelSize)%modelSize);
}
136
137
138
139

void WIView::onSlewButtonClicked()
{
    ///Slew map to selected sky-object
140
141
    SkyObject * so = m_CurSoItem->getSkyObject();
    KStars * kstars = KStars::Instance();
142
143
    if (so != 0)
    {
144
145
146
        kstars->map()->setFocusPoint(so);
        kstars->map()->setFocusObject(so);
        kstars->map()->setDestination(*kstars->map()->focusPoint());
147
148
    }
}
149

150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
void WIView::onSlewTelescopeButtonClicked()
{

    if(KMessageBox::Continue==KMessageBox::warningContinueCancel(NULL, "Are you sure you want your telescope to slew to this object?",
            i18n("Continue Slew"),  KStandardGuiItem::cont(), KStandardGuiItem::cancel(), "continue_wi_slew_warning"))
    {

#ifdef HAVE_INDI

    if (INDIListener::Instance()->size() == 0)
    {
        KMessageBox::sorry(0, i18n("KStars did not find any active telescopes."));
        return;
    }

    foreach(ISD::GDInterface * gd, INDIListener::Instance()->getDevices())
    {
        INDI::BaseDevice * bd = gd->getBaseDevice();

        if (gd->getType() != KSTARS_TELESCOPE)
            continue;

        if (bd == NULL)
            continue;

        if (bd->isConnected() == false)
        {
            KMessageBox::error(0, i18n("Telescope %1 is offline. Please connect and retry again.", gd->getDeviceName()));
            return;
        }


        ISD::GDSetCommand SlewCMD(INDI_SWITCH, "ON_COORD_SET", "TRACK", ISS_ON, this);

        gd->setProperty(&SlewCMD);
        gd->runCommand(INDI_SEND_COORDS, m_CurSoItem->getSkyObject());

        ///Slew map to selected sky-object
        onSlewButtonClicked();

        return;

    }

    KMessageBox::sorry(0, i18n("KStars did not find any active telescopes."));

#endif
    }


}

202
203
204
void WIView::onDetailsButtonClicked()
{
    ///Code taken from WUTDialog::slotDetails()
205
206
207
    KStars * kstars = KStars::Instance();
    SkyObject * so = m_CurSoItem->getSkyObject();
    DetailDialog * detail = new DetailDialog(so, kstars->data()->lt(), kstars->data()->geo(), kstars);
208
209
210
    detail->exec();
    delete detail;
}
211
212
213

void WIView::onSettingsIconClicked()
{
214
    KStars * kstars = KStars::Instance();
215
    kstars->showWISettingsUI();
216
}
217

218
219
220
221
222
void WIView::onReloadIconClicked()
{
    updateModels(m_Obs);
}

223
void WIView::updateModels(ObsConditions * obs)
224
225
226
227
228
229
230
231
232
{
    m_Obs = obs;
    m_ModManager->updateModels(m_Obs);
    m_Ctxt->setContextProperty("soListModel", m_ModManager->returnModel(0));
    m_Ctxt->setContextProperty("soListModel", m_ModManager->returnModel(1));
    m_Ctxt->setContextProperty("soListModel", m_ModManager->returnModel(2));
    m_Ctxt->setContextProperty("soListModel", m_ModManager->returnModel(3));
    m_Ctxt->setContextProperty("soListModel", m_ModManager->returnModel(4));
    m_Ctxt->setContextProperty("soListModel", m_ModManager->returnModel(5));
233
234
    m_Ctxt->setContextProperty("soListModel", m_ModManager->returnModel(6));
    m_Ctxt->setContextProperty("soListModel", m_ModManager->returnModel(7));
235

236
    if (m_CurCategorySelected >=0 && m_CurCategorySelected <= 7)
237
        m_Ctxt->setContextProperty("soListModel", m_ModManager->returnModel(m_CurCategorySelected));
238
239
}

240
void WIView::loadDetailsView(SkyObjItem * soitem, int index)
241
242
243
244
{
    m_CurSoItem = soitem;
    m_CurIndex = index;

245
246
247
    int modelSize = m_ModManager->returnModel(m_CurCategorySelected)->rowCount();
    SkyObjItem * nextItem = m_ModManager->returnModel(m_CurCategorySelected)->getSkyObjItem((m_CurIndex+1)%modelSize);
    SkyObjItem * prevItem = m_ModManager->returnModel(m_CurCategorySelected)->getSkyObjItem((m_CurIndex-1+modelSize)%modelSize);
248

Vijay Dhameliya's avatar
Vijay Dhameliya committed
249
250
251
252
253
254
255
256
257
    if(modelSize <= 1)
    {
        m_NextObj->setProperty("visible", "false");
        m_PrevObj->setProperty("visible", "false");
    }
    else
    {
        m_NextObj->setProperty("visible", "true");
        m_PrevObj->setProperty("visible", "true");
258
        QObject * nextTextObj = m_NextObj->findChild<QObject *>("nextTextObj");
Vijay Dhameliya's avatar
Vijay Dhameliya committed
259
        nextTextObj->setProperty("text", nextItem->getName());
260
        QObject * prevTextObj = m_PrevObj->findChild<QObject *>("prevTextObj");
Vijay Dhameliya's avatar
Vijay Dhameliya committed
261
262
        prevTextObj->setProperty("text", prevItem->getName());
    }
263

264
265
    QObject * sonameObj = m_DetailsViewObj->findChild<QObject *>("sonameObj");
    QObject * posTextObj = m_DetailsViewObj->findChild<QObject *>("posTextObj");
266
    QObject * detailImage = m_DetailsViewObj->findChild<QObject *>("detailImage");
267
    QObject * descTextObj = m_DetailsViewObj->findChild<QObject *>("descTextObj");
268
    QObject * infoBoxTextObj = m_DetailsViewObj->findChild<QObject *>("infoBoxText");
269
    QObject * detailsTextObj = m_DetailsViewObj->findChild<QObject *>("detailsTextObj");
270
    QObject * autoCenterCheckBox = m_DetailsViewObj->findChild<QObject *>("autoCenterCheckbox");
271
272
273

    sonameObj->setProperty("text", soitem->getLongName());
    posTextObj->setProperty("text", soitem->getPosition());
274
    detailImage->setProperty("refreshableSource", soitem->getImageURL(false));
275
    descTextObj->setProperty("text", soitem->getDesc());
276
    if(soitem->getType() != SkyObjItem::Planet)
277
        loadObjectDescription(descTextObj, soitem);
278
279
280

    infoBoxTextObj->setProperty("text", "trying to Load infoText box from Wikipedia. . .");
    loadObjectInfoBox(infoBoxTextObj, soitem);
281

282
    QString summary=soitem->getSummary(false);
283

284
285
    QString magText;
    if (soitem->getType() == SkyObjItem::Constellation)
Jasem Mutlaq's avatar
Jasem Mutlaq committed
286
        magText = xi18n("Magnitude:  --");
287
    else
288
        magText = xi18n("Magnitude: %1", QLocale().toString(soitem->getMagnitude(),'f', 2));
289

Jasem Mutlaq's avatar
Jasem Mutlaq committed
290
    QString sbText = xi18n("Surface Brightness: %1", soitem->getSurfaceBrightness());
291

Jasem Mutlaq's avatar
Jasem Mutlaq committed
292
    QString sizeText = xi18n("Size: %1", soitem->getSize());
293

294
    QString details = summary + "<BR>" + sbText + "<BR>" + magText + "<BR>" + sizeText;
295
296
    detailsTextObj->setProperty("text", details);

297
298
299
300
    if(autoCenterCheckBox->property("checked")==true){
        onSlewButtonClicked();
    }

301
302
303
}


304
void WIView::tryToLoadDescFromWikipedia(QObject * descTextObj, SkyObjItem * soitem)
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
{
    QString name;
    if(soitem->getName().startsWith("M "))
        name = soitem->getName().replace("M ","messier_").toLower().remove( ' ' );
    else if(soitem->getType() == SkyObjItem::Constellation)
        name = soitem->getName().toLower().remove( ' ' ) + "_constellation";
    else if(soitem->getType() == SkyObjItem::Star){
        StarObject *star=dynamic_cast<StarObject*>(soitem->getSkyObject());
        if(star)
            name = star->gname().toLower().remove( ' ' ); //the greek name seems to give the most consistent search results.
        else
            name = soitem->getName().toLower().remove( ' ' );
    }else
        name = soitem->getName().toLower().remove( ' ' );

    QUrl url("https://en.wikipedia.org/w/api.php?action=opensearch&search=" + name + "&format=xml");

    QNetworkAccessManager * manager = new QNetworkAccessManager();
    QNetworkReply * response = manager->get(QNetworkRequest(url));
324
    connect(manager, &QNetworkAccessManager::finished, this, [soitem, this, descTextObj, manager, response]{
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
      response->deleteLater();
      manager->deleteLater();
      if (response->error() != QNetworkReply::NoError) return;
      QString contentType =
        response->header(QNetworkRequest::ContentTypeHeader).toString();
      if (!contentType.contains("charset=utf-8")) {
        qWarning() << "Content charsets other than utf-8 are not implemented yet.";
        return;
      }
    QString result = QString::fromUtf8(response->readAll());
    int leftPos=result.indexOf("<Description")+34;
    if(leftPos<34)
        return;
    int rightPos=result.indexOf("</Description>")-leftPos;

    int leftURL=result.indexOf("<Url xml:space=\"preserve\">")+26;
    int rightURL=result.indexOf("</Url>")-leftURL;

343
344
    QString srchtml="\n<p style=text-align:right>Source: (<a href='" + result.mid(leftURL,rightURL) + "'>" + "Wikipedia</a>)";  //Note the \n is so that the description is put on another line in the file.  Doesn't affect the display but allows the source to be loaded in the details but not the list.
    QString html="<HTML>" + result.mid(leftPos,rightPos) + srchtml + "</HTML>";
345

346
      saveObjectText( soitem, "description", html);
347
348
      descTextObj->setProperty("text", html);
    });
349
350
351
352


}

353
void WIView::loadObjectDescription(QObject * descTextObj, SkyObjItem * soitem){
354
355
356
357
358
359
    QFile file;
    QString fname = "description-" + soitem->getName().toLower().remove( ' ' ) + ".html";
    file.setFileName( KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + "descriptions/" + fname ) ; //determine filename in local user KDE directory tree.

    if(file.exists()){

360
        if(file.open(QIODevice::ReadOnly))
361
        {
362
363
            QTextStream in(&file);
            QString line = in.readAll();
364
            descTextObj->setProperty("text", line);
365
            file.close();
366
367
368
        }
    }
    else{
369
        tryToLoadDescFromWikipedia(descTextObj, soitem);
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
    }
}

void WIView::loadObjectInfoBox(QObject * infoBoxText, SkyObjItem * soitem)
{
    QFile file;
    QString fname = "infoText-" + soitem->getName().toLower().remove( ' ' ) + ".html";
    file.setFileName( KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + "descriptions/" + fname ) ; //determine filename in local user KDE directory tree.

    if(file.exists())
    {
        if(file.open(QIODevice::ReadOnly))
        {
            QTextStream in(&file);
            QString line;
            while ( !in.atEnd() )
            {
                line = in.readAll();
                infoBoxText->setProperty("text", line);
                QTimer::singleShot(500, infoBoxText, SLOT(doLayout()));
            }
            file.close();
        }
    }
    else
    {
        tryToLoadInfoBoxFromWikipedia(infoBoxText, soitem);
    }
}

void WIView::tryToLoadInfoBoxFromWikipedia(QObject * infoBoxText, SkyObjItem * soitem)
{
    QString name;
    if(soitem->getName().toLower().startsWith("m "))
        name = soitem->getName().replace("M ","Messier_").remove( ' ' );
    else if(soitem->getName().toLower().startsWith("ngc"))
        name = soitem->getName().toLower().replace("ngc","NGC_").remove( ' ' );
    else if(soitem->getName().toLower().startsWith("ic"))
        name = soitem->getName().toLower().replace("ic","IC_").remove( ' ' );
409
410
411
412
413
414
415
416
417
418
419
    else if(soitem->getType() == SkyObjItem::Constellation){
        QStringList words = soitem->getName().split(" ");
        for(int i=0;i<words.size();i++){
            QString temp=words.at(i).toLower();
            temp[0]=temp[0].toUpper();
            words.replace(i,temp);
        }
        name = words.join("_")+ "_(constellation)";
    }
    else if(soitem->getType() == SkyObjItem::Planet)
        name = soitem->getName().remove( ' ' ) + "_(planet)";
420
421
422
423
424
425
426
427
    else if(soitem->getType() == SkyObjItem::Star){
        StarObject *star=dynamic_cast<StarObject*>(soitem->getSkyObject());
        if(star)
            name = star->gname().toLower().remove( ' ' ); //the greek name seems to give the most consistent search results.
        else
            name = soitem->getName().toLower().remove( ' ' );
    }else
        name = soitem->getName().toLower().remove( ' ' );
428
    qDebug()<<name;
429
430
431
432
433

    QUrl url("https://en.wikipedia.org/w/index.php?action=render&title="+ name + "&redirects");

    QNetworkAccessManager * manager = new QNetworkAccessManager();
    QNetworkReply * response = manager->get(QNetworkRequest(url));
434
    connect(manager, &QNetworkAccessManager::finished, this, [infoBoxText, name, manager, response, soitem, this]{
435
436
      if (response->error() != QNetworkReply::NoError) return;
    QString result = QString::fromUtf8(response->readAll());
437
    int leftPos=result.indexOf("<table class=\"infobox");
438
439
440
441
    int rightPos=result.indexOf("</table>")-leftPos;

    QString infoText=result.mid(leftPos,rightPos).replace("href=\"//","href=\"http://").replace("src=\"//","src=\"http://").replace("background:","color:black;background:").replace("background-color:","color:black;background:");
    infoText.replace("style=\"width:22em\"","style=\"width:100%;border: 1px solid #a2a9b1;border-spacing: 3px;background-color: black;color: white;margin: 0.5em 0 0.5em 1em;padding: 0.2em;line-height: 1.5em;\"");
442
    infoText=infoText + "<BR>(Source: <a href='" + "https://en.wikipedia.org/w/index.php?title="+ name + "&redirects" + "'>Wikipedia</a>)";
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
    int leftImg=infoText.indexOf("src=\"")+5;
    int rightImg=infoText.indexOf("\"",leftImg)-leftImg;
    QString imgURL=infoText.mid(leftImg,rightImg);
    saveImageURL( soitem, imgURL);
    downloadWikipediaImage(soitem, imgURL);

    QString html="<HTML><style type=text/css>a {text-decoration: none;color: yellow}</style><body><CENTER>" +  infoText + "</CENTER></body></HTML>";
    infoBoxText->setProperty("text", html);
    saveObjectText( soitem, "infoText", html);

      QTimer::singleShot(500, infoBoxText, SLOT(doLayout())); //This should make the image load after the html loads

      response->deleteLater();
      manager->deleteLater();
    });
}

void WIView::saveObjectText(SkyObjItem * soitem, QString type, QString text){

    QFile file;
    QString fname = type + "-" + soitem->getName().toLower().remove( ' ' ) + ".html";

    QDir writableDir;
    QString filePath=KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + "descriptions";
    writableDir.mkpath(filePath);

    file.setFileName( filePath + "/" + fname ) ; //determine filename in local user KDE directory tree.

    if(file.exists())
        return;

    if (file.open(QIODevice::WriteOnly) == false)
    {
        qDebug()<<"Image text cannot be saved for later.  file save error";
        return;
    }
    else
    {
        QTextStream stream( &file );
        stream << text;
        file.close();
    }
}



void WIView::saveImageURL(SkyObjItem * soitem, QString imageURL){

    QFile file;
    file.setFileName( KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + "image_url.dat" ) ; //determine filename in local user KDE directory tree.
    QString entry = soitem->getName() + ':' + "Show Wikipedia Image" + ':' + imageURL;

    if(file.open(QIODevice::ReadOnly)){
        QTextStream in(&file);
        QString line;
        while ( !in.atEnd() )
        {
            line = in.readLine();
            if (line==entry){
                file.close();
                return;
            }
        }
        file.close();
    }

    if ( !file.open( QIODevice::ReadWrite | QIODevice::Append ) )
    {
        qDebug()<<"Image URL cannot be saved for later.  image_url.dat error";
        return;
    }
    else
    {
        QTextStream stream( &file );
        stream << entry << endl;
        file.close();
    }
}


void WIView::downloadWikipediaImage(SkyObjItem * soitem, QString imageURL)
{
    QString fname = "wikiImage-" + soitem->getName().toLower().remove( ' ' ) + ".png";

    QDir writableDir;
    QString filePath=KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + "descriptions";
    writableDir.mkpath(filePath);

    QString fileN =filePath + "/" + fname;

533
534
    //qDebug()<<fileN;
    //qDebug()<<imageURL;
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553

    QUrl url(imageURL);

    QNetworkAccessManager * manager = new QNetworkAccessManager();
    QNetworkReply * response = manager->get(QNetworkRequest(url));
    connect(manager, &QNetworkAccessManager::finished, this, [fileN, manager, response, this]{
      response->deleteLater();
      manager->deleteLater();
      if (response->error() != QNetworkReply::NoError) return;

        QImage* image = new QImage();
        QByteArray responseData=response->readAll();
        image->loadFromData(responseData);
        image->save(fileN);


    });


554
}
555