[education/kstars] /: Implement refresh button. Avoid adding to status widget when not in main thread.

Hy Murveit null at kde.org
Sun Aug 20 08:38:43 BST 2023


Git commit cd028a5753ebed609a209567560f1a341747faa4 by Hy Murveit.
Committed on 20/08/2023 at 09:09.
Pushed by murveit into branch 'master'.

Implement refresh button. Avoid adding to status widget when not in main thread.

M  +1    -1    doc/config.docbook
M  +2    -0    kstars/options/opsimageoverlay.cpp
M  +1    -1    kstars/options/opsimageoverlay.ui
M  +30   -29   kstars/skycomponents/imageoverlaycomponent.cpp
M  +4    -1    kstars/skycomponents/imageoverlaycomponent.h

https://invent.kde.org/education/kstars/-/commit/cd028a5753ebed609a209567560f1a341747faa4

diff --git a/doc/config.docbook b/doc/config.docbook
index 9e5b759bf..642900f33 100644
--- a/doc/config.docbook
+++ b/doc/config.docbook
@@ -1192,7 +1192,7 @@ Image overlays are custom images (typically .jpg) that are rendered onto the sky
 The <guilabel>Image Overlays</guilabel> page lets you configure whether image overlays will be shown on the skymap, and helps you add them to the system. The image at the start of this section shows the skymap with image overlays enabled and some image overlays loaded.
 </para>
 <para>
-  Each time it starts up, KStars looks for new image overlay images in a special directory, parallel to the logs directory, named imageOverlays. On Linux this can be found in ~/.local/share/kstars/imageOverlays. The exact location for your system can be found by clicking the <guilabel>Overlay Directory</guilabel> button near the top of the Image Overlays config page shown at the top of this section. To start, add your images to that directory. Ideally, for performance reasons these aren't massive files, but probably images with widths 1000 or 2000 should be fine. To add additional images in the future,  add them to the same directory and restart KStars.
+  Each time it starts up, KStars looks for new image overlay images in a special directory, parallel to the logs directory, named imageOverlays. On Linux this can be found in ~/.local/share/kstars/imageOverlays. The exact location for your system can be found by clicking the <guilabel>Overlay Directory</guilabel> button near the top of the Image Overlays config page shown at the top of this section. To start, add your images to that directory. Ideally, for performance reasons these aren't massive files, but probably images with widths 1000 or 2000 should be fine. To add additional images in the future,  add them to the same directory and click the refresh button or restart KStars. To remove overlays, remove them from the directory and click the refresh button or restart KStars.
 </para>
 <para>
 Start KStars once you have images in the imageOverlays directory. If you then go to the Image Overlays config page, you should see the new files listed in the table. The new images will show their status as "Unprocessed". Only images whose status is "OK" are displayed on the SkyMap. That is because KStars needs to know the sky location, size, and orientation for these images before it can display them. To change the status to OK you need to plate-solve the images or add the required information manually--see below.
diff --git a/kstars/options/opsimageoverlay.cpp b/kstars/options/opsimageoverlay.cpp
index a5c4679e8..5ff11e864 100644
--- a/kstars/options/opsimageoverlay.cpp
+++ b/kstars/options/opsimageoverlay.cpp
@@ -35,6 +35,8 @@ OpsImageOverlay::OpsImageOverlay() : QFrame(KStars::Instance())
                 KStarsData::Instance()->skyComposite()->imageOverlay());
     connect(solveButton, &QPushButton::clicked, overlayComponent, &ImageOverlayComponent::startSolving,
             Qt::UniqueConnection);
