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();
824 if (!Options::dontSyncToRealTime())
831 getCurrentProfile(m_CurrentProfile);
832 m_LocalMode = m_CurrentProfile->isLocal();
834 ProfileSettings::Instance()->setProfile(m_CurrentProfile);
837 updateProfileLocation(m_CurrentProfile);
839 bool haveCCD =
false, haveGuider =
false;
843 if (m_CurrentProfile->guidertype == Ekos::Guide::GUIDE_PHD2)
845 Options::setPHD2Host(m_CurrentProfile->guiderhost);
846 Options::setPHD2Port(m_CurrentProfile->guiderport);
848 else if (m_CurrentProfile->guidertype == Ekos::Guide::GUIDE_LINGUIDER)
850 Options::setLinGuiderHost(m_CurrentProfile->guiderhost);
851 Options::setLinGuiderPort(m_CurrentProfile->guiderport);
855 QJsonParseError jsonError;
856 QJsonArray profileScripts;
860 profileScripts = doc.
array();
862 ekosLiveClient->message()->setPendingPropertiesEnabled(
true);
867 auto drv = driversList.value(m_CurrentProfile->mount());
870 managedDrivers.append(drv->clone());
872 drv = driversList.value(m_CurrentProfile->ccd());
875 managedDrivers.append(drv->clone());
879 Options::setGuiderType(m_CurrentProfile->guidertype);
881 drv = driversList.value(m_CurrentProfile->guider());
892 if (haveCCD && m_CurrentProfile->guider() == m_CurrentProfile->ccd())
894 if (checkUniqueBinaryDriver( driversList.value(m_CurrentProfile->ccd()), drv))
900 drv->setUniqueLabel(drv->getLabel() +
" Guide");
905 managedDrivers.append(drv->clone());
908 drv = driversList.value(m_CurrentProfile->ao());
910 managedDrivers.append(drv->clone());
912 drv = driversList.value(m_CurrentProfile->filter());
914 managedDrivers.append(drv->clone());
916 drv = driversList.value(m_CurrentProfile->focuser());
918 managedDrivers.append(drv->clone());
920 drv = driversList.value(m_CurrentProfile->dome());
922 managedDrivers.append(drv->clone());
924 drv = driversList.value(m_CurrentProfile->weather());
926 managedDrivers.append(drv->clone());
928 drv = driversList.value(m_CurrentProfile->aux1());
931 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
932 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
933 managedDrivers.append(drv->clone());
935 drv = driversList.value(m_CurrentProfile->aux2());
938 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
939 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
940 managedDrivers.append(drv->clone());
943 drv = driversList.value(m_CurrentProfile->aux3());
946 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
947 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
948 managedDrivers.append(drv->clone());
951 drv = driversList.value(m_CurrentProfile->aux4());
954 if (!checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->ccd()), drv) &&
955 !checkUniqueBinaryDriver(driversList.value(m_CurrentProfile->guider()), drv))
956 managedDrivers.append(drv->clone());
960 if (m_CurrentProfile->remotedrivers.isEmpty() ==
false && m_CurrentProfile->remotedrivers.contains(
"@"))
962 for (
auto remoteDriver : m_CurrentProfile->remotedrivers.split(
","))
964 QString
name,
label, host(
"localhost"), port(
"7624"), hostport(host +
':' + port);
974 QStringList device_location = remoteDriver.split(
'@');
977 if (device_location.
length() > 0)
978 name = device_location[0];
981 if (device_location.
length() > 1)
982 hostport = device_location[1];
986 QStringList
location = hostport.split(
':');
997 QSharedPointer<DriverInfo> dv(
new DriverInfo(name));
998 dv->setRemoteHost(host);
999 dv->setRemotePort(port);
1004 dv->setLabel(label);
1005 dv->setUniqueLabel(label);
1006 managedDrivers.
append(dv);
1011 if (haveCCD ==
false && haveGuider ==
false && m_CurrentProfile->remotedrivers.isEmpty())
1013 KSNotification::error(
i18n(
"Ekos requires at least one CCD or Guider to operate."));
1014 managedDrivers.clear();
1015 m_ekosStatus = Ekos::Error;
1016 emit ekosStatusChanged(m_ekosStatus);
1020 m_DriverDevicesCount = managedDrivers.count();
1024 QSharedPointer<DriverInfo> remote_indi(
new DriverInfo(QString(
"Ekos Remote Host")));
1026 remote_indi->setHostParameters(m_CurrentProfile->host, m_CurrentProfile->port);
1028 remote_indi->setDriverSource(GENERATED_SOURCE);
1030 managedDrivers.append(remote_indi);
1032 haveCCD = m_CurrentProfile->drivers.contains(
"CCD");
1033 haveGuider = m_CurrentProfile->drivers.contains(
"Guider");
1035 Options::setGuiderType(m_CurrentProfile->guidertype);
1037 if (haveCCD ==
false && haveGuider ==
false && m_CurrentProfile->remotedrivers.isEmpty())
1039 KSNotification::error(
i18n(
"Ekos requires at least one CCD or Guider to operate."));
1040 m_DriverDevicesCount = 0;
1041 m_ekosStatus = Ekos::Error;
1042 emit ekosStatusChanged(m_ekosStatus);
1046 m_DriverDevicesCount = m_CurrentProfile->drivers.count();
1051 QList<QSharedPointer<DriverInfo >> sortedList;
1052 for (
const auto &oneRule : qAsConst(profileScripts))
1054 auto driver = oneRule.toObject()[
"Driver"].toString();
1055 auto matchingDriver = std::find_if(managedDrivers.begin(), managedDrivers.end(), [oneRule, driver](
const auto & oneDriver)
1058 return oneDriver->getLabel() == driver || (driver.startsWith(
"@") && !oneDriver->getRemoteHost().isEmpty());
1061 if (matchingDriver != managedDrivers.end())
1063 (*matchingDriver)->setStartupShutdownRule(oneRule.toObject());
1064 sortedList.
append(*matchingDriver);
1072 for (
auto &oneDriver : managedDrivers)
1074 if (sortedList.
contains(oneDriver) ==
false)
1075 sortedList.
append(oneDriver);
1078 managedDrivers = sortedList;
1081 connect(DriverManager::Instance(), &DriverManager::serverStarted,
this,
1083 connect(DriverManager::Instance(), &DriverManager::serverFailed,
this,
1085 connect(DriverManager::Instance(), &DriverManager::clientStarted,
this,
1087 connect(DriverManager::Instance(), &DriverManager::clientFailed,
this,
1089 connect(DriverManager::Instance(), &DriverManager::clientTerminated,
this,
1092 connect(INDIListener::Instance(), &INDIListener::newDevice,
this, &Ekos::Manager::processNewDevice);
1097 if (m_LocalMode || m_CurrentProfile->host ==
"localhost")
1099 if (isRunning(
"PTPCamera"))
1102 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?"),
1103 i18n(
"PTP Camera")))
1107 p.
start(
"killall PTPCamera");
1115 auto executeStartINDIServices = [
this]()
1117 appendLogText(
i18n(
"Starting INDI services..."));
1119 m_ekosStatus = Ekos::Pending;
1120 emit ekosStatusChanged(m_ekosStatus);
1122 DriverManager::Instance()->startDevices(managedDrivers);
1126 if (isRunning(
"indiserver"))
1131 DriverManager::Instance()->stopAllDevices();
1134 const QString program =
"pkill";
1135 QStringList arguments;
1136 arguments <<
"indiserver";
1137 p.
start(program, arguments);
1145 executeStartINDIServices();
1148 KSMessageBox::Instance()->questionYesNo(
i18n(
"Ekos detected an instance of INDI server running. Do you wish to "
1149 "shut down the existing instance before starting a new one?"),
1150 i18n(
"INDI Server"), 5);
1153 executeStartINDIServices();
1158 auto runConnection = [
this]()
1161 if (m_ekosStatus != Ekos::Pending)
1165 i18n(
"Connecting to remote INDI server at %1 on port %2 ...", m_CurrentProfile->host, m_CurrentProfile->port));
1167 DriverManager::Instance()->connectRemoteHost(managedDrivers.first());
1170 auto runProfile = [
this, runConnection]()
1173 if (m_ekosStatus != Ekos::Pending)
1176 INDI::WebManager::syncCustomDrivers(m_CurrentProfile);
1177 INDI::WebManager::checkVersion(m_CurrentProfile);
1179 if (INDI::WebManager::areDriversRunning(m_CurrentProfile) ==
false)
1181 INDI::WebManager::stopProfile(m_CurrentProfile);
1183 if (INDI::WebManager::startProfile(m_CurrentProfile) ==
false)
1185 appendLogText(
i18n(
"Failed to start profile on remote INDI Web Manager."));
1189 appendLogText(
i18n(
"Starting profile on remote INDI Web Manager..."));
1190 m_RemoteManagerStart =
true;
1196 m_ekosStatus = Ekos::Pending;
1197 emit ekosStatusChanged(m_ekosStatus);
1200 if (m_CurrentProfile->INDIWebManagerPort > 0)
1202 appendLogText(
i18n(
"Establishing communication with remote INDI Web Manager..."));
1203 m_RemoteManagerStart =
false;
1204 QFutureWatcher<bool> *watcher =
new QFutureWatcher<bool>();
1210 if (m_ekosStatus != Ekos::Pending)
1222 appendLogText(
i18n(
"Warning: INDI Web Manager is not online."));
1228 QFuture<bool> result = INDI::AsyncWebManager::isOnline(m_CurrentProfile);
1238 if (m_extensions.discover())
1240 foreach (QString extension, m_extensions.found->keys())
1242 extensions::extDetails m_ext = m_extensions.found->value(extension);
1243 extensionCombo->addItem(m_ext.icon, extension);
1246 if (extensionCombo->count() > 0)
1248 groupBox_4->setHidden(
false);
1252void Manager::setClientStarted(
const QString &host,
int port)
1254 if (managedDrivers.size() > 0)
1258 if (m_CurrentProfile->autoConnect)
1259 appendLogText(
i18n(
"INDI services started on port %1.", port));
1262 i18n(
"INDI services started on port %1. Please connect devices.", port));
1267 i18n(
"INDI services started. Connection to remote INDI server %1:%2 is successful. Waiting for devices...", host, port));
1271 auto maxTimeout = MAX_LOCAL_INDI_TIMEOUT;
1274 QJsonParseError jsonError;
1275 QJsonArray profileScripts;
1282 profileScripts = doc.
array();
1283 for (
const auto &oneRule : qAsConst(profileScripts))
1285 const auto &oneRuleObj = oneRule.toObject();
1286 auto totalDelay = (oneRuleObj[
"PreDelay"].toDouble(0) + oneRuleObj[
"PostDelay"].toDouble(0)) * 1000;
1287 if (totalDelay >= maxTimeout)
1288 maxTimeout = totalDelay + MAX_LOCAL_INDI_TIMEOUT;
1295void Manager::setClientFailed(
const QString &host,
int port,
const QString &errorMessage)
1298 appendLogText(
i18n(
"Failed to connect to local INDI server %1:%2", host, port));
1300 appendLogText(
i18n(
"Failed to connect to remote INDI server %1:%2", host, port));
1305 m_ekosStatus = Ekos::Error;
1306 emit ekosStatusChanged(m_ekosStatus);
1307 KSNotification::error(errorMessage,
i18n(
"Error"), 15);
1310void Manager::setClientTerminated(
const QString &host,
int port,
const QString &errorMessage)
1313 appendLogText(
i18n(
"Lost connection to local INDI server %1:%2", host, port));
1315 appendLogText(
i18n(
"Lost connection to remote INDI server %1:%2", host, port));
1320 m_ekosStatus = Ekos::Error;
1321 emit ekosStatusChanged(m_ekosStatus);
1322 KSNotification::error(errorMessage,
i18n(
"Error"), 15);
1325void Manager::setServerStarted(
const QString &host,
int port)
1327 if (m_LocalMode && m_CurrentProfile->indihub != INDIHub::None)
1329 if (QFile(Options::iNDIHubAgent()).exists())
1331 indiHubAgent =
new QProcess();
1334 args <<
"--indi-server" << QString(
"%1:%2").arg(host).arg(port);
1335 if (m_CurrentProfile->guidertype == Ekos::Guide::GUIDE_PHD2)
1336 args <<
"--phd2-server" << QString(
"%1:%2").arg(m_CurrentProfile->guiderhost).arg(m_CurrentProfile->guiderport);
1337 args <<
"--mode" << INDIHub::toString(m_CurrentProfile->indihub);
1338 indiHubAgent->start(Options::iNDIHubAgent(), args);
1340 qCDebug(KSTARS_EKOS) <<
"Started INDIHub agent.";
1345void Manager::setServerFailed(
const QString &host,
int port,
const QString &message)
1349 managedDrivers.clear();
1350 m_ekosStatus = Ekos::Error;
1351 emit ekosStatusChanged(m_ekosStatus);
1352 KSNotification::error(message,
i18n(
"Error"), 15);
1373void Manager::checkINDITimeout()
1376 if (m_ekosStatus != Ekos::Pending)
1379 if (m_indiStatus != Ekos::Pending || m_CurrentProfile->portSelector || m_CurrentProfile->autoConnect ==
false)
1382 QStringList disconnectedDevices;
1383 for (
auto &oneDevice : INDIListener::devices())
1385 if (oneDevice->isConnected() ==
false)
1386 disconnectedDevices << oneDevice->getDeviceName();
1391 if (disconnectedDevices.
count() == 1)
1392 message =
i18n(
"Failed to connect to %1. Please ensure device is connected and powered on.", disconnectedDevices.
first());
1394 message =
i18n(
"Failed to connect to \n%1\nPlease ensure each device is connected and powered on.",
1395 disconnectedDevices.
join(
"\n"));
1397 appendLogText(message);
1398 KSNotification::event(QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1403 if (m_DriverDevicesCount <= 0)
1405 m_ekosStatus = Ekos::Success;
1406 emit ekosStatusChanged(m_ekosStatus);
1412 QStringList remainingDevices;
1413 for (
auto &drv : managedDrivers)
1415 if (drv->getDevices().count() == 0)
1416 remainingDevices << QString(
"+ %1").arg(
1417 drv->getUniqueLabel().isEmpty() ==
false ? drv->getUniqueLabel() : drv->getName());
1420 if (remainingDevices.
count() == 1)
1422 QString message =
i18n(
"Unable to establish:\n%1\nPlease ensure the device is connected and powered on.",
1423 remainingDevices.
at(0));
1424 appendLogText(message);
1425 KSNotification::event(QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1430 QString message =
i18n(
"Unable to establish the following devices:\n%1\nPlease ensure each device is connected "
1431 "and powered on.", remainingDevices.
join(
"\n"));
1432 appendLogText(message);
1433 KSNotification::event(QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1439 QStringList remainingDevices;
1441 for (
auto &driver : m_CurrentProfile->drivers.values())
1443 bool driverFound =
false;
1445 for (
auto &device : INDIListener::devices())
1447 if (device->getBaseDevice().getDriverName() == driver)
1454 if (driverFound ==
false)
1455 remainingDevices << QString(
"+ %1").arg(driver);
1458 if (remainingDevices.
count() == 1)
1460 QString message =
i18n(
"Unable to remotely establish:\n%1\nPlease ensure the device is connected and powered on.",
1461 remainingDevices.
at(0));
1462 appendLogText(message);
1463 KSNotification::event(QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1468 QString message =
i18n(
"Unable to remotely establish the following devices:\n%1\nPlease ensure each device is connected "
1469 "and powered on.", remainingDevices.
join(
"\n"));
1470 appendLogText(message);
1471 KSNotification::event(QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1476 m_ekosStatus = Ekos::Error;
1479bool Manager::isINDIReady()
1484 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1486 auto devices = INDIListener::devices();
1487 for (
auto &device : devices)
1490 if (device->isConnected() && device->isReady())
1493 if (devices.count() == nConnected)
1495 m_indiStatus = Ekos::Success;
1496 emit indiStatusChanged(m_indiStatus);
1500 m_indiStatus = Ekos::Pending;
1501 if (previousStatus != m_indiStatus)
1502 emit indiStatusChanged(m_indiStatus);
1507void Manager::connectDevices()
1512 auto devices = INDIListener::devices();
1514 for (
auto &device : devices)
1516 qCDebug(KSTARS_EKOS) <<
"Connecting " << device->getDeviceName();
1520 connectB->setEnabled(
false);
1521 disconnectB->setEnabled(
true);
1522 extensionCombo->setEnabled(
true);
1523 if (extensionCombo->currentText() !=
"")
1524 extensionB->setEnabled(
true);
1526 appendLogText(
i18n(
"Connecting INDI devices..."));
1529void Manager::disconnectDevices()
1531 for (
auto &device : INDIListener::devices())
1533 qCDebug(KSTARS_EKOS) <<
"Disconnecting " << device->getDeviceName();
1534 device->Disconnect();
1537 appendLogText(
i18n(
"Disconnecting INDI devices..."));
1540void Manager::cleanDevices(
bool stopDrivers)
1542 if (m_ekosStatus == Ekos::Idle)
1546 mountModule()->stopTimers();
1548 ekosLiveClient->message()->setPendingPropertiesEnabled(
false);
1552 if (managedDrivers.isEmpty() ==
false)
1557 DriverManager::Instance()->stopDevices(managedDrivers);
1563 DriverManager::Instance()->disconnectRemoteHost(managedDrivers.first());
1565 if (m_RemoteManagerStart && m_CurrentProfile->INDIWebManagerPort != -1)
1566 INDI::WebManager::stopProfile(m_CurrentProfile);
1568 m_RemoteManagerStart =
false;
1574 profileGroup->setEnabled(
true);
1576 appendLogText(
i18n(
"INDI services stopped."));
1581 qCInfo(KSTARS_EKOS) <<
"Ekos received a new device: " << device->getDeviceName();
1583 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1595 m_indiStatus = Ekos::Idle;
1596 if (previousStatus != m_indiStatus)
1597 emit indiStatusChanged(m_indiStatus);
1599 m_DriverDevicesCount--;
1617 connect(device.
get(), &ISD::GenericDevice::propertyDeleted,
this, &Ekos::Manager::processDeleteProperty,
1619 connect(device.
get(), &ISD::GenericDevice::propertyUpdated,
this, &Ekos::Manager::processUpdateProperty,
1627 if (m_CurrentProfile->ccd() != m_CurrentProfile->guider())
1629 for (
auto &oneCamera : INDIListener::devices())
1632 m_PrimaryCamera = QString(oneCamera->getDeviceName());
1633 else if (oneCamera->getDeviceName().startsWith(m_CurrentProfile->guider(),
Qt::CaseInsensitive))
1634 m_GuideCamera = QString(oneCamera->getDeviceName());
1638 if (m_DriverDevicesCount <= 0)
1640 m_ekosStatus = Ekos::Success;
1641 emit ekosStatusChanged(m_ekosStatus);
1643 connectB->setEnabled(
true);
1644 disconnectB->setEnabled(
false);
1645 extensionCombo->setEnabled(
false);
1646 extensionB->setEnabled(
false);
1648 if (m_LocalMode ==
false && m_DriverDevicesCount == 0)
1650 if (m_CurrentProfile->autoConnect)
1651 appendLogText(
i18n(
"Remote devices established."));
1653 appendLogText(
i18n(
"Remote devices established. Please connect devices."));
1658void Manager::deviceConnected()
1660 connectB->setEnabled(
false);
1661 disconnectB->setEnabled(
true);
1662 processINDIB->setEnabled(
false);
1663 extensionCombo->setEnabled(
true);
1664 if (extensionCombo->currentText() !=
"")
1665 extensionB->setEnabled(
true);
1667 auto device = qobject_cast<ISD::GenericDevice *>(sender());
1669 if (Options::verboseLogging())
1671 qCInfo(KSTARS_EKOS) << device->getDeviceName()
1672 <<
"Version:" << device->getDriverVersion()
1673 <<
"Interface:" << device->getDriverInterface()
1677 if (Options::neverLoadConfig() ==
false)
1679 INDIConfig tConfig = Options::loadConfigOnConnection() ? LOAD_LAST_CONFIG : LOAD_DEFAULT_CONFIG;
1681 for (
auto &oneDevice : INDIListener::devices())
1683 if (oneDevice == device)
1687 auto configProp = device->getBaseDevice().getSwitch(
"CONFIG_PROCESS");
1688 if (configProp && configProp.getState() == IPS_IDLE)
1689 device->setConfig(tConfig);
1696void Manager::deviceDisconnected()
1698 ISD::GenericDevice * dev =
static_cast<ISD::GenericDevice *
>(sender());
1700 Ekos::CommunicationStatus previousStatus = m_indiStatus;
1704 if (dev->getState(
"CONNECTION") == IPS_ALERT)
1705 m_indiStatus = Ekos::Error;
1706 else if (dev->getState(
"CONNECTION") == IPS_BUSY)
1707 m_indiStatus = Ekos::Pending;
1709 m_indiStatus = Ekos::Idle;
1711 if (Options::verboseLogging())
1712 qCDebug(KSTARS_EKOS) << dev->getDeviceName() <<
" is disconnected.";
1715 if (m_indiStatus == Ekos::Error)
1717 QString message =
i18n(
"%1 failed to connect.\nPlease ensure the device is connected and powered on.",
1718 dev->getDeviceName());
1719 appendLogText(message);
1720 KSNotification::event(QLatin1String(
"IndiServerMessage"), message, KSNotification::General, KSNotification::Warn);
1722 else if (m_indiStatus == Ekos::Idle)
1724 QString message =
i18n(
"%1 is disconnected.", dev->getDeviceName());
1725 appendLogText(message);
1729 m_indiStatus = Ekos::Idle;
1731 if (previousStatus != m_indiStatus)
1732 emit indiStatusChanged(m_indiStatus);
1734 connectB->setEnabled(
true);
1735 disconnectB->setEnabled(
false);
1736 processINDIB->setEnabled(
true);
1737 extensionCombo->setEnabled(
false);
1738 extensionB->setEnabled(
false);
1743 ekosLiveClient->message()->sendScopes();
1745 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1747 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1752 ekosLiveClient.get()->media()->registerCameras();
1754 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1756 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1759void Manager::addFilterWheel(ISD::FilterWheel * device)
1761 QString
name = device->getDeviceName();
1762 appendLogText(
i18n(
"%1 filter is online.", name));
1764 createFilterManager(device);
1766 emit newDevice(name, device->getDriverInterface());
1771 appendLogText(
i18n(
"%1 focuser is online.", device->getDeviceName()));
1773 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1778 appendLogText(
i18n(
"Rotator %1 is online.", device->getDeviceName()));
1782 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1785void Manager::addDome(
ISD::Dome * device)
1787 appendLogText(
i18n(
"%1 is online.", device->getDeviceName()));
1789 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1794 appendLogText(
i18n(
"%1 Weather is online.", device->getDeviceName()));
1796 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1799void Manager::addGPS(ISD::GPS * device)
1801 appendLogText(
i18n(
"%1 GPS is online.", device->getDeviceName()));
1803 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1808 OpticalTrainManager::Instance()->syncDevices();
1810 appendLogText(
i18n(
"%1 Dust cap is online.", device->getDeviceName()));
1812 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1817 appendLogText(
i18n(
"%1 Light box is online.", device->getDeviceName()));
1819 emit newDevice(device->getDeviceName(), device->getDriverInterface());
1824 createModules(device);
1829 auto camera = device->getCamera();
1835 if (camera->hasCooler())
1837 QSharedPointer<ISD::GenericDevice>
generic;
1838 if (INDIListener::findDevice(camera->getDeviceName(), generic))
1839 focusModule()->addTemperatureSource(generic);
1848 auto mount = device->getMount();
1853 QSharedPointer<ISD::GenericDevice>
generic;
1854 if (INDIListener::findDevice(
mount->getDeviceName(), generic))
1856 mountModule()->addTimeSource(generic);
1857 mountModule()->addLocationSource(generic);
1866 auto focuser = device->getFocuser();
1872 QSharedPointer<ISD::GenericDevice>
generic;
1873 if (INDIListener::findDevice(focuser->getDeviceName(), generic))
1874 focusModule()->addTemperatureSource(generic);
1889 auto dome = device->getDome();
1893 captureProcess->setDome(dome);
1895 alignProcess->setDome(dome);
1896 if (observatoryProcess)
1897 observatoryProcess->setDome(dome);
1903 auto weather = device->getWeather();
1906 if (observatoryProcess)
1907 observatoryProcess->addWeatherSource(weather);
1911 QSharedPointer<ISD::GenericDevice>
generic;
1912 if (INDIListener::findDevice(weather->getDeviceName(), generic))
1913 focusModule()->addTemperatureSource(generic);
1920 auto gps = device->getGPS();
1925 QSharedPointer<ISD::GenericDevice>
generic;
1926 if (INDIListener::findDevice(gps->getDeviceName(), generic))
1928 mountModule()->addTimeSource(generic);
1929 mountModule()->addLocationSource(generic);
1939 alignModule()->removeDevice(device);
1941 captureProcess->removeDevice(device);
1943 focusModule()->removeDevice(device);
1945 mountModule()->removeDevice(device);
1947 guideProcess->removeDevice(device);
1948 if (observatoryProcess)
1949 observatoryProcess->removeDevice(device);
1951 m_PortSelector->removeDevice(device->getDeviceName());
1953 DarkLibrary::Instance()->removeDevice(device);
1956 for (
auto &oneManager : m_FilterManagers)
1958 oneManager->removeDevice(device);
1962 for (
auto &oneController : m_RotatorControllers)
1964 oneController->close();
1967 appendLogText(
i18n(
"%1 is offline.", device->getDeviceName()));
1970 if (INDIListener::devices().isEmpty())
1977void Manager::processDeleteProperty(INDI::Property prop)
1979 ekosLiveClient.get()->message()->processDeleteProperty(prop);
1982void Manager::processMessage(
int id)
1984 auto origin =
static_cast<ISD::GenericDevice *
>(sender());
1988 QSharedPointer<ISD::GenericDevice> device;
1989 if (!INDIListener::findDevice(origin->getDeviceName(), device))
1992 ekosLiveClient.
get()->message()->processMessage(device,
id);
1995void Manager::processUpdateProperty(INDI::Property prop)
1997 ekosLiveClient.get()->message()->processUpdateProperty(prop);
1999 if (prop.isNameMatch(
"CCD_INFO") ||
2000 prop.isNameMatch(
"GUIDER_INFO") ||
2001 prop.isNameMatch(
"CCD_FRAME") ||
2002 prop.isNameMatch(
"GUIDER_FRAME"))
2004 if (focusModule() !=
nullptr)
2005 focusModule()->syncCameraInfo(prop.getDeviceName());
2007 if (guideModule() !=
nullptr && guideModule()->camera() == prop.getDeviceName())
2008 guideModule()->syncCameraInfo();
2010 if (alignModule() !=
nullptr && alignModule()->camera() == prop.getDeviceName())
2011 alignModule()->syncCameraInfo();
2017void Manager::processNewProperty(INDI::Property prop)
2019 QSharedPointer<ISD::GenericDevice> device;
2020 if (!INDIListener::findDevice(prop.getDeviceName(), device))
2023 settleTimer.start();
2025 ekosLiveClient.
get()->message()->processNewProperty(prop);
2027 if (prop.isNameMatch(
"DEVICE_PORT_SCAN") || prop.isNameMatch(
"CONNECTION_TYPE"))
2029 if (!m_PortSelector)
2034 m_PortSelectorTimer.start();
2035 portSelectorB->setEnabled(
true);
2036 m_PortSelector->addDevice(device);
2041 if (prop.isNameMatch(
"DEBUG"))
2043 uint16_t
interface = device->getDriverInterface();
2044 if ( opsLogs->getINDIDebugInterface() & interface )
2047 auto debugSP = prop.getSwitch();
2048 debugSP->at(0)->setState(ISS_ON);
2049 debugSP->at(1)->setState(ISS_OFF);
2050 device->sendNewProperty(debugSP);
2056 if (prop.isNameMatch(
"DEBUG_LEVEL"))
2058 uint16_t
interface = device->getDriverInterface();
2060 if ( opsLogs->getINDIDebugInterface() & interface )
2063 auto debugLevel = prop.getSwitch();
2064 for (
auto &it : *debugLevel)
2065 it.setState(ISS_ON);
2067 device->sendNewProperty(debugLevel);
2072 if (prop.isNameMatch(
"ASTROMETRY_SOLVER"))
2074 for (
auto &oneDevice : INDIListener::devices())
2076 if (oneDevice->getDeviceName() == prop.getDeviceName())
2079 alignModule()->setAstrometryDevice(oneDevice);
2087 if (focusModule() !=
nullptr && strstr(prop.getName(),
"FOCUS_"))
2089 focusModule()->checkFocusers();
2094void Manager::processTabChange()
2096 auto currentWidget = toolsWidget->currentWidget();
2098 if (alignProcess && alignModule() == currentWidget)
2100 auto alignReady = alignModule()->isEnabled() ==
false && alignModule()->isParserOK();
2101 auto captureReady = captureProcess && captureModule()->isEnabled();
2102 auto mountReady = mountProcess && mountModule()->isEnabled();
2103 if (alignReady && captureReady && mountReady)
2104 alignModule()->setEnabled(
true);
2106 alignModule()->checkCamera();
2108 else if (captureProcess && currentWidget == captureModule())
2110 captureModule()->process()->checkCamera();
2112 else if (focusProcess && currentWidget == focusModule())
2114 focusModule()->checkCameras();
2116 else if (guideProcess && currentWidget == guideModule())
2118 guideModule()->checkCamera();
2124void Manager::updateLog()
2126 QWidget * currentWidget = toolsWidget->currentWidget();
2128 if (currentWidget == setupTab)
2129 ekosLogOut->setPlainText(m_LogText.join(
"\n"));
2130 else if (currentWidget == alignModule())
2131 ekosLogOut->setPlainText(alignModule()->getLogText());
2132 else if (currentWidget == captureModule())
2133 ekosLogOut->setPlainText(captureModule()->getLogText());
2134 else if (currentWidget == focusModule())
2135 ekosLogOut->setPlainText(focusModule()->getLogText());
2136 else if (currentWidget == guideModule())
2137 ekosLogOut->setPlainText(guideModule()->getLogText());
2138 else if (currentWidget == mountModule())
2139 ekosLogOut->setPlainText(mountModule()->getLogText());
2140 else if (currentWidget == schedulerModule())
2141 ekosLogOut->setPlainText(schedulerModule()->moduleState()->getLogText());
2142 else if (currentWidget == observatoryProcess.get())
2143 ekosLogOut->setPlainText(observatoryProcess->getLogText());
2144 else if (currentWidget == analyzeProcess.get())
2145 ekosLogOut->setPlainText(analyzeProcess->getLogText());
2152void Manager::appendLogText(
const QString &text)
2154 m_LogText.insert(0,
i18nc(
"log entry; %1 is the date, %2 is the text",
"%1 %2",
2155 KStarsData::Instance()->lt().
toString(
"yyyy-MM-ddThh:mm:ss"), text));
2157 qCInfo(KSTARS_EKOS) << text;
2164void Manager::clearLog()
2166 QWidget * currentWidget = toolsWidget->currentWidget();
2168 if (currentWidget == setupTab)
2173 else if (currentWidget == alignModule())
2174 alignModule()->clearLog();
2175 else if (currentWidget == captureModule())
2176 captureModule()->clearLog();
2177 else if (currentWidget == focusModule())
2178 focusModule()->clearLog();
2179 else if (currentWidget == guideModule())
2180 guideModule()->clearLog();
2181 else if (currentWidget == mountModule())
2182 mountModule()->clearLog();
2183 else if (currentWidget == schedulerModule())
2184 schedulerModule()->process()->clearLog();
2185 else if (currentWidget == observatoryProcess.get())
2186 observatoryProcess->clearLog();
2187 else if (currentWidget == analyzeProcess.get())
2188 analyzeProcess->clearLog();
2191void Manager::initCapture()
2193 if (captureModule() !=
nullptr)
2196 captureProcess.reset(
new Capture());
2198 emit newModule(
"Capture");
2201 if (mountModule() !=
nullptr)
2202 captureModule()->setMeridianFlipState(mountModule()->getMeridianFlipState());
2204 capturePreview->shareCaptureModule(captureModule());
2205 int index = addModuleTab(EkosModule::Capture, captureModule(), QIcon(
":/icons/ekos_ccd.png"));
2206 toolsWidget->tabBar()->setTabToolTip(index,
i18nc(
"Charge-Coupled Device",
"CCD"));
2207 if (Options::ekosLeftIcons())
2211 QIcon icon = toolsWidget->tabIcon(index);
2212 QPixmap pix = icon.
pixmap(QSize(48, 48));
2214 toolsWidget->setTabIcon(index, icon);
2216 connect(captureModule(), &Ekos::Capture::newLog,
this, &Ekos::Manager::updateLog);
2217 connect(captureModule(), &Ekos::Capture::newLog,
this, [
this]()
2219 QJsonObject cStatus =
2221 {
"log", captureModule()->getLogText()}
2224 ekosLiveClient.get()->message()->updateCaptureStatus(cStatus);
2226 connect(captureModule(), &Ekos::Capture::newStatus,
this, &Ekos::Manager::updateCaptureStatus);
2227 connect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
2228 connect(captureModule(), &Ekos::Capture::driverTimedout,
this, &Ekos::Manager::restartDriver);
2229 connect(captureModule(), &Ekos::Capture::newExposureProgress,
this, &Ekos::Manager::updateExposureProgress);
2230 capturePreview->setEnabled(
true);
2233 connect(captureModule(), &Ekos::Capture::newFilterStatus, capturePreview->captureStatusWidget,
2234 &LedStatusWidget::setFilterState);
2237 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
2239 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
this, [
this](
double distance)
2241 capturePreview->updateTargetDistance(distance);
2248void Manager::initAlign()
2250 if (alignModule() !=
nullptr)
2253 alignProcess.reset(
new Ekos::Align(m_CurrentProfile));
2255 emit newModule(
"Align");
2257 int index = addModuleTab(EkosModule::Align, alignModule(), QIcon(
":/icons/ekos_align.png"));
2258 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Align"));
2259 connect(alignModule(), &Ekos::Align::newLog,
this, &Ekos::Manager::updateLog);
2260 connect(alignModule(), &Ekos::Align::newLog,
this, [
this]()
2262 QJsonObject cStatus =
2264 {
"log", alignModule()->getLogText()}
2267 ekosLiveClient.get()->message()->updateAlignStatus(cStatus);
2269 connect(alignModule(), &Ekos::Align::newDownloadProgress,
this, [
this](QString info)
2271 QJsonObject cStatus =
2273 {
"downloadProgress", info}
2276 ekosLiveClient.get()->message()->updateAlignStatus(cStatus);
2278 if (Options::ekosLeftIcons())
2282 QIcon icon = toolsWidget->tabIcon(index);
2283 QPixmap pix = icon.
pixmap(QSize(48, 48));
2285 toolsWidget->setTabIcon(index, icon);
2291void Manager::initFocus()
2293 if (focusModule() !=
nullptr)
2296 focusProcess.reset(
new Ekos::FocusModule());
2298 emit newModule(
"Focus");
2300 int index = addModuleTab(EkosModule::Focus, focusModule(), QIcon(
":/icons/ekos_focus.png"));
2302 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Focus"));
2305 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStatus,
this, &Ekos::Manager::updateFocusStatus);
2306 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStarPixmap, focusProgressWidget,
2307 &Ekos::FocusProgressWidget::updateFocusStarPixmap);
2308 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newHFR,
this, &Ekos::Manager::updateCurrentHFR);
2310 connect(focusModule(), &Ekos::FocusModule::newLog,
this, [
this]()
2315 QJsonObject cStatus =
2317 {
"log", focusModule()->getLogText()}
2320 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2322 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusAdvisorMessage,
this, [
this](
const QString & message)
2324 QJsonObject cStatus =
2326 {
"focusAdvisorMessage", message}
2329 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2331 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusAdvisorStage, ekosLiveClient.get()->message(),
2334 QJsonObject cStatus =
2336 {
"focusAdvisorStage", stage}
2339 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2348 focusProgressWidget->hfrVPlot->init(str, starUnits, minimum, useWeights, showPosition);
2351 {
"focusinitHFRPlot",
true}
2354 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2360 focusProgressWidget->hfrVPlot->setTitle(title, plot);
2366 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2369 &FocusHFRVPlot::setTitle);
2371 &FocusHFRVPlot::redraw);
2373 &FocusHFRVPlot::addPosition);
2375 &FocusHFRVPlot::drawPolynomial);
2377 &FocusHFRVPlot::finalUpdates);
2379 &FocusHFRVPlot::drawMinimum);
2382 &FocusHFRVPlot::drawCurve);
2385 if (Options::ekosLeftIcons())
2389 QIcon icon = toolsWidget->tabIcon(index);
2392 toolsWidget->setTabIcon(index, icon);
2395 focusProgressWidget->init();
2396 focusProgressWidget->setEnabled(
true);
2398 for (
auto &oneDevice : INDIListener::devices())
2400 auto prop1 = oneDevice->getProperty(
"CCD_TEMPERATURE");
2401 auto prop2 = oneDevice->getProperty(
"FOCUSER_TEMPERATURE");
2402 auto prop3 = oneDevice->getProperty(
"WEATHER_PARAMETERS");
2403 if (prop1 || prop2 || prop3)
2404 focusModule()->addTemperatureSource(oneDevice);
2410void Manager::updateCurrentHFR(
double newHFR,
int position,
bool inAutofocus)
2412 Q_UNUSED(inAutofocus);
2413 focusProgressWidget->updateCurrentHFR(newHFR);
2415 QJsonObject cStatus =
2421 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2424void Manager::updateSigmas(
double ra,
double de)
2426 guideManager->updateSigmas(ra, de);
2428 QJsonObject cStatus = { {
"rarms", ra}, {
"derms", de} };
2430 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2433void Manager::initMount()
2435 if (mountModule() !=
nullptr)
2438 mountProcess.reset(
new Ekos::Mount());
2441 if (captureModule() !=
nullptr)
2442 captureModule()->setMeridianFlipState(mountModule()->getMeridianFlipState());
2444 emit newModule(
"Mount");
2446 int index = addModuleTab(EkosModule::Mount, mountModule(), QIcon(
":/icons/ekos_mount.png"));
2448 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Mount"));
2449 connect(mountModule(), &Ekos::Mount::newLog,
this, &Ekos::Manager::updateLog);
2456 connect(mountModule(), &Ekos::Mount::pierSideChanged,
this, [&](ISD::Mount::PierSide side)
2458 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject({{
"pierSide", side}}));
2460 connect(mountModule()->getMeridianFlipState().
get(),
2461 &Ekos::MeridianFlipState::newMountMFStatus, [&](MeridianFlipState::MeridianFlipMountState status)
2463 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject(
2465 {
"meridianFlipStatus",
status},
2468 connect(mountModule()->getMeridianFlipState().
get(),
2469 &Ekos::MeridianFlipState::newMeridianFlipMountStatusText, [&](
const QString & text)
2472 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject(
2474 {
"meridianFlipText", text},
2475 }), mountModule()->getMeridianFlipState()->getMeridianFlipMountState() == MeridianFlipState::MOUNT_FLIP_NONE);
2476 meridianFlipStatusWidget->setStatus(text);
2478 connect(mountModule(), &Ekos::Mount::autoParkCountdownUpdated,
this, [&](
const QString & text)
2480 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject({{
"autoParkCountdown", text}}),
true);
2483 connect(mountModule(), &Ekos::Mount::trainChanged, ekosLiveClient.get()->message(),
2486 connect(mountModule(), &Ekos::Mount::slewRateChanged,
this, [&](
int slewRate)
2488 QJsonObject
status = { {
"slewRate", slewRate} };
2489 ekosLiveClient.get()->message()->updateMountStatus(status);
2492 if (Options::ekosLeftIcons())
2496 QIcon icon = toolsWidget->tabIcon(index);
2497 QPixmap pix = icon.
pixmap(QSize(48, 48));
2499 toolsWidget->setTabIcon(index, icon);
2502 mountGroup->setEnabled(
true);
2503 capturePreview->shareMountModule(mountModule());
2508void Manager::initGuide()
2510 if (guideModule() ==
nullptr)
2512 guideProcess.reset(
new Ekos::Guide());
2514 emit newModule(
"Guide");
2517 if (toolsWidget->indexOf(guideModule()) == -1)
2522 int index = addModuleTab(EkosModule::Guide, guideModule(), QIcon(
":/icons/ekos_guide.png"));
2523 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Guide"));
2524 connect(guideModule(), &Ekos::Guide::newLog,
this, &Ekos::Manager::updateLog);
2525 connect(guideModule(), &Ekos::Guide::driverTimedout,
this, &Ekos::Manager::restartDriver);
2527 guideManager->setEnabled(
true);
2529 connect(guideModule(), &Ekos::Guide::newStatus,
this, &Ekos::Manager::updateGuideStatus);
2530 connect(guideModule(), &Ekos::Guide::newStarPixmap, guideManager, &Ekos::GuideManager::updateGuideStarPixmap);
2531 connect(guideModule(), &Ekos::Guide::newAxisSigma,
this, &Ekos::Manager::updateSigmas);
2532 connect(guideModule(), &Ekos::Guide::newAxisDelta, [&](
double ra,
double de)
2534 QJsonObject
status = { {
"drift_ra", ra}, {
"drift_de", de} };
2535 ekosLiveClient.get()->message()->updateGuideStatus(status);
2537 connect(guideModule(), &Ekos::Guide::newLog, ekosLiveClient.get()->message(),
2540 QJsonObject cStatus =
2542 {
"log", guideModule()->getLogText()}
2545 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2548 if (Options::ekosLeftIcons())
2552 QIcon icon = toolsWidget->tabIcon(index);
2553 QPixmap pix = icon.
pixmap(QSize(48, 48));
2555 toolsWidget->setTabIcon(index, icon);
2557 guideManager->init(guideModule());
2563void Manager::initObservatory()
2565 if (observatoryProcess.get() ==
nullptr)
2568 observatoryProcess.reset(
new Ekos::Observatory());
2570 emit newModule(
"Observatory");
2572 int index = addModuleTab(EkosModule::Observatory, observatoryProcess.get(), QIcon(
":/icons/ekos_observatory.png"));
2573 toolsWidget->tabBar()->setTabToolTip(index,
i18n(
"Observatory"));
2574 connect(observatoryProcess.get(), &Ekos::Observatory::newLog,
this, &Ekos::Manager::updateLog);
2576 if (Options::ekosLeftIcons())
2580 QIcon icon = toolsWidget->tabIcon(index);
2581 QPixmap pix = icon.
pixmap(QSize(48, 48));
2583 toolsWidget->setTabIcon(index, icon);
2588void Manager::addGuider(ISD::Guider * device)
2590 appendLogText(
i18n(
"Guider port from %1 is ready.", device->getDeviceName()));
2593void Manager::removeTabs()
2597 for (
int i = numPermanentTabs; i < toolsWidget->count(); i++)
2598 toolsWidget->removeTab(i);
2600 alignProcess.reset();
2601 captureProcess.reset();
2602 focusProcess.reset();
2603 guideProcess.reset();
2604 mountProcess.reset();
2605 observatoryProcess.reset();
2610bool Manager::isRunning(
const QString &process)
2614 ps.
start(
"pgrep", QStringList() << process);
2617 return output.
length() > 0;
2619 ps.
start(
"ps", QStringList() <<
"-o"
2622 <<
"-C" << process);
2629void Manager::addObjectToScheduler(
SkyObject *
object)
2631 if (schedulerModule() !=
nullptr)
2632 schedulerModule()->addObject(
object);
2635QString Manager::getCurrentJobName()
2637 return schedulerModule()->getCurrentJobName();
2640bool Manager::setProfile(
const QString &profileName)
2642 int index = profileCombo->findText(profileName);
2647 profileCombo->setCurrentIndex(index);
2652void Manager::editNamedProfile(
const QJsonObject &profileInfo)
2654 ProfileEditor editor(
this);
2655 setProfile(profileInfo[
"name"].
toString());
2656 if (getCurrentProfile(m_CurrentProfile))
2658 editor.setPi(m_CurrentProfile);
2659 editor.setSettings(profileInfo);
2660 editor.saveProfile();
2664void Manager::addNamedProfile(
const QJsonObject &profileInfo)
2666 ProfileEditor editor(
this);
2668 editor.setSettings(profileInfo);
2669 editor.saveProfile();
2672 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2673 getCurrentProfile(m_CurrentProfile);
2676void Manager::deleteNamedProfile(
const QString &name)
2678 if (!getCurrentProfile(m_CurrentProfile))
2681 for (
auto &pi : profiles)
2685 if (pi->name ==
"Simulators" || pi->name != name || (pi.get() == m_CurrentProfile && ekosStatus() != Idle))
2688 KStarsData::Instance()->
userdb()->PurgeProfile(pi);
2691 getCurrentProfile(m_CurrentProfile);
2698 QJsonObject profileInfo;
2701 for (
auto &pi : profiles)
2703 if (name == pi->name)
2704 return pi->toJson();
2707 return QJsonObject();
2712 QStringList profiles;
2714 for (
int i = 0; i < profileCombo->count(); i++)
2715 profiles << profileCombo->itemText(i);
2720void Manager::addProfile()
2722 ProfileEditor editor(
this);
2728 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2731 getCurrentProfile(m_CurrentProfile);
2734void Manager::editProfile()
2736 ProfileEditor editor(
this);
2738 if (getCurrentProfile(m_CurrentProfile))
2741 editor.setPi(m_CurrentProfile);
2745 int currentIndex = profileCombo->currentIndex();
2749 profileCombo->setCurrentIndex(currentIndex);
2752 getCurrentProfile(m_CurrentProfile);
2756void Manager::deleteProfile()
2758 if (!getCurrentProfile(m_CurrentProfile))
2761 if (m_CurrentProfile->name ==
"Simulators")
2764 auto executeDeleteProfile = [&]()
2766 KStarsData::Instance()->
userdb()->PurgeProfile(m_CurrentProfile);
2769 getCurrentProfile(m_CurrentProfile);
2776 executeDeleteProfile();
2779 KSMessageBox::Instance()->questionYesNo(
i18n(
"Are you sure you want to delete the profile?"),
2780 i18n(
"Confirm Delete"));
2784void Manager::wizardProfile()
2790 ProfileEditor editor(
this);
2792 editor.setProfileName(wz.profileName);
2793 editor.setAuxDrivers(wz.selectedAuxDrivers());
2794 if (wz.useInternalServer ==
false)
2795 editor.setHostPort(wz.host, wz.port);
2796 editor.setWebManager(wz.useWebManager);
2797 editor.setGuiderType(wz.selectedExternalGuider());
2799 editor.setConnectionOptionsEnabled(
false);
2805 profileCombo->setCurrentIndex(profileCombo->count() - 1);
2808 getCurrentProfile(m_CurrentProfile);
2814 for (
auto &pi : profiles)
2816 if (profileCombo->currentText() == pi->name)
2828 if (profile->city.isEmpty() ==
false)
2832 appendLogText(
i18n(
"Site location updated to %1.", KStarsData::Instance()->
geo()->
fullName()));
2834 appendLogText(
i18n(
"Failed to update site location to %1. City not found.",
2839void Manager::updateMountStatus(ISD::Mount::Status status)
2841 static ISD::Mount::Status lastStatus = ISD::Mount::MOUNT_IDLE;
2843 if (status == lastStatus)
2848 mountStatus->setMountState(mountModule()->statusString(), status);
2849 mountStatus->setStyleSheet(QString());
2851 QJsonObject cStatus =
2853 {
"status", mountModule()->statusString(
false)}
2856 ekosLiveClient.get()->message()->updateMountStatus(cStatus);
2859void Manager::updateMountCoords(
const SkyPoint position, ISD::Mount::PierSide pierSide,
const dms &ha)
2867 QJsonObject cStatus =
2878 ekosLiveClient.get()->message()->updateMountStatus(cStatus,
true);
2883 capturePreview->updateCaptureStatus(status, captureModule()->isActiveJobPreview(), trainname);
2892 m_CountdownTimer.stop();
2895 m_CountdownTimer.start();
2901 QJsonObject cStatus =
2904 {
"seqt", capturePreview->captureCountsWidget->sequenceRemainingTime->text()},
2905 {
"ovt", capturePreview->captureCountsWidget->overallRemainingTime->text()},
2906 {
"train", trainname}
2909 ekosLiveClient.get()->message()->updateCaptureStatus(cStatus);
2915 capturePreview->updateJobProgress(job, data, trainname);
2919 {
"seqv", job->getCompleted()},
2920 {
"seqr", job->getCoreProperty(SequenceJob::SJ_Count).toInt()},
2921 {
"seql", capturePreview->captureCountsWidget->sequenceRemainingTime->text()}
2924 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2926 if (data && job->getStatus() == JOB_BUSY)
2930 if (Options::useFITSViewer() ==
false)
2931 ekosLiveClient.get()->media()->sendData(data, data->objectName());
2933 if (job->jobType() != SequenceJob::JOBTYPE_PREVIEW)
2934 ekosLiveClient.get()->cloud()->sendData(data, data->objectName());
2942 {
"expv", job->getExposeLeft()},
2943 {
"expr", job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble()},
2944 {
"train", trainname}
2947 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2950void Manager::updateCaptureCountDown()
2952 capturePreview->updateCaptureCountDown(-1);
2956 {
"seqt", capturePreview->captureCountsWidget->sequenceRemainingTime->text()},
2957 {
"ovt", capturePreview->captureCountsWidget->overallRemainingTime->text()},
2958 {
"ovp", capturePreview->captureCountsWidget->gr_overallProgressBar->value()},
2959 {
"ovl", capturePreview->captureCountsWidget->gr_overallLabel->text()}
2962 ekosLiveClient.get()->message()->updateCaptureStatus(status);
2966void Manager::updateFocusStatus(Ekos::FocusState status)
2968 focusProgressWidget->updateFocusStatus(status);
2970 QJsonObject cStatus =
2972 {
"status", getFocusStatusString(status,
false)}
2975 ekosLiveClient.get()->message()->updateFocusStatus(cStatus);
2978void Manager::updateGuideStatus(Ekos::GuideState status)
2980 guideManager->updateGuideStatus(status);
2981 QJsonObject cStatus =
2983 {
"status", getGuideStatusString(status,
false)}
2986 ekosLiveClient.get()->message()->updateGuideStatus(cStatus);
2989void Manager::setTarget(
const QString &name)
2991 capturePreview->targetLabel->setVisible(!
name.
isEmpty());
2992 capturePreview->mountTarget->setVisible(!
name.
isEmpty());
2993 capturePreview->mountTarget->setText(name);
2994 ekosLiveClient.get()->message()->updateMountStatus(QJsonObject({{
"target",
name}}));
2997 mountModule()->setTargetName(name);
3000void Manager::showEkosOptions()
3002 QWidget * currentWidget = toolsWidget->currentWidget();
3004 if (alignModule() && alignModule() == currentWidget)
3010 alignSettings->
show();
3015 if (guideModule() && guideModule() == currentWidget)
3021 if (focusModule() && focusModule() == currentWidget)
3023 focusModule()->showOptions();
3027 if (schedulerModule() == currentWidget)
3039 if(captureModule() == currentWidget)
3051 const bool isAnalyze = (analyzeProcess.get() && analyzeProcess.get() == currentWidget);
3057 if (isAnalyze) index = 1;
3058 opsEkos->setCurrentIndex(index);
3071 if (ekosOptionsWidget ==
nullptr)
3088void Manager::updateDebugInterfaces()
3092 for (
auto &device : INDIListener::devices())
3094 auto debugProp = device->getProperty(
"DEBUG");
3098 auto debugSP = debugProp.getSwitch();
3101 if ( ( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
3102 debugSP->sp[0].s != ISS_ON)
3104 debugSP->at(0)->setState(ISS_ON);
3105 debugSP->at(1)->setState(ISS_OFF);
3107 appendLogText(
i18n(
"Enabling debug logging for %1...", device->getDeviceName()));
3109 else if ( !( opsLogs->getINDIDebugInterface() & device->getDriverInterface() ) &&
3110 debugSP->sp[0].s != ISS_OFF)
3112 debugSP->at(0)->setState(ISS_OFF);
3113 debugSP->at(1)->setState(ISS_ON);
3115 appendLogText(
i18n(
"Disabling debug logging for %1...", device->getDeviceName()));
3118 if (opsLogs->isINDISettingsChanged())
3119 device->setConfig(SAVE_CONFIG);
3123void Manager::watchDebugProperty(INDI::Property prop)
3125 if (prop.isNameMatch(
"DEBUG"))
3127 auto svp = prop.getSwitch();
3129 ISD::GenericDevice * deviceInterface = qobject_cast<ISD::GenericDevice *>(sender());
3132 if (deviceInterface->getDriverInterface() == INDI::BaseDevice::GENERAL_INTERFACE)
3137 if (svp->s == IPS_OK && svp->sp[0].s == ISS_OFF &&
3138 (opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
3140 svp->sp[0].s = ISS_ON;
3141 svp->sp[1].s = ISS_OFF;
3142 deviceInterface->sendNewProperty(svp);
3143 appendLogText(
i18n(
"Re-enabling debug logging for %1...", deviceInterface->getDeviceName()));
3149 else if (svp->s == IPS_OK && svp->sp[0].s == ISS_ON
3150 && !(opsLogs->getINDIDebugInterface() & deviceInterface->getDriverInterface()))
3152 svp->sp[0].s = ISS_OFF;
3153 svp->sp[1].s = ISS_ON;
3154 deviceInterface->sendNewProperty(svp);
3155 appendLogText(
i18n(
"Re-disabling debug logging for %1...", deviceInterface->getDeviceName()));
3160void Manager::announceEvent(
const QString &message, KSNotification::EventSource source, KSNotification::EventType event)
3162 ekosLiveClient.get()->message()->sendEvent(message, source, event);
3165void Manager::connectModules()
3168 connect(DarkLibrary::Instance(), &DarkLibrary::newImage, ekosLiveClient.get()->media(),
3170 connect(DarkLibrary::Instance(), &DarkLibrary::trainChanged, ekosLiveClient.get()->message(),
3172 connect(DarkLibrary::Instance(), &DarkLibrary::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3174 connect(DarkLibrary::Instance(), &DarkLibrary::settingsUpdated, ekosLiveClient.get()->message(),
3178 if (captureProcess && guideProcess)
3184 connect(guideModule(), &Ekos::Guide::newStatus, captureModule(), &Ekos::Capture::setGuideStatus,
3199 connect(guideModule(), &Ekos::Guide::guideChipUpdated, captureModule(), &Ekos::Capture::setGuideChip,
3205 connect(captureModule(), &Ekos::Capture::guideAfterMeridianFlip, guideModule(),
3210 if (guideProcess && mountProcess)
3221 if (guideProcess && focusProcess)
3231 if (captureProcess && focusProcess)
3234 connect(captureModule(), &Ekos::Capture::checkFocus, focusModule(), &Ekos::FocusModule::checkFocus,
3238 connect(captureProcess.get(), &Ekos::Capture::runAutoFocus, focusModule(), &Ekos::FocusModule::runAutoFocus,
3242 connect(captureModule(), &Ekos::Capture::resetFocusFrame, focusModule(), &Ekos::FocusModule::resetFrame,
3253 connect(captureModule(), &Ekos::Capture::adaptiveFocus, focusModule(), &Ekos::FocusModule::adaptiveFocus,
3264 connect(focusModule(), &Ekos::FocusModule::newFocusTemperatureDelta, captureModule(),
3268 connect(focusModule(), &Ekos::FocusModule::inSequenceAF, captureModule(),
3272 connect(captureModule(), &Ekos::Capture::meridianFlipStarted, focusModule(), &Ekos::FocusModule::meridianFlipStarted,
3277 if (captureProcess && alignProcess)
3280 connect(alignModule(), &Ekos::Align::newStatus, captureModule(), &Ekos::Capture::setAlignStatus,
3283 connect(alignModule(), &Ekos::Align::newSolverResults, captureModule(), &Ekos::Capture::setAlignResults,
3286 connect(captureModule(), &Ekos::Capture::newStatus, alignModule(), &Ekos::Align::setCaptureStatus,
3291 if (captureProcess && mountProcess)
3295 captureModule()->registerNewModule(
"Mount");
3296 mountModule()->registerNewModule(
"Capture");
3312 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated, ekosLiveClient->message(),
3314 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::configurationRequested, ekosLiveClient->message(),
3319 if (captureProcess && ekosLiveClient)
3323 connect(captureModule(), &Ekos::Capture::dslrInfoRequested, ekosLiveClient.get()->message(),
3325 connect(captureModule(), &Ekos::Capture::sequenceChanged, ekosLiveClient.get()->message(),
3327 connect(captureModule(), &Ekos::Capture::settingsUpdated, ekosLiveClient.get()->message(),
3329 connect(captureModule(), &Ekos::Capture::newLocalPreview, ekosLiveClient.get()->message(),
3331 connect(captureModule(), &Ekos::Capture::trainChanged, ekosLiveClient.get()->message(),
3336 if (focusProcess && alignProcess)
3338 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newStatus, alignModule(), &Ekos::Align::setFocusStatus,
3343 if (focusProcess && mountProcess)
3350 if (mountProcess && alignProcess)
3363 if (mountProcess && guideProcess)
3365 connect(mountModule(), &Ekos::Mount::pierSideChanged, guideModule(), &Ekos::Guide::setPierSide,
3370 if (alignProcess && ekosLiveClient)
3375 connect(alignModule(), &Ekos::Align::newStatus, ekosLiveClient.get()->message(), &EkosLive::Message::setAlignStatus,
3377 connect(alignModule(), &Ekos::Align::newSolution, ekosLiveClient.get()->message(),
3379 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHStage,
3380 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHStage,
3382 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newPAHMessage,
3383 ekosLiveClient.get()->message(),
3385 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::PAHEnabled,
3386 ekosLiveClient.get()->message(), &EkosLive::Message::setPAHEnabled,
3388 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::polarResultUpdated,
3389 ekosLiveClient.get()->message(),
3391 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::updatedErrorsChanged,
3392 ekosLiveClient.get()->message(),
3394 connect(alignModule()->polarAlignmentAssistant(), &Ekos::PolarAlignmentAssistant::newCorrectionVector,
3395 ekosLiveClient.get()->media(),
3398 connect(alignModule(), &Ekos::Align::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3400 connect(alignModule(), &Ekos::Align::newFrame, ekosLiveClient.get()->media(), &EkosLive::Media::sendUpdatedFrame,
3403 connect(alignModule(), &Ekos::Align::settingsUpdated, ekosLiveClient.get()->message(),
3406 connect(alignModule(), &Ekos::Align::trainChanged, ekosLiveClient.get()->message(),
3409 connect(alignModule(), &Ekos::Align::manualRotatorChanged, ekosLiveClient.get()->message(),
3414 if (focusProcess && ekosLiveClient)
3416 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::settingsUpdated, ekosLiveClient.get()->message(),
3419 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newImage, ekosLiveClient.get()->media(),
3420 &EkosLive::Media::sendModuleFrame,
3423 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::trainChanged, ekosLiveClient.get()->message(),
3424 &EkosLive::Message::sendTrainProfiles,
3427 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusAborted,
3432 if (guideProcess && ekosLiveClient)
3434 connect(guideModule(), &Ekos::Guide::settingsUpdated, ekosLiveClient.get()->message(),
3437 connect(guideModule(), &Ekos::Guide::trainChanged, ekosLiveClient.get()->message(),
3440 connect(guideModule(), &Ekos::Guide::newImage, ekosLiveClient.get()->media(), &EkosLive::Media::sendModuleFrame,
3448 connect(schedulerModule(), &Ekos::Scheduler::jobStarted,
3450 connect(schedulerModule(), &Ekos::Scheduler::jobEnded,
3452 connect(schedulerModule(), &Ekos::Scheduler::targetDistance,
3458 connect(captureModule(), &Ekos::Capture::captureComplete,
3460 connect(captureModule(), &Ekos::Capture::captureStarting,
3462 connect(captureModule(), &Ekos::Capture::captureAborted,
3466 connect(captureModule(), &Ekos::Capture::meridianFlipStarted,
3468 connect(captureModule(), &Ekos::Capture::meridianFlipCompleted,
3476 connect(guideModule(), &Ekos::Guide::newStatus,
3479 connect(guideModule(), &Ekos::Guide::guideStats,
3486 if (focusProcess && analyzeProcess)
3488 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusComplete,
3492 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusStarting,
3494 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::autofocusAborted,
3496 connect(focusModule()->mainFocuser().
get(), &Ekos::Focus::newFocusTemperatureDelta,
3501 if (alignProcess && analyzeProcess)
3503 connect(alignModule(), &Ekos::Align::newStatus,
3509 if (mountProcess && analyzeProcess)
3515 connect(mountModule()->getMeridianFlipState().
get(), &Ekos::MeridianFlipState::newMountMFStatus,
3520void Manager::setEkosLiveConnected(
bool enabled)
3522 ekosLiveClient.get()->setConnected(enabled);
3525void Manager::setEkosLiveConfig(
bool rememberCredentials,
bool autoConnect)
3527 ekosLiveClient.get()->setConfig(rememberCredentials, autoConnect);
3530void Manager::setEkosLiveUser(
const QString &username,
const QString &password)
3532 ekosLiveClient.get()->setUser(username, password);
3535bool Manager::ekosLiveStatus()
3537 return ekosLiveClient.get()->isConnected();
3543 if (!primaryDriver || !secondaryDriver)
3546 return (primaryDriver->getExecutable() == secondaryDriver->getExecutable() &&
3547 primaryDriver->getAuxInfo().value(
"mdpd",
false).toBool() ==
true);
3550void Manager::restartDriver(
const QString &deviceName)
3552 qCInfo(KSTARS_EKOS) <<
"Restarting driver" << deviceName;
3555 for (
auto &oneDevice : INDIListener::devices())
3557 if (oneDevice->getDeviceName() == deviceName)
3559 DriverManager::Instance()->restartDriver(oneDevice->getDriverInfo());
3565 INDI::WebManager::restartDriver(m_CurrentProfile, deviceName);
3568void Manager::setEkosLoggingEnabled(
const QString &name,
bool enabled)
3571 if (name ==
"LOGGING")
3573 Options::setDisableLogging(!enabled);
3577 else if (name ==
"FILE")
3579 Options::setLogToFile(enabled);
3583 else if (name ==
"DEFAULT")
3585 Options::setLogToDefault(enabled);
3590 else if (name ==
"VERBOSE")
3592 Options::setVerboseLogging(enabled);
3596 else if (name ==
"INDI")
3598 Options::setINDILogging(enabled);
3601 else if (name ==
"FITS")
3603 Options::setFITSLogging(enabled);
3606 else if (name ==
"CAPTURE")
3608 Options::setCaptureLogging(enabled);
3609 Options::setINDICCDLogging(enabled);
3610 Options::setINDIFilterWheelLogging(enabled);
3613 else if (name ==
"FOCUS")
3615 Options::setFocusLogging(enabled);
3616 Options::setINDIFocuserLogging(enabled);
3619 else if (name ==
"GUIDE")
3621 Options::setGuideLogging(enabled);
3622 Options::setINDICCDLogging(enabled);
3625 else if (name ==
"ALIGNMENT")
3627 Options::setAlignmentLogging(enabled);
3630 else if (name ==
"MOUNT")
3632 Options::setMountLogging(enabled);
3633 Options::setINDIMountLogging(enabled);
3636 else if (name ==
"SCHEDULER")
3638 Options::setSchedulerLogging(enabled);
3641 else if (name ==
"OBSERVATORY")
3643 Options::setObservatoryLogging(enabled);
3648void Manager::acceptPortSelection()
3651 m_PortSelector->accept();
3654void Manager::setPortSelectionComplete()
3656 if (m_CurrentProfile->portSelector)
3659 m_CurrentProfile->portSelector =
false;
3660 KStarsData::Instance()->
userdb()->SaveProfile(m_CurrentProfile);
3663 if (m_CurrentProfile->autoConnect)
3667void Manager::activateModule(
const QString &name,
bool popup)
3669 auto child = toolsWidget->findChild<QWidget *>(
name);
3672 toolsWidget->setCurrentWidget(child);
3684 if (device->isConnected())
3686 if (device->getDriverInterface() & INDI::BaseDevice::CCD_INTERFACE)
3693 if (device->getDriverInterface() & INDI::BaseDevice::FILTER_INTERFACE)
3699 if (device->getDriverInterface() & INDI::BaseDevice::FOCUSER_INTERFACE)
3701 if (device->getDriverInterface() & INDI::BaseDevice::TELESCOPE_INTERFACE)
3708 if (device->getDriverInterface() & INDI::BaseDevice::ROTATOR_INTERFACE)
3713 if (device->getDriverInterface() & INDI::BaseDevice::DOME_INTERFACE)
3719 if (device->getDriverInterface() & INDI::BaseDevice::WEATHER_INTERFACE)
3724 if (device->getDriverInterface() & INDI::BaseDevice::DUSTCAP_INTERFACE)
3728 if (device->getDriverInterface() & INDI::BaseDevice::LIGHTBOX_INTERFACE)
3732 if (device->getDriverInterface() & INDI::BaseDevice::GPS_INTERFACE)
3739void Manager::setDeviceReady()
3743 if (isINDIReady() ==
false)
3745 auto device =
static_cast<ISD::GenericDevice*
>(sender());
3749 if (device->isConnected() ==
false && m_CurrentProfile->autoConnect)
3752 if (m_CurrentProfile->portSelector)
3758 if (!m_PortSelector)
3759 m_PortSelectorTimer.start();
3763 qCInfo(KSTARS_EKOS) <<
"Connecting to" << device->getDeviceName();
3768 qCInfo(KSTARS_EKOS) << device->getDeviceName() <<
"is connected and ready.";
3771 if (m_ekosStatus != Ekos::Success)
3776 if (m_DriverDevicesCount <= 0 && (m_CurrentProfile->portSelector ==
false || !m_PortSelector))
3778 for (
auto &device : INDIListener::devices())
3779 syncGenericDevice(device);
3780 OpticalTrainManager::Instance()->setProfile(m_CurrentProfile);
3784void Manager::createFilterManager(ISD::FilterWheel *device)
3786 auto name = device->getDeviceName();
3787 if (m_FilterManagers.contains(name) ==
false)
3789 QSharedPointer<FilterManager> newFM(
new FilterManager(
this));
3790 newFM->setFilterWheel(device);
3791 m_FilterManagers.insert(name, std::move(newFM));
3794 m_FilterManagers[
name]->setFilterWheel(device);
3800 if (m_FilterManagers.contains(name))
3802 fm = m_FilterManagers[
name];
3810 if (m_FilterManagers.size() > 0)
3812 fm = m_FilterManagers.values()[0];
3818void Manager::createRotatorController(
ISD::Rotator *device)
3820 auto Name = device->getDeviceName();
3821 if (m_RotatorControllers.contains(Name) ==
false)
3823 QSharedPointer<RotatorSettings> newRC(
new RotatorSettings(
this));
3825 m_RotatorControllers[Name] = newRC;
3831 if (m_RotatorControllers.contains(Name))
3833 rs = m_RotatorControllers[Name];
3839bool Manager::existRotatorController()
3841 return (!m_RotatorControllers.empty());
3844void Manager::setFITSfromFile(
bool previewFromFile)
3846 if (previewFromFile && !FITSfromFile)
3849 QObject::disconnect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
3850 FITSfromFile = previewFromFile;
3851 appendLogText(
i18n(
"Preview source set to external"));
3853 else if (!previewFromFile && FITSfromFile)
3856 QObject::connect(captureModule(), &Ekos::Capture::newImage,
this, &Ekos::Manager::updateCaptureProgress);
3857 FITSfromFile = previewFromFile;
3858 appendLogText(
i18n(
"Preview source reset to internal"));
3862void Manager::previewFile(
QString filePath)
3864 capturePreview->updateJobPreview(filePath);
3865 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)