[pan2: 158/268] [+] added ability to change download destination



commit 50a8fac0fdb60d5916ec02f38584cbc10881622f
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date:   Wed Sep 14 19:01:53 2011 +0200

    [+] added ability to change download destination

 pan.cbp                  |    1 +
 pan/gui/gui.cc           |    6 --
 pan/gui/gui.h            |    1 -
 pan/gui/post-ui.cc       |    5 +-
 pan/gui/post-ui.h        |    2 +-
 pan/gui/task-pane.cc     |  221 +++++++++++++++++++++++++++++++++++++++++++---
 pan/gui/task-pane.h      |   23 +++++
 pan/tasks/task-article.h |    3 +-
 8 files changed, 238 insertions(+), 24 deletions(-)
---
diff --git a/pan.cbp b/pan.cbp
index 60646f3..d9a0bbc 100644
--- a/pan.cbp
+++ b/pan.cbp
@@ -190,6 +190,7 @@
 		<Unit filename="pan/gui/tango-colors.h" />
 		<Unit filename="pan/gui/task-pane.cc" />
 		<Unit filename="pan/gui/task-pane.h" />
+		<Unit filename="pan/gui/taskpane.ui.h" />
 		<Unit filename="pan/gui/url.cc" />
 		<Unit filename="pan/gui/url.h" />
 		<Unit filename="pan/gui/wait.h" />
diff --git a/pan/gui/gui.cc b/pan/gui/gui.cc
index b44b18c..9e71753 100644
--- a/pan/gui/gui.cc
+++ b/pan/gui/gui.cc
@@ -212,7 +212,6 @@ GUI :: GUI (Data& data, Queue& queue, ArticleCache& cache, EncodeCache& encode_c
 
   _group_pane = new GroupPane (*this, data, _prefs);
   _header_pane = new HeaderPane (*this, data, _queue, _cache, _prefs, _group_prefs, *this);
-  _header_panes.push_back(_header_pane);
   _body_pane = new BodyPane (data, _cache, _prefs);
 
   std::string path = "/ui/main-window-toolbar";
@@ -1759,13 +1758,8 @@ void GUI :: do_read_selected_group ()
   const bool changed  (old_group != group);
   if (changed)
   {
-    HeaderPane * tmp = new HeaderPane (*this, _data, _queue, _cache, _prefs, _group_prefs, *this);
-
-//    g_object_ref (tmp->root());
-    _header_pane = tmp;
     _header_pane->set_group (group);
     _header_pane->set_focus ();
-    _header_panes.push_back(tmp);
   }
   watch_cursor_off ();
 
diff --git a/pan/gui/gui.h b/pan/gui/gui.h
index e3efe87..5c74462 100644
--- a/pan/gui/gui.h
+++ b/pan/gui/gui.h
@@ -203,7 +203,6 @@ namespace pan
       GtkWidget * _toolbar;
       GroupPane * _group_pane;
       HeaderPane * _header_pane;
-      std::vector<HeaderPane*> _header_panes;
       BodyPane * _body_pane;
       GtkUIManager * _ui_manager;
 
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index ed86f12..a601bbe 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -597,13 +597,10 @@ PostUI :: add_actions (GtkWidget * box)
   gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (gtk_action_group_get_action (_agroup, "wrap")),
                                 _prefs.get_flag ("compose-wrap-enabled", true));
 //  gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (gtk_action_group_get_action (_agroup, "inline-or-bulk")), false);
-  gtk_ui_manager_insert_action_group (_uim, _agroup, 0);
 
    //add popup actions
-  _pgroup = gtk_action_group_new ("fq");
-  gtk_action_group_set_translation_domain (_pgroup, NULL);
   gtk_action_group_add_actions (_agroup, filequeue_popup_entries, G_N_ELEMENTS(filequeue_popup_entries), this);
-  gtk_ui_manager_insert_action_group (_uim, _pgroup, 0);
+  gtk_ui_manager_insert_action_group (_uim, _agroup, 0);
 
 }
 
diff --git a/pan/gui/post-ui.h b/pan/gui/post-ui.h
index 887e9b7..4a77123 100644
--- a/pan/gui/post-ui.h
+++ b/pan/gui/post-ui.h
@@ -149,7 +149,7 @@ namespace pan
       std::string _charset;
       TextMassager _tm;
       GtkUIManager * _uim;