+    connect(refreshB, &QPushButton::clicked, overlayComponent, &ImageOverlayComponent::reload,
+            Qt::UniqueConnection);
     connect(kcfg_ShowImageOverlays, &QCheckBox::stateChanged, [](int state)
     {
         Options::setShowImageOverlays(state);
diff --git a/kstars/options/opsimageoverlay.ui b/kstars/options/opsimageoverlay.ui
index 4d78bf233..85ca38c8e 100644
--- a/kstars/options/opsimageoverlay.ui
+++ b/kstars/options/opsimageoverlay.ui
@@ -162,7 +162,7 @@
              </size>
             </property>
             <property name="toolTip">
-             <string>Refresh</string>
+              <string><html><head/><body><p>Refresh from the overlay directory. Add overlays that have been added there, and remove overlays that are no longer there.</p></body></html></string>
             </property>
             <property name="text">
              <string/>
diff --git a/kstars/skycomponents/imageoverlaycomponent.cpp b/kstars/skycomponents/imageoverlaycomponent.cpp
index 40eb4205a..bd1fa621e 100644
--- a/kstars/skycomponents/imageoverlaycomponent.cpp
+++ b/kstars/skycomponents/imageoverlaycomponent.cpp
@@ -130,6 +130,7 @@ ImageOverlayComponent::ImageOverlayComponent(SkyComposite *parent) : SkyComponen
     dir.mkpath(".");
     m_Directory = dir.absolutePath();
     connect(&m_TryAgainTimer, &QTimer::timeout, this, &ImageOverlayComponent::tryAgain, Qt::UniqueConnection);
+    connect(this, &ImageOverlayComponent::updateLog, this, &ImageOverlayComponent::updateStatusDisplay, Qt::UniqueConnection);
 
     // Get the latest from the User DB
     loadFromUserDB();
@@ -160,7 +161,7 @@ void ImageOverlayComponent::cellChanged(int row, int col)
         {
             item->setText(dms(overlay.m_RA).toHMSString());
             QString msg = i18n("Bad RA string entered for %1. Reset to original value.", overlay.m_Filename);
-            updateStatusDisplay(msg);
+            emit updateLog(msg);
         }
         else
             // Re-format the user-entered value.
@@ -174,7 +175,7 @@ void ImageOverlayComponent::cellChanged(int row, int col)
         {
             item->setText(toDecString(overlay.m_DEC));
             QString msg = i18n("Bad DEC string entered for %1. Reset to original value.", overlay.m_Filename);
-            updateStatusDisplay(msg);
+            emit updateLog(msg);
         }
         else
             item->setText(toDecString(decDMS));
@@ -187,7 +188,7 @@ void ImageOverlayComponent::cellChanged(int row, int col)
         {
             item->setText(QString("%1").arg(overlay.m_Orientation, 0, 'f', 2));
             QString msg = i18n("Bad orientation angle string entered for %1. Reset to original value.", overlay.m_Filename);
-            updateStatusDisplay(msg);
+            emit updateLog(msg);
         }
     }
     else if (col == ARCSEC_PER_PIXEL_COL)
@@ -198,7 +199,7 @@ void ImageOverlayComponent::cellChanged(int row, int col)
         {
             item->setText(QString("%1").arg(overlay.m_ArcsecPerPixel, 0, 'f', 2));
             QString msg = i18n("Bad scale angle string entered for %1. Reset to original value.", overlay.m_Filename);
-            updateStatusDisplay(msg);
+            emit updateLog(msg);
         }
     }
     connect(m_ImageOverlayTable, &QTableWidget::cellChanged, this, &ImageOverlayComponent::cellChanged, Qt::UniqueConnection);
@@ -228,7 +229,7 @@ void ImageOverlayComponent::statusCellChanged(int row)
         if (!raOK || raDMS.Degrees() == 0)
         {
             QString msg = i18n("Cannot set status to OK. Legal non-0 RA value required.");
-            updateStatusDisplay(msg);
+            emit updateLog(msg);
             failed = true;
         }
 
@@ -239,7 +240,7 @@ void ImageOverlayComponent::statusCellChanged(int row)
         if (!decOK)
         {
             QString msg = i18n("Cannot set status to OK. Legal non-0 DEC value required.");
-            updateStatusDisplay(msg);
+            emit updateLog(msg);
             failed = true;
         }
 
@@ -250,7 +251,7 @@ void ImageOverlayComponent::statusCellChanged(int row)
         if (!angleOK || angle > 360 || angle < -360)
         {
             QString msg = i18n("Cannot set status to OK. Legal orientation value required.");
-            updateStatusDisplay(msg);
+            emit updateLog(msg);
             failed = true;
         }
 
@@ -261,7 +262,7 @@ void ImageOverlayComponent::statusCellChanged(int row)
         if (!scaleOK || scale < 0 || scale > 1000)
         {
             QString msg = i18n("Cannot set status to OK. Legal non-0 a-s/px value required.");
-            updateStatusDisplay(msg);
+            emit updateLog(msg);
             failed = true;
         }
 
@@ -291,7 +292,7 @@ void ImageOverlayComponent::statusCellChanged(int row)
             }
             saveToUserDB();
             QString msg = i18n("Stored OK status for %1.", m_Overlays[row].m_Filename);
-            updateStatusDisplay(msg);
+            emit updateLog(msg);
         }
     }
     connect(m_ImageOverlayTable, &QTableWidget::cellChanged, this, &ImageOverlayComponent::cellChanged, Qt::UniqueConnection);
