Hi all.
I just made a few modifications to PAN for fun as I needed the ability to create NZB files from the GUI. Pan had already built that in, I just implemented some functions. I copied the nzb_to_xml function and let it skip the non-standard <path> xml tag.
I tested it on a few files and it worked flawlessly.

Enjoy!
imhotep
diff -rupNBbE -X ignore_patch pan2_orig//pan/gui/actions.cc 
pan2/pan/gui/actions.cc
--- pan2_orig//pan/gui/actions.cc       2011-05-03 11:50:53.084976986 +0200
+++ pan2/pan/gui/actions.cc     2011-05-03 07:33:19.309262717 +0200
@@ -106,6 +106,7 @@ namespace
   void do_unsubscribe_selected_groups  (GtkAction*) { 
pan_ui->do_unsubscribe_selected_groups(); }
   void do_save_articles                (GtkAction*) { 
pan_ui->do_save_articles(); }
   void do_save_articles_from_nzb       (GtkAction*) { 
pan_ui->do_save_articles_from_nzb(); }
+  void do_save_articles_to_nzb        (GtkAction*) { 
pan_ui->do_save_articles_to_nzb(); }
   void do_print                        (GtkAction*) { pan_ui->do_print(); }
   void do_import_tasks                 (GtkAction*) { 
pan_ui->do_import_tasks(); }
   void do_cancel_latest_task           (GtkAction*) { 
pan_ui->do_cancel_latest_task(); }
@@ -324,6 +325,11 @@ namespace
       N_("Save Articles from this NZB"),
       G_CALLBACK(do_save_articles_from_nzb) },
 
+    { "save-articles-to-nzb", GTK_STOCK_SAVE,
+      N_("_Save Articles to an NZB File..."), NULL,
+      N_("Save Articles to an NZB File"),
+      G_CALLBACK(do_save_articles_to_nzb) },
+
     { "print", GTK_STOCK_PRINT,
       NULL, "<control>P",
       NULL,
diff -rupNBbE -X ignore_patch pan2_orig//pan/gui/gui.cc pan2/pan/gui/gui.cc
--- pan2_orig//pan/gui/gui.cc   2011-05-03 11:50:53.088310527 +0200
+++ pan2/pan/gui/gui.cc 2011-05-03 13:14:45.890487705 +0200
@@ -21,6 +21,7 @@
 #include <map>
 #include <string>
 #include <sstream>
+#include <fstream>
 extern "C" {
   #include <sys/types.h> // for chmod
   #include <sys/stat.h> // for chmod
@@ -498,7 +499,7 @@ GUI :: disable_accelerators_when_focused
 
 namespace
 {
-  static std::string prev_path;
+  static std::string prev_path, prev_file;
 }
 
 std::string
@@ -528,6 +529,39 @@ GUI :: prompt_user_for_save_path (GtkWin
   return path;
 }
 
+std::string
+GUI :: prompt_user_for_filename (GtkWindow * parent, const Prefs& prefs)
+{
+       
+  if (prev_path.empty())
+    prev_path = prefs.get_string ("default-save-attachments-path", 
g_get_home_dir ());
+  if (!file :: file_exists (prev_path.c_str()))
+  prev_path = g_get_home_dir ();
+    prev_file = std::string(_("Untitled.nzb"));
+    
+  GtkWidget * w = gtk_file_chooser_dialog_new (_("Save NZB File as"),
+                                     parent,
+                                     GTK_FILE_CHOOSER_ACTION_SAVE,
+                                     GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                     GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+                                     NULL);
+       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());
+       gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (w), 
prev_file.c_str());
+       
+       std::string file;
+       const int response (gtk_dialog_run (GTK_DIALOG(w)));
+       if (response == GTK_RESPONSE_ACCEPT) {
+               char *tmp;
+               tmp = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (w));
+               file=tmp;
+               g_free (tmp);
+       }
+       gtk_widget_destroy (w);
+
+  return file;
+}
+
 void GUI :: do_save_articles ()
 {
   std::string path;
@@ -544,6 +578,34 @@ void GUI :: do_save_articles ()
   }
 }
 
