Load source images in the background with a progress window
Decoding a batch of photographs took seconds on the main thread, so the window froze with no sign of what was happening. loadImages now takes an optional LoadProgress (per-file callback plus a cancel flag) and hands files out from a shared cursor, so one large file cannot stall the queue behind it. The GUI decodes off the main thread and shows a progress window with the count, the current file and a Cancel button; it only appears if the batch is still running after 250 ms. Headless mode keeps a "reading n/total" line on stderr when it is attached to a terminal. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+28
-1
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <gtkmm.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -34,7 +35,12 @@ private:
|
||||
void onAddImages();
|
||||
void onImagesChosen(const Glib::RefPtr<Gio::AsyncResult>& result,
|
||||
const Glib::RefPtr<Gtk::FileDialog>& dialog);
|
||||
void addPaths(const std::vector<std::string>& paths);
|
||||
void addPaths(const std::vector<std::string>& paths); // decodes in the background
|
||||
void onLoadProgress(); // dispatcher: one file finished decoding
|
||||
void onLoadFinished(); // dispatcher: the batch is done or was cancelled
|
||||
void showLoadWindow();
|
||||
void closeLoadWindow();
|
||||
void cancelLoad();
|
||||
void appendSourceRow(const std::string& path);
|
||||
void removeSource(Gtk::ListBoxRow* row);
|
||||
|
||||
@@ -65,6 +71,22 @@ private:
|
||||
std::uint64_t seed_ = 0;
|
||||
bool suspendRender_ = true;
|
||||
|
||||
// Source loading. Decoding a batch of large photographs takes seconds, so
|
||||
// it runs off the main thread and reports into a small progress window.
|
||||
std::thread loader_;
|
||||
Glib::Dispatcher loadProgress_;
|
||||
Glib::Dispatcher loadFinished_;
|
||||
std::atomic<bool> loadCancel_{false};
|
||||
std::atomic<std::size_t> loadDone_{0};
|
||||
std::size_t loadTotal_ = 0;
|
||||
std::mutex loadMutex_;
|
||||
std::string loadCurrent_;
|
||||
std::vector<Image> loadedImages_;
|
||||
std::vector<LoadFailure> loadFailures_;
|
||||
std::vector<std::string> loadQueue_; // chosen while another batch was loading
|
||||
bool loading_ = false;
|
||||
sigc::connection loadWindowDelay_;
|
||||
|
||||
// Render job
|
||||
Glib::Dispatcher renderDone_;
|
||||
std::thread worker_;
|
||||
@@ -78,6 +100,11 @@ private:
|
||||
|
||||
// Widgets
|
||||
Gtk::Label banner_;
|
||||
Gtk::Button* addButton_ = nullptr;
|
||||
// Built fresh with the progress window, and null whenever it is closed.
|
||||
std::unique_ptr<Gtk::Window> loadWindow_;
|
||||
Gtk::ProgressBar* loadBar_ = nullptr;
|
||||
Gtk::Label* loadFileLabel_ = nullptr;
|
||||
Gtk::ListBox sourceList_;
|
||||
Gtk::SpinButton widthSpin_;
|
||||
Gtk::SpinButton heightSpin_;
|
||||
|
||||
Reference in New Issue
Block a user