@@ -383,7 +384,7 @@ void ImageOverlayComponent::updateTable()
 {
     // Get the list of files from the image overlay directory.
     QDir directory(m_Directory);
-    updateStatusDisplay(i18n("Updating from directory: %1", m_Directory));
+    emit updateLog(i18n("Updating from directory: %1", m_Directory));
     QStringList images = directory.entryList(QStringList() << "*", QDir::Files);
     QSet<QString> imageFiles;
     foreach(QString filename, images)
@@ -432,8 +433,8 @@ void ImageOverlayComponent::updateTable()
             numNew++;
         }
     }
-    updateStatusDisplay(i18n("%1 overlays (%2 new, %3 deleted) %4 solved", m_Overlays.size(), numNew, numDeleted,
-                             numAvailable()));
+    emit updateLog(i18n("%1 overlays (%2 new, %3 deleted) %4 solved", m_Overlays.size(), numNew, numDeleted,
+                        numAvailable()));
     m_TableGroupBox->setTitle(i18n("Image Overlays.  %1 images, %2 available.", m_Overlays.size(), numAvailable()));
 
     initializeGui();
@@ -447,13 +448,13 @@ void ImageOverlayComponent::loadAllImageFiles()
 
 void ImageOverlayComponent::loadImageFileLoop()
 {
-    updateStatusDisplay(i18n("Loading image files..."));
+    emit updateLog(i18n("Loading image files..."));
     while (loadImageFile());
     int num = 0;
     for (const auto &o : m_Overlays)
         if (o.m_Img.get() != nullptr)
             num++;
-    updateStatusDisplay(i18n("%1 image files loaded.", num));
+    emit updateLog(i18n("%1 image files loaded.", num));
     // Restore editing for the table.
     m_ImageOverlayTable->setEditTriggers(m_EditTriggers);
     m_Initialized = true;
@@ -593,9 +594,9 @@ void ImageOverlayComponent::solveImage(const QString &filename)
     connect(m_Solver.get(), &SolverUtils::done, this, &ImageOverlayComponent::solverDone, Qt::UniqueConnection);
 
     if (m_RowsToSolve.size() > 1)
-        updateStatusDisplay(i18n("Solving: %1. %2 in queue.", filename, m_RowsToSolve.size()));
+        emit updateLog(i18n("Solving: %1. %2 in queue.", filename, m_RowsToSolve.size()));
     else
-        updateStatusDisplay(i18n("Solving: %1.", filename));
+        emit updateLog(i18n("Solving: %1.", filename));
 
     // If the user added some RA/DEC/Scale values to the table, they will be used in the solve
     // (but aren't remembered in the DB unless the solve is successful).
@@ -660,12 +661,12 @@ void ImageOverlayComponent::show()
         {
             if (m_Overlays[row].m_Status != ImageOverlay::AVAILABLE)
             {
-                updateStatusDisplay(i18n("Can't show %1. Not plate solved.", m_Overlays[row].m_Filename));
+                emit updateLog(i18n("Can't show %1. Not plate solved.", m_Overlays[row].m_Filename));
                 return;
             }
             if (m_Overlays[row].m_Img.get() == nullptr)
             {
-                updateStatusDisplay(i18n("Can't show %1. Image not loaded.", m_Overlays[row].m_Filename));
+                emit updateLog(i18n("Can't show %1. Image not loaded.", m_Overlays[row].m_Filename));
                 return;
             }
             const double ra = m_Overlays[row].m_RA;
@@ -698,7 +699,7 @@ void ImageOverlayComponent::abortSolving()
     m_RowsToSolve.clear();
     if (m_Solver)
         m_Solver->abort();
-    updateStatusDisplay(i18n("Solving aborted."));
+    emit updateLog(i18n("Solving aborted."));
     m_SolveButton->setText(i18n("Solve"));
 }
 
@@ -733,7 +734,7 @@ void ImageOverlayComponent::startSolving()
                 if ((m_Overlays[row].m_Status == ImageOverlay::AVAILABLE) &&
                         !shouldSolveAnyway(m_ImageOverlayTable, row))
                 {
-                    updateStatusDisplay(i18n("Skipping already solved: %1.", m_Overlays[row].m_Filename));
+                    emit updateLog(i18n("Skipping already solved: %1.", m_Overlays[row].m_Filename));
                     continue;
                 }
                 selectedRows.insert(row);
@@ -752,7 +753,7 @@ void ImageOverlayComponent::startSolving()
         if ((m_Overlays[row].m_Status == ImageOverlay::AVAILABLE) &&
                 !shouldSolveAnyway(m_ImageOverlayTable, row))
         {
-            updateStatusDisplay(i18n("%1 already solved. Skipping.", filename));
+            emit updateLog(i18n("%1 already solved. Skipping.", filename));
             m_RowsToSolve.removeFirst();
             if (m_RowsToSolve.size() > 0)
                 startSolving();
@@ -769,10 +770,10 @@ void ImageOverlayComponent::startSolving()
 void ImageOverlayComponent::reload()
 {
     if (!m_Initialized) return;
-    //updateTable();
-    // Problem with reload is it can crash kstars if the image load loop is running, or
-    // if something else is messing with m_Overlays. Need mutex protection.
-    updateStatusDisplay(i18n("Reload not yet implemented. Currently you need to restart KStars to do this."));
+    m_Initialized = false;
+    emit updateLog(i18n("Reloading. Image overlays temporarily disabled."));
+    updateTable();
+    loadAllImageFiles();
 }
 
 void ImageOverlayComponent::solverDone(bool timedOut, bool success, const FITSImage::Solution &solution,
@@ -789,13 +790,13 @@ void ImageOverlayComponent::solverDone(bool timedOut, bool success, const FITSIm
     QComboBox *statusItem = dynamic_cast<QComboBox*>(m_ImageOverlayTable->cellWidget(solverRow, STATUS_COL));
     if (timedOut)
     {
-        updateStatusDisplay(i18n("Solver timed out in %1s", QString::number(elapsedSeconds, 'f', 1)));
+        emit updateLog(i18n("Solver timed out in %1s", QString::number(elapsedSeconds, 'f', 1)));
         m_Overlays[solverRow].m_Status = ImageOverlay::PLATE_SOLVE_FAILURE;
         statusItem->setCurrentIndex(static_cast<int>(m_Overlays[solverRow].m_Status));
     }
     else if (!success)
     {
-        updateStatusDisplay(i18n("Solver failed in %1s", QString::number(elapsedSeconds, 'f', 1)));
+        emit updateLog(i18n("Solver failed in %1s", QString::number(elapsedSeconds, 'f', 1)));
         m_Overlays[solverRow].m_Status = ImageOverlay::PLATE_SOLVE_FAILURE;
         statusItem->setCurrentIndex(static_cast<int>(m_Overlays[solverRow].m_Status));
     }
@@ -814,7 +815,7 @@ void ImageOverlayComponent::solverDone(bool timedOut, bool success, const FITSIm
                            QString::number(solution.dec, 'f', 2),
                            QString::number(solution.pixscale, 'f', 2),
                            QString::number(solution.orientation, 'f', 2));
-        updateStatusDisplay(msg);
+        emit updateLog(msg);
 
         // Store the new values in the table.
         auto overlay = m_Overlays[solverRow];
@@ -840,7 +841,7 @@ void ImageOverlayComponent::solverDone(bool timedOut, bool success, const FITSIm
         startSolving();
     else
     {
-        updateStatusDisplay(i18n("Done solving. %1 available.", numAvailable()));
+        emit updateLog(i18n("Done solving. %1 available.", numAvailable()));
         m_TableGroupBox->setTitle(i18n("Image Overlays.  %1 images, %2 available.", m_Overlays.size(), numAvailable()));
     }
 }
diff --git a/kstars/skycomponents/imageoverlaycomponent.h b/kstars/skycomponents/imageoverlaycomponent.h
index ea8a37b41..1277a2b8b 100644
--- a/kstars/skycomponents/imageoverlaycomponent.h
+++ b/kstars/skycomponents/imageoverlaycomponent.h
@@ -94,8 +94,12 @@ class ImageOverlayComponent : public QObject, public SkyComponent
         return m_Directory;
     };
 
+ signals:
+    void updateLog(const QString &message);
+
 private slots:
     void tryAgain();
+    void updateStatusDisplay(const QString &message);
 
 private:
     void loadFromUserDB();
@@ -104,7 +108,6 @@ private:
     void solverDone(bool timedOut, bool success, const FITSImage::Solution &solution, double elapsedSeconds);
     void initializeGui();
     int numAvailable();
-    void updateStatusDisplay(const QString &message);
     void cellChanged(int row, int col);
     void statusCellChanged(int row);
     void selectionChanged();


More information about the kde-doc-english mailing list