-      GtkActionGroup * _agroup, * _pgroup, * _epgroup;
+      GtkActionGroup * _agroup;
       std::string _current_signature;
       TaskPost * _post_task;
       typedef std::map<std::string, std::string> str2str_t;
diff --git a/pan/gui/task-pane.cc b/pan/gui/task-pane.cc
index d6a6224..cb49bb9 100644
--- a/pan/gui/task-pane.cc
+++ b/pan/gui/task-pane.cc
@@ -25,6 +25,7 @@ extern "C" {
 }
 #include <pan/general/e-util.h>
 #include <pan/general/debug.h>
+#include <pan/general/file-util.h>
 #include <pan/general/macros.h>
 #include <pan/general/utf8-utils.h>
 #include <pan/tasks/queue.h>
@@ -32,6 +33,7 @@ extern "C" {
 #include "pad.h"
 #include "render-bytes.h"
 #include "task-pane.h"
+#include "taskpane.ui.h"
 
 enum
 {
@@ -40,13 +42,10 @@ enum
   NUM_COLS
 };
 
-
 /**
 ***  Internal Utility
 **/
 
-typedef Queue::tasks_t tasks_t;
-
 void
 TaskPane :: get_selected_tasks_foreach (GtkTreeModel *model, GtkTreePath *, GtkTreeIter *iter, gpointer list_g)
 {
@@ -141,9 +140,8 @@ TaskPane:: on_tooltip_query(GtkWidget  *widget,
     const Article& a(tu->get_article());
     date = date_maker.get_date_string (tu->get_article().time_posted);
     g_snprintf(buffer,sizeof(buffer),
-               _("\
-\n<u>Upload</u>\n\n<i>Subject:</i> <b>\"%s\"</b>\n<i>From:</i> <b>%s</b>\n\
-<i>Groups:</i> <b>%s</b>\n<i>Sourcefile:</i> <b>%s</b>\n"),
+               _("\n<u>Upload</u>\n\n<i>Subject:</i> <b>\"%s\"</b>\n<i>From:</i> <b>%s</b>\n"
+                 "<i>Groups:</i> <b>%s</b>\n<i>Sourcefile:</i> <b>%s</b>\n"),
                a.subject.to_string().c_str(), escaped(a.author.to_string()).c_str(),
                tu->get_groups().c_str(), tu->get_filename().c_str());
   }
@@ -154,9 +152,8 @@ TaskPane:: on_tooltip_query(GtkWidget  *widget,
     const Article& a(ta->get_article());
     date = date_maker.get_date_string (ta->get_article().time_posted);
     g_snprintf(buffer,sizeof(buffer),
-               _("\
-\n<u>Download</u>\n\n<i>Subject:</i> <b>\"%s\"</b>\n<i>From:</i> <b>%s</b>\n<i>Date:</i> <b>%s</b>\n\
-<i>Groups:</i> <b>%s</b>\n<i>Save Path:</i> <b>%s</b>\n"),
+               _("\n<u>Download</u>\n\n<i>Subject:</i> <b>\"%s\"</b>\n<i>From:</i> <b>%s</b>\n<i>Date:</i> <b>%s</b>\n"
+                 "<i>Groups:</i> <b>%s</b>\n<i>Save Path:</i> <b>%s</b>\n"),
                a.subject.to_string().c_str(), escaped(a.author.to_string()).c_str(), date ? date : _("unknown"),
                ta->get_groups().c_str(), ta->get_save_path().to_string().c_str());
   }
@@ -173,6 +170,50 @@ TaskPane:: on_tooltip_query(GtkWidget  *widget,
   return true;
 }
 
+void
+TaskPane::  do_popup_menu (GtkWidget *treeview, GdkEventButton *event, gpointer userdata)
+{
+  TaskPane * self (static_cast<TaskPane*>(userdata));
+  GtkWidget * menu (gtk_ui_manager_get_widget (self->_uim, "/taskpane-popup"));
+  gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL,
+                  (event ? event->button : 0),
+                  (event ? event->time : 0));
+}
+
+gboolean
+TaskPane :: on_button_pressed (GtkWidget *treeview, GdkEventButton *event, gpointer userdata)
+{
+
+  if (event->type == GDK_BUTTON_PRESS )
+  {
+    GtkTreeSelection *selection;
+    selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
+
+    if ( event->button == 3)
+    {
+
+      if (gtk_tree_selection_count_selected_rows(selection)  <= 1)
+      {
+         GtkTreePath *path;
+         /* Get tree path for row that was clicked */
+         if (gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(treeview),
+                                           (gint) event->x,
+                                           (gint) event->y,
+                                           &path, NULL, NULL, NULL))
+         {
+           gtk_tree_selection_unselect_all(selection);
+           gtk_tree_selection_select_path(selection, path);
+           gtk_tree_path_free(path);
+         }
+      }
+      do_popup_menu(treeview, event, userdata);
+      return true;
+    }
+
+  }
+  return false;
+}
+
 void TaskPane :: online_toggled_cb (GtkToggleButton* b, Queue *queue)
 {
   queue->set_online (gtk_toggle_button_get_active (b));
@@ -206,6 +247,60 @@ void TaskPane :: restart_clicked_cb (GtkButton*, TaskPane* pane)
   pane->_queue.restart_tasks (pane->get_selected_tasks());
 }
 
