11 const Glib::ustring& v_size,
12 const Glib::ustring& v_type,
13 const Glib::ustring& v_source,
14 const Glib::ustring& v_detail,
15 const Glib::ustring& v_confidence) {
16 auto row = Glib::make_refptr_for_instance<ResultRow>(
new ResultRow());
17 row->offset = v_offset;
20 row->source = v_source;
21 row->detail = v_detail;
22 row->confidence = v_confidence;
27 : Glib::ObjectBase(
"ResultRow"),
28 offset(*this,
"offset",
""),
29 size(*this,
"size",
""),
30 type(*this,
"type",
""),
31 source(*this,
"source",
""),
32 detail(*this,
"detail",
""),
41 set_title(
tr(
"BastionGuard Recovery Data"));
42 set_default_size(1280, 760);
45 root_.set_margin_top(12);
46 root_.set_margin_bottom(12);
47 root_.set_margin_start(12);
48 root_.set_margin_end(12);
65 store_ = Gio::ListStore<ResultRow>::create();
71 results_scroller_.set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
103 auto factory = Gtk::SignalListItemFactory::create();
105 factory->signal_setup().connect([](
const Glib::RefPtr<Gtk::ListItem>& item) {
106 auto* label = Gtk::make_managed<Gtk::Label>();
107 label->set_xalign(0.0f);
108 label->set_selectable(
true);
109 label->set_wrap(
true);
110 item->set_child(*label);
113 factory->signal_bind().connect([property_name](
const Glib::RefPtr<Gtk::ListItem>& item) {
114 auto base = item->get_item();
115 auto row = std::dynamic_pointer_cast<ResultRow>(base);
116 auto* label =
dynamic_cast<Gtk::Label*
>(item->get_child());
118 if (!row || !label) {
124 if (std::strcmp(property_name,
"offset") == 0) {
125 text = row->offset.get_value();
126 }
else if (std::strcmp(property_name,
"size") == 0) {
127 text = row->size.get_value();
128 }
else if (std::strcmp(property_name,
"type") == 0) {
129 text = row->type.get_value();
130 }
else if (std::strcmp(property_name,
"source") == 0) {
131 text = row->source.get_value();
132 }
else if (std::strcmp(property_name,
"detail") == 0) {
133 text = row->detail.get_value();
134 }
else if (std::strcmp(property_name,
"confidence") == 0) {
135 text = row->confidence.get_value();
138 label->set_text(text);
141 auto column = Gtk::ColumnViewColumn::create(title, factory);
142 column->set_resizable(
true);
163 status_.set_text(
tr(
"File ready for scan"));
165 }
catch (
const Glib::Error& ex) {
166 append_log(
trs(
"File selection cancelled or failed:") +
" " + ex.what());
174 status_.set_text(
tr(
"Select a file first"));
182 while (
store_->get_n_items() > 0) {
188 status_.set_text(
tr(
"Scanning in progress..."));
195 Glib::signal_idle().connect_once([
this, report]() {
204 for (
const auto& line : report.
logs) {
208 for (
const auto& r : report.
results) {
209 std::ostringstream conf;
210 conf << std::fixed << std::setprecision(2) << (r.confidence * 100.0) <<
"%";
250 const std::string path = file->get_path();
253 if (path.size() >= 5 && path.substr(path.size() - 5) ==
".json") {
264 status_.set_text(
tr(
"Report save failed"));
266 }
catch (
const Glib::Error& ex) {
267 append_log(
trs(
"Report save cancelled or failed:") +
" " + ex.what());
278 const char* units[] = {
"B",
"KiB",
"MiB",
"GiB",
"TiB"};
279 double value =
static_cast<double>(bytes);
281 while (value >= 1024.0 && idx < 4) {
285 std::ostringstream oss;
286 oss << std::fixed << std::setprecision(2) << value <<
' ' << units[idx];
291 std::ostringstream oss;
292 oss << bytes <<
" (0x" << std::hex << std::uppercase << bytes <<
')';
314 append_log(
trs(
"Internal error: output dialog unavailable."));
324 status_.set_text(
tr(
"Recovery in progress..."));
331 Glib::signal_idle().connect_once([
this, rr]() {
335 }
catch (
const Glib::Error& ex) {
336 append_log(
trs(
"Destination selection cancelled or failed:") + std::string(
" ") + ex.what());
342 for (
const auto& line : result.
logs) {
348 status_.set_text(
tr(
"Recovery completed"));
Gtk::ColumnView column_view_
void on_recovery_completed(const RecoveryResult &result)
Glib::RefPtr< Gtk::FileDialog > file_dialog_
void on_output_folder_chosen(const Glib::RefPtr< Gio::AsyncResult > &result)
RecoveryWorker recovery_worker_
static std::string human_offset(uint64_t bytes)
void on_report_file_chosen(const Glib::RefPtr< Gio::AsyncResult > &result)
void on_save_report_clicked()
void on_file_chosen(const Glib::RefPtr< Gio::AsyncResult > &result)
void on_choose_output_folder()
void append_log(const std::string &line)
Gtk::Button btn_save_report_
Glib::RefPtr< Gtk::TextBuffer > log_buffer_
std::string selected_path_
Gtk::ScrolledWindow results_scroller_
static std::string human_size(uint64_t bytes)
Glib::RefPtr< Gtk::FileDialog > save_dialog_
Glib::RefPtr< Gtk::SingleSelection > selection_model_
void on_scan_completed(const ScanReport &report)
void add_text_column(const Glib::ustring &title, const char *property_name)
Glib::RefPtr< Gtk::FileDialog > output_dialog_
Glib::RefPtr< Gio::ListStore< ResultRow > > store_
Gtk::ScrolledWindow logs_scroller_
void start(const ScanReport &report, const std::string &output_dir, const std::vector< size_t > &selected_result_indices, CompletionCallback cb)
static bool save_json(const ScanReport &report, const std::string &path, std::string &error_out)
static bool save_text(const ScanReport &report, const std::string &path, std::string &error_out)
static Glib::RefPtr< ResultRow > create(const Glib::ustring &offset, const Glib::ustring &size, const Glib::ustring &type, const Glib::ustring &source, const Glib::ustring &detail, const Glib::ustring &confidence)
Glib::Property< Glib::ustring > offset
Glib::Property< Glib::ustring > confidence
Glib::Property< Glib::ustring > type
Glib::Property< Glib::ustring > source
Glib::Property< Glib::ustring > size
Glib::Property< Glib::ustring > detail
void start(const std::string &path, CompletionCallback cb, ProgressCallback progress_cb={})
const char * tr(const char *msgid)
std::string trs(const char *msgid)
std::vector< std::string > logs
std::vector< std::string > exported_images
std::vector< std::string > recovered_files
std::vector< ScanResult > results
std::vector< std::string > logs