/*************************************************************************** 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. * * * ***************************************************************************/ #include #include #include #include #include "wiview.h" #include "skymap.h" #include "dialogs/detaildialog.h" #include #include "kspaths.h" #include "starobject.h" #include "skymap.h" #include "Options.h" #include "wiequipsettings.h" #include "skymapcomposite.h" #include #ifdef HAVE_INDI #include #include "indi/indilistener.h" #include "indi/indistd.h" #include "indi/driverinfo.h" #endif WIView::WIView(QWidget * parent) : QWidget(parent), m_CurrentObjectListName(-1) { //These settings are like this just to get it started. int bortle = Options::bortleClass(); int aperture = 100; ObsConditions::Equipment equip = ObsConditions::Telescope; ObsConditions::TelescopeType telType = ObsConditions::Reflector; m_Obs = new ObsConditions(bortle, aperture, equip, telType); m_ModManager = new ModelManager(m_Obs); m_BaseView = new QQuickView(); ///To use i18n() instead of qsTr() in qml/wiview.qml for translation //KDeclarative kd; // kd.setDeclarativeEngine(m_BaseView->engine()); //kd.initialize(); //kd.setupBindings(); m_Ctxt = m_BaseView->rootContext(); m_Ctxt->setContextProperty("soListModel", m_ModManager->getTempModel()); // This is to avoid an error saying it doesn't exist. ///Use instead of KDeclarative m_Ctxt->setContextObject(new KLocalizedContext(m_BaseView)); QString WI_Location; #if defined(Q_OS_OSX) WI_Location = QCoreApplication::applicationDirPath()+"/../Resources/data/tools/whatsinteresting/qml/wiview.qml"; if(!QFileInfo(WI_Location).exists()) WI_Location = KSPaths::locate(QStandardPaths::AppDataLocation, "tools/whatsinteresting/qml/wiview.qml"); #elif defined(Q_OS_WIN) WI_Location = KSPaths::locate(QStandardPaths::GenericDataLocation, "tools/whatsinteresting/qml/wiview.qml"); #else WI_Location = KSPaths::locate(QStandardPaths::AppDataLocation, "tools/whatsinteresting/qml/wiview.qml"); #endif m_BaseView->setSource(QUrl::fromLocalFile(WI_Location)); m_BaseObj = m_BaseView->rootObject(); m_ProgressBar = m_BaseObj->findChild("progressBar"); m_loadingMessage = m_BaseObj->findChild("loadingMessage"); m_CategoryTitle = m_BaseObj->findChild(QString("categoryTitle")); m_ViewsRowObj = m_BaseObj->findChild(QString("viewsRowObj")); connect(m_ViewsRowObj, SIGNAL(categorySelected(QString)), this, SLOT(onCategorySelected(QString))); connect(m_ViewsRowObj, SIGNAL(inspectSkyObject(QString)), this, SLOT(inspectSkyObject(QString))); m_SoListObj = m_BaseObj->findChild("soListObj"); connect(m_SoListObj, SIGNAL(soListItemClicked(int)), this, SLOT(onSoListItemClicked(int))); m_DetailsViewObj = m_BaseObj->findChild("detailsViewObj"); descTextObj = m_DetailsViewObj->findChild("descTextObj"); infoBoxText = m_DetailsViewObj->findChild("infoBoxText"); m_skyObjView = m_BaseObj->findChild("skyObjView"); m_ContainerObj = m_BaseObj->findChild("containerObj"); m_NextObj = m_BaseObj->findChild("nextObj"); connect(m_NextObj, SIGNAL(nextObjClicked()), this, SLOT(onNextObjClicked())); m_PrevObj = m_BaseObj->findChild("prevObj"); connect(m_PrevObj, SIGNAL(prevObjClicked()), this, SLOT(onPrevObjClicked())); m_CenterButtonObj = m_BaseObj->findChild("centerButtonObj"); connect(m_CenterButtonObj, SIGNAL(centerButtonClicked()), this, SLOT(onCenterButtonClicked())); autoCenterCheckbox = m_DetailsViewObj->findChild("autoCenterCheckbox"); autoTrackCheckbox = m_DetailsViewObj->findChild("autoTrackCheckbox"); m_SlewTelescopeButtonObj = m_BaseObj->findChild("slewTelescopeButtonObj"); connect(m_SlewTelescopeButtonObj, SIGNAL(slewTelescopeButtonClicked()), this, SLOT(onSlewTelescopeButtonClicked())); m_DetailsButtonObj = m_BaseObj->findChild("detailsButtonObj"); connect(m_DetailsButtonObj, SIGNAL(detailsButtonClicked()), this, SLOT(onDetailsButtonClicked())); QObject * settingsIconObj = m_BaseObj->findChild("settingsIconObj"); connect(settingsIconObj, SIGNAL(settingsIconClicked()), this, SLOT(onSettingsIconClicked())); inspectIconObj = m_BaseObj->findChild("inspectIconObj"); connect(inspectIconObj, SIGNAL(inspectIconClicked(bool)), this, SLOT(onInspectIconClicked(bool))); visibleIconObj = m_BaseObj->findChild("visibleIconObj"); connect(visibleIconObj, SIGNAL(visibleIconClicked(bool)), this, SLOT(onVisibleIconClicked(bool))); favoriteIconObj = m_BaseObj->findChild("favoriteIconObj"); connect(favoriteIconObj, SIGNAL(favoriteIconClicked(bool)), this, SLOT(onFavoriteIconClicked(bool))); QObject * reloadIconObj = m_BaseObj->findChild("reloadIconObj"); connect(reloadIconObj, SIGNAL(reloadIconClicked()), this, SLOT(onReloadIconClicked())); QObject * downloadIconObj = m_BaseObj->findChild("downloadIconObj"); connect(downloadIconObj, SIGNAL(downloadIconClicked()), this, SLOT(onUpdateIconClicked())); m_BaseView->setResizeMode(QQuickView::SizeRootObjectToView); m_BaseView->show(); connect(KStars::Instance()->map(),SIGNAL(objectClicked(SkyObject*)),this, SLOT(inspectSkyObjectOnClick(SkyObject*))); manager = new QNetworkAccessManager(); setProgressBarVisible(true); connect(m_ModManager, SIGNAL(loadProgressUpdated(double)),this,SLOT(updateProgress(double))); connect(m_ModManager, SIGNAL(modelUpdated()),this,SLOT(refreshListView())); m_ViewsRowObj->setProperty("enabled",false); inspectOnClick = false; nightVision = m_BaseObj->findChild("nightVision"); if(Options::darkAppColors()) nightVision->setProperty("state","active"); } WIView::~WIView() { delete m_ModManager; delete m_CurSoItem; delete manager; } void WIView::setNightVisionOn(bool on){ if(on) nightVision->setProperty("state","active"); else nightVision->setProperty("state",""); if(m_CurSoItem) loadDetailsView(m_CurSoItem, m_CurIndex); } void WIView::setProgressBarVisible(bool visible){ m_ProgressBar->setProperty("visible", visible); } void WIView::updateProgress(double value){ m_ProgressBar->setProperty("value", value); if(value==1){ setProgressBarVisible(false); m_ViewsRowObj->setProperty("enabled",true); m_loadingMessage->setProperty("state", ""); } else{ setProgressBarVisible(true); m_loadingMessage->setProperty("state", "loading"); } } void WIView::updateObservingConditions(){ int bortle = Options::bortleClass(); /** NOTE This part of the code dealing with equipment type is presently not required as WI does not differentiate between Telescope and Binoculars. It only needs the aperture of the equipment whichever available. However this is kept as a part of the code as support to be utilised in the future. **/ ObsConditions::Equipment equip = ObsConditions::None; if (Options::telescopeCheck() && Options::binocularsCheck()) equip = ObsConditions::Both; else if (Options::telescopeCheck()) equip = ObsConditions::Telescope; else if (Options::binocularsCheck()) equip = ObsConditions::Binoculars; ObsConditions::TelescopeType telType; if(KStars::Instance()->getWIEquipSettings()) telType = (equip == ObsConditions::Telescope) ? KStars::Instance()->getWIEquipSettings()->getTelType() : ObsConditions::Invalid; else telType = ObsConditions::Invalid; int aperture=100; //This doesn't work correctly, FIXME!! // if(KStars::Instance()->getWIEquipSettings()) // aperture = KStars::Instance()->getWIEquipSettings()->getAperture(); if (!m_Obs) m_Obs = new ObsConditions(bortle, aperture, equip, telType); else m_Obs->setObsConditions(bortle, aperture, equip, telType); } void WIView::onCategorySelected(QString model) { m_CurrentObjectListName = model; m_Ctxt->setContextProperty("soListModel", m_ModManager->returnModel(m_CurrentObjectListName)); m_CurIndex = -2; if(!m_ModManager->showOnlyVisibleObjects()) visibleIconObj->setProperty("state","unchecked"); if(!m_ModManager->showOnlyFavoriteObjects()) favoriteIconObj->setProperty("state","unchecked"); if(model=="ngc"&&(!m_ModManager->isNGCLoaded())){ QtConcurrent::run(m_ModManager,&ModelManager::loadNGCCatalog); return; } if(model=="ic"&&(!m_ModManager->isICLoaded())){ QtConcurrent::run(m_ModManager,&ModelManager::loadICCatalog); return; } if(model=="sharpless"&&(!m_ModManager->isSharplessLoaded())){ QtConcurrent::run(m_ModManager,&ModelManager::loadSharplessCatalog); return; } updateModel(m_Obs); } void WIView::onSoListItemClicked(int index) { SkyObjItem * soitem = m_ModManager->returnModel(m_CurrentObjectListName)->getSkyObjItem(index); if(soitem) loadDetailsView(soitem, index); } void WIView::onNextObjClicked() { if( m_CurrentObjectListName!=""){ int modelSize = m_ModManager->returnModel(m_CurrentObjectListName)->rowCount(); SkyObjItem * nextItem = m_ModManager->returnModel(m_CurrentObjectListName)->getSkyObjItem((m_CurIndex+1)%modelSize); loadDetailsView(nextItem, (m_CurIndex+1)%modelSize); } } void WIView::onPrevObjClicked() { if( m_CurrentObjectListName!=""){ int modelSize = m_ModManager->returnModel(m_CurrentObjectListName)->rowCount(); SkyObjItem * prevItem = m_ModManager->returnModel(m_CurrentObjectListName)->getSkyObjItem((m_CurIndex-1+modelSize)%modelSize); loadDetailsView(prevItem, (m_CurIndex-1+modelSize)%modelSize); } } void WIView::onCenterButtonClicked() { ///Center map on selected sky-object SkyObject * so = m_CurSoItem->getSkyObject(); KStars * kstars = KStars::Instance(); if (so) { kstars->map()->setFocusPoint(so); kstars->map()->setFocusObject(so); kstars->map()->setDestination(*kstars->map()->focusPoint()); Options::setIsTracking(autoTrackCheckbox->property("checked")==true); } } 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 onCenterButtonClicked(); return; } KMessageBox::sorry(0, i18n("KStars did not find any active telescopes.")); #endif } } void WIView::onDetailsButtonClicked() { ///Code taken from WUTDialog::slotDetails() KStars * kstars = KStars::Instance(); SkyObject * so = m_CurSoItem->getSkyObject(); if(so){ DetailDialog * detail = new DetailDialog(so, kstars->data()->lt(), kstars->data()->geo(), kstars); detail->exec(); delete detail; } } void WIView::onSettingsIconClicked() { KStars * kstars = KStars::Instance(); kstars->showWISettingsUI(); } void WIView::onReloadIconClicked() { if(m_CurrentObjectListName!=""){ updateModel(m_Obs); m_CurIndex=m_ModManager->returnModel(m_CurrentObjectListName)->getSkyObjIndex(m_CurSoItem); } loadDetailsView(m_CurSoItem, m_CurIndex); } void WIView::onVisibleIconClicked(bool visible) { m_ModManager->setShowOnlyVisibleObjects(visible); onReloadIconClicked(); } void WIView::onFavoriteIconClicked(bool favorites) { m_ModManager->setShowOnlyFavoriteObjects(favorites); onReloadIconClicked(); } void WIView::onUpdateIconClicked(){ QMessageBox mbox; mbox.setText( "Please choose which object(s) to try to update with Wikipedia data." ); QPushButton * currentObject = mbox.addButton("Current Object" , QMessageBox::AcceptRole); QPushButton * missingObjects; QPushButton * allObjects; if(m_CurrentObjectListName!=""){ missingObjects = mbox.addButton("Objects with no data" , QMessageBox::AcceptRole); allObjects = mbox.addButton("Entire List" , QMessageBox::AcceptRole); } QPushButton * cancel = mbox.addButton( "Cancel", QMessageBox::AcceptRole ); mbox.setDefaultButton(cancel); mbox.exec(); if(mbox.clickedButton()==currentObject) { if(m_CurSoItem) { tryToUpdateWikipediaInfo(m_CurSoItem, getWikipediaName(m_CurSoItem)); } } else if(mbox.clickedButton()==allObjects||mbox.clickedButton()==missingObjects) { SkyObjListModel *model = m_ModManager->returnModel(m_CurrentObjectListName); if(model->rowCount() > 0) { tryToUpdateWikipediaInfoInModel(mbox.clickedButton()==missingObjects); } else { qDebug()<<"No Objects in List!"; } } } void WIView::refreshListView(){ m_Ctxt->setContextProperty("soListModel",0); if (m_CurrentObjectListName !="") m_Ctxt->setContextProperty("soListModel", m_ModManager->returnModel(m_CurrentObjectListName)); if(m_CurIndex==-2) onSoListItemClicked(0); if(m_CurIndex!=-1) m_SoListObj->setProperty("currentIndex", m_CurIndex); } void WIView::updateModel(ObsConditions * obs) { if(m_CurrentObjectListName!=""){ m_Obs = obs; m_ModManager->updateModel(m_Obs,m_CurrentObjectListName); } } void WIView::inspectSkyObject(QString name){ if(name != "" && name != "star"){ SkyObject *obj=KStarsData::Instance()->skyComposite()->findByName(name); if(obj) inspectSkyObject(obj); } } void WIView::inspectSkyObjectOnClick(SkyObject *obj){ if(inspectOnClick&&KStars::Instance()->isWIVisible()){ inspectSkyObject(obj); } } void WIView::inspectSkyObject(SkyObject *obj){ if(obj){ if(obj->name()!="star"){ m_CurrentObjectListName=""; loadDetailsView(new SkyObjItem(obj),-1); m_BaseObj->setProperty("state", "singleItemSelected"); m_CategoryTitle->setProperty("text", "Selected Object"); } } } void WIView::loadDetailsView(SkyObjItem * soitem, int index) { if(!soitem) return; m_CurSoItem = soitem; m_CurIndex = index; int modelSize; if(index==-1) modelSize=-1; else modelSize = m_ModManager->returnModel(m_CurrentObjectListName)->rowCount(); if(modelSize <= 1) { m_NextObj->setProperty("visible", "false"); m_PrevObj->setProperty("visible", "false"); } else { SkyObjItem * nextItem = m_ModManager->returnModel(m_CurrentObjectListName)->getSkyObjItem((m_CurIndex+1)%modelSize); SkyObjItem * prevItem = m_ModManager->returnModel(m_CurrentObjectListName)->getSkyObjItem((m_CurIndex-1+modelSize)%modelSize); m_NextObj->setProperty("visible", "true"); m_PrevObj->setProperty("visible", "true"); QObject * nextTextObj = m_NextObj->findChild("nextTextObj"); nextTextObj->setProperty("text", nextItem->getName()); QObject * prevTextObj = m_PrevObj->findChild("prevTextObj"); prevTextObj->setProperty("text", prevItem->getName()); } QObject * sonameObj = m_DetailsViewObj->findChild("sonameObj"); QObject * posTextObj = m_DetailsViewObj->findChild("posTextObj"); QObject * detailImage = m_DetailsViewObj->findChild("detailImage"); QObject * detailsTextObj = m_DetailsViewObj->findChild("detailsTextObj"); sonameObj->setProperty("text", soitem->getDescName()); posTextObj->setProperty("text", soitem->getPosition()); detailImage->setProperty("refreshableSource", soitem->getImageURL(false)); loadObjectDescription(soitem); infoBoxText->setProperty("text", "

