9#include "analyze/analyze.h"
10#include "capture/capture.h"
11#include "scheduler/scheduler.h"
12#include "scheduler/schedulerprocess.h"
13#include "scheduler/schedulermodulestate.h"
14#include "focus/focus.h"
15#include "focus/focusmodule.h"
16#include "align/align.h"
17#include "guide/guide.h"
18#include "mount/mount.h"
19#include "observatory/observatory.h"
22#include "ekosadaptor.h"
24#include "kstarsdata.h"
26#include "ekos/capture/rotatorsettings.h"
27#include "profileeditor.h"
28#include "profilewizard.h"
30#include "auxiliary/darklibrary.h"
31#include "auxiliary/ksmessagebox.h"
32#include "auxiliary/profilesettings.h"
33#include "capture/sequencejob.h"
34#include "capture/cameraprocess.h"
35#include "fitsviewer/fitsview.h"
36#include "fitsviewer/fitsdata.h"
37#include "indi/clientmanager.h"
38#include "indi/driverinfo.h"
39#include "indi/drivermanager.h"
40#include "indi/guimanager.h"
41#include "indi/indilistener.h"
42#include "auxiliary/opticaltrainmanager.h"
43#include "auxiliary/opticaltrainsettings.h"
44#include "indi/indiwebmanager.h"
45#include "indi/indigps.h"
46#include "indi/indiguider.h"
47#include "indi/indirotator.h"
48#include "mount/meridianflipstatuswidget.h"
49#include "ekos/auxiliary/rotatorutils.h"
51#include "ekoslive/ekosliveclient.h"
52#include "ekoslive/message.h"
53#include "ekoslive/media.h"
55#include <basedevice.h>
57#include <KConfigDialog>
59#include <KActionCollection>
60#include <knotification.h>
62#include <QFutureWatcher>
64#include <QDesktopServices>
66#include <ekos_debug.h>
68#define MAX_REMOTE_INDI_TIMEOUT 15000
69#define MAX_LOCAL_INDI_TIMEOUT 10000
74Manager *Manager::_Manager =
nullptr;
76Manager *Manager::Instance()
78 if (_Manager ==
nullptr)
79 _Manager =
new Manager(Options::independentWindowEkos() ?
nullptr :
KStars::Instance());
84void Manager::release()
86 ProfileSettings::release();
87 OpticalTrainManager::release();
88 OpticalTrainSettings::release();
89 RotatorUtils::release();
93Manager::Manager(QWidget * parent) : QDialog(parent), m_networkManager(this)
97 if (Options::independentWindowEkos())
106 if (Options::independentWindowEkos())
112 capturePreview->targetLabel->setVisible(
false);
113 capturePreview->mountTarget->setVisible(
false);
116 deviceSplitter->setSizes(
QList<int>({20000, 10000}));
118 qRegisterMetaType<Ekos::CommunicationStatus>(
"Ekos::CommunicationStatus");
119 qDBusRegisterMetaType<Ekos::CommunicationStatus>();
121 new EkosAdaptor(
this);
127 profileModel->setHorizontalHeaderLabels(
QStringList() <<
"id"
132 m_CountdownTimer.setInterval(1000);
135 toolsWidget->setIconSize(
QSize(48, 48));
139 toolsWidget->setTabEnabled(1,
false);
142 toolsWidget->setTabEnabled(2,
false);
147 processINDIB->setToolTip(
i18n(
"Start"));
155 ekosLiveClient.reset(
new EkosLive::Client(
this));
156 connect(ekosLiveClient.get(), &EkosLive::Client::connected,
this, [
this]()
158 emit ekosLiveStatusChanged(true);
160 connect(ekosLiveClient.get(), &EkosLive::Client::disconnected,
this, [
this]()
162 emit ekosLiveStatusChanged(false);
169 ekosLiveClient.get()->show();
170 ekosLiveClient.get()->raise();
173 connect(
this, &Manager::ekosStatusChanged, ekosLiveClient.get()->message(), &EkosLive::Message::setEkosStatingStatus);
174 connect(
this, &Manager::indiStatusChanged, ekosLiveClient.get()->message(), &EkosLive::Message::setINDIStatus);
175 connect(ekosLiveClient.get()->message(), &EkosLive::Message::connected,
this, [&]()
177 ekosLiveB->setIcon(QIcon(
":/icons/cloud-online.svg"));
179 connect(ekosLiveClient.get()->message(), &EkosLive::Message::disconnected,
this, [&]()
181 ekosLiveB->setIcon(QIcon::fromTheme(
"folder-cloud"));
183 connect(ekosLiveClient.get()->media(), &EkosLive::Media::newBoundingRect, ekosLiveClient.get()->message(),
184 &EkosLive::Message::setBoundingRect);
185 connect(ekosLiveClient.get()->message(), &EkosLive::Message::resetPolarView, ekosLiveClient.get()->media(),
186 &EkosLive::Media::resetPolarView);
187 connect(KSMessageBox::Instance(), &KSMessageBox::newMessage, ekosLiveClient.get()->message(),
188 &EkosLive::Message::sendDialog);
191 m_PortSelectorTimer.setInterval(500);
192 m_PortSelectorTimer.setSingleShot(
true);
195 if (m_PortSelector && m_CurrentProfile->portSelector)
197 if (m_PortSelector->shouldShow())
199 m_PortSelector->show();
200 m_PortSelector->raise();
202 ekosLiveClient.get()->message()->requestPortSelection(
true);
205 else if (m_CurrentProfile->autoConnect)
206 setPortSelectionComplete();
208 else if (m_CurrentProfile->autoConnect)
209 setPortSelectionComplete();
215 m_PortSelector->show();
216 m_PortSelector->raise();
220 connect(
this, &Ekos::Manager::ekosStatusChanged,
this, [&](Ekos::CommunicationStatus status)
222 indiControlPanelB->setEnabled(status == Ekos::Success);
223 connectB->setEnabled(
false);
224 disconnectB->setEnabled(
false);
225 extensionB->setEnabled(
false);
226 extensionCombo->setEnabled(
false);
227 profileGroup->setEnabled(status == Ekos::Idle || status == Ekos::Error);
228 m_isStarted = (
status == Ekos::Success ||
status == Ekos::Pending);
229 if (status == Ekos::Success)
232 processINDIB->setToolTip(
i18n(
"Stop"));
233 setWindowTitle(
i18nc(
"@title:window",
"Ekos - %1 Profile", m_CurrentProfile->name));
235 else if (status == Ekos::Error || status == Ekos::Idle)
238 processINDIB->setToolTip(
i18n(
"Start"));
243 processINDIB->setToolTip(
i18n(
"Connection in progress. Click to abort."));
279 Options::setProfile(text);
280 if (text ==
"Simulators")
282 editProfileB->setEnabled(
false);
283 deleteProfileB->setEnabled(
false);
287 editProfileB->setEnabled(
true);
288 deleteProfileB->setEnabled(
true);
294 settleTimer.setInterval(1000);
297 if (m_settleStatus != Ekos::Success)
299 m_settleStatus = Ekos::Success;
300 emit settleStatusChanged(m_settleStatus);
336 toolsWidget->tabBar()->setTabIcon(0,
QIcon(
":/icons/ekos_setup.png"));
337 toolsWidget->tabBar()->setTabToolTip(0,
i18n(
"Setup"));
340 schedulerProcess.reset(
new Scheduler());
341 int index = addModuleTab(EkosModule::Scheduler, schedulerModule(),
QIcon(
":/icons/ekos_scheduler.png"));
342 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Scheduler"));
343 capturePreview->shareSchedulerModuleState(schedulerModule()->moduleState());
344 connect(schedulerModule()->process().data(), &SchedulerProcess::newLog,
this, &Ekos::Manager::updateLog);
345 connect(schedulerModule(), &Ekos::Scheduler::newTarget,
this, &Manager::setTarget);
347 connect(schedulerModule(), &Ekos::Scheduler::jobsUpdated, ekosLiveClient.get()->message(),
349 connect(schedulerModule(), &Ekos::Scheduler::settingsUpdated, ekosLiveClient.get()->message(),
351 connect(schedulerModule()->process().data(), &SchedulerProcess::newLog, ekosLiveClient.get()->message(),
354 QJsonObject cStatus =
356 {
"log", schedulerModule()->moduleState()->getLogText()}
359 ekosLiveClient.get()->message()->sendSchedulerStatus(cStatus);
361 connect(schedulerModule(), &Ekos::Scheduler::newStatus, ekosLiveClient.get()->message(),
362 [
this](Ekos::SchedulerState state)
364 QJsonObject cStatus =
369 ekosLiveClient.get()->message()->sendSchedulerStatus(cStatus);
374 connect(analyzeProcess.get(), &Ekos::Analyze::newLog,
this, &Ekos::Manager::updateLog);
376 index = addModuleTab(EkosModule::Analyze, analyzeProcess.get(),
QIcon(
":/icons/ekos_analyze.png"));
377 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Analyze"));
379 numPermanentTabs = index + 1;
382 extensionTimer.setSingleShot(
true);
383 groupBox_4->setHidden(
true);
387 if (extensionB->icon().name() ==
"media-playback-start")
389 extensionTimer.setInterval(1000);
392 appendLogText(
i18n(
"Extension '%1' failed to start, aborting", extensionCombo->currentText()));
395 extensionTimer.start();
396 extensionAbort =
false;
397 m_extensions.run(extensionCombo->currentText());
399 else if (extensionB->icon().name() ==
"media-playback-stop")
403 extensionTimer.setInterval(10000);
406 appendLogText(
i18n(
"Extension '%1' failed to stop, abort enabled", extensionCombo->currentText()));
407 extensionB->setEnabled(
true);
408 extensionAbort =
true;
410 extensionTimer.start();
415 appendLogText(
i18n(
"Extension '%1' aborting", extensionCombo->currentText()));
420 connect(&m_extensions, &extensions::extensionStateChanged,
this, [
this](Ekos::ExtensionState state)
424 case EXTENSION_START_REQUESTED:
425 appendLogText(
i18n(
"Extension '%1' start requested", extensionCombo->currentText()));
426 extensionB->setEnabled(
false);
427 extensionCombo->setEnabled(
false);
429 case EXTENSION_STARTED:
430 appendLogText(
i18n(
"Extension '%1' started", extensionCombo->currentText()));
432 extensionB->setEnabled(
true);
433 extensionCombo->setEnabled(
false);
434 extensionTimer.stop();
437 case EXTENSION_STOP_REQUESTED:
438 appendLogText(
i18n(
"Extension '%1' stop requested", extensionCombo->currentText()));
439 extensionB->setEnabled(
false);
440 extensionCombo->setEnabled(
false);
442 case EXTENSION_STOPPED:
443 appendLogText(
i18n(
"Extension '%1' stopped", extensionCombo->currentText()));
445 extensionB->setEnabled(
true);
446 extensionCombo->setEnabled(
true);
447 extensionTimer.stop();
450 m_extensionStatus = state;
451 emit extensionStatusChanged();
455 extensionCombo->setToolTip(m_extensions.getTooltip(text));
457 connect(&m_extensions, &extensions::extensionOutput,
this, [
this] (
QString message)
459 appendLogText(
QString(
i18n(
"Extension '%1': %2", extensionCombo->currentText(), message.
trimmed())));
468 m_SummaryView.reset(
new SummaryFITSView(capturePreview->previewWidget));
472 m_SummaryView->createFloatingToolBar();
473 m_SummaryView->setCursorMode(FITSView::dragCursor);
474 m_SummaryView->showProcessInfo(
false);
475 capturePreview->setSummaryFITSView(m_SummaryView);
478 if (Options::ekosLeftIcons())
484 for (
int i = 0; i < numPermanentTabs; ++i)
486 QIcon icon = toolsWidget->tabIcon(i);
489 toolsWidget->setTabIcon(i, icon);
497 for (
auto &button : qButtons)
498 button->setAutoDefault(
false);
501 resize(Options::ekosWindowWidth(), Options::ekosWindowHeight());
518 toolsWidget->disconnect(
this);
535 Options::setEkosWindowWidth(width());
536 Options::setEkosWindowHeight(height());
544bool Manager::checkIfPageExists(
const QString &urlString)
550 QNetworkRequest request(url);
551 QNetworkReply *reply = m_networkManager.get(request);
584 QString urlStr(
"https://kstars-docs.kde.org/%1/user_manual/ekos.html");
585 QWidget *widget = toolsWidget->currentWidget();
588 if (widget == alignModule())
589 urlStr =
"https://kstars-docs.kde.org/%1/user_manual/ekos-align.html";
590 else if (widget == captureModule())
591 urlStr =
"https://kstars-docs.kde.org/%1/user_manual/ekos-capture.html";
592 else if (widget == focusModule())
593 urlStr =
"https://kstars-docs.kde.org/%1/user_manual/ekos-focus.html";
594 else if (widget == guideModule())
595 urlStr =
"https://kstars-docs.kde.org/%1/user_manual/ekos-guide.html";
598 else if (widget == schedulerModule())
599 urlStr =
"https://kstars-docs.kde.org/%1/user_manual/ekos-scheduler.html";
602 else if (widget == analyzeProcess.get())
603 urlStr =
"https://kstars-docs.kde.org/%1/user_manual/ekos-analyze.html";
606 QString fullStr = QString(urlStr).arg(locale.
name());
607 if (!checkIfPageExists(fullStr))
609 const int underscoreIndex = locale.
name().
indexOf(
'_');
610 QString firstPart = locale.
name().
mid(0, underscoreIndex);
611 fullStr = QString(urlStr).
arg(firstPart);
612 if (!checkIfPageExists(fullStr))
613 fullStr = QString(urlStr).
arg(
"en");
625 if (profileWizardLaunched ==
false && profiles.count() == 1)
627 profileWizardLaunched =
true;
634 focusProgressWidget->updateFocusDetailView();
635 guideManager->updateGuideDetailView();
638void Manager::loadProfiles()
643 profileModel->clear();
645 for (
auto &pi : profiles)
647 QList<QStandardItem *> info;
649 info <<
new QStandardItem(pi->id) <<
new QStandardItem(pi->name) <<
new QStandardItem(pi->host)
650 <<
new QStandardItem(pi->port);
651 profileModel->appendRow(info);
654 profileModel->sort(0);
655 profileCombo->blockSignals(
true);
656 profileCombo->setModel(profileModel.get());
657 profileCombo->setModelColumn(1);
658 profileCombo->blockSignals(
false);
661 int index = profileCombo->findText(Options::profile());
665 profileCombo->setCurrentIndex(index);
668int Manager::addModuleTab(Manager::EkosModule module,
QWidget *tab,
const QIcon &icon)
673 case EkosModule::Observatory:
674 index += guideProcess ? 1 : 0;
675 case EkosModule::Guide:
676 index += alignProcess ? 1 : 0;
677 case EkosModule::Align:
678 index += mountProcess ? 1 : 0;
679 case EkosModule::Mount:
680 index += focusProcess ? 1 : 0;
681 case EkosModule::Focus:
682 index += captureProcess ? 1 : 0;
683 case EkosModule::Capture:
684 index += analyzeProcess ? 1 : 0;
685 case EkosModule::Analyze:
686 index += schedulerProcess ? 1 : 0;
687 case EkosModule::Scheduler:
689 case EkosModule::Setup:
693 index = toolsWidget->count();
697 toolsWidget->insertTab(index, tab, icon,
"");
701void Manager::loadDrivers()
703 for (
auto &dv : DriverManager::Instance()->getDrivers())
705 if (dv->getDriverSource() != HOST_SOURCE)
706 driversList[dv->getLabel()] = dv;
712 qCDebug(KSTARS_EKOS) <<
"Resetting Ekos Manager...";
714 ProfileSettings::release();
715 OpticalTrainManager::release();
716 OpticalTrainSettings::release();
717 RotatorUtils::release();
719 m_DriverDevicesCount = 0;
723 captureProcess.reset();
724 focusProcess.reset();
725 guideProcess.reset();
726 alignProcess.reset();
727 mountProcess.reset();
728 observatoryProcess.reset();
730 for (
auto &oneManger : m_FilterManagers)
732 m_FilterManagers.clear();
734 for (
auto &oneController : m_RotatorControllers)
735 oneController.reset();
736 m_RotatorControllers.clear();
738 DarkLibrary::Release();
739 m_PortSelector.reset();
740 m_PortSelectorTimer.stop();
742 Ekos::CommunicationStatus previousStatus;
744 previousStatus = m_settleStatus;
745 m_settleStatus = Ekos::Idle;
746 if (previousStatus != m_settleStatus)
747 emit settleStatusChanged(m_settleStatus);
749 previousStatus = m_ekosStatus;
750 m_ekosStatus = Ekos::Idle;
751 if (previousStatus != m_ekosStatus)
752 emit ekosStatusChanged(m_ekosStatus);
754 previousStatus = m_indiStatus;
755 m_indiStatus = Ekos::Idle;
756 if (previousStatus != m_indiStatus)
757 emit indiStatusChanged(m_indiStatus);
759 connectB->setEnabled(
false);
760 disconnectB->setEnabled(
false);
761 extensionB->setEnabled(
false);
762 extensionCombo->setEnabled(
false);
764 processINDIB->setEnabled(
true);
766 mountGroup->setEnabled(
false);
767 capturePreview->setEnabled(
false);
768 capturePreview->reset();
770 mountStatus->setStyleSheet(QString());
771 focusProgressWidget->reset();
772 guideManager->reset();
777 processINDIB->setToolTip(
i18n(
"Start"));
780void Manager::processINDI()
782 if (m_isStarted ==
false)
791 m_PortSelector.reset();
792 m_PortSelectorTimer.stop();
793 m_CountdownTimer.stop();
794 portSelectorB->setEnabled(
false);
797 indiHubAgent->terminate();
799 profileGroup->setEnabled(
true);
801 setWindowTitle(
i18nc(
"@title:window",
"Ekos"));
804 extensionCombo->clear();
805 m_extensions.found->clear();
806 groupBox_4->setHidden(
true);
811 if (analyzeProcess && Options::analyzeRestartWithEkos())
812 analyzeProcess->restart();
815 if (m_ekosStatus == Ekos::Pending || m_ekosStatus == Ekos::Success)
817 qCWarning(KSTARS_EKOS) <<
"Ekos Manager start called but current Ekos Status is" << m_ekosStatus <<
"Ignoring request.";
821 managedDrivers.clear();
830 getCurrentProfile(m_CurrentProfile);
831 m_LocalMode = m_CurrentProfile->isLocal();
833 ProfileSettings::Instance()->setProfile(m_CurrentProfile);
836 updateProfileLocation(m_CurrentProfile);
838 bool haveCCD =
false, haveGuider =
false;
842 if (m_CurrentProfile->guidertype == Ekos::Guide::GUIDE_PHD2)
844 Options::setPHD2Host(m_CurrentProfile->guiderhost);
845 Options::setPHD2Port(m_CurrentProfile->guiderport);
847 else if (m_CurrentProfile->guidertype == Ekos::Guide::GUIDE_LINGUIDER)
849 Options::setLinGuiderHost(m_CurrentProfile->guiderhost);
850 Options::setLinGuiderPort(m_CurrentProfile->guiderport);
854 QJsonParseError jsonError;
855 QJsonArray profileScripts;
859 profileScripts = doc.
array();
861 ekosLiveClient->message()->setPendingPropertiesEnabled(
true);
866 auto drv = driversList.value(m_CurrentProfile->mount());
869 managedDrivers.append(drv->clone());
871 drv = driversList.value(m_CurrentProfile->ccd());
874 managedDrivers.append(drv->clone());
878 Options::setGuiderType(m_CurrentProfile->guidertype);
880 drv = driversList.value(m_CurrentProfile->guider());
891 if (haveCCD && m_CurrentProfile->guider() == m_CurrentProfile->ccd())
893 if (checkUniqueBinaryDriver( driversList.value(m_CurrentProfile->ccd()), drv))
899 drv->setUniqueLabel(drv->getLabel() +
" Guide");
904 managedDrivers.append(drv->clone());
907 drv = driversList.value(m_CurrentProfile->ao());
909 managedDrivers.append(drv->clone());
911 drv = driversList.value(m_CurrentProfile->filter());
913 managedDrivers.append(drv->clone());
915 drv = driversList.value(m_CurrentProfile->focuser());
917 managedDrivers.append(drv->clone());
919 drv = driversList.value(m_CurrentProfile->dome());
921 managedDrivers.append(drv->clone());
923 drv = driversList.value(m_CurrentProfile->weather());
925 managedDrivers.append(drv->clone());
927 drv = driversList.value(m_CurrentProfile->aux1());
930 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
931 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
932 managedDrivers.append(drv->clone());
934 drv = driversList.value(m_CurrentProfile->aux2());
937 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
938 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
939 managedDrivers.append(drv->clone());
942 drv = driversList.value(m_CurrentProfile->aux3());
945 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
946 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
947 managedDrivers.append(drv->clone());
950 drv = driversList.value(m_CurrentProfile->aux4());
953 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
954 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
955 managedDrivers.append(drv->clone());
959 if (m_CurrentProfile->remotedrivers.isEmpty() ==
false && m_CurrentProfile->remotedrivers.contains(
"@"))
961 for (
auto remoteDriver : m_CurrentProfile->remotedrivers.split(
","))
963 QString
name,
label, host(
"localhost"), port(
"7624"), hostport(host +
':' + port);
973 QStringList device_location = remoteDriver.split(
'@');
976 if (device_location.
length() > 0)
977 name = device_location[0];
980 if (device_location.
length() > 1)
981 hostport = device_location[1];
985 QStringList
location = hostport.split(
':');
996 QSharedPointer<DriverInfo> dv(
new DriverInfo(name));
997 dv->setRemoteHost(host);
998 dv->setRemotePort(port);
1003 dv->setLabel(label);
1004 dv->setUniqueLabel(label);
1005 managedDrivers.
append(dv);
1010 if (haveCCD ==
false && haveGuider ==
false && m_CurrentProfile->remotedrivers.isEmpty())
1012 KSNotification::error(
i18n(
"Ekos requires at least one CCD or Guider to operate."));
1013 managedDrivers.clear();
1014 m_ekosStatus = Ekos::Error;
1015 emit ekosStatusChanged(m_ekosStatus);
1019 m_DriverDevicesCount = managedDrivers.count();
1023 QSharedPointer<DriverInfo> remote_indi(
new DriverInfo(QString(
"Ekos Remote Host")));
1025 remote_indi->setHostParameters(m_CurrentProfile->host, m_CurrentProfile->port);
1027 remote_indi->setDriverSource(GENERATED_SOURCE);
1029 managedDrivers.append(remote_indi);
1031 haveCCD = m_CurrentProfile->drivers.contains(
"CCD");
1032 haveGuider = m_CurrentProfile->drivers.contains(
"Guider");
1034 Options::setGuiderType(m_CurrentProfile->guidertype);
1036 if (haveCCD ==
false && haveGuider ==
false && m_CurrentProfile->remotedrivers.isEmpty())
1038 KSNotification::error(
i18n(
"Ekos requires at least one CCD or Guider to operate."));
1039 m_DriverDevicesCount = 0;
1040 m_ekosStatus = Ekos::Error;
1041 emit ekosStatusChanged(m_ekosStatus);
1045 m_DriverDevicesCount = m_CurrentProfile->drivers.count();
1050 QList<QSharedPointer<DriverInfo >> sortedList;
1051 for (
const auto &oneRule : qAsConst(profileScripts))
1053 auto driver = oneRule.toObject()[
"Driver"].toString();
1054 auto matchingDriver = std::find_if(managedDrivers.begin(), managedDrivers.end(), [oneRule, driver](
const auto & oneDriver)
1057 return oneDriver->getLabel() == driver || (driver.startsWith(
"@") && !oneDriver->getRemoteHost().isEmpty());
1060 if (matchingDriver != managedDrivers.end())
1062 (*matchingDriver)->setStartupShutdownRule(oneRule.toObject());
1063 sortedList.
append(*matchingDriver);
1071 for (
auto &oneDriver : managedDrivers)
1073 if (sortedList.
contains(oneDriver) ==
false)
1074 sortedList.
append(oneDriver);
1077 managedDrivers = sortedList;
1080 connect(DriverManager::Instance(), &DriverManager::serverStarted,
this,
1082 connect(DriverManager::Instance(), &DriverManager::serverFailed,
this,
1084 connect(DriverManager::Instance(), &DriverManager::clientStarted,
this,
1086 connect(DriverManager::Instance(), &DriverManager::clientFailed,
this,
1088 connect(DriverManager::Instance(), &DriverManager::clientTerminated,
this,
1091 connect(INDIListener::Instance(), &INDIListener::newDevice,
this, &Ekos::Manager::processNewDevice);
1096 if (m_LocalMode || m_CurrentProfile->host ==
"localhost")
1098 if (isRunning(
"PTPCamera"))
1101 i18n(
"Ekos detected that PTP Camera is running and may prevent a Canon or Nikon camera from connecting to Ekos. Do you want to quit PTP Camera now?"),
1102 i18n(
"PTP Camera")))
1106 p.
start(
"killall PTPCamera");
1114 auto executeStartINDIServices = [
this]()
1116 appendLogText(
i18n(
"Starting INDI services..."));
1118 m_ekosStatus = Ekos::Pending;
1119 emit ekosStatusChanged(m_ekosStatus);
1121 DriverManager::Instance()->startDevices(managedDrivers);
1125 if (isRunning(
"indiserver"))
1130 DriverManager::Instance()->stopAllDevices();
1133 const QString program =
"pkill";
1134 QStringList arguments;
1135 arguments <<
"indiserver";
1136 p.
start(program, arguments);
1144 executeStartINDIServices();
1147 KSMessageBox::Instance()->questionYesNo(
i18n(
"Ekos detected an instance of INDI server running. Do you wish to "
1148 "shut down the existing instance before starting a new one?"),
1149 i18n(
"INDI Server"), 5);
1152 executeStartINDIServices();
1157 auto runConnection = [
this]()
1160 if (m_ekosStatus != Ekos::Pending)
1164 i18n(
"Connecting to remote INDI server at %1 on port %2 ...", m_CurrentProfile->host, m_CurrentProfile->port));
1166 DriverManager::Instance()->connectRemoteHost(managedDrivers.first());
1169 auto runProfile = [
this, runConnection]()
1172 if (m_ekosStatus != Ekos::Pending)
1175 INDI::WebManager::syncCustomDrivers(m_CurrentProfile);
1176 INDI::WebManager::checkVersion(m_CurrentProfile);
1178 if (INDI::WebManager::areDriversRunning(m_CurrentProfile) ==
false)
1180 INDI::WebManager::stopProfile(m_CurrentProfile);
1182 if (INDI::WebManager::startProfile(m_CurrentProfile) ==
false)
1184 appendLogText(
i18n(
"Failed to start profile on remote INDI Web Manager."));
1188 appendLogText(
i18n(
"Starting profile on remote INDI Web Manager..."));
1189 m_RemoteManagerStart =
true;
1195 m_ekosStatus = Ekos::Pending;
1196 emit ekosStatusChanged(m_ekosStatus);
1199 if (m_CurrentProfile->INDIWebManagerPort > 0)
1201 appendLogText(
i18n(
"Establishing communication with remote INDI Web Manager..."));
1202 m_RemoteManagerStart =
false;
1203 QFutureWatcher<bool> *watcher =
new QFutureWatcher<bool>();
1209 if (m_ekosStatus != Ekos::Pending)
1221 appendLogText(
i18n(
"Warning: INDI Web Manager is not online."));
1227 QFuture<bool> result = INDI::AsyncWebManager::isOnline(m_CurrentProfile);
1237 if (m_extensions.discover())
1239 foreach (QString extension, m_extensions.found->keys())
1241 extensions::extDetails m_ext = m_extensions.found->value(extension);
1242 extensionCombo->addItem(m_ext.icon, extension);
1245 if (extensionCombo->count() > 0)
1247 groupBox_4->setHidden(
false);
1251void Manager::setClientStarted(
const QString &host,
int port)
1253 if (managedDrivers.size() > 0)
1257 if (m_CurrentProfile->autoConnect)
1258 appendLogText(
i18n(
"INDI services started on port %1.", port));
1261 i18n(
"INDI services started on port %1. Please connect devices.", port));
1266 i18n(
"INDI services started. Connection to remote INDI server %1:%2 is successful. Waiting for devices...", host, port));
1270 auto maxTimeout = MAX_LOCAL_INDI_TIMEOUT;
1273 QJsonParseError jsonError;
1274 QJsonArray profileScripts;
1281 profileScripts = doc.
array();
1282 for (
const auto &oneRule : qAsConst(profileScripts))
1284 const auto &oneRuleObj = oneRule.toObject();
1285 auto totalDelay = (oneRuleObj[
"PreDelay"].toDouble(0) + oneRuleObj[
"PostDelay"].toDouble(0)) * 1000;
1286 if (totalDelay >= maxTimeout)
1287 maxTimeout = totalDelay + MAX_LOCAL_INDI_TIMEOUT;
1294void Manager::setClientFailed(
const QString &host,
int port,
const QString &errorMessage)
1297 appendLogText(
i18n(
"Failed to connect to local INDI server %1:%2", host, port));
1299 appendLogText(
i18n(
"Failed to connect to remote INDI server %1:%2", host, port));
1304 m_ekosStatus = Ekos::Error;
1305 emit ekosStatusChanged(m_ekosStatus);
1306 KSNotification::error(errorMessage,
i18n(
"Error"), 15);
1309void Manager::setClientTerminated(
const QString &host,
int port,
const QString &errorMessage)
1312 appendLogText(
i18n(
"Lost connection to local INDI server %1:%2", host, port));
1314 appendLogText(
i18n(
"Lost connection to remote INDI server %1:%2", host, port));
1319 m_ekosStatus = Ekos::Error;
1320 emit ekosStatusChanged(m_ekosStatus);
1321 KSNotification::error(errorMessage,
i18n(
"Error"), 15);
1324void Manager::setServerStarted(
const QString &host,
int port)
1326 if (m_LocalMode && m_CurrentProfile->indihub != INDIHub::None)
1328 if (QFile(Options::iNDIHubAgent()).exists())
1330 indiHubAgent =
new QProcess();
1333 args <<
"--indi-server" << QString(
"%1:%2").arg(host).arg(port);
1334 if (m_CurrentProfile->guidertype == Ekos::Guide::GUIDE_PHD2)
1335 args <<
"--phd2-server" << QString(
"%1:%2").arg(m_CurrentProfile->guiderhost).arg(m_CurrentProfile->guiderport);
1336 args <<
"--mode" << INDIHub::toString(m_CurrentProfile->indihub);
1337 indiHubAgent->start(Options::iNDIHubAgent(), args);
1339 qCDebug(KSTARS_EKOS) <<
"Started INDIHub agent.";
1344void Manager::setServerFailed(
const QString &host,
int port,
const QString &message)
1348 managedDrivers.clear();
1349 m_ekosStatus = Ekos::Error;
1350 emit ekosStatusChanged(m_ekosStatus);
1351 KSNotification::error(message,
i18n(
"Error"), 15);
1372void Manager::checkINDITimeout()
1375 if (m_ekosStatus != Ekos::Pending)
1378 if (m_indiStatus != Ekos::Pending || m_CurrentProfile->portSelector || m_CurrentProfile->autoConnect ==
false)
1381 QStringList disconnectedDevices;
1382 for (
auto &oneDevice : INDIListener::devices())
1384 if (oneDevice->isConnected() ==
false)
1385 disconnectedDevices << oneDevice->getDeviceName();
1390 if (disconnectedDevices.
count() == 1)
1391 message =
i18n(
"Failed to connect to %1. Please ensure device is connected and powered on.", disconnectedDevices.
first());
1393 message =
i18n(
"Failed to connect to \n%1\nPlease ensure each device is connected and powered on.",
1394 disconnectedDevices.
join(
"\n"));
1396 appendLogText(message);
1397 KSNotification::event(QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1402 if (m_DriverDevicesCount <= 0)
1404 m_ekosStatus = Ekos::Success;
1405 emit ekosStatusChanged(m_ekosStatus);
1411 QStringList remainingDevices;
1412 for (
auto &drv : managedDrivers)
1414 if (drv->getDevices().count() == 0)
1415 remainingDevices << QString(
"+ %1").arg(
1416 drv->getUniqueLabel().isEmpty() ==
false ? drv->getUniqueLabel() : drv->getName());
1419 if (remainingDevices.
count() == 1)
1421 QString message =
i18n(
"Unable to establish:\n%1\nPlease ensure the device is connected and powered on.",
1422 remainingDevices.
at(0));
1423 appendLogText(message);
1424 KSNotification::event(QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1429 QString message =
i18n(
"Unable to establish the following devices:\n%1\nPlease ensure each device is connected "
1430 "and powered on.", remainingDevices.
join(
"\n"));
1431 appendLogText(message);
1432 KSNotification::event(QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1438 QStringList remainingDevices;
1440 for (
auto &driver : m_CurrentProfile->drivers.values())
1442 bool driverFound =
false;
1444 for (
auto &device : INDIListener::devices())
1446 if (device->getBaseDevice().getDriverName() == driver)
1453 if (driverFound ==
false)
1454 remainingDevices << QString(
"+ %1").arg(driver);
1457 if (remainingDevices.
count() == 1)
1459 QString message =
i18n(
"Unable to remotely establish:\n%1\nPlease ensure the device is connected and powered on.",
1460 remainingDevices.
at(0));
1461 appendLogText(message);
1462 KSNotification::event(QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1467 QString message =
i18n(
"Unable to remotely establish the following devices:\n%1\nPlease ensure each device is connected "
1468 "and powered on.", remainingDevices.
join(
"\n"));
1469 appendLogText(message);
1470 KSNotification::event(QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1475 m_ekosStatus = Ekos::Error;
1478bool Manager::isINDIReady()
1483 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1485 auto devices = INDIListener::devices();
1486 for (
auto &device : devices)
1489 if (device->isConnected() && device->isReady())
1492 if (devices.count() == nConnected)
1494 m_indiStatus = Ekos::Success;
1495 emit indiStatusChanged(m_indiStatus);
1499 m_indiStatus = Ekos::Pending;
1500 if (previousStatus != m_indiStatus)
1501 emit indiStatusChanged(m_indiStatus);
1506void Manager::connectDevices()
1511 auto devices = INDIListener::devices();
1513 for (
auto &device : devices)
1515 qCDebug(KSTARS_EKOS) <<
"Connecting " << device->getDeviceName();
1519 connectB->setEnabled(
false);
1520 disconnectB->setEnabled(
true);
1521 extensionCombo->setEnabled(
true);
1522 if (extensionCombo->currentText() !=
"")
1523 extensionB->setEnabled(
true);
1525 appendLogText(
i18n(
"Connecting INDI devices..."));
1528void Manager::disconnectDevices()
1530 for (
auto &device : INDIListener::devices())
1532 qCDebug(KSTARS_EKOS) <<
"Disconnecting " << device->getDeviceName();
1533 device->Disconnect();
1536 appendLogText(
i18n(
"Disconnecting INDI devices..."));
1539void Manager::cleanDevices(
bool stopDrivers)
1541 if (m_ekosStatus == Ekos::Idle)
1545 mountModule()->stopTimers();
1547 ekosLiveClient->message()->setPendingPropertiesEnabled(
false);
1551 if (managedDrivers.isEmpty() ==
false)
1556 DriverManager::Instance()->stopDevices(managedDrivers);
1562 DriverManager::Instance()->disconnectRemoteHost(managedDrivers.first());
1564 if (m_RemoteManagerStart && m_CurrentProfile->INDIWebManagerPort != -1)
1565 INDI::WebManager::stopProfile(m_CurrentProfile);
1567 m_RemoteManagerStart =
false;
1573 profileGroup->setEnabled(
true);
1575 appendLogText(
i18n(
"INDI services stopped."));
1580 qCInfo(KSTARS_EKOS) <<
"Ekos received a new device: " << device->getDeviceName();
1582 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1594 m_indiStatus = Ekos::Idle;
1595 if (previousStatus != m_indiStatus)
1596 emit indiStatusChanged(m_indiStatus);
1598 m_DriverDevicesCount--;
1616 connect(device.
get(), &ISD::GenericDevice::propertyDeleted,
this, &Ekos::Manager::processDeleteProperty,
1618 connect(device.
get(), &ISD::GenericDevice::propertyUpdated,
this, &Ekos::Manager::processUpdateProperty,
1626 if (m_CurrentProfile->ccd() != m_CurrentProfile->guider())
1628 for (
auto &oneCamera : INDIListener::devices())
1631 m_PrimaryCamera = QString(oneCamera->getDeviceName());
1632 else if (oneCamera->getDeviceName().startsWith(m_CurrentProfile->guider(),
Qt::CaseInsensitive))
1633 m_GuideCamera = QString(oneCamera->getDeviceName());
1637 if (m_DriverDevicesCount <= 0)
1639 m_ekosStatus = Ekos::Success;
1640 emit ekosStatusChanged(m_ekosStatus);
1642 connectB->setEnabled(
true);
1643 disconnectB->setEnabled(
false);
1644 extensionCombo->setEnabled(
false);
1645 extensionB->setEnabled(
false);
1647 if (m_LocalMode ==
false && m_DriverDevicesCount == 0)
1649 if (m_CurrentProfile->autoConnect)
1650 appendLogText(
i18n(
"Remote devices established."));
1652 appendLogText(
i18n(
"Remote devices established. Please connect devices."));
1657void Manager::deviceConnected()
1659 connectB->setEnabled(
false);
1660 disconnectB->setEnabled(
true);
1661 processINDIB->setEnabled(
false);
1662 extensionCombo->setEnabled(
true);
1663 if (extensionCombo->currentText() !=
"")
1664 extensionB->setEnabled(
true);
1666 auto device = qobject_cast<ISD::GenericDevice *>(sender());
1668 if (Options::verboseLogging())
1670 qCInfo(KSTARS_EKOS) << device->getDeviceName()
1671 <<
"Version:" << device->getDriverVersion()
1672 <<
"Interface:" << device->getDriverInterface()
1676 if (Options::neverLoadConfig() ==
false)
1678 INDIConfig tConfig = Options::loadConfigOnConnection() ? LOAD_LAST_CONFIG : LOAD_DEFAULT_CONFIG;
1680 for (
auto &oneDevice : INDIListener::devices())
1682 if (oneDevice == device)
1686 auto configProp = device->getBaseDevice().getSwitch(
"CONFIG_PROCESS");
1687 if (configProp && configProp.getState() == IPS_IDLE)
1688 device->setConfig(tConfig);
1695void Manager::deviceDisconnected()
1697 ISD::GenericDevice * dev =
static_cast<ISD::GenericDevice *
>(sender());
1699 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1703 if (dev->getState(
"CONNECTION") == IPS_ALERT)
1704 m_indiStatus = Ekos::Error;
1705 else if (dev->getState(
"CONNECTION") == IPS_BUSY)
1706 m_indiStatus = Ekos::Pending;
1708 m_indiStatus = Ekos::Idle;
1710 if (Options::verboseLogging())
1711 qCDebug(KSTARS_EKOS) << dev->getDeviceName() <<
" is disconnected.";
1714 if (m_indiStatus == Ekos::Error)
1716 QString message =
i18n(
"%1 failed to connect.\nPlease ensure the device is connected and powered on.",
1717 dev->getDeviceName());
1718 appendLogText(message);
1719 KSNotification::event(QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1721 else if (m_indiStatus == Ekos::Idle)
1723 QString message =
i18n(
"%1 is disconnected.", dev->getDeviceName());
1724 appendLogText(message);
1728 m_indiStatus = Ekos::Idle;
1730 if (previousStatus != m_indiStatus)
1731 emit indiStatusChanged(m_indiStatus);
1733 connectB->setEnabled(
true);
1734 disconnectB->setEnabled(
false);
1735 processINDIB->setEnabled(
true);
1736 extensionCombo->setEnabled(
false);
1737 extensionB->setEnabled(
false);
1742 ekosLiveClient->message()->sendScopes();
1744 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1746 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1751 ekosLiveClient.get()->media()->registerCameras();
1753 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1755 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1758void Manager::addFilterWheel(ISD::FilterWheel * device)
1760 QString
name = device->getDeviceName();
1761 appendLogText(
i18n(
"%1 filter is online.", name));
1763 createFilterManager(device);
1765 emit newDevice(name, device->getDriverInterface());
1770 appendLogText(
i18n(
"%1 focuser is online.", device->getDeviceName()));
1772 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1777 appendLogText(
i18n(
"Rotator %1 is online.", device->getDeviceName()));
1781 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1784void Manager::addDome(
ISD::Dome * device)
1786 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1788 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1793 appendLogText(
i18n(
"%1 Weather is online.", device->getDeviceName()));
1795 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1798void Manager::addGPS(ISD::GPS * device)
1800 appendLogText(
i18n(
"%1 GPS is online.", device->getDeviceName()));
1802 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1807 OpticalTrainManager::Instance()->syncDevices();
1809 appendLogText(
i18n(
"%1 Dust cap is online.", device->getDeviceName()));
1811 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1816 appendLogText(
i18n(
"%1 Light box is online.", device->getDeviceName()));
1818 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1823 createModules(device);
1828 auto camera = device->getCamera();
1834 if (camera->hasCooler())
1836 QSharedPointer<ISD::GenericDevice>
generic;
1837 if (INDIListener::findDevice(camera->getDeviceName(), generic))
1838 focusModule()->addTemperatureSource(generic);
1847 auto mount = device->getMount();
1852 QSharedPointer<ISD::GenericDevice>
generic;
1853 if (INDIListener::findDevice(
mount->getDeviceName(), generic))
1855 mountModule()->addTimeSource(generic);
1856 mountModule()->addLocationSource(generic);
1865 auto focuser = device->getFocuser();
1871 QSharedPointer<ISD::GenericDevice>
generic;
1872 if (INDIListener::findDevice(focuser->getDeviceName(), generic))
1873 focusModule()->addTemperatureSource(generic);
1888 auto dome = device->getDome();
1892 captureProcess->setDome(dome);
1894 alignProcess->setDome(dome);
1895 if (observatoryProcess)
1896 observatoryProcess->setDome(dome);
1902 auto weather = device->getWeather();
1905 if (observatoryProcess)
1906 observatoryProcess->addWeatherSource(weather);
1910 QSharedPointer<ISD::GenericDevice>
generic;
1911 if (INDIListener::findDevice(weather->getDeviceName(), generic))
1912 focusModule()->addTemperatureSource(generic);
1919 auto gps = device->getGPS();
1924 QSharedPointer<ISD::GenericDevice>
generic;
1925 if (INDIListener::findDevice(gps->getDeviceName(), generic))
1927 mountModule()->addTimeSource(generic);
1928 mountModule()->addLocationSource(generic);
1938 alignModule()->removeDevice(device);
1940 captureProcess->removeDevice(device);
1942 focusModule()->removeDevice(device);
1944 mountModule()->removeDevice(device);
1946 guideProcess->removeDevice(device);
1947 if (observatoryProcess)
1948 observatoryProcess->removeDevice(device);
1950 m_PortSelector->removeDevice(device->getDeviceName());
1952 DarkLibrary::Instance()->removeDevice(device);
1955 for (
auto &oneManager : m_FilterManagers)
1957 oneManager->removeDevice(device);
1961 for (
auto &oneController : m_RotatorControllers)
1963 oneController->close();
1966 appendLogText(
i18n(
"%1 is offline.", device->getDeviceName()));
1969 if (INDIListener::devices().isEmpty())
1976void Manager::processDeleteProperty(INDI::Property prop)
1978 ekosLiveClient.get()->message()->processDeleteProperty(prop);
1981void Manager::processMessage(
int id)
1983 auto origin =
static_cast<ISD::GenericDevice *
>(sender());
1987 QSharedPointer<ISD::GenericDevice> device;
1988 if (!INDIListener::findDevice(origin->getDeviceName(), device))
1991 ekosLiveClient.
get()->message()->processMessage(device,
id);
1994void Manager::processUpdateProperty(INDI::Property prop)
1996 ekosLiveClient.get()->message()->processUpdateProperty(prop);
1998 if (prop.isNameMatch(
"CCD_INFO") ||
1999 prop.isNameMatch(
"GUIDER_INFO") ||
2000 prop.isNameMatch(
"CCD_FRAME") ||
2001 prop.isNameMatch(
"GUIDER_FRAME"))
2003 if (focusModule() !=
nullptr)
2004 focusModule()->syncCameraInfo(prop.getDeviceName());
2006 if (guideModule() !=
nullptr && guideModule()->camera() == prop.getDeviceName())
2007 guideModule()->syncCameraInfo();
2009 if (alignModule() !=
nullptr && alignModule()->camera() == prop.getDeviceName())
2010 alignModule()->syncCameraInfo();
2016void Manager::processNewProperty(INDI::Property prop)
2018 QSharedPointer<ISD::GenericDevice> device;
2019 if (!INDIListener::findDevice(prop.getDeviceName(), device))
2022 settleTimer.start();
2024 ekosLiveClient.
get()->message()->processNewProperty(prop);
2026 if (prop.isNameMatch(
"DEVICE_PORT_SCAN") || prop.isNameMatch(
"CONNECTION_TYPE"))
2028 if (!m_PortSelector)
2033 m_PortSelectorTimer.start();
2034 portSelectorB->setEnabled(
true);
2035 m_PortSelector->addDevice(device);
2040 if (prop.isNameMatch(
"DEBUG"))
2042 uint16_t
interface = device->getDriverInterface();
2043 if ( opsLogs->getINDIDebugInterface() & interface )
2046 auto debugSP = prop.getSwitch();
2047 debugSP->at(0)->setState(ISS_ON);
2048 debugSP->at(1)->setState(ISS_OFF);
2049 device->sendNewProperty(debugSP);
2055 if (prop.isNameMatch(
"DEBUG_LEVEL"))
2057 uint16_t
interface = device->getDriverInterface();
2059 if ( opsLogs->getINDIDebugInterface() & interface )
2062 auto debugLevel = prop.getSwitch();
2063 for (
auto &it : *debugLevel)
2064 it.setState(ISS_ON);
2066 device->sendNewProperty(debugLevel);
2071 if (prop.isNameMatch(
"ASTROMETRY_SOLVER"))
2073 for (
auto &oneDevice : INDIListener::devices())
2075 if (oneDevice->getDeviceName() == prop.getDeviceName())
2078 alignModule()->setAstrometryDevice(oneDevice);
2086 if (focusModule() !=
nullptr && strstr(prop.getName(),
"FOCUS_"))
2088 focusModule()->checkFocusers();
2093void Manager::processTabChange()
2095 auto currentWidget = toolsWidget->currentWidget();
2097 if (alignProcess && alignModule() == currentWidget)
2099 auto alignReady = alignModule()->isEnabled() ==
false && alignModule()->isParserOK();
2100 auto captureReady = captureProcess && captureModule()->isEnabled();
2101 auto mountReady = mountProcess && mountModule()->isEnabled();
2102 if (alignReady && captureReady && mountReady)
2103 alignModule()->setEnabled(
true);
2105 alignModule()->checkCamera();
2107 else if (captureProcess && currentWidget == captureModule())
2109 captureModule()->process()->checkCamera();
2111 else if (focusProcess && currentWidget == focusModule())
2113 focusModule()->checkCameras();
2115 else if (guideProcess && currentWidget == guideModule())
2117 guideModule()->checkCamera();
2123void Manager::updateLog()
2125 QWidget * currentWidget = toolsWidget->currentWidget();
2127 if (currentWidget == setupTab)
2128 ekosLogOut->setPlainText(m_LogText.join(
"\n"));
2129 else if (currentWidget == alignModule())
2130 ekosLogOut->setPlainText(alignModule()->getLogText());
2131 else if (currentWidget == captureModule())
2132 ekosLogOut->setPlainText(captureModule()->getLogText());
2133 else if (currentWidget == focusModule())
2134 ekosLogOut->setPlainText(focusModule()->getLogText());
2135 else if (currentWidget == guideModule())
2136 ekosLogOut->setPlainText(guideModule()->getLogText());
2137 else if (currentWidget == mountModule())
2138 ekosLogOut->setPlainText(mountModule()->getLogText());
2139 else if (currentWidget == schedulerModule())
2140 ekosLogOut->setPlainText(schedulerModule()->moduleState()->getLogText());
2141 else if (currentWidget == observatoryProcess.get())
2142 ekosLogOut->setPlainText(observatoryProcess->getLogText());
2143 else if (currentWidget == analyzeProcess.get())
2144 ekosLogOut->setPlainText(analyzeProcess->getLogText());
2151void Manager::appendLogText(
const QString &text)
2153 m_LogText.insert(0,
i18nc(
"log entry; %1 is the date, %2 is the text",
"%1 %2",
2154 KStarsData::Instance()->lt().
toString(
"yyyy-MM-ddThh:mm:ss"), text));
2156 qCInfo(KSTARS_EKOS) << text;
2163void Manager::clearLog()
2165 QWidget * currentWidget = toolsWidget->currentWidget();
2167 if (currentWidget == setupTab)
2172 else if (currentWidget == alignModule())
2173 alignModule()->clearLog();
2174 else if (currentWidget == captureModule())
2175 captureModule()->clearLog();
2176 else if (currentWidget == focusModule())
2177 focusModule()->clearLog();
2178 else if (currentWidget == guideModule())
2179 guideModule()->clearLog();
2180 else if (currentWidget == mountModule())
2181 mountModule()->clearLog();
2182 else if (currentWidget == schedulerModule())
2183 schedulerModule()->process()->clearLog();
2184 else if (currentWidget == observatoryProcess.get())
2185 observatoryProcess->clearLog();
2186 else if (currentWidget == analyzeProcess.get())
2187 analyzeProcess->clearLog();
2190void Manager::initCapture()
2192 if (captureModule() !=
nullptr)
2195 captureProcess.reset(
new Capture());
2197 emit newModule(
"Capture");
2200 if (mountModule() !=
nullptr)
2201 captureModule()->setMeridianFlipState(mountModule()->getMeridianFlipState());
2203 capturePreview->shareCaptureModule(captureModule());
2204 int index = addModuleTab(EkosModule::Capture, captureModule(), QIcon(
":/icons/ekos_ccd.png"));
2205 toolsWidget->tabBar()->setTabToolTip(index,
i18nc(
"Charge-Coupled Device",
"CCD"));
2206 if (Options::ekosLeftIcons())
2210 QIcon icon = toolsWidget->tabIcon(index);
2211 QPixmap pix = icon.
pixmap(QSize(48, 48));
2213 toolsWidget->setTabIcon(index, icon);
2215 connect(captureModule(), &Ekos::Capture::newLog,
this, &Ekos::Manager::updateLog);
2216 connect(captureModule(), &Ekos::Capture::newLog,
this, [
this]()
2218 QJsonObject cStatus =
2220 {
"log", captureModule()->getLogText()}
2223 ekosLiveClient.get()->message()->updateCaptureStatus(cStatus);
2225 connect(captureModule(), &Ekos::Capture::newStatus,
this, &Ekos::Manager::updateCaptureStatus);
2226 connect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
2227 connect(captureModule(), &Ekos::Capture::driverTimedout,
this, &Ekos::Manager::restartDriver);
2228 connect(captureModule(), &Ekos::Capture::newExposureProgress,
this, &Ekos::Manager::updateExposureProgress);
2229 capturePreview->setEnabled(
true);
2232 connect(captureModule(), &Ekos::Capture::newFilterStatus, capturePreview->captureStatusWidget,
2233 &LedStatusWidget::setFilterState);
2236 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
2238 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
this, [
this](
double distance)
2240 capturePreview->updateTargetDistance(distance);
2247void Manager::initAlign()
2249 if (alignModule() !=
nullptr)
2252 alignProcess.reset(
new Ekos::Align(m_CurrentProfile));
2254 emit newModule(
"Align");
2256 int index = addModuleTab(EkosModule::Align, alignModule(), QIcon(
":/icons/ekos_align.png"));
2257 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Align"));
2258 connect(alignModule(), &Ekos::Align::newLog,
this, &Ekos::Manager::updateLog);
2259 connect(alignModule(), &Ekos::Align::newLog,
this, [
this]()
2261 QJsonObject cStatus =
2263 {
"log", alignModule()->getLogText()}
2266 ekosLiveClient.get()->message()->updateAlignStatus(cStatus);
2268 connect(alignModule(), &Ekos::Align::newDownloadProgress,
this, [
this](QString info)
2270 QJsonObject cStatus =
2272 {
"downloadProgress", info}
2275 ekosLiveClient.get()->message()->updateAlignStatus(cStatus);
2277 if (Options::ekosLeftIcons())
2281 QIcon icon = toolsWidget->tabIcon(index);
2282 QPixmap pix = icon.
pixmap(QSize(48, 48));
2284 toolsWidget->setTabIcon(index, icon);
2290void Manager::initFocus()
2292 if (focusModule() !=
nullptr)
2295 focusProcess.reset(
new Ekos::FocusModule());
2297 emit newModule(
"Focus");
2299 int index = addModuleTab(EkosModule::Focus, focusModule(), QIcon(
":/icons/ekos_focus.png"));
2301 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Focus"));
2304 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStatus,
this, &Ekos::Manager::updateFocusStatus);
2305 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStarPixmap, focusProgressWidget,
2306 &Ekos::FocusProgressWidget::updateFocusStarPixmap);
2307 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newHFR,
this, &Ekos::Manager::updateCurrentHFR);
2309 connect(focusModule(), &Ekos::FocusModule::newLog,
this, [
this]()
2314 QJsonObject cStatus =
2316 {
"log", focusModule()->getLogText()}
2319 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2321 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusAdvisorMessage,
this, [
this](
const QString & message)
2323 QJsonObject cStatus =
2325 {
"focusAdvisorMessage", message}
2328 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2330 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusAdvisorStage, ekosLiveClient.get()->message(),
2333 QJsonObject cStatus =
2335 {
"focusAdvisorStage", stage}
2338 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2347 focusProgressWidget->hfrVPlot->init(str, starUnits, minimum, useWeights, showPosition);
2350 {
"focusinitHFRPlot",
true}
2353 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2359 focusProgressWidget->hfrVPlot->setTitle(title, plot);
2365 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2368 &FocusHFRVPlot::setTitle);
2370 &FocusHFRVPlot::redraw);
2372 &FocusHFRVPlot::addPosition);
2374 &FocusHFRVPlot::drawPolynomial);
2376 &FocusHFRVPlot::finalUpdates);
2378 &FocusHFRVPlot::drawMinimum);
2381 &FocusHFRVPlot::drawCurve);
2384 if (Options::ekosLeftIcons())
2388 QIcon icon = toolsWidget->tabIcon(index);
2391 toolsWidget->setTabIcon(index, icon);
2394 focusProgressWidget->init();
2395 focusProgressWidget->setEnabled(
true);
2397 for (
auto &oneDevice : INDIListener::devices())
2399 auto prop1 = oneDevice->getProperty(
"CCD_TEMPERATURE");
2400 auto prop2 = oneDevice->getProperty(
"FOCUSER_TEMPERATURE");
2401 auto prop3 = oneDevice->getProperty(
"WEATHER_PARAMETERS");
2402 if (prop1 || prop2 || prop3)
2403 focusModule()->addTemperatureSource(oneDevice);
2409void Manager::updateCurrentHFR(
double newHFR,
int position,
bool inAutofocus)
2411 Q_UNUSED(inAutofocus);
2412 focusProgressWidget->updateCurrentHFR(newHFR);
2414 QJsonObject cStatus =
2420 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2423void Manager::updateSigmas(
double ra,
double de)
2425 guideManager->updateSigmas(ra, de);
2427 QJsonObject cStatus = { {
"rarms", ra}, {
"derms", de} };
2429 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2432void Manager::initMount()
2434 if (mountModule() !=
nullptr)
2437 mountProcess.reset(
new Ekos::Mount());
2440 if (captureModule() !=
nullptr)
2441 captureModule()->setMeridianFlipState(mountModule()->getMeridianFlipState());
2443 emit newModule(
"Mount");
2445 int index = addModuleTab(EkosModule::Mount, mountModule(), QIcon(
":/icons/ekos_mount.png"));
2447 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Mount"));
2448 connect(mountModule(), &Ekos::Mount::newLog,
this, &Ekos::Manager::updateLog);
2455 connect(mountModule(), &Ekos::Mount::pierSideChanged,
this, [&](ISD::Mount::PierSide side)
2457 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject({{
"pierSide", side}}));
2459 connect(mountModule()->getMeridianFlipState().
get(),
2460 &Ekos::MeridianFlipState::newMountMFStatus, [&](MeridianFlipState::MeridianFlipMountState status)
2462 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject(
2464 {
"meridianFlipStatus",
status},
2467 connect(mountModule()->getMeridianFlipState().
get(),
2468 &Ekos::MeridianFlipState::newMeridianFlipMountStatusText, [&](
const QString & text)
2471 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject(
2473 {
"meridianFlipText", text},
2474 }), mountModule()->getMeridianFlipState()->getMeridianFlipMountState() == MeridianFlipState::MOUNT_FLIP_NONE);
2475 meridianFlipStatusWidget->setStatus(text);
2477 connect(mountModule(), &Ekos::Mount::autoParkCountdownUpdated,
this, [&](
const QString & text)
2479 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject({{
"autoParkCountdown", text}}),
true);
2482 connect(mountModule(), &Ekos::Mount::trainChanged, ekosLiveClient.get()->message(),
2485 connect(mountModule(), &Ekos::Mount::slewRateChanged,
this, [&](
int slewRate)
2487 QJsonObject
status = { {
"slewRate", slewRate} };
2488 ekosLiveClient.get()->message()->updateMountStatus(status);
2491 if (Options::ekosLeftIcons())
2495 QIcon icon = toolsWidget->tabIcon(index);
2496 QPixmap pix = icon.
pixmap(QSize(48, 48));
2498 toolsWidget->setTabIcon(index, icon);
2501 mountGroup->setEnabled(
true);
2502 capturePreview->shareMountModule(mountModule());
2507void Manager::initGuide()
2509 if (guideModule() ==
nullptr)
2511 guideProcess.reset(
new Ekos::Guide());
2513 emit newModule(
"Guide");
2516 if (toolsWidget->indexOf(guideModule()) == -1)
2521 int index = addModuleTab(EkosModule::Guide, guideModule(), QIcon(
":/icons/ekos_guide.png"));
2522 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Guide"));
2523 connect(guideModule(), &Ekos::Guide::newLog,
this, &Ekos::Manager::updateLog);
2524 connect(guideModule(), &Ekos::Guide::driverTimedout,
this, &Ekos::Manager::restartDriver);
2526 guideManager->setEnabled(
true);
2528 connect(guideModule(), &Ekos::Guide::newStatus,
this, &Ekos::Manager::updateGuideStatus);
2529 connect(guideModule(), &Ekos::Guide::newStarPixmap, guideManager, &Ekos::GuideManager::updateGuideStarPixmap);
2530 connect(guideModule(), &Ekos::Guide::newAxisSigma,
this, &Ekos::Manager::updateSigmas);
2531 connect(guideModule(), &Ekos::Guide::newAxisDelta, [&](
double ra,
double de)
2533 QJsonObject
status = { {
"drift_ra", ra}, {
"drift_de", de} };
2534 ekosLiveClient.get()->message()->updateGuideStatus(status);
2536 connect(guideModule(), &Ekos::Guide::newLog, ekosLiveClient.get()->message(),
2539 QJsonObject cStatus =
2541 {
"log", guideModule()->getLogText()}
2544 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2547 if (Options::ekosLeftIcons())
2551 QIcon icon = toolsWidget->tabIcon(index);
2552 QPixmap pix = icon.
pixmap(QSize(48, 48));
2554 toolsWidget->setTabIcon(index, icon);
2556 guideManager->init(guideModule());
2562void Manager::initObservatory()
2564 if (observatoryProcess.get() ==
nullptr)
2567 observatoryProcess.reset(
new Ekos::Observatory());
2569 emit newModule(
"Observatory");
2571 int index = addModuleTab(EkosModule::Observatory, observatoryProcess.get(), QIcon(
":/icons/ekos_observatory.png"));
2572 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Observatory"));
2573 connect(observatoryProcess.get(), &Ekos::Observatory::newLog,
this, &Ekos::Manager::updateLog);
2575 if (Options::ekosLeftIcons())
2579 QIcon icon = toolsWidget->tabIcon(index);
2580 QPixmap pix = icon.
pixmap(QSize(48, 48));
2582 toolsWidget->setTabIcon(index, icon);
2587void Manager::addGuider(ISD::Guider * device)
2589 appendLogText(
i18n(
"Guider port from %1 is ready.", device->getDeviceName()));
2592void Manager::removeTabs()
2596 for (
int i = numPermanentTabs; i < toolsWidget->count(); i++)
2597 toolsWidget->removeTab(i);
2599 alignProcess.reset();
2600 captureProcess.reset();
2601 focusProcess.reset();
2602 guideProcess.reset();
2603 mountProcess.reset();
2604 observatoryProcess.reset();
2609bool Manager::isRunning(
const QString &process)
2613 ps.
start(
"pgrep", QStringList() << process);
2616 return output.
length() > 0;
2618 ps.
start(
"ps", QStringList() <<
"-o"
2621 <<
"-C" << process);
2628void Manager::addObjectToScheduler(
SkyObject *
object)
2630 if (schedulerModule() !=
nullptr)
2631 schedulerModule()->addObject(
object);
2634QString Manager::getCurrentJobName()
2636 return schedulerModule()->getCurrentJobName();
2639bool Manager::setProfile(
const QString &profileName)
2641 int index = profileCombo->findText(profileName);
2646 profileCombo->setCurrentIndex(index);
2651void Manager::editNamedProfile(
const QJsonObject &profileInfo)
2653 ProfileEditor editor(
this);
2654 setProfile(profileInfo[
"name"].
toString());
2655 if (getCurrentProfile(m_CurrentProfile))
2657 editor.setPi(m_CurrentProfile);
2658 editor.setSettings(profileInfo);
2659 editor.saveProfile();
2663void Manager::addNamedProfile(
const QJsonObject &profileInfo)
2665 ProfileEditor editor(
this);
2667 editor.setSettings(profileInfo);
2668 editor.saveProfile();
2671 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2672 getCurrentProfile(m_CurrentProfile);
2675void Manager::deleteNamedProfile(
const QString &name)
2677 if (!getCurrentProfile(m_CurrentProfile))
2680 for (
auto &pi : profiles)
2684 if (pi->name ==
"Simulators" || pi->name != name || (pi.get() == m_CurrentProfile && ekosStatus() != Idle))
2687 KStarsData::Instance()->
userdb()->PurgeProfile(pi);
2690 getCurrentProfile(m_CurrentProfile);
2697 QJsonObject profileInfo;
2700 for (
auto &pi : profiles)
2702 if (name == pi->name)
2703 return pi->toJson();
2706 return QJsonObject();
2711 QStringList profiles;
2713 for (
int i = 0; i < profileCombo->count(); i++)
2714 profiles << profileCombo->itemText(i);
2719void Manager::addProfile()
2721 ProfileEditor editor(
this);
2727 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2730 getCurrentProfile(m_CurrentProfile);
2733void Manager::editProfile()
2735 ProfileEditor editor(
this);
2737 if (getCurrentProfile(m_CurrentProfile))
2740 editor.setPi(m_CurrentProfile);
2744 int currentIndex = profileCombo->currentIndex();
2748 profileCombo->setCurrentIndex(currentIndex);
2751 getCurrentProfile(m_CurrentProfile);
2755void Manager::deleteProfile()
2757 if (!getCurrentProfile(m_CurrentProfile))
2760 if (m_CurrentProfile->name ==
"Simulators")
2763 auto executeDeleteProfile = [&]()
2765 KStarsData::Instance()->
userdb()->PurgeProfile(m_CurrentProfile);
2768 getCurrentProfile(m_CurrentProfile);
2775 executeDeleteProfile();
2778 KSMessageBox::Instance()->questionYesNo(
i18n(
"Are you sure you want to delete the profile?"),
2779 i18n(
"Confirm Delete"));
2783void Manager::wizardProfile()
2789 ProfileEditor editor(
this);
2791 editor.setProfileName(wz.profileName);
2792 editor.setAuxDrivers(wz.selectedAuxDrivers());
2793 if (wz.useInternalServer ==
false)
2794 editor.setHostPort(wz.host, wz.port);
2795 editor.setWebManager(wz.useWebManager);
2796 editor.setGuiderType(wz.selectedExternalGuider());
2798 editor.setConnectionOptionsEnabled(
false);
2804 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2807 getCurrentProfile(m_CurrentProfile);
2813 for (
auto &pi : profiles)
2815 if (profileCombo->currentText() == pi->name)
2827 if (profile->city.isEmpty() ==
false)
2831 appendLogText(
i18n(
"Site location updated to %1.", KStarsData::Instance()->
geo()->
fullName()));
2833 appendLogText(
i18n(
"Failed to update site location to %1. City not found.",
2838void Manager::updateMountStatus(ISD::Mount::Status status)
2840 static ISD::Mount::Status lastStatus = ISD::Mount::MOUNT_IDLE;
2842 if (status == lastStatus)
2847 mountStatus->setMountState(mountModule()->statusString(), status);
2848 mountStatus->setStyleSheet(QString());
2850 QJsonObject cStatus =
2852 {
"status", mountModule()->statusString(
false)}
2855 ekosLiveClient.get()->message()->updateMountStatus(cStatus);
2858void Manager::updateMountCoords(
const SkyPoint position, ISD::Mount::PierSide pierSide,
const dms &ha)
2866 QJsonObject cStatus =
2877 ekosLiveClient.get()->message()->updateMountStatus(cStatus,
true);
2882 capturePreview->updateCaptureStatus(status, captureModule()->isActiveJobPreview(), trainname);
2891 m_CountdownTimer.stop();
2894 m_CountdownTimer.start();
2900 QJsonObject cStatus =
2903 {
"seqt", capturePreview->captureCountsWidget->sequenceRemainingTime->text()},
2904 {
"ovt", capturePreview->captureCountsWidget->overallRemainingTime->text()},
2905 {
"train", trainname}
2908 ekosLiveClient.get()->message()->updateCaptureStatus(cStatus);
2914 capturePreview->updateJobProgress(job, data, trainname);
2918 {
"seqv", job->getCompleted()},
2919 {
"seqr", job->getCoreProperty(SequenceJob::SJ_Count).toInt()},
2920 {
"seql", capturePreview->captureCountsWidget->sequenceRemainingTime->text()}
2923 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2925 if (data && job->getStatus() == JOB_BUSY)
2929 if (Options::useFITSViewer() ==
false)
2930 ekosLiveClient.get()->media()->sendData(data, data->objectName());
2932 if (job->jobType() != SequenceJob::JOBTYPE_PREVIEW)
2933 ekosLiveClient.get()->cloud()->sendData(data, data->objectName());
2941 {
"expv", job->getExposeLeft()},
2942 {
"expr", job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble()},
2943 {
"train", trainname}
2946 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2949void Manager::updateCaptureCountDown()
2951 capturePreview->updateCaptureCountDown(-1);
2955 {
"seqt", capturePreview->captureCountsWidget->sequenceRemainingTime->text()},
2956 {
"ovt", capturePreview->captureCountsWidget->overallRemainingTime->text()},
2957 {
"ovp", capturePreview->captureCountsWidget->gr_overallProgressBar->value()},
2958 {
"ovl", capturePreview->captureCountsWidget->gr_overallLabel->text()}
2961 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2965void Manager::updateFocusStatus(Ekos::FocusState status)
2967 focusProgressWidget->updateFocusStatus(status);
2969 QJsonObject cStatus =
2971 {
"status", getFocusStatusString(status,
false)}
2974 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2977void Manager::updateGuideStatus(Ekos::GuideState status)
2979 guideManager->updateGuideStatus(status);
2980 QJsonObject cStatus =
2982 {
"status", getGuideStatusString(status,
false)}
2985 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2988void Manager::setTarget(
const QString &name)
2990 capturePreview->targetLabel->setVisible(!
name.
isEmpty());
2991 capturePreview->mountTarget->setVisible(!
name.
isEmpty());
2992 capturePreview->mountTarget->setText(name);
2993 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject({{
"target",
name}}));
2996 mountModule()->setTargetName(name);
2999void Manager::showEkosOptions()
3001 QWidget * currentWidget = toolsWidget->currentWidget();
3003 if (alignModule() && alignModule() == currentWidget)
3009 alignSettings->
show();
3014 if (guideModule() && guideModule() == currentWidget)
3020 if (focusModule() && focusModule() == currentWidget)
3022 focusModule()->showOptions();
3026 if (schedulerModule() == currentWidget)
3038 if(captureModule() == currentWidget)
3050 const bool isAnalyze = (analyzeProcess.get() && analyzeProcess.get() == currentWidget);
3056 if (isAnalyze) index = 1;
3057 opsEkos->setCurrentIndex(index);
3070 if (ekosOptionsWidget ==
nullptr)
3087void Manager::updateDebugInterfaces()
3091 for (
auto &device : INDIListener::devices())
3093 auto debugProp = device->getProperty(
"DEBUG");
3097 auto debugSP = debugProp.getSwitch();
3100 if ( ( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
3101 debugSP->sp[0].s != ISS_ON)
3103 debugSP->at(0)->setState(ISS_ON);
3104 debugSP->at(1)->setState(ISS_OFF);
3106 appendLogText(
i18n(
"Enabling debug logging for %1...", device->getDeviceName()));
3108 else if ( !( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
3109 debugSP->sp[0].s != ISS_OFF)
3111 debugSP->at(0)->setState(ISS_OFF);
3112 debugSP->at(1)->setState(ISS_ON);
3114 appendLogText(
i18n(
"Disabling debug logging for %1...", device->getDeviceName()));
3117 if (opsLogs->isINDISettingsChanged())
3118 device->setConfig(SAVE_CONFIG);
3122void Manager::watchDebugProperty(INDI::Property prop)
3124 if (prop.isNameMatch(
"DEBUG"))
3126 auto svp = prop.getSwitch();
3128 ISD::GenericDevice * deviceInterface = qobject_cast<ISD::GenericDevice *>(sender());
3131 if (deviceInterface->getDriverInterface() == INDI::BaseDevice::GENERAL_INTERFACE)
3136 if (svp->s == IPS_OK && svp->sp[0].s == ISS_OFF &&
3137 (opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
3139 svp->sp[0].s = ISS_ON;
3140 svp->sp[1].s = ISS_OFF;
3141 deviceInterface->sendNewProperty(svp);
3142 appendLogText(
i18n(
"Re-enabling debug logging for %1...", deviceInterface->getDeviceName()));
3148 else if (svp->s == IPS_OK && svp->sp[0].s == ISS_ON
3149 && !(opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
3151 svp->sp[0].s = ISS_OFF;
3152 svp->sp[1].s = ISS_ON;
3153 deviceInterface->sendNewProperty(svp);
3154 appendLogText(
i18n(
"Re-disabling debug logging for %1...", deviceInterface->getDeviceName()));
3159void Manager::announceEvent(
const QString &message, KSNotification::EventSource source, KSNotification::EventType event)
3161 ekosLiveClient.get()->message()->sendEvent(message, source, event);
3164void Manager::connectModules()
3167 connect(DarkLibrary::Instance(), &DarkLibrary::newImage, ekosLiveClient.get()->media(),
3169 connect(DarkLibrary::Instance(), &DarkLibrary::trainChanged, ekosLiveClient.get()->message(),
3171 connect(DarkLibrary::Instance(), &DarkLibrary::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3173 connect(DarkLibrary::Instance(), &DarkLibrary::settingsUpdated, ekosLiveClient.get()->message(),
3177 if (captureProcess && guideProcess)
3183 connect(guideModule(), &Ekos::Guide::newStatus, captureModule(), &Ekos::Capture::setGuideStatus,
3198 connect(guideModule(), &Ekos::Guide::guideChipUpdated, captureModule(), &Ekos::Capture::setGuideChip,
3204 connect(captureModule(), &Ekos::Capture::guideAfterMeridianFlip, guideModule(),
3209 if (guideProcess && mountProcess)
3220 if (guideProcess && focusProcess)
3230 if (captureProcess && focusProcess)
3233 connect(captureModule(), &Ekos::Capture::checkFocus, focusModule(), &Ekos::FocusModule::checkFocus,
3237 connect(captureProcess.get(), &Ekos::Capture::runAutoFocus, focusModule(), &Ekos::FocusModule::runAutoFocus,
3241 connect(captureModule(), &Ekos::Capture::resetFocusFrame, focusModule(), &Ekos::FocusModule::resetFrame,
3252 connect(captureModule(), &Ekos::Capture::adaptiveFocus, focusModule(), &Ekos::FocusModule::adaptiveFocus,
3263 connect(focusModule(), &Ekos::FocusModule::newFocusTemperatureDelta, captureModule(),
3267 connect(focusModule(), &Ekos::FocusModule::inSequenceAF, captureModule(),
3271 connect(captureModule(), &Ekos::Capture::meridianFlipStarted, focusModule(), &Ekos::FocusModule::meridianFlipStarted,
3276 if (captureProcess && alignProcess)
3279 connect(alignModule(), &Ekos::Align::newStatus, captureModule(), &Ekos::Capture::setAlignStatus,
3282 connect(alignModule(), &Ekos::Align::newSolverResults, captureModule(), &Ekos::Capture::setAlignResults,
3285 connect(captureModule(), &Ekos::Capture::newStatus, alignModule(), &Ekos::Align::setCaptureStatus,
3290 if (captureProcess && mountProcess)
3294 captureModule()->registerNewModule(
"Mount");
3295 mountModule()->registerNewModule(
"Capture");
3311 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated, ekosLiveClient->message(),
3313 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::configurationRequested, ekosLiveClient->message(),
3318 if (captureProcess && ekosLiveClient)
3322 connect(captureModule(), &Ekos::Capture::dslrInfoRequested, ekosLiveClient.get()->message(),
3324 connect(captureModule(), &Ekos::Capture::sequenceChanged, ekosLiveClient.get()->message(),
3326 connect(captureModule(), &Ekos::Capture::settingsUpdated, ekosLiveClient.get()->message(),
3328 connect(captureModule(), &Ekos::Capture::newLocalPreview, ekosLiveClient.get()->message(),
3330 connect(captureModule(), &Ekos::Capture::trainChanged, ekosLiveClient.get()->message(),
3335 if (focusProcess && alignProcess)
3337 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStatus, alignModule(), &Ekos::Align::setFocusStatus,
3342 if (focusProcess && mountProcess)
3349 if (mountProcess && alignProcess)
3362 if (mountProcess && guideProcess)
3364 connect(mountModule(), &Ekos::Mount::pierSideChanged, guideModule(), &Ekos::Guide::setPierSide,
3369 if (alignProcess && ekosLiveClient)
3374 connect(alignModule(), &Ekos::Align::newStatus, ekosLiveClient.get()->message(), &EkosLive::Message::setAlignStatus,
3376 connect(alignModule(), &Ekos::Align::newSolution, ekosLiveClient.get()->message(),
3378 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHStage,
3379 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHStage,
3381 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHMessage,
3382 ekosLiveClient.get()->message(),
3384 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::PAHEnabled,
3385 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHEnabled,
3387 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::polarResultUpdated,
3388 ekosLiveClient.get()->message(),
3390 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::updatedErrorsChanged,
3391 ekosLiveClient.get()->message(),
3393 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newCorrectionVector,
3394 ekosLiveClient.get()->media(),
3397 connect(alignModule(), &Ekos::Align::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3399 connect(alignModule(), &Ekos::Align::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendUpdatedFrame,
3402 connect(alignModule(), &Ekos::Align::settingsUpdated, ekosLiveClient.get()->message(),
3405 connect(alignModule(), &Ekos::Align::trainChanged, ekosLiveClient.get()->message(),
3408 connect(alignModule(), &Ekos::Align::manualRotatorChanged, ekosLiveClient.get()->message(),
3413 if (focusProcess && ekosLiveClient)
3415 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::settingsUpdated, ekosLiveClient.get()->message(),
3418 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newImage, ekosLiveClient.get()->media(),
3419 &EkosLive::Media::sendModuleFrame,
3422 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::trainChanged, ekosLiveClient.get()->message(),
3423 &EkosLive::Message::sendTrainProfiles,
3426 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusAborted,
3431 if (guideProcess && ekosLiveClient)
3433 connect(guideModule(), &Ekos::Guide::settingsUpdated, ekosLiveClient.get()->message(),
3436 connect(guideModule(), &Ekos::Guide::trainChanged, ekosLiveClient.get()->message(),
3439 connect(guideModule(), &Ekos::Guide::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3447 connect(schedulerModule(), &Ekos::Scheduler::jobStarted,
3449 connect(schedulerModule(), &Ekos::Scheduler::jobEnded,
3451 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
3457 connect(captureModule(), &Ekos::Capture::captureComplete,
3459 connect(captureModule(), &Ekos::Capture::captureStarting,
3461 connect(captureModule(), &Ekos::Capture::captureAborted,
3465 connect(captureModule(), &Ekos::Capture::meridianFlipStarted,
3467 connect(captureModule(), &Ekos::Capture::meridianFlipCompleted,
3475 connect(guideModule(), &Ekos::Guide::newStatus,
3478 connect(guideModule(), &Ekos::Guide::guideStats,
3485 if (focusProcess && analyzeProcess)
3487 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusComplete,
3491 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusStarting,
3493 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusAborted,
3495 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusTemperatureDelta,
3500 if (alignProcess && analyzeProcess)
3502 connect(alignModule(), &Ekos::Align::newStatus,
3508 if (mountProcess && analyzeProcess)
3514 connect(mountModule()->getMeridianFlipState().
get(), &Ekos::MeridianFlipState::newMountMFStatus,
3519void Manager::setEkosLiveConnected(
bool enabled)
3521 ekosLiveClient.get()->setConnected(enabled);
3524void Manager::setEkosLiveConfig(
bool rememberCredentials,
bool autoConnect)
3526 ekosLiveClient.get()->setConfig(rememberCredentials, autoConnect);
3529void Manager::setEkosLiveUser(
const QString &username,
const QString &password)
3531 ekosLiveClient.get()->setUser(username, password);
3534bool Manager::ekosLiveStatus()
3536 return ekosLiveClient.get()->isConnected();
3542 if (!primaryDriver || !secondaryDriver)
3545 return (primaryDriver->getExecutable() == secondaryDriver->getExecutable() &&
3546 primaryDriver->getAuxInfo().value(
"mdpd",
false).toBool() ==
true);
3549void Manager::restartDriver(
const QString &deviceName)
3551 qCInfo(KSTARS_EKOS) <<
"Restarting driver" << deviceName;
3554 for (
auto &oneDevice : INDIListener::devices())
3556 if (oneDevice->getDeviceName() == deviceName)
3558 DriverManager::Instance()->restartDriver(oneDevice->getDriverInfo());
3564 INDI::WebManager::restartDriver(m_CurrentProfile, deviceName);
3567void Manager::setEkosLoggingEnabled(
const QString &name,
bool enabled)
3570 if (name ==
"LOGGING")
3572 Options::setDisableLogging(!enabled);
3576 else if (name ==
"FILE")
3578 Options::setLogToFile(enabled);
3582 else if (name ==
"DEFAULT")
3584 Options::setLogToDefault(enabled);
3589 else if (name ==
"VERBOSE")
3591 Options::setVerboseLogging(enabled);
3595 else if (name ==
"INDI")
3597 Options::setINDILogging(enabled);
3600 else if (name ==
"FITS")
3602 Options::setFITSLogging(enabled);
3605 else if (name ==
"CAPTURE")
3607 Options::setCaptureLogging(enabled);
3608 Options::setINDICCDLogging(enabled);
3609 Options::setINDIFilterWheelLogging(enabled);
3612 else if (name ==
"FOCUS")
3614 Options::setFocusLogging(enabled);
3615 Options::setINDIFocuserLogging(enabled);
3618 else if (name ==
"GUIDE")
3620 Options::setGuideLogging(enabled);
3621 Options::setINDICCDLogging(enabled);
3624 else if (name ==
"ALIGNMENT")
3626 Options::setAlignmentLogging(enabled);
3629 else if (name ==
"MOUNT")
3631 Options::setMountLogging(enabled);
3632 Options::setINDIMountLogging(enabled);
3635 else if (name ==
"SCHEDULER")
3637 Options::setSchedulerLogging(enabled);
3640 else if (name ==
"OBSERVATORY")
3642 Options::setObservatoryLogging(enabled);
3647void Manager::acceptPortSelection()
3650 m_PortSelector->accept();
3653void Manager::setPortSelectionComplete()
3655 if (m_CurrentProfile->portSelector)
3658 m_CurrentProfile->portSelector =
false;
3659 KStarsData::Instance()->
userdb()->SaveProfile(m_CurrentProfile);
3662 if (m_CurrentProfile->autoConnect)
3666void Manager::activateModule(
const QString &name,
bool popup)
3668 auto child = toolsWidget->findChild<QWidget *>(
name);
3671 toolsWidget->setCurrentWidget(child);
3683 if (device->isConnected())
3685 if (device->getDriverInterface() & INDI::BaseDevice::CCD_INTERFACE)
3692 if (device->getDriverInterface() & INDI::BaseDevice::FILTER_INTERFACE)
3698 if (device->getDriverInterface() & INDI::BaseDevice::FOCUSER_INTERFACE)
3700 if (device->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)
3707 if (device->getDriverInterface() & INDI::BaseDevice::ROTATOR_INTERFACE)
3712 if (device->getDriverInterface() & INDI::BaseDevice::DOME_INTERFACE)
3718 if (device->getDriverInterface() & INDI::BaseDevice::WEATHER_INTERFACE)
3723 if (device->getDriverInterface() & INDI::BaseDevice::DUSTCAP_INTERFACE)
3727 if (device->getDriverInterface() & INDI::BaseDevice::LIGHTBOX_INTERFACE)
3731 if (device->getDriverInterface() & INDI::BaseDevice::GPS_INTERFACE)
3738void Manager::setDeviceReady()
3742 if (isINDIReady() ==
false)
3744 auto device =
static_cast<ISD::GenericDevice*
>(sender());
3748 if (device->isConnected() ==
false && m_CurrentProfile->autoConnect)
3751 if (m_CurrentProfile->portSelector)
3757 if (!m_PortSelector)
3758 m_PortSelectorTimer.start();
3762 qCInfo(KSTARS_EKOS) <<
"Connecting to" << device->getDeviceName();
3767 qCInfo(KSTARS_EKOS) << device->getDeviceName() <<
"is connected and ready.";
3770 if (m_ekosStatus != Ekos::Success)
3775 if (m_DriverDevicesCount <= 0 && (m_CurrentProfile->portSelector ==
false || !m_PortSelector))
3777 for (
auto &device : INDIListener::devices())
3778 syncGenericDevice(device);
3779 OpticalTrainManager::Instance()->setProfile(m_CurrentProfile);
3783void Manager::createFilterManager(ISD::FilterWheel *device)
3785 auto name = device->getDeviceName();
3786 if (m_FilterManagers.contains(name) ==
false)
3788 QSharedPointer<FilterManager> newFM(
new FilterManager(
this));
3789 newFM->setFilterWheel(device);
3790 m_FilterManagers.insert(name, std::move(newFM));
3793 m_FilterManagers[
name]->setFilterWheel(device);
3799 if (m_FilterManagers.contains(name))
3801 fm = m_FilterManagers[
name];
3809 if (m_FilterManagers.size() > 0)
3811 fm = m_FilterManagers.values()[0];
3817void Manager::createRotatorController(
ISD::Rotator *device)
3819 auto Name = device->getDeviceName();
3820 if (m_RotatorControllers.contains(Name) ==
false)
3822 QSharedPointer<RotatorSettings> newRC(
new RotatorSettings(
this));
3824 m_RotatorControllers[Name] = newRC;
3830 if (m_RotatorControllers.contains(Name))
3832 rs = m_RotatorControllers[Name];
3838bool Manager::existRotatorController()
3840 return (!m_RotatorControllers.empty());
3843void Manager::setFITSfromFile(
bool previewFromFile)
3845 if (previewFromFile && !FITSfromFile)
3848 QObject::disconnect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
3849 FITSfromFile = previewFromFile;
3850 appendLogText(
i18n(
"Preview source set to external"));
3852 else if (!previewFromFile && FITSfromFile)
3855 QObject::connect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
3856 FITSfromFile = previewFromFile;
3857 appendLogText(
i18n(
"Preview source reset to internal"));
3861void Manager::previewFile(
QString filePath)
3863 capturePreview->updateJobPreview(filePath);
3864 appendLogText(
i18n(
"Received external preview file"));
Analysis tab for Ekos sessions.
void setHFR(double newHFR, int position, bool inAutofocus, const QString &trainname)
setHFR Receive the measured HFR value of the latest frame
void updateTargetDistance(double targetDiff)
Slot receiving the update of the current target distance.
void inSequenceAFRequested(bool requested, const QString &trainname)
inSequenceAFRequested Focuser informs that the user wishes an AF run as soon as possible.
void setFocusStatus(FocusState newstate, const QString &trainname)
setFocusStatus Forward the new focus state to the capture module state machine
void setFocusTemperatureDelta(double focusTemperatureDelta, double absTemperature, const QString &trainname)
setFocusTemperatureDelta update the focuser's temperature delta
void setGuideDeviation(double delta_ra, double delta_dec)
setGuideDeviation Set the guiding deviation as measured by the guiding module.
void focusAdaptiveComplete(bool success, const QString &trainname)
focusAdaptiveComplete Forward the new focus state to the capture module state machine
void drawPolynomial(PolynomialFit *poly, bool isVShape, bool activate, bool plot=true)
draw the approximating polynomial into the HFR V-graph
void newHFRPlotPosition(double pos, double hfr, double sigma, bool outlier, int pulseDuration, bool plot=true)
new HFR plot position with sigma
void redrawHFRPlot(PolynomialFit *poly, double solutionPosition, double solutionValue)
redraw the entire HFR plot
void focuserTimedout(const QString &focuser)
focuserTimedout responding to requests
void initHFRPlot(QString str, double starUnits, bool minimum, bool useWeights, bool showPosition)
initialize the HFR V plot
void drawCFZ(double minPosition, double minValue, int m_cfzSteps, bool plt)
Draw Critical Focus Zone on graph.
void finalUpdates(const QString &title, bool plot=true)
final updates after focus run comopletes on the focus plot
void minimumFound(double solutionPosition, double solutionValue, bool plot=true)
Focus solution with minimal HFR found.
void setTitle(const QString &title, bool plot=true)
draw a title on the focus plot
void drawCurve(CurveFitting *curve, bool isVShape, bool activate, bool plot=true)
draw the curve into the HFR V-graph
void adaptiveFocusComplete(const QString &filter, double temperature, double tempTicks, double altitude, double altTicks, int prevPosError, int thisPosError, int totalTicks, int position, bool focuserMoved)
Signal Analyze that an Adaptive Focus iteration is complete.
Q_SCRIPTABLE bool resume()
DBUS interface function.
Q_SCRIPTABLE bool suspend()
DBUS interface function.
Q_SCRIPTABLE bool dither()
DBUS interface function.
void resetNonGuidedDither()
Reset non guided dithering properties and initialize the random generator seed if not already done.
Q_SCRIPTABLE bool abort()
DBUS interface function.
void newTarget(SkyPoint ¤tCoord)
The mount has finished the slew to a new target.
void paaStageChanged(int stage)
React upon status changes of the polar alignment - mainly to avoid meridian flips happening during po...
void newTargetName(const QString &name)
The mount has finished the slew to a new target.
void newStatus(ISD::Mount::Status status)
Change in the mount status.
void suspendAltLimits()
suspendAltLimits calls enableAltitudeLimits(false).
void newCoords(const SkyPoint &position, ISD::Mount::PierSide pierSide, const dms &ha)
Update event with the current telescope position.
void resumeAltLimits()
resumeAltLimits calls enableAltitudeLimits(true).
Enables the user to set logging options.
Camera class controls an INDI Camera device.
void sendNewProperty(INDI::Property prop)
Send new property command to server.
Class handles control of INDI dome devices.
Handles operation of a remotely controlled dust cover cap.
Focuser class handles control of INDI focuser devices.
Handles operation of a remotely controlled light box.
device handle controlling Mounts.
Rotator class handles control of INDI Rotator devices.
Focuser class handles control of INDI Weather devices.
Q_INVOKABLE QAction * action(const QString &name) const
static bool showDialog(const QString &name)
KPageWidgetItem * addPage(QWidget *page, const QString &itemName, const QString &pixmapName=QString(), const QString &header=QString(), bool manage=true)
static KConfigDialog * exists(const QString &name)
static void beep(const QString &reason=QString())
QPushButton * button(QDialogButtonBox::StandardButton which) const
void setCurrentPage(KPageWidgetItem *item)
void setIcon(const QIcon &icon)
bool GetAllProfiles(QList< QSharedPointer< ProfileInfo > > &profiles)
GetAllProfiles Return all profiles in a QList.
static void UseDefault()
Use the default logging mechanism.
static void SyncFilterRules()
SyncFilterRules Sync QtLogging filter rules from Options.
static void Disable()
Disable logging.
static void UseFile()
Store all logs into the specified file.
Q_INVOKABLE SimClock * clock()
static KStars * Instance()
Q_SCRIPTABLE bool setGeoLocation(const QString &city, const QString &province, const QString &country)
DBUS interface function.
virtual KActionCollection * actionCollection() const
void setRealTime(bool on=true)
Realtime mode will lock SimClock with system clock.
Provides all necessary information about an object in the sky: its coordinates, name(s),...
The sky coordinates of a point in the sky.
const CachingDms & dec() const
const CachingDms & ra0() const
const CachingDms & ra() const
const CachingDms & dec0() const
An angle, stored as degrees, but expressible in many ways.
static dms fromString(const QString &s, bool deg)
Static function to create a DMS object from a QString.
const QString toDMSString(const bool forceSign=false, const bool machineReadable=false, const bool highPrecision=false) const
const QString toHMSString(const bool machineReadable=false, const bool highPrecision=false) const
const double & Degrees() const
void setTarget(const SkyPoint &targetCoord)
Set the alignment target where the mount is expected to point at.
void setTelescopeCoordinates(const SkyPoint &position)
Set the coordinates that the mount reports as its position.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QString fullName(const PartType &type)
char * toString(const EngineQuery &query)
Ekos is an advanced Astrophotography tool for Linux.
CaptureState
Capture states.
KIOCORE_EXPORT SimpleJob * mount(bool ro, const QByteArray &fstype, const QString &dev, const QString &point, JobFlags flags=DefaultFlags)
KIOCORE_EXPORT TransferJob * get(const QUrl &url, LoadType reload=NoReload, JobFlags flags=DefaultFlags)
GeoCoordinates geo(const QVariant &location)
QVariant location(const QVariant &res)
ButtonCode warningContinueCancel(QWidget *parent, const QString &text, const QString &title=QString(), const KGuiItem &buttonContinue=KStandardGuiItem::cont(), const KGuiItem &buttonCancel=KStandardGuiItem::cancel(), const QString &dontAskAgainName=QString(), Options options=Notify)
QString name(StandardAction id)
QString label(StandardShortcut id)
NETWORKMANAGERQT_EXPORT NetworkManager::Status status()
void currentTextChanged(const QString &text)
QCoreApplication * instance()
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
QDBusConnection sessionBus()
bool openUrl(const QUrl &url)
int exec(ProcessEventsFlags flags)
void setFuture(const QFuture< T > &future)
QPixmap pixmap(QWindow *window, const QSize &size, Mode mode, State state) const const
QIcon fromTheme(const QString &name)
QJsonArray array() const const
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
void append(QList< T > &&value)
const_reference at(qsizetype i) const const
bool contains(const AT &value) const const
qsizetype count() const const
bool isEmpty() const const
qsizetype length() const const
QString name() const const
NetworkError error() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QByteArray readAllStandardOutput()
void start(OpenMode mode)
bool waitForFinished(int msecs)
QString & append(QChar ch)
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString fromLatin1(QByteArrayView str)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString trimmed() const const
QString join(QChar separator) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setInterval(int msec)
bool isActive() const const
void setSingleShot(bool singleShot)