+std::string
+TaskPane :: prompt_user_for_new_dest (GtkWindow * parent, const Quark& current_path)
+{
+  char buf[4096];
+  struct stat sb;
+  std::string path;
+
+  std::string prev_path(current_path.c_str());
+  if (!file :: file_exists (prev_path.c_str()))
+    prev_path = g_get_home_dir ();
+
+  GtkWidget * w = gtk_file_chooser_dialog_new (_("Choose new destination for selected Tasks"),
+                                                GTK_WINDOW(parent),
+                                                GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
+                                                GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                                GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+                                                NULL);
+  gtk_dialog_set_default_response (GTK_DIALOG(w), GTK_RESPONSE_ACCEPT);
+  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (w), TRUE);
+  gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (w), prev_path.c_str());
+
+  if (GTK_RESPONSE_ACCEPT == gtk_dialog_run(GTK_DIALOG(w)))
+  {
+    char * tmp = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (w));
+    path = tmp;
+    g_free (tmp);
+  } else
+    path.clear();
+
+  gtk_widget_destroy (w);
+  return path;
+}
+
+void
+TaskPane :: change_destination (const tasks_t& tasks)
+{
+
+  if (tasks.empty()) return;
+  TaskArticle * t (dynamic_cast<TaskArticle*>(tasks[0]));
+  std::string new_path(prompt_user_for_new_dest(GTK_WINDOW(_root),t->get_save_path()));
+  if (new_path.empty()) return; // user cancelled/aborted
+  foreach_const (tasks_t, tasks, it) {
+    TaskArticle * task (dynamic_cast<TaskArticle*>(*it));
+    if (task)
+      task->set_save_path(Quark(new_path));
+  }
+
+}
+
+void TaskPane :: change_dest_clicked_cb (GtkButton*, TaskPane* pane)
+{
+  pane->change_destination (pane->get_selected_tasks());
+}
+
 /**
 ***  Display
 **/
@@ -506,6 +601,102 @@ namespace
   }
 }
 
