7#include "focusmodule.h" 
    9#include "focusadaptor.h" 
   12#include "auxiliary/ksmessagebox.h" 
   13#include "ekos/auxiliary/opticaltrainmanager.h" 
   14#include "kstarsdata.h" 
   16#include <KConfigDialog> 
   18#include "ekos_focus_debug.h" 
   20#define TAB_BUTTON_SIZE 20 
   25FocusModule::FocusModule()
 
   29    focusTabs->setTabsClosable(
true);
 
   34    QPushButton *addButton = 
new QPushButton;
 
   36    addButton->
setFixedSize(TAB_BUTTON_SIZE, TAB_BUTTON_SIZE);
 
   37    addButton->
setToolTip(
i18n(
"<p>Add additional focuser</p><p><b>WARNING</b>: This feature is experimental!</p>"));
 
   40        FocusModule::addFocuser();
 
   43    focusTabs->addTab(newTab, 
"");
 
   49    m_FocusLogFile.setFileName(m_FocusLogFileName);
 
   55    qRegisterMetaType<FocusState>(
"FocusState");
 
   56    qDBusRegisterMetaType<FocusState>();
 
   57    new FocusAdaptor(
this);
 
   61FocusModule::~FocusModule()
 
   63    m_FocusLogFile.close();
 
   66QSharedPointer<Focus> &FocusModule::focuser(
int i)
 
   68    if (i < m_Focusers.count())
 
   72        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << i;
 
   78QString FocusModule::filterWheel(
const QString &trainname)
 
   80    int id = findFocuser(trainname, 
true);
 
   81    if (0 <= 
id && 
id < m_Focusers.count())
 
   82        return m_Focusers[id]->filterWheel();
 
   85        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
   90bool FocusModule::setFilter(
const QString &filter, 
const QString &trainname)
 
   92    int id = findFocuser(trainname, 
true);
 
   93    if (0 <= 
id && 
id < m_Focusers.count())
 
   94        return m_Focusers[id]->setFilter(filter);
 
   97        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  102QString FocusModule::filter(
const QString &trainname)
 
  104    int id = findFocuser(trainname, 
true);
 
  105    if (0 <= 
id && 
id < m_Focusers.count())
 
  106        return m_Focusers[id]->filter();
 
  109        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  114double FocusModule::getHFR(
const QString &trainname)
 
  116    int id = findFocuser(trainname, 
true);
 
  117    if (0 <= 
id && 
id < m_Focusers.count())
 
  118        return m_Focusers[id]->getHFR();
 
  121        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  126bool FocusModule::setExposure(
double value, 
const QString &trainname)
 
  128    int id = findFocuser(trainname, 
true);
 
  129    if (0 <= 
id && 
id < m_Focusers.count())
 
  131        m_Focusers[id]->setExposure(value);
 
  136        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  141double FocusModule::exposure(
const QString &trainname)
 
  143    int id = findFocuser(trainname, 
true);
 
  144    if (0 <= 
id && 
id < m_Focusers.count())
 
  145        return m_Focusers[id]->exposure();
 
  148        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  153bool FocusModule::canAutoFocus(
const QString &trainname)
 
  155    int id = findFocuser(trainname, 
true);
 
  156    if (0 <= 
id && 
id < m_Focusers.count())
 
  157        return m_Focusers[id]->canAutoFocus();
 
  160        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  165bool FocusModule::useFullField(
const QString &trainname)
 
  167    int id = findFocuser(trainname, 
true);
 
  168    if (0 <= 
id && 
id < m_Focusers.count())
 
  169        return m_Focusers[id]->useFullField();
 
  172        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  177bool FocusModule::setBinning(
int binX, 
int binY, 
const QString &trainname)
 
  179    int id = findFocuser(trainname, 
true);
 
  180    if (0 <= 
id && 
id < m_Focusers.count())
 
  182        m_Focusers[id]->setBinning(binX, binY);
 
  187        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  192bool FocusModule::setAutoStarEnabled(
bool enable, 
const QString &trainname)
 
  194    int id = findFocuser(trainname, 
true);
 
  195    if (0 <= 
id && 
id < m_Focusers.count())
 
  197        m_Focusers[id]->setAutoStarEnabled(enable);
 
  202        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  207bool FocusModule::setAutoSubFrameEnabled(
bool enable, 
const QString &trainname)
 
  209    int id = findFocuser(trainname, 
true);
 
  210    if (0 <= 
id && 
id < m_Focusers.count())
 
  212        m_Focusers[id]->setAutoSubFrameEnabled(enable);
 
  217        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  222bool FocusModule::setAutoFocusParameters(
const QString &trainname, 
int boxSize, 
int stepSize, 
int maxTravel,
 
  225    int id = findFocuser(trainname, 
true);
 
  226    if (0 <= 
id && 
id < m_Focusers.count())
 
  228        m_Focusers[id]->setAutoFocusParameters(boxSize, stepSize, maxTravel, tolerance);
 
  233        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  238QSharedPointer<Focus> FocusModule::mainFocuser()
 
  240    if (m_Focusers.size() <= 0)
 
  242        QSharedPointer<Focus> newFocuser;
 
  243        newFocuser.
reset(
new Focus(0));
 
  244        m_Focusers.append(newFocuser);
 
  246    return m_Focusers[0];
 
  249int FocusModule::findFocuser(
const QString &trainname, 
bool addIfNecessary)
 
  251    for (
int pos = 0; 
pos < m_Focusers.count(); 
pos++)
 
  252        if (m_Focusers[
pos]->opticalTrain() == trainname)
 
  257        addFocuser(trainname);
 
  258        return m_Focusers.count() - 1;
 
  264void FocusModule::checkFocus(
double requiredHFR, 
const QString &trainname)
 
  268    for (
auto focuser : m_Focusers)
 
  269        if (trainname == 
"" || focuser->opticalTrain() == trainname)
 
  271            focuser->checkFocus(requiredHFR);
 
  277        QSharedPointer newFocuser = addFocuser(trainname);
 
  278        newFocuser->checkFocus(requiredHFR);
 
  282void FocusModule::runAutoFocus(
const AutofocusReason autofocusReason, 
const QString &reasonInfo, 
const QString &trainname)
 
  286    for (
auto focuser : m_Focusers)
 
  287        if (trainname == 
"" || focuser->opticalTrain() == trainname)
 
  289            focuser->runAutoFocus(autofocusReason, reasonInfo);
 
  295        QSharedPointer newFocuser = addFocuser(trainname);
 
  296        newFocuser->runAutoFocus(autofocusReason, reasonInfo);
 
  300void FocusModule::resetFrame(
const QString &trainname)
 
  304    for (
auto focuser : m_Focusers)
 
  305        if (trainname == 
"" || focuser->opticalTrain() == trainname)
 
  307            focuser->resetFrame();
 
  313        QSharedPointer newFocuser = addFocuser(trainname);
 
  314        newFocuser->resetFrame();
 
  318void FocusModule::abort(
const QString &trainname)
 
  322    for (
auto focuser : m_Focusers)
 
  323        if (trainname == 
"" || focuser->opticalTrain() == trainname)
 
  331        QSharedPointer newFocuser = addFocuser(trainname);
 
  336void FocusModule::adaptiveFocus(
const QString &trainname)
 
  340    for (
auto focuser : m_Focusers)
 
  341        if (trainname == 
"" || focuser->opticalTrain() == trainname)
 
  343            focuser->adaptiveFocus();
 
  349        QSharedPointer newFocuser = addFocuser(trainname);
 
  350        newFocuser->adaptiveFocus();
 
  354void FocusModule::meridianFlipStarted(
const QString &trainname)
 
  358    for (
auto focuser : m_Focusers)
 
  359        if (trainname == 
"" || focuser->opticalTrain() == trainname)
 
  361            focuser->meridianFlipStarted();
 
  367        QSharedPointer newFocuser = addFocuser(trainname);
 
  368        newFocuser->meridianFlipStarted();
 
  372void FocusModule::setMountStatus(ISD::Mount::Status newState)
 
  375    for (
auto focuser : m_Focusers)
 
  376        focuser->setMountStatus(newState);
 
  379void FocusModule::setMountCoords(
const SkyPoint &position, ISD::Mount::PierSide pierSide, 
const dms &ha)
 
  382    for (
auto focuser : m_Focusers)
 
  383        focuser->setMountCoords(position, pierSide, ha);
 
  386FocusState FocusModule::status(
const QString &trainname)
 
  388    int id = findFocuser(trainname, 
true);
 
  389    if (0 <= 
id && 
id < m_Focusers.count())
 
  390        return m_Focusers[id]->status();
 
  393        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  394        return FocusState::FOCUS_IDLE;
 
  398QString FocusModule::camera(
const QString &trainname)
 
  400    int id = findFocuser(trainname, 
true);
 
  401    if (0 <= 
id && 
id < m_Focusers.count())
 
  402        return m_Focusers[id]->camera();
 
  405        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  410QString FocusModule::focuser(
const QString &trainname)
 
  412    int id = findFocuser(trainname, 
true);
 
  413    if (0 <= 
id && 
id < m_Focusers.count())
 
  414        return m_Focusers[id]->focuser();
 
  417        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  422bool FocusModule::addTemperatureSource(
const QSharedPointer<ISD::GenericDevice> &device)
 
  427    for (
auto &oneSource : m_TemperatureSources)
 
  429        if (oneSource->getDeviceName() == device->getDeviceName())
 
  433    m_TemperatureSources.append(device);
 
  436    for (
auto focuser : m_Focusers)
 
  437        focuser->updateTemperatureSources(m_TemperatureSources);
 
  442void FocusModule::syncCameraInfo(
const char* devicename)
 
  445    for (
auto focuser : m_Focusers)
 
  446        if (focuser->camera() == devicename)
 
  447            focuser->syncCameraInfo();
 
  450void FocusModule::clearLog()
 
  453    emit newLog(QString());
 
  456void FocusModule::appendLogText(
const QString &logtext)
 
  458    m_LogText.insert(0, 
i18nc(
"log entry; %1 is the date, %2 is the text", 
"%1 %2",
 
  459                              KStarsData::Instance()->lt().
toString(
"yyyy-MM-ddThh:mm:ss"), logtext));
 
  461    qCInfo(KSTARS_EKOS_FOCUS) << logtext;
 
  463    emit newLog(logtext);
 
  466void FocusModule::appendFocusLogText(
const QString &lines)
 
  468    if (Options::focusLogging())
 
  471        if (!m_FocusLogFile.exists())
 
  475            dir.mkpath(
"focuslogs");
 
  477            if (m_FocusLogEnabled)
 
  479                QTextStream header(&m_FocusLogFile);
 
  480                header << 
"date, time, position, temperature, filter, HFR, altitude\n";
 
  484                qCWarning(KSTARS_EKOS_FOCUS) << 
"Failed to open focus log file: " << m_FocusLogFileName;
 
  487        if (m_FocusLogEnabled)
 
  489            QTextStream out(&m_FocusLogFile);
 
  497bool FocusModule::start(
const QString &trainname)
 
  499    int id = findFocuser(trainname, 
true);
 
  500    if (0 <= 
id && 
id < m_Focusers.count())
 
  502        m_Focusers[id]->start();
 
  507        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  512bool FocusModule::capture(
const QString &trainname, 
double settleTime)
 
  514    int id = findFocuser(trainname, 
true);
 
  515    if (0 <= 
id && 
id < m_Focusers.count())
 
  517        m_Focusers[id]->capture(settleTime);
 
  522        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  527bool FocusModule::focusIn(
const QString &trainname, 
int ms)
 
  529    int id = findFocuser(trainname, 
true);
 
  530    if (0 <= 
id && 
id < m_Focusers.count())
 
  531        return m_Focusers[id]->focusIn(ms);
 
  534        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  539bool FocusModule::focusOut(
const QString &trainname, 
int ms)
 
  541    int id = findFocuser(trainname, 
true);
 
  542    if (0 <= 
id && 
id < m_Focusers.count())
 
  543        return m_Focusers[id]->focusOut(ms);
 
  546        qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << id;
 
  552void FocusModule::removeDevice(
const QSharedPointer<ISD::GenericDevice> &deviceRemoved)
 
  555    for (
auto &oneSource : m_TemperatureSources)
 
  556        if (oneSource->getDeviceName() == deviceRemoved->getDeviceName())
 
  557            m_TemperatureSources.removeAll(oneSource);
 
  560    for (
auto focuser : m_Focusers)
 
  561        focuser->removeDevice(deviceRemoved);
 
  565void FocusModule::initFocuser(QSharedPointer<Focus> newFocuser)
 
  567    connect(newFocuser.
get(), &Focus::focuserChanged, 
this, &FocusModule::updateFocuser);
 
  568    connect(newFocuser.
get(), &Focus::suspendGuiding, 
this, &FocusModule::suspendGuiding);
 
  569    connect(newFocuser.
get(), &Focus::resumeGuiding, 
this, &FocusModule::resumeGuiding);
 
  570    connect(newFocuser.
get(), &Focus::resumeGuiding, 
this, &FocusModule::resumeGuiding);
 
  571    connect(newFocuser.
get(), &Focus::newStatus, 
this, &FocusModule::newStatus);
 
  572    connect(newFocuser.
get(), &Focus::focusAdaptiveComplete, 
this, &FocusModule::focusAdaptiveComplete);
 
  573    connect(newFocuser.
get(), &Focus::newHFR, 
this, &FocusModule::newHFR);
 
  574    connect(newFocuser.
get(), &Focus::newFocusTemperatureDelta, 
this, &FocusModule::newFocusTemperatureDelta);
 
  575    connect(newFocuser.
get(), &Focus::inSequenceAF, 
this, &FocusModule::inSequenceAF);
 
  576    connect(newFocuser.
get(), &Focus::newLog, 
this, &FocusModule::appendLogText);
 
  577    connect(newFocuser.
get(), &Focus::newFocusLog, 
this, &FocusModule::appendFocusLogText);
 
  580QSharedPointer<Focus> FocusModule::addFocuser(
const QString &trainname)
 
  582    QSharedPointer<Focus> newFocuser;
 
  583    newFocuser.
reset(
new Focus(m_Focusers.count()));
 
  586    const int tabIndex = focusTabs->insertTab(std::max(0, focusTabs->count() - 1), newFocuser.
get(), 
"new Focuser");
 
  587    focusTabs->setCurrentIndex(tabIndex);
 
  593    const QString train = tabIndex == 0 ? 
"" : findUnusedOpticalTrain();
 
  595    m_Focusers.append(newFocuser);
 
  598        newFocuser->opticalTrainCombo->setCurrentText(train);
 
  601    newFocuser->updateTemperatureSources(m_TemperatureSources);
 
  603    if (trainname != 
"" && newFocuser->opticalTrainCombo->findText(trainname))
 
  604        newFocuser->opticalTrainCombo->setCurrentText(trainname);
 
  607    updateFocuser(tabIndex, 
true);
 
  608    initFocuser(newFocuser);
 
  613void FocusModule::updateFocuser(
int tabID, 
bool isValid)
 
  617        if (tabID < focusTabs->count() && tabID < m_Focusers.count() && !m_Focusers[tabID].isNull())
 
  619            const QString 
name = m_Focusers[tabID]->m_Focuser != 
nullptr ?
 
  620                                 m_Focusers[tabID]->m_Focuser->getDeviceName() :
 
  622            focusTabs->setTabText(tabID, name);
 
  625            qCWarning(KSTARS_EKOS_FOCUS) << 
"Unknown focuser ID:" << tabID;
 
  628        focusTabs->setTabText(focusTabs->currentIndex(), 
"no focuser");
 
  631void FocusModule::closeFocuserTab(
int tabIndex)
 
  634    if (tabIndex == focusTabs->count() - 1)
 
  637    focusTabs->removeTab(tabIndex);
 
  639    focusTabs->setCurrentIndex(std::max(0, tabIndex - 1));
 
  641    auto focuser = m_Focusers.at(tabIndex);
 
  642    focuser->disconnect(
this);
 
  643    focuser->disconnectSyncSettings();
 
  644    m_Focusers.removeAt(tabIndex);
 
  647void FocusModule::showOptions()
 
  649    int tabID = focusTabs->currentIndex();
 
  653        focusSettings->
show();
 
  654        focusSettings->
raise();
 
  658void FocusModule::checkCloseFocuserTab(
int tabIndex)
 
  660    if (m_Focusers[tabIndex]->isBusy())
 
  666            m_Focusers[tabIndex]->abort();
 
  667            closeFocuserTab(tabIndex);
 
  675        KSMessageBox::Instance()->warningContinueCancel(
i18n(
"Camera %1 is busy. Abort to close?",
 
  676                m_Focusers[tabIndex]->m_Focuser->getDeviceName()), 
i18n(
"Stop capturing"), 30, 
false, 
i18n(
"Abort"));
 
  680        closeFocuserTab(tabIndex);
 
  685const QString FocusModule::findUnusedOpticalTrain()
 
  687    QList<QString> names = OpticalTrainManager::Instance()->getTrainNames();
 
  688    foreach(
auto focuser, m_Focusers)
 
  689        names.
removeAll(focuser->opticalTrain());
 
  694        return names.
first();
 
static KConfigDialog * exists(const QString &name)
 
QString i18nc(const char *context, const char *text, const TYPE &arg...)
 
QString i18n(const char *text, const TYPE &arg...)
 
char * toString(const EngineQuery &query)
 
Ekos is an advanced Astrophotography tool for Linux.
 
KIOCORE_EXPORT QString dir(const QString &fileClass)
 
QString name(StandardAction id)
 
QDateTime currentDateTime()
 
QString toString(QStringView format, QCalendar cal) const const
 
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
 
QDBusConnection sessionBus()
 
QIcon fromTheme(const QString &name)
 
bool isEmpty() const const
 
qsizetype removeAll(const AT &t)
 
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
 
bool disconnect(const QMetaObject::Connection &connection)
 
bool isNull() const const