No Wikipedia information.
Please try to download it using the orange download button below."); loadObjectInfoBox(soitem); QString summary=soitem->getSummary(false); QString magText; if (soitem->getType() == SkyObjItem::Constellation) magText = xi18n("Magnitude: --"); else magText = xi18n("Magnitude: %1", QLocale().toString(soitem->getMagnitude(),'f', 2)); QString sbText = xi18n("Surface Brightness: %1", soitem->getSurfaceBrightness()); QString sizeText = xi18n("Size: %1", soitem->getSize()); QString details = summary + "
" + sbText + "
" + magText + "
" + sizeText; detailsTextObj->setProperty("text", details); if(autoCenterCheckbox->property("checked")==true){ QTimer::singleShot(500, this, SLOT(onCenterButtonClicked())); } if(m_CurIndex!=-1) m_SoListObj->setProperty("currentIndex", m_CurIndex); } QString WIView::getWikipediaName(SkyObjItem *soitem){ if(!soitem) return ""; 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( ' ' ); else if(soitem->getType() == SkyObjItem::Constellation){ QStringList words = soitem->getName().split(" "); for(int i=0;igetTypeName() == "Asteroid") name = soitem->getName().remove( ' ' ) + "_(asteroid)"; else if(soitem->getTypeName() == "Comet") name = soitem->getLongName(); else if(soitem->getType() == SkyObjItem::Planet&&soitem->getName()!="Sun"&&soitem->getName()!="Moon") name = soitem->getName().remove( ' ' ) + "_(planet)"; else if(soitem->getType() == SkyObjItem::Star) { StarObject *star=dynamic_cast(soitem->getSkyObject()); name = star->gname(false).replace( " ", "_" ); //the greek name seems to give the most consistent search results for opensearch. if(name=="") name = soitem->getName().replace( " ", "_" ) + "_(star)"; name.remove("[").remove("]"); } else name = soitem->getName().remove( ' ' ); return name; } void WIView::updateWikipediaDescription(SkyObjItem * soitem) { if(!soitem) return; QString name=getWikipediaName(soitem); QUrl url("https://en.wikipedia.org/w/api.php?action=opensearch&search=" + name + "&format=xml"); QNetworkReply * response = manager->get(QNetworkRequest(url)); QTimer::singleShot(30000, response, [response] { //Shut it down after 30 sec. response->abort(); response->deleteLater(); qDebug()<<"Wikipedia Download Timed out."; }); connect(response, &QNetworkReply::finished, this, [soitem, this, response]{ response->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("")-leftPos; int leftURL=result.indexOf("")+26; int rightURL=result.indexOf("")-leftURL; QString srchtml="\n

