|
@@ -199,14 +199,21 @@ public:
|
|
|
m_MenuItemSelectNone.signal_activate().connect([this](){ on_selection_change(false); });
|
|
m_MenuItemSelectNone.signal_activate().connect([this](){ on_selection_change(false); });
|
|
|
m_MenuPopup.append(m_MenuItemSelectNone);
|
|
m_MenuPopup.append(m_MenuItemSelectNone);
|
|
|
|
|
|
|
|
|
|
+ m_MenuPopup.append(m_MenuSeparator);
|
|
|
|
|
+
|
|
|
|
|
+ m_MenuItemDelete.set_label("Delete Selected Pictures");
|
|
|
|
|
+ auto delete_img = Gtk::manage(new Gtk::Image());
|
|
|
|
|
+ delete_img->set_from_icon_name("user-trash", Gtk::ICON_SIZE_MENU);
|
|
|
|
|
+ m_MenuItemDelete.set_image(*delete_img);
|
|
|
|
|
+ m_MenuItemDelete.set_always_show_image(true);
|
|
|
|
|
+ m_MenuItemDelete.signal_activate().connect(sigc::mem_fun(*this, &RenamerWindow::on_delete_selected));
|
|
|
|
|
+ m_MenuPopup.append(m_MenuItemDelete);
|
|
|
|
|
+
|
|
|
m_MenuPopup.show_all();
|
|
m_MenuPopup.show_all();
|
|
|
- // FIX 1: Attach menu to widget (required in some GTK versions/contexts)
|
|
|
|
|
m_MenuPopup.attach_to_widget(m_IconView);
|
|
m_MenuPopup.attach_to_widget(m_IconView);
|
|
|
|
|
|
|
|
- // FIX 2: Explicitly enable button press events for SELECTION_NONE mode
|
|
|
|
|
m_IconView.add_events(Gdk::BUTTON_PRESS_MASK);
|
|
m_IconView.add_events(Gdk::BUTTON_PRESS_MASK);
|
|
|
m_IconView.signal_button_press_event().connect(sigc::mem_fun(*this, &RenamerWindow::on_iconview_button_press), false);
|
|
m_IconView.signal_button_press_event().connect(sigc::mem_fun(*this, &RenamerWindow::on_iconview_button_press), false);
|
|
|
- // ----------------------------------------
|
|
|
|
|
|
|
|
|
|
m_ScrolledWindow.add(m_IconView);
|
|
m_ScrolledWindow.add(m_IconView);
|
|
|
m_VBox.pack_start(m_ProgressBar, Gtk::PACK_SHRINK);
|
|
m_VBox.pack_start(m_ProgressBar, Gtk::PACK_SHRINK);
|
|
@@ -243,7 +250,8 @@ protected:
|
|
|
Gtk::Menu m_MenuPopup;
|
|
Gtk::Menu m_MenuPopup;
|
|
|
Gtk::MenuItem m_MenuItemSelectAll;
|
|
Gtk::MenuItem m_MenuItemSelectAll;
|
|
|
Gtk::MenuItem m_MenuItemSelectNone;
|
|
Gtk::MenuItem m_MenuItemSelectNone;
|
|
|
- // --------------------
|
|
|
|
|
|
|
+ Gtk::SeparatorMenuItem m_MenuSeparator;
|
|
|
|
|
+ Gtk::ImageMenuItem m_MenuItemDelete;
|
|
|
|
|
|
|
|
struct ModelColumns : public Gtk::TreeModel::ColumnRecord {
|
|
struct ModelColumns : public Gtk::TreeModel::ColumnRecord {
|
|
|
ModelColumns() { add(m_col_path); add(m_col_filename); add(m_col_pixbuf); add(m_col_checked); add(m_col_markup); add(m_col_time); add(m_col_info_str); }
|
|
ModelColumns() { add(m_col_path); add(m_col_filename); add(m_col_pixbuf); add(m_col_checked); add(m_col_markup); add(m_col_time); add(m_col_info_str); }
|
|
@@ -281,7 +289,6 @@ protected:
|
|
|
if(it) { (*it)[m_Columns.m_col_checked] = !(*it)[m_Columns.m_col_checked]; update_preview(); }
|
|
if(it) { (*it)[m_Columns.m_col_checked] = !(*it)[m_Columns.m_col_checked]; update_preview(); }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // --- Selection Helper ---
|
|
|
|
|
void on_selection_change(bool select_all) {
|
|
void on_selection_change(bool select_all) {
|
|
|
if (!m_RefListStore) return;
|
|
if (!m_RefListStore) return;
|
|
|
for (auto row : m_RefListStore->children()) {
|
|
for (auto row : m_RefListStore->children()) {
|
|
@@ -290,15 +297,33 @@ protected:
|
|
|
update_preview();
|
|
update_preview();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // --- Mouse Button Handler ---
|
|
|
|
|
bool on_iconview_button_press(GdkEventButton* event) {
|
|
bool on_iconview_button_press(GdkEventButton* event) {
|
|
|
- if (event->type == GDK_BUTTON_PRESS && event->button == 3) { // Right Click
|
|
|
|
|
|
|
+ if (event->type == GDK_BUTTON_PRESS && event->button == 3) {
|
|
|
m_MenuPopup.popup(event->button, event->time);
|
|
m_MenuPopup.popup(event->button, event->time);
|
|
|
- return true; // We handled it
|
|
|
|
|
|
|
+ return true;
|
|
|
}
|
|
}
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
- // ----------------------------
|
|
|
|
|
|
|
+
|
|
|
|
|
+ void on_delete_selected() {
|
|
|
|
|
+ int count = 0;
|
|
|
|
|
+ for (auto row : m_RefListStore->children()) if (row[m_Columns.m_col_checked]) count++;
|
|
|
|
|
+ if (count == 0) return;
|
|
|
|
|
+
|
|
|
|
|
+ Gtk::MessageDialog dialog(*this, "Confirm Deletion", false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO);
|
|
|
|
|
+ dialog.set_secondary_text("Are you sure you want to permanently delete " + std::to_string(count) + " selected pictures?");
|
|
|
|
|
+ if (dialog.run() != Gtk::RESPONSE_YES) return;
|
|
|
|
|
+
|
|
|
|
|
+ for (auto it = m_RefListStore->children().begin(); it != m_RefListStore->children().end(); ) {
|
|
|
|
|
+ if ((*it)[m_Columns.m_col_checked]) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ fs::remove((std::string)(*it)[m_Columns.m_col_path]);
|
|
|
|
|
+ it = m_RefListStore->erase(it);
|
|
|
|
|
+ } catch (...) { ++it; }
|
|
|
|
|
+ } else ++it;
|
|
|
|
|
+ }
|
|
|
|
|
+ update_preview();
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
void on_stop_reload_clicked() {
|
|
void on_stop_reload_clicked() {
|
|
|
if (m_is_loading) m_stop_flag = true;
|
|
if (m_is_loading) m_stop_flag = true;
|
|
@@ -315,8 +340,6 @@ protected:
|
|
|
int count = 0;
|
|
int count = 0;
|
|
|
for (auto row : m_RefListStore->children()) {
|
|
for (auto row : m_RefListStore->children()) {
|
|
|
std::string original = row[m_Columns.m_col_filename], meta = row[m_Columns.m_col_info_str], new_name = original;
|
|
std::string original = row[m_Columns.m_col_filename], meta = row[m_Columns.m_col_info_str], new_name = original;
|
|
|
-
|
|
|
|
|
- // Only modify name if checked
|
|
|
|
|
if (row[m_Columns.m_col_checked]) {
|
|
if (row[m_Columns.m_col_checked]) {
|
|
|
if (mode == 0 && !pattern.empty()) {
|
|
if (mode == 0 && !pattern.empty()) {
|
|
|
std::string num = std::to_string(start_num + count);
|
|
std::string num = std::to_string(start_num + count);
|
|
@@ -331,7 +354,6 @@ protected:
|
|
|
if (pos != std::string::npos) { new_name = original; new_name.replace(pos, m_EntryFind.get_text().length(), m_EntryReplace.get_text()); }
|
|
if (pos != std::string::npos) { new_name = original; new_name.replace(pos, m_EntryFind.get_text().length(), m_EntryReplace.get_text()); }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
std::stringstream mu; mu << "<span font='9'>";
|
|
std::stringstream mu; mu << "<span font='9'>";
|
|
|
if (new_name != original) mu << "<span size='small' alpha='60%'>" << Glib::Markup::escape_text(original) << "</span>\n<span foreground='#3584e4' weight='bold'>" << Glib::Markup::escape_text(new_name) << "</span>";
|
|
if (new_name != original) mu << "<span size='small' alpha='60%'>" << Glib::Markup::escape_text(original) << "</span>\n<span foreground='#3584e4' weight='bold'>" << Glib::Markup::escape_text(new_name) << "</span>";
|
|
|
else mu << "<span weight='bold'>" << Glib::Markup::escape_text(original) << "</span>";
|
|
else mu << "<span weight='bold'>" << Glib::Markup::escape_text(original) << "</span>";
|
|
@@ -347,11 +369,8 @@ protected:
|
|
|
size_t hpos = pat.find('#');
|
|
size_t hpos = pat.find('#');
|
|
|
int pad = (hpos != std::string::npos && mode == 0) ? (pat.find_last_of('#') - hpos + 1) : 0;
|
|
int pad = (hpos != std::string::npos && mode == 0) ? (pat.find_last_of('#') - hpos + 1) : 0;
|
|
|
int count = 0;
|
|
int count = 0;
|
|
|
-
|
|
|
|
|
for (auto row : m_RefListStore->children()) {
|
|
for (auto row : m_RefListStore->children()) {
|
|
|
- // Strict check for unchecked items
|
|
|
|
|
if (!row[m_Columns.m_col_checked]) continue;
|
|
if (!row[m_Columns.m_col_checked]) continue;
|
|
|
-
|
|
|
|
|
std::string orig = row[m_Columns.m_col_filename], next = orig;
|
|
std::string orig = row[m_Columns.m_col_filename], next = orig;
|
|
|
if (mode == 0) {
|
|
if (mode == 0) {
|
|
|
std::string num = std::to_string(start + count);
|
|
std::string num = std::to_string(start + count);
|
|
@@ -518,7 +537,6 @@ protected:
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int main(int argc, char *argv[]) {
|
|
|
- Glib::thread_init();
|
|
|
|
|
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.renamer_v03_1");
|
|
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.renamer_v03_1");
|
|
|
RenamerWindow window;
|
|
RenamerWindow window;
|
|
|
return app->run(window);
|
|
return app->run(window);
|