+
+void GUI :: do_save_articles_to_nzb ()
+{
+
+  std::string path;
+  const std::vector<const Article*> articles 
(_header_pane->get_full_selection_v ());
+
+  std::vector<Article> copies;
+  copies.reserve (articles.size());
+  foreach_const (std::vector<const Article*>, articles, it)
+    copies.push_back (**it);
+
+  const std::string file (GUI :: prompt_user_for_filename (get_window(_root), 
_prefs));
+    if (!file.empty()) {
+      Queue::tasks_t tasks;
+      std::string emptystring;
+      foreach_const (std::vector<Article>, copies, it)
+        tasks.push_back (new TaskArticle (_data, _data, *it, _cache, _data, 0, 
TaskArticle::RAW,emptystring));
+    
+          // write them to a file
+          std::ofstream tmp(file.c_str());
+          if (tmp.good()) {
+            NZB :: nzb_to_xml_file (tmp, tasks); 
+            tmp.close();
+          }
+    }
+}
+
 namespace
 {
   struct SaveArticlesFromNZB: public Progress::Listener
diff -rupNBbE -X ignore_patch pan2_orig//pan/gui/gui.h pan2/pan/gui/gui.h
--- pan2_orig//pan/gui/gui.h    2011-05-03 11:50:53.088310527 +0200
+++ pan2/pan/gui/gui.h  2011-05-03 07:54:35.077667959 +0200
@@ -79,6 +79,7 @@ namespace pan
       virtual void do_prompt_for_charset ();
       virtual void do_save_articles ();
       virtual void do_save_articles_from_nzb ();
+      virtual void do_save_articles_to_nzb ();
       virtual void do_print ();
       virtual void do_quit ();
       virtual void do_import_tasks ();
@@ -159,7 +160,7 @@ namespace pan
 
     public:
       static std::string prompt_user_for_save_path (GtkWindow * parent, const 
Prefs& prefs);
-
+         static std::string prompt_user_for_filename  (GtkWindow * parent, 
const Prefs& prefs);
 
     private: // Queue::Listener
       friend class Queue;
diff -rupNBbE -X ignore_patch pan2_orig//pan/gui/header-pane.cc 
pan2/pan/gui/header-pane.cc
--- pan2_orig//pan/gui/header-pane.cc   2011-05-03 11:50:53.091644045 +0200
+++ pan2/pan/gui/header-pane.cc 2011-05-03 07:36:26.745133407 +0200
@@ -1564,6 +1564,7 @@ HeaderPane :: on_selection_changed_idle
     "download-selected-article",
     "save-articles",
     "save-articles-from-nzb",
+    "save-articles-to-nzb",
     "read-selected-article",
     "show-selected-article-info",
     "mark-article-read",
diff -rupNBbE -X ignore_patch pan2_orig//pan/gui/pan-ui.h pan2/pan/gui/pan-ui.h
--- pan2_orig//pan/gui/pan-ui.h 2011-05-03 11:50:53.091644045 +0200
+++ pan2/pan/gui/pan-ui.h       2011-05-03 07:33:31.993223734 +0200
@@ -33,6 +33,7 @@ namespace pan
     virtual void do_prompt_for_charset () = 0;
     virtual void do_save_articles () = 0;
     virtual void do_save_articles_from_nzb () = 0;
+    virtual void do_save_articles_to_nzb () = 0;
     virtual void do_print () = 0;
     virtual void do_import_tasks () = 0;
     virtual void do_cancel_latest_task () = 0;
diff -rupNBbE -X ignore_patch pan2_orig//pan/gui/pan.ui.h pan2/pan/gui/pan.ui.h
--- pan2_orig//pan/gui/pan.ui.h 2011-05-03 11:50:53.091644045 +0200
+++ pan2/pan/gui/pan.ui.h       2011-05-03 07:31:52.171614506 +0200
@@ -113,6 +113,7 @@ const char * fallback_ui_file =
 "      <menu action='article-actions-menu'>\n"
 "        <menuitem action='save-articles' />\n"
 "        <menuitem action='save-articles-from-nzb' />\n"
+"        <menuitem action='save-articles-to-nzb' />\n"
 "        <separator />\n"
 "        <menuitem action='read-selected-article' />\n"
 "        <menuitem action='download-selected-article' />\n"
@@ -174,6 +175,7 @@ const char * fallback_ui_file =
 "  <popup name='header-pane-popup'>\n"
 "    <menuitem action='save-articles' />\n"
 "    <menuitem action='save-articles-from-nzb' />\n"
+"    <menuitem action='save-articles-to-nzb' />\n"
 "    <separator />\n"
 "    <menuitem action='read-selected-article' />\n"
 "    <menuitem action='download-selected-article' />\n"
diff -rupNBbE -X ignore_patch pan2_orig//pan/tasks/nzb.cc pan2/pan/tasks/nzb.cc
--- pan2_orig//pan/tasks/nzb.cc 2011-05-03 11:50:53.101644447 +0200
+++ pan2/pan/tasks/nzb.cc       2011-05-03 13:15:58.293965902 +0200
@@ -215,6 +215,7 @@ namespace
   }
 }
 