+namespace
+{
+
+  void do_move_up        (GtkAction*, gpointer p)  { static_cast<TaskPane*>(p)->up_clicked_cb(0, static_cast<TaskPane*>(p)); }
+  void do_move_down      (GtkAction*, gpointer p)  { static_cast<TaskPane*>(p)->down_clicked_cb(0, static_cast<TaskPane*>(p)); }
+  void do_move_top       (GtkAction*, gpointer p)  { static_cast<TaskPane*>(p)->top_clicked_cb(0, static_cast<TaskPane*>(p)); }
+  void do_move_bottom    (GtkAction*, gpointer p)  { static_cast<TaskPane*>(p)->bottom_clicked_cb(0, static_cast<TaskPane*>(p)); }
+  void do_stop           (GtkAction*, gpointer p)  { static_cast<TaskPane*>(p)->stop_clicked_cb(0, static_cast<TaskPane*>(p)); }
+  void do_delete         (GtkAction*, gpointer p)  { static_cast<TaskPane*>(p)->delete_clicked_cb(0, static_cast<TaskPane*>(p)); }
+  void do_restart        (GtkAction*, gpointer p)  { static_cast<TaskPane*>(p)->restart_clicked_cb(0, static_cast<TaskPane*>(p)); }
+  void do_change_dest    (GtkAction* a, gpointer p){ static_cast<TaskPane*>(p)->change_dest_clicked_cb(0, static_cast<TaskPane*>(p)); }
+
+  GtkActionEntry taskpane_popup_entries[] =
+  {
+
+    { "move-up", NULL,
+      N_("Move Up"), "",
+      N_("Move Up"),
+      G_CALLBACK(do_move_up) },
+
+    { "move-down", NULL,
+      N_("Move Down"), "",
+      N_("Move Down"),
+      G_CALLBACK(do_move_down) },
+
+    { "move-top", NULL,
+      N_("Move To Top"), "",
+      N_("Move To Top"),
+      G_CALLBACK(do_move_top) },
+
+    { "move-bottom", NULL,
+      N_("Move To Bottom"), "",
+      N_("Move To Bottom"),
+      G_CALLBACK(do_move_bottom) },
+
+    { "stop", NULL,
+      N_("Stop Task"), "",
+      N_("Stop Task"),
+      G_CALLBACK(do_stop) },
+
+    { "delete", NULL,
+      N_("Delete Task"), "",
+      N_("Delete Task"),
+      G_CALLBACK(do_delete) },
+
+    { "restart", NULL,
+      N_("Restart Task"), "",
+      N_("Restart Task"),
+      G_CALLBACK(do_restart) },
+
+    { "change-dest", NULL,
+      N_("Change Download Destination"), "",
+      N_("Change Download Destination"),
+      G_CALLBACK(do_change_dest) }
+  };
+
+}
+
+void
+TaskPane :: add_actions (GtkWidget * box)
+{
+  // action manager for popup
+  _uim = gtk_ui_manager_new ();
+  // read the file...
+  char * filename = g_build_filename (file::get_pan_home().c_str(), "taskpane.ui", NULL);
+  GError * err (0);
+  if (!gtk_ui_manager_add_ui_from_file (_uim, filename, &err)) {
+    g_clear_error (&err);
+    gtk_ui_manager_add_ui_from_string (_uim, fallback_taskpane_ui, -1, &err);
+  }
+  if (err) {
+    Log::add_err_va (_("Error reading file \"%s\": %s"), filename, err->message);
+    g_clear_error (&err);
+
+  }
+  g_free (filename);
+
+//  g_signal_connect (_uim, "add_widget", G_CALLBACK(add_widget), box);
+
+   //add popup actions
+  _pgroup = gtk_action_group_new ("taskpane");
+  gtk_action_group_set_translation_domain (_pgroup, NULL);
+  gtk_action_group_add_actions (_pgroup, taskpane_popup_entries, G_N_ELEMENTS(taskpane_popup_entries), this);
+  gtk_ui_manager_insert_action_group (_uim, _pgroup, 0);
+
+}
+
+namespace
+{
+  gboolean on_popup_menu (GtkWidget * treeview, gpointer userdata)
+  {
+    TaskPane::do_popup_menu (treeview, NULL, userdata);
+    return true;
+  }
+}
+
 TaskPane :: TaskPane (Queue& queue, Prefs& prefs): _queue(queue)
 {
   _root = gtk_window_new (GTK_WINDOW_TOPLEVEL);
@@ -544,7 +735,7 @@ TaskPane :: TaskPane (Queue& queue, Prefs& prefs): _queue(queue)
     gtk_box_pack_start (GTK_BOX(buttons), gtk_vseparator_new(), 0, 0, 0);
     w = add_button (buttons, GTK_STOCK_CLOSE, 0, 0);
     g_signal_connect_swapped (w, "clicked", G_CALLBACK(gtk_widget_destroy), _root);
-    pan_box_pack_start_defaults (GTK_BOX(buttons), gtk_event_box_new()); // eat h space
+    pan_box_pack_start_defaults (GTK_BOX(buttons), gtk_event_box_new()); // eat horizontal space
 
   gtk_box_pack_start (GTK_BOX(vbox), buttons, false, false, 0);
   gtk_box_pack_start (GTK_BOX(vbox), gtk_hseparator_new(), false, false, 0);
@@ -566,9 +757,17 @@ TaskPane :: TaskPane (Queue& queue, Prefs& prefs): _queue(queue)
   GtkTreeSelection * selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (_view));
   gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
 