Source: (" + "Wikipedia)"; //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="" + result.mid(leftPos,rightPos) + srchtml + ""; saveObjectInfoBoxText( soitem, "description", html); QString color = (Options::darkAppColors()) ? "red" : "white"; QString linkColor = (Options::darkAppColors()) ? "red" : "yellow"; html = "" + html + ""; if(soitem==m_CurSoItem) descTextObj->setProperty("text", html); refreshListView(); }); } void WIView::loadObjectDescription(SkyObjItem * soitem){ 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()){ if(file.open(QIODevice::ReadOnly)) { QTextStream in(&file); QString color = (Options::darkAppColors()) ? "red" : "white"; QString linkColor = (Options::darkAppColors()) ? "red" : "yellow"; QString line = "
" + in.readAll() + ""; descTextObj->setProperty("text", line); file.close(); } } else { descTextObj->setProperty("text", soitem->getTypeName()); } } void WIView::loadObjectInfoBox(SkyObjItem * soitem) { if(!soitem) return; 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 infoBoxHTML; while ( !in.atEnd() ) { infoBoxHTML = in.readAll(); QString wikiImageName=QUrl::fromLocalFile(KSPaths::locate(QStandardPaths::GenericDataLocation, "descriptions/wikiImage-" + soitem->getName().toLower().remove( ' ' ) + ".png" )).url(); if(wikiImageName!=""){ int captionEnd = infoBoxHTML.indexOf(""); //Start looking for the image AFTER the caption. Planets have images in their caption. if(captionEnd == -1) captionEnd = 0; int leftImg=infoBoxHTML.indexOf("src=\"", captionEnd)+5; int rightImg=infoBoxHTML.indexOf("\"",leftImg)-leftImg; QString imgURL=infoBoxHTML.mid(leftImg,rightImg); infoBoxHTML.replace(imgURL,wikiImageName); } QString color = (Options::darkAppColors()) ? "red" : "white"; QString linkColor = (Options::darkAppColors()) ? "red" : "yellow"; if(Options::darkAppColors()) infoBoxHTML.replace("color: white","color: " + color); infoBoxHTML = "" + infoBoxHTML + ""; infoBoxText->setProperty("text", infoBoxHTML); } file.close(); } } } void WIView::tryToUpdateWikipediaInfoInModel(bool onlyMissing){ SkyObjListModel *model = m_ModManager->returnModel(m_CurrentObjectListName); int objectNum=model->rowCount(); for(int i = 0; i < objectNum; i++) { SkyObjItem * soitem = model->getSkyObjItem(i); 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()&&onlyMissing) continue; tryToUpdateWikipediaInfo(soitem, getWikipediaName(soitem)); } } void WIView::tryToUpdateWikipediaInfo(SkyObjItem * soitem, QString name) { if(name==""||!soitem) return; QUrl url("https://en.wikipedia.org/w/index.php?action=render&title="+ name + "&redirects"); QNetworkReply * response = manager->get(QNetworkRequest(url)); QTimer::singleShot(30000, response, [response] { //Shut it down after 30 sec. response->abort(); response->deleteLater(); qDebug()<<"Wikipedia Download Timed out."; }); connect(response, &QNetworkReply::finished, this, [name, response, soitem, this]{ response->deleteLater(); if (response->error()==QNetworkReply::ContentNotFoundError){ QString html="
Sorry, No Wikipedia article with this object name seems to exist. It is possible that one does exist but does not match the namimg scheme."; saveObjectInfoBoxText( soitem, "infoText" , html); infoBoxText->setProperty("text", html); return; } if (response->error() != QNetworkReply::NoError) return; QString result = QString::fromUtf8(response->readAll()); int leftPos=result.indexOf("", leftPos)-leftPos; if(leftPos==-1){ //No InfoBox is Found if(soitem->getType()==SkyObjItem::Star&&name!=soitem->getName().replace(" ", "_")) //For stars, the regular name rather than gname { tryToUpdateWikipediaInfo(soitem, soitem->getName().replace(" ", "_")); return; } QString html="
Sorry, no Information Box in the object's Wikipedia article was found."; saveObjectInfoBoxText( soitem, "infoText" , html); infoBoxText->setProperty("text", html); return; } updateWikipediaDescription(soitem); QString infoText=result.mid(leftPos,rightPos); //This if statement should correct for a situation like for the planets where there is a single internal table inside the infoText Box. if(infoText.indexOf("", leftPos+rightPos+6)-leftPos; infoText=result.mid(leftPos,rightPos); } //This next section is for the headers in the colored boxes. It turns them black instead of white because they are more visible that way. infoText.replace("background: #","color:black;background: #").replace("background-color: #","color:black;background: #").replace("background:#","color:black;background:#").replace("background-color:#","color:black;background:#").replace("background: pink","color:black;background: pink"); infoText.replace("//","http://"); //This is to fix links on wikipedia which are missing http from the url infoText.replace("https:http:","https:").replace("http:http:","http:");//Just in case it was done to an actual complete url //This section is intended to remove links from the object name header at the top. The links break up the header. int thLeft=infoText.indexOf("
", thLeft); int firstA=infoText.indexOf("", firstA)-firstA+1; infoText.remove(firstA, rightA); int endA=infoText.indexOf("", firstA); infoText.remove(endA,4); } } int annotationLeft=infoText.indexOf("" , annotationLeft) + 13 - annotationLeft; infoText.remove(annotationLeft,annotationRight); //This removes the annotation that does not render correctly for some DSOs. int mathLeft=infoText.indexOf("" , mathLeft) + 1 - mathLeft ; infoText.remove(mathLeft, mathRight);//This removes an image that doesn't render properly for some DSOs. infoText.replace("style=\"width:22em\"","style=\"width:100%;background-color: black;color: white;\""); infoText=infoText + "
(Source: Wikipedia)"; saveInfoURL(soitem, "https://en.wikipedia.org/w/index.php?title="+ name + "&redirects"); int captionEnd = infoText.indexOf(""); //Start looking for the image AFTER the caption. Planets have images in their caption. if(captionEnd == -1) captionEnd = 0; int leftImg=infoText.indexOf("src=\"", captionEnd)+5; if(leftImg > captionEnd + 5){ int rightImg=infoText.indexOf("\"",leftImg)-leftImg; QString imgURL=infoText.mid(leftImg,rightImg); imgURL.replace("http://upload.wikimedia.org","https://upload.wikimedia.org"); //Although they will display, the images apparently don't download properly unless they are https. saveImageURL( soitem, imgURL); downloadWikipediaImage(soitem, imgURL); } QString html="
" + infoText + "
"; saveObjectInfoBoxText( soitem, "infoText", html); QString color = (Options::darkAppColors()) ? "red" : "white"; QString linkColor = (Options::darkAppColors()) ? "red" : "yellow"; if(Options::darkAppColors()) html.replace("color: white","color: " + color); html = "" + html + ""; if(soitem==m_CurSoItem) infoBoxText->setProperty("text", html); }); } void WIView::saveObjectInfoBoxText(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.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::saveInfoURL(SkyObjItem * soitem, QString infoURL){ QFile file; file.setFileName( KSPaths::writableLocation(QStandardPaths::GenericDataLocation) + "info_url.dat" ) ; //determine filename in local user KDE directory tree. QString entry = soitem->getName() + ':' + "Wikipedia Page" + ':' + infoURL; 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()<<"Info URL cannot be saved for later. info_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; QNetworkReply * response = manager->get(QNetworkRequest(QUrl(imageURL))); QTimer::singleShot(60000, response, [response] { //Shut it down after 60 sec. response->abort(); response->deleteLater(); qDebug()<<"Image Download Timed out."; }); connect(response, &QNetworkReply::finished, this, [fileN, response, this]{ response->deleteLater(); if (response->error() != QNetworkReply::NoError) return; QImage* image = new QImage(); QByteArray responseData=response->readAll(); if(image->loadFromData(responseData)){ image->save(fileN); refreshListView(); //This is to update the images displayed with the new image. } else qDebug()<<"image not downloaded"; }); }