+/* Saves all current tasks to tasks.nzb */
 std::ostream&
 NZB :: nzb_to_xml (std::ostream             & out,
                    const std::vector<Task*> & tasks)
@@ -252,6 +253,68 @@ NZB :: nzb_to_xml (std::ostream
 
     // what groups was this crossposted in?
     quarks_t groups;
+    foreach_const (Xref, a.xref, xit)
+      groups.insert (xit->group);
+    out << indent(depth++) << "<groups>\n";
+    foreach_const (quarks_t, groups, git)
+      out << indent(depth) << "<group>" << *git << "</group>\n";
+    out << indent(--depth) << "</groups>\n";
+
+    // now for the parts...
+    out << indent(depth++) << "<segments>\n";
+    for (Article::part_iterator it(a.pbegin()), end(a.pend()); it!=end; ++it)
+    {
+      std::string mid = it.mid ();
+
+      // remove the surrounding < > as per nzb spec
+      if (mid.size()>=2 && mid[0]=='<') {
+        mid.erase (0, 1);
+        mid.resize (mid.size()-1);
+      }
+
+      // serialize this part
+      out << indent(depth)
+          << "<segment" << " bytes=\"" << it.bytes() << '"'
+                        << " number=\"" << it.number() << '"'
+                        << ">";
+      escaped(out, mid);
+      out  << "</segment>\n";
+    }
+    out << indent(--depth) << "</segments>\n";
+    out << indent(--depth) << "</file>\n";
+  }
+
+  out << indent(--depth) << "</nzb>\n";
+  return out;
+}
+
+/* Saves selected files to a chosen XML file */
+std::ostream&
+NZB :: nzb_to_xml_file (std::ostream             & out,
+                   const std::vector<Task*> & tasks)
+{
+  int depth (0);
+
+  out << "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
+      << "<!DOCTYPE nzb PUBLIC \"-//newzBin//DTD NZB 1.0//EN\" 
\"http://www.newzbin.com/DTD/nzb/nzb-1.0.dtd\";>\n"
+      << indent(depth++)
+      << "<nzb xmlns=\"http://www.newzbin.com/DTD/2003/nzb\";>\n";
+
+  foreach_const (tasks_t, tasks, it)
+  {
+    TaskArticle * task (dynamic_cast<TaskArticle*>(*it));
+    if (!task) // not a download task...
+      continue;
+
+    const Article& a (task->get_article());
+    out << indent(depth++)
+        << "<file" << " poster=\"";
+    escaped (out, a.author.to_view());
+    out  << "\" date=\"" << a.time_posted << "\" subject=\"";
+    escaped (out, a.subject.to_view()) << "\">\n";
+
+    // what groups was this crossposted in?
+    quarks_t groups;
     foreach_const (Xref, a.xref, xit)
       groups.insert (xit->group);
     out << indent(depth++) << "<groups>\n";
diff -rupNBbE -X ignore_patch pan2_orig//pan/tasks/nzb.h pan2/pan/tasks/nzb.h
--- pan2_orig//pan/tasks/nzb.h  2011-05-03 11:50:53.101644447 +0200
+++ pan2/pan/tasks/nzb.h        2011-05-03 13:14:35.589992901 +0200
@@ -53,6 +54,11 @@ namespace pan
 
     static std::ostream&  nzb_to_xml (std::ostream             & out,
                                       const std::vector<Task*> & tasks);
+                                      
+    
+    static std::ostream&  nzb_to_xml_file (std::ostream             & out,
+                                      const std::vector<Task*> & tasks);
+
   };
 }
 
diff -rupNBbE -X ignore_patch pan2_orig//pan/tasks/queue.h 
pan2/pan/tasks/queue.h
--- pan2_orig//pan/tasks/queue.h        2011-05-03 11:50:53.101644447 +0200
+++ pan2/pan/tasks/queue.h      2011-05-03 12:12:36.671794343 +0200
@@ -25,8 +25,8 @@
 #include <vector>
 #include <pan/general/macros.h> // for UNUSED
 #include <pan/general/map-vector.h>
-#include <pan/general/quark.h>
 #include <pan/tasks/decoder.h>
+#include <pan/general/quark.h>
 #include <pan/tasks/nntp-pool.h>
 #include <pan/tasks/socket.h>
 #include <pan/tasks/adaptable-set.h>
_______________________________________________
Pan-users mailing list
Pan-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/pan-users

Reply via email to