+  // tooltips for articles
   gtk_widget_set_has_tooltip (_view, true);
   g_signal_connect(_view,"query-tooltip",G_CALLBACK(on_tooltip_query), this);
-//  gtk_widget_set_tooltip_window (_view, _tooltip_window);
+
+  // connect signals for popup menu
+  g_signal_connect (_view, "popup-menu", G_CALLBACK(on_popup_menu), this);
+  g_signal_connect (_view, "button-press-event", G_CALLBACK(on_button_pressed), this);
+
+  // actions
+  add_actions(_view);
+  gtk_window_add_accel_group (GTK_WINDOW(_root), gtk_ui_manager_get_accel_group (_uim));
 
   w = gtk_scrolled_window_new (NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(w), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
diff --git a/pan/gui/task-pane.h b/pan/gui/task-pane.h
index 3b4192f..caaaaec 100644
--- a/pan/gui/task-pane.h
+++ b/pan/gui/task-pane.h
@@ -26,6 +26,8 @@
 #include <pan/tasks/queue.h>
 #include "prefs.h"
 
+typedef Queue::tasks_t tasks_t;
+
 namespace pan
 {
   /**
@@ -69,6 +71,10 @@ namespace pan
       gulong _online_toggle_handler;
       guint _update_timeout_tag;
       bool _dampen_move_feedback_loop;
+      GtkUIManager * _uim;
+      GtkActionGroup * _pgroup;
+    private:
+      std::string prompt_user_for_new_dest (GtkWindow * parent, const Quark& current_path);
 
     private:
       void update_status (const Queue::task_states_t&);
@@ -76,12 +82,18 @@ namespace pan
       static gboolean periodic_refresh (gpointer);
       static void root_destroyed_cb (GtkWidget, gpointer);
 
+    public:
+      static void do_popup_menu (GtkWidget*, GdkEventButton *event, gpointer pane_g);
+      static gboolean on_button_pressed (GtkWidget * treeview, GdkEventButton *event, gpointer userdata);
+      void add_actions (GtkWidget * box);
+      void change_destination (const tasks_t& tasks);
 
     private:
       typedef std::vector<Task*> task_list;
       task_list get_selected_tasks () const;
       static void get_selected_tasks_foreach (GtkTreeModel*, GtkTreePath*, GtkTreeIter*, gpointer);
       static void online_toggled_cb  (GtkToggleButton*, Queue*);
+    public:   /// FIXME, privatize this again...
       static void up_clicked_cb      (GtkButton*, TaskPane*);
       static void down_clicked_cb    (GtkButton*, TaskPane*);
       static void top_clicked_cb     (GtkButton*, TaskPane*);
@@ -89,6 +101,17 @@ namespace pan
       static void stop_clicked_cb    (GtkButton*, TaskPane*);
       static void delete_clicked_cb  (GtkButton*, TaskPane*);
       static void restart_clicked_cb (GtkButton*, TaskPane*);
+      static void change_dest_clicked_cb (GtkButton*, TaskPane*);
+
+    private:
+//      static void do_move_up     (GtkAction*, gpointer p);
+//      static void do_move_down   (GtkAction*, gpointer p);
+//      static void do_move_top    (GtkAction*, gpointer p);
+//      static void do_move_bottom (GtkAction*, gpointer p);
+//      static void do_stop        (GtkAction*, gpointer p);
+//      static void do_delete      (GtkAction*, gpointer p);
+//      static void do_restart     (GtkAction*, gpointer p);
+//      static void do_change_dest (GtkAction*, gpointer p);
   };
 }
 
diff --git a/pan/tasks/task-article.h b/pan/tasks/task-article.h
index 64cefa1..778b614 100644
--- a/pan/tasks/task-article.h
+++ b/pan/tasks/task-article.h
@@ -61,6 +61,7 @@ namespace pan
       virtual ~TaskArticle ();
       time_t get_time_posted () const { return _time_posted; }
       const Quark& get_save_path () const { return _save_path; }
+      void  set_save_path (const Quark& q) { _save_path = q;}
       const Article& get_article () const { return _article; }
       const std::string& get_groups () const { return _groups; }
 
@@ -87,7 +88,7 @@ namespace pan
       void on_worker_done (bool cancelled);
 
     protected:
-      const Quark _save_path;
+      Quark _save_path;
       const ServerRank& _server_rank;
       ArticleCache& _cache;
       ArticleRead& _read;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]