[pan2: 41/268] playing with gtk notebook and stuff... * file upload queue now with TaskUpload* * perhaps this could
- From: Heinrich MÃller <henmull src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pan2: 41/268] playing with gtk notebook and stuff... * file upload queue now with TaskUpload* * perhaps this could
- Date: Mon, 2 Jan 2012 15:41:27 +0000 (UTC)
commit b066f150fb84a168354b63b0c7cfe1248f404521
Author: Heinrich MÃller <sphemuel stud informatik uni-erlangen de>
Date: Sun May 29 14:09:51 2011 +0200
playing with gtk notebook and stuff...
* file upload queue now with TaskUpload*
* perhaps this could be improved with different STL containers...
* upload works flawlessly
pan/data/Makefile.am | 6 +-
pan/data/file-queue.cc | 118 ---------
pan/data/file-queue.h | 93 -------
pan/gui/group-pane.cc | 2 +-
pan/gui/gui.h | 1 -
pan/gui/pan.cc | 9 +-
pan/gui/post-ui.cc | 491 +++++++++++++++++++++++--------------
pan/gui/post-ui.h | 32 ++-
pan/tasks/encoder.cc | 39 ++--
pan/tasks/encoder.h | 9 +-
pan/tasks/nzb.cc | 187 +++++++++++----
pan/tasks/nzb.h | 6 +-
pan/tasks/queue.cc | 3 +
pan/tasks/task-upload.cc | 107 +++++---
pan/tasks/task-upload.h | 53 +++--
pan/usenet-utils/message-check.cc | 26 ++-
pan/usenet-utils/message-check.h | 3 +-
17 files changed, 625 insertions(+), 560 deletions(-)
---
diff --git a/pan/data/Makefile.am b/pan/data/Makefile.am
index e899618..7c0f654 100644
--- a/pan/data/Makefile.am
+++ b/pan/data/Makefile.am
@@ -9,8 +9,7 @@ libdata_a_SOURCES = \
article-cache.cc \
data.cc \
parts.cc \
- xref.cc \
- file-queue.cc
+ xref.cc
noinst_HEADERS = \
article.h \
@@ -19,8 +18,7 @@ noinst_HEADERS = \
defgroup.h \
parts.h \
server-info.h \
- xref.h \
- file-queue.h
+ xref.h
noinst_PROGRAMS = \
article-test \
diff --git a/pan/gui/group-pane.cc b/pan/gui/group-pane.cc
index a7e55e2..fe51921 100644
--- a/pan/gui/group-pane.cc
+++ b/pan/gui/group-pane.cc
@@ -148,7 +148,7 @@ void
GroupPane :: do_popup_menu (GtkWidget*, GdkEventButton *event, gpointer pane_g)
{
GroupPane * self (static_cast<GroupPane*>(pane_g));
- GtkWidget * menu (self->_action_manager.get_action_widget ("/filequeue-popup"));
+ GtkWidget * menu (self->_action_manager.get_action_widget ("/group-pane-popup"));
gtk_menu_popup (GTK_MENU(menu), NULL, NULL, NULL, NULL,
(event ? event->button : 0),
(event ? event->time : 0));
diff --git a/pan/gui/gui.h b/pan/gui/gui.h
index 64eb6e9..4706ed3 100644
--- a/pan/gui/gui.h
+++ b/pan/gui/gui.h
@@ -22,7 +22,6 @@
#include <pan/general/log.h>
#include <pan/general/progress.h>
#include <pan/data/article-cache.h>
-#include <pan/data/file-queue.h>
#include <pan/tasks/queue.h>
#include <pan/gui/group-pane.h>
#include <pan/gui/action-manager.h>
diff --git a/pan/gui/pan.cc b/pan/gui/pan.cc
index 5268ef7..4c31ff8 100644
--- a/pan/gui/pan.cc
+++ b/pan/gui/pan.cc
@@ -36,6 +36,7 @@ extern "C" {
#include <pan/tasks/socket-impl-gio.h>
#include <pan/tasks/task-groups.h>
#include <pan/tasks/task-xover.h>
+#include <pan/tasks/task-xzver-test.h>
#include <pan/tasks/nzb.h>
#include <pan/data-impl/data-impl.h>
#include <pan/icons/pan-pixbufs.h>
@@ -113,8 +114,10 @@ namespace
DataAndQueue * foo (static_cast<DataAndQueue*>(user_data));
const quarks_t new_servers (foo->data->get_servers());
foreach_const (quarks_t, new_servers, it)
- if (foo->data->get_server_limits(*it))
+ if (foo->data->get_server_limits(*it)) {
+ foo->queue->add_task (new TaskXZVerTest(*foo->data, *it));
foo->queue->add_task (new TaskGroups (*foo->data, *it));
+ }
g_free (foo);
}
@@ -175,7 +178,7 @@ namespace
~PanKiller() { q.remove_listener(this); }
/** Method from Queue::Listener interface: quits program on zero sized Q*/
- void on_queue_size_changed (Queue&, int active, int total)
+ void on_queue_size_changed (Queue&, int active, int total)
{ if (!active && !total) mainloop_quit(); }
// all below methods from Queue::Listener interface are noops
@@ -278,7 +281,7 @@ main (int argc, char *argv[])
nzb = true;
else if (!strcmp (tok, "--version"))
{ std::cerr << "Pan " << VERSION << '\n'; return 0; }
- else if (!strcmp (tok, "-o") && i<argc-1)
+ else if (!strcmp (tok, "-o") && i<argc-1)
nzb_output_path = argv[++i];
else if (!memcmp (tok, "--output=", 9))
nzb_output_path = tok+9;
diff --git a/pan/gui/post-ui.cc b/pan/gui/post-ui.cc
index d778284..4a9300c 100644
--- a/pan/gui/post-ui.cc
+++ b/pan/gui/post-ui.cc
@@ -221,7 +221,7 @@ namespace
{ "add-files", GTK_STOCK_OPEN, N_("Add _Files to Queue"), "<control>O", N_("Add Files to Queue"), G_CALLBACK(do_add_files) },
};
- void do_remove_files (GtkAction*, gpointer p) { static_cast<PostUI*>(p)->remove_files(); }
+ void do_remove_files (GtkAction*, gpointer p) {static_cast<PostUI*>(p)->remove_files(); }
void do_clear_list (GtkAction*, gpointer p) { static_cast<PostUI*>(p)->clear_list(); }
void do_select_parts (GtkAction*, gpointer p) { static_cast<PostUI*>(p)->select_parts(); }
void do_move_up (GtkAction*, gpointer p) { static_cast<PostUI*>(p)->move_up(); }
@@ -433,6 +433,12 @@ namespace
static_cast<PostUI*>(user_data)->close_window ();
return true; // don't invoke the default handler that destroys the widget
}
+
+ gboolean delete_parts_cb (GtkWidget* w, GdkEvent*, gpointer user_data)
+ {
+ return false;
+ }
+
}
void
@@ -478,7 +484,7 @@ PostUI :: check_message (const Quark& server, GMimeMessage * msg)
quarks_t groups_this_server_has;
_gs.server_get_groups (server, groups_this_server_has);
- MessageCheck :: message_check (msg, _hidden_headers["X-Draft-Attribution"], groups_this_server_has, errors, goodness);
+ MessageCheck :: message_check (msg, _hidden_headers["X-Draft-Attribution"], groups_this_server_has, errors, goodness, !_file_queue_empty);
if (goodness.is_ok())
return true;
@@ -580,7 +586,7 @@ PostUI :: add_files ()
{
if (!check_charset())
return;
- prompt_user_for_queueable_files (_file_queue, GTK_WINDOW (gtk_widget_get_toplevel(_root)), _prefs);
+ prompt_user_for_queueable_files (_file_queue_tasks, GTK_WINDOW (gtk_widget_get_toplevel(_root)), _prefs);
}
void
@@ -593,17 +599,6 @@ PostUI :: send_now ()
g_object_unref (G_OBJECT(message));
}
-//void
-//PostUI :: send_binfiles_now()
-//{
-// if (!check_charset())
-// return;
-// GMimeMessage * message (new_message_from_ui (POSTING));
-//
-// //change headers according to
-// g_object_unref (G_OBJECT(message));
-//}
-
void
PostUI :: done_sending_message (GMimeMessage * message, bool ok)
{
@@ -808,23 +803,12 @@ PostUI :: maybe_post_message (GMimeMessage * message)
_post_task = new TaskPost (server, message);
_post_task->add_listener (this);
_queue.add_task (_post_task, Queue::TOP);
- }
- else
- {
- FileQueue::articles_it it = _file_queue.begin();
- GMimeMessage* msg = new_message_from_ui(POSTING);
- std::string groups = std::string(g_mime_object_get_header ((GMimeObject*)msg, "Newsgroups"));
- std::string subject= std::string(g_mime_object_get_header ((GMimeObject*)msg, "Subject"));
- std::string author;
- profile.get_from_header (author);
-
- for (; it != _file_queue.end(); ++it) {
- _queue.add_task (new TaskUpload (*it,profile.posting_server,groups,subject,author), Queue::BOTTOM);
- }
- close_window(true); // dont wait for the upload queue
+ } else {
+ foreach_const (tasks_set, _file_queue_tasks, it)
+ _queue.add_task (*it, Queue::BOTTOM);
+ close_window(true); // dont wait for the upload queue
}
-
/**
*** Maybe remember the charsets
**/
@@ -1039,7 +1023,6 @@ PostUI :: open_draft ()
g_object_unref (G_OBJECT(parser));
g_object_unref (G_OBJECT(stream));
}
-
}
gtk_widget_destroy (d);
}
@@ -1913,7 +1896,6 @@ PostUI :: create_main_tab ()
// Newsgroup
++row;
- std::cerr<<" create main tab\n";
g_snprintf (buf, sizeof(buf), "<b>%s:</b>", _("_Newsgroups"));
l = gtk_label_new_with_mnemonic (buf);
gtk_label_set_use_markup (GTK_LABEL(l), true);
@@ -1963,6 +1945,199 @@ namespace
}
}
+namespace
+{
+ GtkWidget * add_button (GtkWidget * box,
+ const gchar * stock_id,
+ GCallback callback,
+ gpointer user_data)
+ {
+ GtkWidget * w = gtk_button_new_from_stock (stock_id);
+ gtk_button_set_relief (GTK_BUTTON(w), GTK_RELIEF_NONE);
+ if (callback)
+ g_signal_connect (w, "clicked", callback, user_data);
+ gtk_box_pack_start (GTK_BOX(box), w, false, false, 0);
+ return w;
+ }
+
+ void
+ render_filename (GtkTreeViewColumn * ,
+ GtkCellRenderer * renderer,
+ GtkTreeModel * model,
+ GtkTreeIter * iter,
+ gpointer)
+ {
+
+ TaskUpload* fd(0);
+ gtk_tree_model_get (model, iter, 0, &fd, -1);
+ if (fd)
+ g_object_set (renderer, "text", fd->basename().c_str(), NULL);
+ }
+
+}
+
+GtkWidget*
+PostUI :: create_filequeue_tab ()
+{
+ GtkWidget *w ;
+ GtkListStore *list_store;
+ GtkTreeIter iter;
+ GtkCellRenderer *renderer;
+ GtkWidget * vbox = gtk_vbox_new (false, 0);
+ GtkWidget * buttons = gtk_hbox_new (false, PAD_SMALL);
+
+ // add button row
+ add_button (buttons, GTK_STOCK_GO_UP, G_CALLBACK(up_clicked_cb), this);
+ add_button (buttons, GTK_STOCK_GOTO_TOP, G_CALLBACK(top_clicked_cb), this);
+ gtk_box_pack_start (GTK_BOX(buttons), gtk_vseparator_new(), 0, 0, 0);
+ add_button (buttons, GTK_STOCK_GO_DOWN, G_CALLBACK(down_clicked_cb), this);
+ add_button (buttons, GTK_STOCK_GOTO_BOTTOM, G_CALLBACK(bottom_clicked_cb), this);
+ gtk_box_pack_start (GTK_BOX(buttons), gtk_vseparator_new(), 0, 0, 0);
+ w = add_button (buttons, GTK_STOCK_DELETE, G_CALLBACK(delete_clicked_cb), this);
+ gtk_widget_set_tooltip_text( w, _("Delete from Queue"));
+ pan_box_pack_start_defaults (GTK_BOX(buttons), gtk_event_box_new());
+
+ gtk_box_pack_start (GTK_BOX(vbox), buttons, false, false, 0);
+ gtk_box_pack_start (GTK_BOX(vbox), gtk_hseparator_new(), false, false, 0);
+
+ list_store = gtk_list_store_new (2, G_TYPE_POINTER, G_TYPE_UINT);
+ w = _filequeue_store = gtk_tree_view_new_with_model (GTK_TREE_MODEL(list_store));
+
+ // add columns
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_insert_column_with_data_func(
+ GTK_TREE_VIEW(w), 0, (_("Filename")), renderer,
+ render_filename, 0, 0);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w), 1,
+ (_("Size (kB)")),renderer,"text", 1,NULL);
+
+ // connect signals for popup menu
+ g_signal_connect (w, "popup-menu", G_CALLBACK(on_popup_menu), this);
+ g_signal_connect (w, "button-press-event", G_CALLBACK(on_button_pressed), this);
+
+ //set hint and selection
+ gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(w),TRUE);
+ GtkTreeSelection * selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (w));
+ gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
+ gtk_tree_view_columns_autosize(GTK_TREE_VIEW(w));
+
+ //append scroll window
+ w = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(w), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(w), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER(w), _filequeue_store);
+ gtk_box_pack_start (GTK_BOX(vbox), w, true, true, 0);
+
+
+ return vbox;
+}
+
+GtkWidget*
+PostUI :: create_parts_tab (TaskUpload* ptr)
+{
+
+ const GtkAttachOptions fill ((GtkAttachOptions)(GTK_FILL));
+ const GtkAttachOptions fe ((GtkAttachOptions)(GTK_FILL|GTK_EXPAND|GTK_SHRINK));
+
+ GtkWidget *w, *l, *store ;
+ char buf[512];
+ int row = -1;
+ GtkCellRenderer * renderer;
+ GtkWidget *t = gtk_table_new (8, 2, false);
+ gtk_table_set_col_spacings (GTK_TABLE(t), PAD);
+
+ ++row; //empty line
+ l = gtk_label_new (NULL);
+ gtk_table_attach (GTK_TABLE(t), l, 0, 2, row, row+1, fe, fill, 0, 0);
+
+ ++row; //1
+ g_snprintf (buf, sizeof(buf), "<b>%s:</b>", _("Filename"));
+ l = gtk_label_new (buf);
+ gtk_label_set_use_markup (GTK_LABEL(l), true);
+ gtk_misc_set_alignment (GTK_MISC(l), 0.0f, 0.5f);
+ gtk_table_attach (GTK_TABLE(t), l, 0, 1, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
+ g_snprintf (buf, sizeof(buf), "%s", ptr->basename().c_str());
+ l = gtk_label_new (buf);
+ gtk_misc_set_alignment (GTK_MISC(l), 0.5f, 0.5f);
+ gtk_widget_set_tooltip_text (l, _("The current filename"));
+ gtk_table_attach (GTK_TABLE(t), l, 1, 2, row, row+1, fe, fill, 0, 0);
+
+ ++row; //2
+ g_snprintf (buf, sizeof(buf), "<b>%s:</b>", _("Subject Line"));
+ l = gtk_label_new (buf);
+ gtk_label_set_use_markup (GTK_LABEL(l), true);
+ gtk_misc_set_alignment (GTK_MISC(l), 0.0f, 0.5f);
+ gtk_table_attach (GTK_TABLE(t), l, 0, 1, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
+ g_snprintf (buf, sizeof(buf), "%s", ptr->subject().c_str());
+ l = gtk_label_new (buf);
+ gtk_misc_set_alignment (GTK_MISC(l), 0.5f, 0.5f);
+ gtk_widget_set_tooltip_text (l, _("The current Subject Line"));
+ gtk_table_attach (GTK_TABLE(t), l, 1, 2, row, row+1, fe, fill, 0, 0);
+
+ ++row; //3
+ g_snprintf (buf, sizeof(buf), "<b>%s:</b>", _("Lines / File"));
+ l = gtk_label_new (buf);
+ gtk_label_set_use_markup (GTK_LABEL(l), true);
+ gtk_misc_set_alignment (GTK_MISC(l), 0.0f, 0.5f);
+ gtk_table_attach (GTK_TABLE(t), l, 0, 1, row, row+1, GTK_FILL, GTK_FILL, 0, 0);
+ //todo make generic!!
+ g_snprintf (buf, sizeof(buf), "%d", 4000);
+ l = gtk_label_new_with_mnemonic (buf);
+ gtk_misc_set_alignment (GTK_MISC(l), 0.5f, 0.5f);
+ gtk_widget_set_tooltip_text (l, _("The current Number of Lines per File"));
+ gtk_table_attach (GTK_TABLE(t), l, 1, 2, row, row+1, fe, fill, 0, 0);
+
+ //4
+ ++row;
+ l = gtk_label_new (NULL);
+ gtk_table_attach (GTK_TABLE(t), l, 0, 2, row, row+1, fe, fill, 0, 0);
+
+
+ //5
+ ++row;
+ gtk_table_attach (GTK_TABLE(gtk_hseparator_new()), l, 0, 2, row, row+1, fe, fill, 0, 0);
+
+
+ // 6
+ //treeview for parts list
+ w = _parts_store = gtk_tree_view_new_with_model (GTK_TREE_MODEL(gtk_list_store_new (2, G_TYPE_BOOLEAN, G_TYPE_STRING)));
+
+ // add columns
+ renderer = gtk_cell_renderer_toggle_new();
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w), 0,
+ (_("Part No.")),renderer,"active", 1,NULL);
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w), 1,
+ (_("Filename")),renderer,"text", 1,NULL);
+
+ //set hint and selection
+ gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(w),TRUE);
+ gtk_tree_view_columns_autosize(GTK_TREE_VIEW(w));
+
+ //append scroll window
+ w = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(w), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(w), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER(w), _parts_store);
+ ++row; //todo
+ gtk_table_attach (GTK_TABLE(t), w, 0, 2, row, row+2, fe, fill, 0, 0);
+
+ //7: OK and close Buttons
+ ++row;
+
+ return t;
+
+}
+
+GtkWidget*
+PostUI :: create_log_tab ()
+{
+ GtkWidget *w;
+
+ return w;
+}
+
GtkWidget*
PostUI :: create_extras_tab ()
{
@@ -2050,106 +2225,64 @@ gtk_widget_set_tooltip_text (w, _("The email account where mail replies to your
return t;
}
-namespace
-{
- GtkWidget * add_button (GtkWidget * box,
- const gchar * stock_id,
- GCallback callback,
- gpointer user_data)
- {
- GtkWidget * w = gtk_button_new_from_stock (stock_id);
- gtk_button_set_relief (GTK_BUTTON(w), GTK_RELIEF_NONE);
- if (callback)
- g_signal_connect (w, "clicked", callback, user_data);
- gtk_box_pack_start (GTK_BOX(box), w, false, false, 0);
- return w;
- }
-}
-
void
PostUI :: get_selected_files_foreach (GtkTreeModel *model, GtkTreePath *, GtkTreeIter *iter, gpointer list_g)
{
- FileQueue::FileData* file (0);
+ TaskUpload* file(0);
gtk_tree_model_get (model, iter, 0, &file, -1);
- static_cast<FileQueue*>(list_g)->add (file->filename.c_str(), FileQueue::END);
+ static_cast<tasks_set*>(list_g)->insert (file);
}
-FileQueue::articles_v&
+tasks_set
PostUI :: get_selected_files () const
{
- FileQueue files;
+ tasks_set tasks;
GtkTreeView * view (GTK_TREE_VIEW (_filequeue_store));
GtkTreeSelection * sel (gtk_tree_view_get_selection (view));
- gtk_tree_selection_selected_foreach (sel, get_selected_files_foreach, &files);
- return files.get_files();
-}
-
-int
-PostUI :: get_top()
-{
- int pos(0);
-
- return pos;
-}
-
-int
-PostUI :: get_bottom()
-{
- int pos(0);
-
-
- return pos;
+ gtk_tree_selection_selected_foreach (sel, get_selected_files_foreach, &tasks);
+ return tasks;
}
void
-PostUI :: remove_files(void)
+PostUI :: remove_files (void)
{
- _file_queue.remove(get_selected_files());
+ tasks_set tasks = get_selected_files();
+ tasks_set::iterator nit;
+ for (nit = tasks.begin(); nit != tasks.end();nit, ++nit)
+ _file_queue_tasks.erase(*nit);
update_filequeue_tab();
}
-void
-PostUI :: move_up(void)
-{
- _file_queue.move_up(get_selected_files(),get_top());
- update_filequeue_tab();
-}
void
-PostUI :: move_down(void)
+PostUI :: move_up (void)
{
- _file_queue.move_down(get_selected_files(),get_bottom());
- update_filequeue_tab();
+
}
void
-PostUI :: move_top(void)
+PostUI :: move_down (void)
{
- _file_queue.move_top(get_selected_files());
- update_filequeue_tab();
+
}
void
-PostUI :: move_bottom(void)
+PostUI :: move_top (void)
{
- _file_queue.move_bottom(get_selected_files());
- update_filequeue_tab();
+
}
void
-PostUI :: select_parts (void)
+PostUI :: move_bottom (void)
{
- //get parts from dialog result
- //_file_queue.remove_parts(_parts_dialog->selection);
- update_filequeue_tab();
+
}
void
PostUI :: clear_list (void)
{
- _file_queue.clear();
- update_filequeue_tab();
-
+ _file_queue_tasks.clear();
+ update_filequeue_tab();
}
void PostUI :: up_clicked_cb (GtkButton*, PostUI* pane)
@@ -2173,82 +2306,6 @@ void PostUI :: delete_clicked_cb (GtkButton*, PostUI* pane)
pane->remove_files ();
}
-namespace
-{
- void
- render_filename (GtkTreeViewColumn * ,
- GtkCellRenderer * renderer,
- GtkTreeModel * model,
- GtkTreeIter * iter,
- gpointer)
- {
-
- FileQueue::FileData* fd;
- unsigned int size;
- gtk_tree_model_get (model, iter, 0, &fd, 1, &size, -1);
- if (fd)
- g_object_set (renderer, "text", fd->basename.c_str(),
- "weight", fd->all_parts ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_LIGHT, NULL);
- }
-}
-
-GtkWidget*
-PostUI :: create_filequeue_tab ()
-{
- GtkWidget *w ;
- GtkListStore *list_store;
- GtkTreeIter iter;
- GtkCellRenderer *renderer;
- GtkWidget * vbox = gtk_vbox_new (false, 0);
- GtkWidget * buttons = gtk_hbox_new (false, PAD_SMALL);
-
- // add button row
- add_button (buttons, GTK_STOCK_GO_UP, G_CALLBACK(up_clicked_cb), this);
- add_button (buttons, GTK_STOCK_GOTO_TOP, G_CALLBACK(top_clicked_cb), this);
- gtk_box_pack_start (GTK_BOX(buttons), gtk_vseparator_new(), 0, 0, 0);
- add_button (buttons, GTK_STOCK_GO_DOWN, G_CALLBACK(down_clicked_cb), this);
- add_button (buttons, GTK_STOCK_GOTO_BOTTOM, G_CALLBACK(bottom_clicked_cb), this);
- gtk_box_pack_start (GTK_BOX(buttons), gtk_vseparator_new(), 0, 0, 0);
- w = add_button (buttons, GTK_STOCK_DELETE, G_CALLBACK(delete_clicked_cb), this);
- gtk_widget_set_tooltip_text( w, _("Delete from Queue"));
- pan_box_pack_start_defaults (GTK_BOX(buttons), gtk_event_box_new());
-
- gtk_box_pack_start (GTK_BOX(vbox), buttons, false, false, 0);
- gtk_box_pack_start (GTK_BOX(vbox), gtk_hseparator_new(), false, false, 0);
-
- list_store = gtk_list_store_new (2, G_TYPE_POINTER, G_TYPE_UINT);
- w = _filequeue_store = gtk_tree_view_new_with_model (GTK_TREE_MODEL(list_store));
-
- // add columns
- renderer = gtk_cell_renderer_text_new ();
- gtk_tree_view_insert_column_with_data_func(
- GTK_TREE_VIEW(w), 0, (_("Filename")), renderer,
- render_filename, 0, 0);
- renderer = gtk_cell_renderer_text_new ();
- gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (w), 1,
- (_("Size (kB)")),renderer,"text", 1,NULL);
-
-
- // connect signals for popup menu
- g_signal_connect (w, "popup-menu", G_CALLBACK(on_popup_menu), this);
- g_signal_connect (w, "button-press-event", G_CALLBACK(on_button_pressed), this);
-
- //set hint and selection
- gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(w),TRUE);
- GtkTreeSelection * selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (w));
- gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
-
- //append scroll window
- w = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(w), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(w), GTK_SHADOW_IN);
- gtk_container_add (GTK_CONTAINER(w), _filequeue_store);
- gtk_box_pack_start (GTK_BOX(vbox), w, true, true, 0);
-
-
- return vbox;
-}
-
void
PostUI :: update_filequeue_tab()
{
@@ -2259,20 +2316,18 @@ PostUI :: update_filequeue_tab()
gtk_list_store_clear(store);
- FileQueue::articles_it it = _file_queue.begin();
+ tasks_set::iterator it = _file_queue_tasks.begin();
int i(0);
- FileQueue::FileData* fd(0);
- for (; it != _file_queue.end(); ++it, ++i )
+ for (; it != _file_queue_tasks.end(); ++it )
{
- fd = &(*it);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
- 0, fd,
- 1, (*it).byte_count/1024,
+ 0, ((TaskUpload*)*it),
+ 1, ((TaskUpload*)*it)->get_byte_count()/1024,
-1);
}
- _file_queue_empty = (i == 0);
+ _file_queue_empty = (_file_queue_tasks.empty());
}
@@ -2284,6 +2339,54 @@ PostUI :: ~PostUI ()
g_object_unref (G_OBJECT(_message));
}
+void
+PostUI :: select_parts ()
+{
+
+ TaskUpload* ptr(0);
+ tasks_set set(get_selected_files());
+ ptr = *set.begin();
+ GtkWidget * w;
+ GtkTreeIter iter;
+ const int total = (int) (((long)ptr->get_byte_count() + (4000*128-1)) / (4000*128));
+
+ std::cerr<<total<<std::endl;
+
+ w = _part_select = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_signal_connect (_part_select, "delete-event", G_CALLBACK(delete_parts_cb), this);
+ gtk_window_set_role (GTK_WINDOW(w), "pan-parts-window");
+ gtk_window_set_title (GTK_WINDOW(w), _("Select Parts"));
+ int x,h;
+ x = 350;
+ h = 450;
+ gtk_window_set_default_size (GTK_WINDOW(w), x, h);
+
+ // populate the window
+ GtkWidget * vbox = gtk_vbox_new (false, PAD_SMALL);
+ gtk_container_add (GTK_CONTAINER(w), vbox);
+
+ GtkWidget * notebook = gtk_notebook_new ();
+ gtk_notebook_append_page (GTK_NOTEBOOK(notebook), create_parts_tab(ptr), gtk_label_new_with_mnemonic(_("_Parts")));
+ gtk_notebook_append_page (GTK_NOTEBOOK(notebook), create_log_tab(), gtk_label_new_with_mnemonic(_("_Log")));
+ pan_box_pack_start_defaults (GTK_BOX(vbox), notebook);
+
+ //populate parts tab
+ GtkListStore *store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(_parts_store)));
+ for (int i=1;i<=total+100;++i)
+ {
+ gtk_list_store_append (store, &iter);
+ gtk_list_store_set (store, &iter,
+ 0, true,
+ 1, ptr->basename().c_str(), -1);
+ }
+
+ gtk_widget_show_all (w);
+
+
+// update_parts_tab();
+
+}
+
PostUI :: PostUI (GtkWindow * parent,
Data & data,
Queue & queue,
@@ -2311,7 +2414,6 @@ PostUI :: PostUI (GtkWindow * parent,
_charset (DEFAULT_CHARSET),
_group_entry_changed_id (0),
_group_entry_changed_idle_tag (0),
- //binpost
_file_queue_empty(true)
{
g_assert (profiles.has_profiles());
@@ -2390,8 +2492,16 @@ PostUI :: create_window (GtkWidget * parent,
}
void
-PostUI :: prompt_user_for_queueable_files (FileQueue& queue, GtkWindow * parent, const Prefs& prefs)
+PostUI :: prompt_user_for_queueable_files (tasks_set& queue, GtkWindow * parent, const Prefs& prefs)
{
+ const Profile profile (get_current_profile ());
+ GMimeMessage * message (new_message_from_ui (POSTING));
+ if (!check_message(profile.posting_server, message))
+ {
+ g_object_unref (G_OBJECT(message));
+ return;
+ }
+
std::string prev_path = prefs.get_string ("default-save-attachments-path", g_get_home_dir ());
GtkWidget * w = gtk_file_chooser_dialog_new (_("Add files to queue"),
@@ -2409,13 +2519,28 @@ PostUI :: prompt_user_for_queueable_files (FileQueue& queue, GtkWindow * parent,
GSList * tmp_list = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER (w));
if (_file_queue_empty) _file_queue_empty=!_file_queue_empty;
GSList * cur = g_slist_nth (tmp_list,0);
- const Profile profile (get_current_profile ());
- const StringView subject(gtk_entry_get_text (GTK_ENTRY(_subject_entry)));
- struct stat stat_buf;
+ GMimeMessage* msg = new_message_from_ui(POSTING);
+ char * tmp;
+ tmp = (char*)g_mime_object_get_header ((GMimeObject*)msg, "Subject");
+ std::string subject= std::string(tmp ? tmp : "");
+ std::string author;
+ profile.get_from_header (author);
+ quarks_t groups;
+ const char * text = gtk_entry_get_text (GTK_ENTRY(_groups_entry));
+ StringView line(text), groupname;
+ while (line.pop_token (groupname, ',')) {
+ groupname.trim ();
+ if (!groupname.empty())
+ groups.insert(groupname);
+ }
for (; cur; cur = cur->next)
{
- _file_queue.add((char*)cur->data, FileQueue::END);
+ TaskUpload::needed_t tmp; //todo
+ _file_queue_tasks.insert( new TaskUpload(std::string((const char*)cur->data),
+ profile.posting_server,
+ groups, subject, author, tmp, 0,
+ TaskUpload::YENC));
}
g_slist_free (tmp_list);
}
diff --git a/pan/gui/post-ui.h b/pan/gui/post-ui.h
index 59fb7de..ded6d83 100644
--- a/pan/gui/post-ui.h
+++ b/pan/gui/post-ui.h
@@ -22,7 +22,6 @@
#include <gmime/gmime-message.h>
#include <pan/gui/prefs.h>
-#include <pan/data/file-queue.h>
#include <pan/general/progress.h>
#include <pan/tasks/queue.h>
#include <pan/usenet-utils/text-massager.h>
@@ -33,6 +32,10 @@ namespace pan
class Profiles;
class TaskPost;
class FileQueue;
+ class Queue;
+
+
+ typedef std::multiset<TaskUpload*> tasks_set;
/**
* Dialog for posting new messages Pan's GTK GUI.
@@ -44,7 +47,7 @@ namespace pan
static PostUI* create_window (GtkWidget*, Data&, Queue&, GroupServer&, Profiles&,
GMimeMessage*, Prefs&, GroupPrefs&);
- void prompt_user_for_queueable_files (FileQueue& queue, GtkWindow * parent, const Prefs& prefs);
+ void prompt_user_for_queueable_files (tasks_set& queue, GtkWindow * parent, const Prefs& prefs);
protected:
PostUI (GtkWindow*, Data&, Queue&, GroupServer&, Profiles&,
@@ -54,6 +57,7 @@ namespace pan
public:
GtkWidget * root() { return _root; }
+ GtkWidget * part_select() { return _part_select; }
void rot13_selection ();
void wrap_body ();
void spawn_editor ();
@@ -71,13 +75,13 @@ namespace pan
void update_filequeue_tab();
//popup action entries
- void remove_files (void);
- void clear_list (void);
- void select_parts (void);
- void move_up (void);
- void move_down (void);
- void move_top (void);
- void move_bottom (void);
+ void remove_files ();
+ void clear_list ();
+ void select_parts ();
+ void move_up ();
+ void move_down ();
+ void move_top ();
+ void move_bottom ();
static void do_popup_menu (GtkWidget*, GdkEventButton *event, gpointer pane_g);
static gboolean on_button_pressed (GtkWidget * treeview, GdkEventButton *event, gpointer userdata);
@@ -105,11 +109,13 @@ namespace pan
Prefs& _prefs;
GroupPrefs& _group_prefs;
GtkWidget * _root;
+ GtkWidget * _part_select;
GtkWidget * _from_combo;
GtkWidget * _subject_entry;
GtkWidget * _groups_entry;
GtkWidget * _filequeue_store;
+ GtkWidget * _parts_store;
GtkWidget * _to_entry;
GtkWidget * _followupto_entry;
@@ -136,7 +142,7 @@ namespace pan
/* binpost */
bool _file_queue_empty;
- FileQueue _file_queue;
+ tasks_set _file_queue_tasks;
private:
void add_actions (GtkWidget* box);
@@ -152,6 +158,8 @@ namespace pan
GtkWidget* create_main_tab ();
GtkWidget* create_extras_tab ();
GtkWidget* create_filequeue_tab ();
+ GtkWidget* create_parts_tab (TaskUpload* ptr);
+ GtkWidget* create_log_tab ();
private:
std::string utf8ize (const StringView&) const;
@@ -171,8 +179,10 @@ namespace pan
void set_spellcheck_enabled (bool);
void spawn_editor_dead(char *);
+ public:
+ tasks_set get_selected_files () const;
+
private:
- FileQueue::articles_v& get_selected_files () const;
static void get_selected_files_foreach (GtkTreeModel*,
GtkTreePath*, GtkTreeIter*, gpointer);
diff --git a/pan/tasks/encoder.cc b/pan/tasks/encoder.cc
index fa857f2..f50aa31 100644
--- a/pan/tasks/encoder.cc
+++ b/pan/tasks/encoder.cc
@@ -56,7 +56,8 @@ Encoder :: ~Encoder()
void
Encoder :: enqueue (TaskUpload * task,
- const FileQueue::FileData & file_data,
+ std::string & filename,
+ std::string & basename,
std::string & groups,
std::string & subject,
std::string & author,
@@ -66,7 +67,8 @@ Encoder :: enqueue (TaskUpload * task,
disable_progress_update ();
this->task = task;
- this->file_data = file_data;
+ this->filename = filename;
+ this->basename = basename;
this->encode_mode = encode_mode;
this->groups = groups;
this->subject = subject;
@@ -91,11 +93,7 @@ Encoder :: do_work()
crc32_t crcptr;
FILE* outfile, * infile ;
-
std::string uulib(file :: get_uulib_path());
-
- std::cerr<<"encoder starting...\n";
-
enable_progress_update();
int res;
@@ -107,31 +105,28 @@ Encoder :: do_work()
UUSetMsgCallback (this, uu_log);
UUSetBusyCallback (this, uu_busy_poll, 100);
- const char* filename = file_data.filename.c_str();
- const char* basename = g_path_get_basename(file_data.filename.c_str());
-
- g_snprintf(buf,bufsz,"%s/%s.%d", uulib.c_str(), basename, cnt);
+ g_snprintf(buf,bufsz,"%s/%s.%d", uulib.c_str(), basename.c_str(), cnt);
outfile = fopen(buf,"wb");
while (1) {
// skip not wanted parts of binary file
- if (file_data.parts.end() != file_data.parts.find(cnt))
- {
- ++cnt;
- res = UURET_CONT;
- goto _end;
- }
+// if (parts->end() != parts->find(cnt))
+// {
+// ++cnt;
+// res = UURET_CONT;
+// goto _end;
+// }
// 4000 lines SHOULD be OK for ANY nntp server ...
- res = UUE_PrepPartial (outfile, NULL, (char*)filename,YENC_ENCODED,
- (char*)basename,0644, cnt, 4000,
- file_data.byte_count, (char*)groups.c_str(),
+ res = UUE_PrepPartial (outfile, NULL, (char*)filename.c_str(),YENC_ENCODED,
+ (char*)basename.c_str(),0644, cnt, 4000,
+ 0, (char*)groups.c_str(),
(char*)author.c_str(), (char*)subject.c_str(),
0);
_end:
if (outfile) fclose(outfile);
if (res != UURET_CONT) break;
- g_snprintf(buf,bufsz,"%s/%s.%d", uulib.c_str(), basename, ++cnt);
+ g_snprintf(buf,bufsz,"%s/%s.%d", uulib.c_str(), basename.c_str(), ++cnt);
outfile = fopen(buf,"wb");
}
@@ -139,7 +134,7 @@ Encoder :: do_work()
{
g_snprintf(buf, bufsz,
_("Error encoding %s: %s"),
- basename,
+ basename.c_str(),
(res==UURET_IOERR)
? file::pan_strerror (UUGetOption (UUOPT_ERRNO, NULL,
NULL, 0))
@@ -208,7 +203,7 @@ Encoder :: uu_busy_poll (void * d, uuprogress *p)
self->mut.lock();
self->percent = self->get_percentage(*p);
self->current_file = p->curfile;
- self->parts = (int)p->numparts - self->file_data.parts.size();
+ self->total_parts = p->numparts;
self->mut.unlock();
return self->was_cancelled(); // returning true tells uulib to abort
diff --git a/pan/tasks/encoder.h b/pan/tasks/encoder.h
index d59b760..5808963 100644
--- a/pan/tasks/encoder.h
+++ b/pan/tasks/encoder.h
@@ -59,7 +59,8 @@ namespace pan
typedef std::vector<std::string> strings_t;
void enqueue (TaskUpload * task,
- const FileQueue::FileData & file_data,
+ std::string & filename,
+ std::string & basename,
std::string & groups,
std::string & subject,
std::string & author,
@@ -76,17 +77,19 @@ namespace pan
private:
+ std::set<int>* parts;
friend class TaskUpload;
TaskUpload * task;
TaskUpload::EncodeMode encode_mode;
- FileQueue::FileData file_data;
+ std::string filename;
+ std::string basename;
std::string subject, author, groups;
// These are set in the worker thread and polled in the main thread.
Mutex mut;
volatile double percent;
std::string current_file; // the current file we are decoding, with path
- int parts;
+ int total_parts;
static void uu_log(void *thiz, char *message, int severity);
double get_percentage (const uuprogress& p) const;
diff --git a/pan/tasks/nzb.cc b/pan/tasks/nzb.cc
index b27e8b4..d8c382e 100644
--- a/pan/tasks/nzb.cc
+++ b/pan/tasks/nzb.cc
@@ -34,6 +34,7 @@ extern "C" {
#include <pan/general/utf8-utils.h>
#include "nzb.h"
#include "task-article.h"
+#include "task-upload.h"
using namespace pan;
@@ -46,7 +47,10 @@ namespace
quarks_t groups;
std::string text;
std::string path;
+ std::vector<std::string> groups_str; // TaskUpload
+ TaskUpload::needed_t needed_parts; // TaskUpload
Article a;
+ Quark posting_server;
PartBatch parts;
tasks_t tasks;
ArticleCache& cache;
@@ -63,11 +67,13 @@ namespace
void file_clear () {
groups.clear ();
+ groups_str.clear();
text.clear ();
path.clear ();
a.clear ();
bytes = 0;
number = 0;
+ needed_parts.clear(); // TaskUpload
}
};
@@ -90,6 +96,16 @@ namespace
}
}
+ else if (!strcmp (element_name, "upload")) {
+ mc.file_clear ();
+ for (const char **k(attribute_names), **v(attribute_vals); *k; ++k, ++v) {
+ if (!strcmp (*k,"author")) mc.a.author = *v;
+ else if (!strcmp (*k,"subject")) mc.a.subject = *v;
+ else if (!strcmp (*k,"server")) mc.posting_server = Quark(*v);
+ }
+ std::cerr<<"upload begin tag\n";
+ }
+
else if (!strcmp (element_name, "segment")) {
mc.bytes = 0;
mc.number = 0;
@@ -98,6 +114,17 @@ namespace
else if (!strcmp (*k,"number")) mc.number = atoi (*v);
}
}
+
+ else if (!strcmp (element_name, "part")) {
+ mc.bytes = 0;
+ mc.number = 0;
+ for (const char **k(attribute_names), **v(attribute_vals); *k; ++k, ++v) {
+ if (!strcmp (*k,"bytes")) mc.bytes = strtoul (*v,0,10);
+ else if (!strcmp (*k,"number")) mc.number = atoi (*v);
+ }
+ std::cerr<<"part begin tag\n";
+ }
+
}
// Called for close tags </foo>
@@ -109,7 +136,10 @@ namespace
MyContext& mc (*static_cast<MyContext*>(user_data));
if (!strcmp(element_name, "group"))
+ {
mc.groups.insert (Quark (mc.text));
+ mc.groups_str.push_back(mc.text);
+ }
else if (!strcmp(element_name, "segment") && mc.number && !mc.text.empty()) {
const std::string mid ("<" + mc.text + ">");
@@ -120,6 +150,15 @@ namespace
mc.parts.add_part (mc.number, mid, mc.bytes);
}
+ else if (!strcmp(element_name, "part") && mc.number && !mc.text.empty()) {
+ TaskUpload::Needed n;
+ n.bytes = mc.bytes;
+ n.filename = mc.text;
+ n.partno = mc.number;
+ mc.needed_parts.push_back(n);
+ std::cerr<<"part end tag\n";
+ }
+
else if (!strcmp(element_name,"path"))
mc.path = mc.text;
@@ -135,7 +174,15 @@ namespace
mc.a.xref.insert (*sit, *git, 0);
}
const StringView p (mc.path.empty() ? mc.fallback_path : StringView(mc.path));
+ debug("adding taskarticle from nzb.\n");
mc.tasks.push_back (new TaskArticle (mc.ranks, mc.gs, mc.a, mc.cache, mc.read, 0, TaskArticle::DECODE, p));
+
+ }
+ else if (!strcmp (element_name, "upload"))
+ {
+ debug("adding taskupload from nzb.\n");
+ mc.tasks.push_back (new TaskUpload (mc.path, const_cast<const Quark&>(mc.posting_server),
+ mc.groups, mc.a.subject.to_string(), mc.a.author.to_string(), mc.needed_parts, 0, TaskUpload::YENC));
}
}
@@ -230,65 +277,113 @@ NZB :: nzb_to_xml (std::ostream & out,
foreach_const (tasks_t, tasks, it)
{
TaskArticle * task (dynamic_cast<TaskArticle*>(*it));
- if (!task) // not a download task...
- continue;
- if (task->get_save_path().empty()) // this task is for reading, not saving...
- continue;
+ if (task)
+ {
- 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";
+ if (task->get_save_path().empty()) // this task is for reading, not saving...
+ 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";
+
+ // path to save this to.
+ // This isn't part of the nzb spec.
+ const Quark& path (task->get_save_path());
+ if (!path.empty()) {
+ out << indent(depth) << "<path>";
+ escaped (out, path.to_view());
+ out << "</path>\n";
+ }
- // path to save this to.
- // This isn't part of the nzb spec.
- const Quark& path (task->get_save_path());
- if (!path.empty()) {
- out << indent(depth) << "<path>";
- escaped (out, path.to_view());
- out << "</path>\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";
+ 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";
}
+ else
+ { // handle upload tasks
+ TaskUpload * task (dynamic_cast<TaskUpload*>(*it));
+ // not an upload task, move on
+ if (!task) continue;
- // 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 ();
+ std::vector<std::string> groups;
- // remove the surrounding < > as per nzb spec
- if (mid.size()>=2 && mid[0]=='<') {
- mid.erase (0, 1);
- mid.resize (mid.size()-1);
+ //info: author, subject, load path, parts to encode / post
+ out << indent(depth)
+ << "<upload" << " author=\"";
+ escaped (out, task->_author);
+ out << "\" subject=\"";
+ escaped (out, task->_subject);
+ out << "\" server=\"";
+ escaped (out, task->_server.to_string());
+ out << "\" encoded=\"";
+ char buf[3];
+ g_snprintf(buf,3,"%d",(int)task->_encoder_has_run);
+ escaped (out, StringView(buf)) << "\">\n";
+ ++depth;
+ out << indent(depth)
+ << "<path>" << task->_filename << "</path>\n";
+ out << indent(depth) << "<groups>\n";
+ ++depth;
+ foreach_const (quarks_t, task->_groups, it)
+ {
+ out << indent(depth)<<"<group>" << (*it).to_string() << "</group>\n";
}
+ --depth;
+ out << indent(depth) << "</groups>\n";
+ out << indent(depth) << "<parts>\n";
+ ++depth;
+
+ foreach_const (TaskUpload::needed_t, task->_needed, it)
+ out << indent(depth)
+ << "<part" << " bytes=\"" << (*it).bytes << '"'
+ << " number=\"" << (*it).partno << '"'
+ << ">" << (*it).filename<< "</part>\n";
+ --depth;
+ out << indent(depth) << "</parts>\n";
+ --depth;
+ out << indent(depth) << "</upload>\n";
+
- // 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 */
+/* Saves selected article-info to a chosen XML file */
std::ostream&
NZB :: nzb_to_xml_file (std::ostream & out,
const std::vector<Task*> & tasks)
@@ -303,7 +398,7 @@ NZB :: nzb_to_xml_file (std::ostream & out,
foreach_const (tasks_t, tasks, it)
{
TaskArticle * task (dynamic_cast<TaskArticle*>(*it));
- if (!task) // not a download task...
+ if (!task) // not a download task, for example an upload task...
continue;
const Article& a (task->get_article());
diff --git a/pan/tasks/nzb.h b/pan/tasks/nzb.h
index 0d9eec1..fe49dfa 100644
--- a/pan/tasks/nzb.h
+++ b/pan/tasks/nzb.h
@@ -53,10 +53,10 @@ 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);
+ const std::vector<Task*> & tasks);
};
}
diff --git a/pan/tasks/queue.cc b/pan/tasks/queue.cc
index ce9de63..f24dc19 100644
--- a/pan/tasks/queue.cc
+++ b/pan/tasks/queue.cc
@@ -550,6 +550,9 @@ Queue :: task_is_active (const Task * task) const
if (task && task==_decoder_task)
return true;
+ if (task && task==_encoder_task)
+ return true;
+
bool task_has_nntp (false);
foreach_const (nntp_to_task_t, _nntp_to_task, it)
if ((task_has_nntp = task==it->second))
diff --git a/pan/tasks/task-upload.cc b/pan/tasks/task-upload.cc
index c915594..0728fe9 100644
--- a/pan/tasks/task-upload.cc
+++ b/pan/tasks/task-upload.cc
@@ -59,27 +59,33 @@ namespace
****
***/
-TaskUpload :: TaskUpload ( const FileQueue::FileData & file_data,
+TaskUpload :: TaskUpload ( const std::string & filename,
const Quark & server,
- std::string groups,
+ quarks_t & groups,
std::string subject,
std::string author,
+ needed_t & todo,
Progress::Listener * listener,
const TaskUpload::EncodeMode enc):
- Task ("UPLOAD", get_description(file_data.filename.c_str(), false)),
- _file_data(file_data),
- _basename (file_data.basename),
+ Task ("UPLOAD", get_description(filename.c_str(), true)),
+ _filename(filename),
+ _basename (std::string(g_path_get_basename(filename.c_str()))),
_server(server),
_groups(groups),
_subject (subject),
_author(author),
_encoder(0),
_encoder_has_run (false),
- _encode_mode(enc)
+ _encode_mode(enc),
+ _extern(todo)
{
if (listener != 0)
add_listener (listener);
+ struct stat sb;
+ stat(filename.c_str(),&sb);
+ _bytes = sb.st_size;
+
update_work ();
}
@@ -88,24 +94,22 @@ TaskUpload :: update_work (NNTP* checkin_pending)
{
int working(0);
- foreach (needed_t, _needed, nit)
- {
+ foreach (needed_t, _needed, nit) {
Needed& n (*nit);
if (n.nntp && n.nntp!=checkin_pending)
++working;
}
- if (!_encoder && !_encoder_has_run)
+ if (!_encoder && !_encoder_has_run )
{
_state.set_need_encoder();
- } else if(working)
+ } else if(working )
{
_state.set_working();
} else if (_encoder_has_run && !_needed.empty())
{
- set_status_va (_("Uploading %s"), _basename.c_str());
_state.set_need_nntp(_server);
- } else if (_needed.empty())
+ } else if (_needed.empty() && _encoder_has_run )
{
_state.set_completed();
set_finished(OK);
@@ -121,8 +125,7 @@ TaskUpload :: use_nntp (NNTP * nntp)
{
Needed * needed (0);
- needed_t::iterator it = _needed.begin();
- for (; it != _needed.end(); ++it)
+ for (needed_t::iterator it(_needed.begin()), end(_needed.end()); !needed && it!=end; ++it)
if (it->nntp==0)
needed = &*it;
@@ -134,11 +137,13 @@ TaskUpload :: use_nntp (NNTP * nntp)
else
{
needed->nntp = nntp;
-
+ set_status_va (_("Uploading \"%s\" - Part %d of %d"), _basename.c_str(), needed->partno, _total_parts);
std::stringstream tmp;
std::ifstream in(needed->filename.c_str(), std::ifstream::in);
- while (in.good())
- tmp << (char) in.get();
+ char tmp_char;
+ while (in.good()) {
+ tmp << (tmp_char=(char) in.get());
+ }
in.close();
nntp->post(StringView(tmp.str()), this);
update_work ();
@@ -152,10 +157,16 @@ TaskUpload :: use_nntp (NNTP * nntp)
void
TaskUpload :: on_nntp_line (NNTP * nntp,
const StringView & line_in)
-{
+{}
-std::cerr<<"line "<<line_in<<std::cerr;
+// delete cached files to avoid "disk full" problems
+namespace
+{
+ void delete_cache(const TaskUpload::Needed& n)
+ {
+ unlink(n.filename.c_str());
+ }
}
void
@@ -169,6 +180,8 @@ TaskUpload :: on_nntp_done (NNTP * nntp,
if (it->nntp == nntp)
break;
+ bool post_ok(false);
+
switch (atoi(response.str))
{
case NO_POSTING:
@@ -176,23 +189,28 @@ TaskUpload :: on_nntp_done (NNTP * nntp,
this->stop();
break;
case POSTING_FAILED:
- Log :: add_err_va (_("Posting failed: %s"), response.str);
+ Log :: add_err_va (_("Posting of file %s failed: %s"), _basename.c_str(), response.str);
break;
case ARTICLE_POSTED_OK:
- if (_needed.empty())
- Log :: add_info_va(_("Posting of file %s succesful: %s"),
- _file_data.basename.c_str(), response.str);
+ post_ok = true;
break;
case TOO_MANY_CONNECTIONS:
// lockout for 120 secs, but try
_state.set_need_nntp(nntp->_server);
break;
+ default:
+ Log :: add_err_va (_("Got unknown response code: %s"),response.str);
+ break;
}
switch (health)
{
case OK:
+ delete_cache(*it);
_needed.erase (it);
+ if (_needed.empty() && post_ok)
+ Log :: add_info_va(_("Posting of file %s succesful: %s"),
+ _basename.c_str(), response.str);
break;
case ERR_NETWORK:
@@ -210,7 +228,6 @@ TaskUpload :: on_nntp_done (NNTP * nntp,
****
***/
-//todo
unsigned long
TaskUpload :: get_bytes_remaining () const
{
@@ -230,7 +247,16 @@ TaskUpload :: use_encoder (Encoder* encoder)
_encoder = encoder;
init_steps(100);
_state.set_working();
- _encoder->enqueue (this, _file_data, _groups, _subject, _author, YENC);
+ // build group name
+ std::string groups;
+ quarks_t::iterator it = _groups.begin();
+ int i(0);
+ for (; it != _groups.end(); ++it, ++i)
+ {
+ if (i<_groups.size()&& i>0 && _groups.size()>1) groups += ",";
+ groups += (*it).to_string();
+ }
+ _encoder->enqueue (this, _filename, _basename, groups, _subject, _author, YENC);
debug ("encoder thread was free, enqueued work");
}
@@ -260,38 +286,37 @@ TaskUpload :: on_worker_done (bool cancelled)
foreach_const(Encoder::log_t, _encoder->log_infos, it)
Log :: add_info(it->c_str());
-
if (!_encoder->log_errors.empty())
set_error (_encoder->log_errors.front());
if (!_encoder->log_severe.empty())
_state.set_health (ERR_LOCAL);
else {
- // get parts number from encoder
- _parts = _encoder->parts;
set_step (100);
_encoder_has_run = true;
+ _total_parts = _encoder->total_parts;
/*enqueue all parts into the global needed_t list.
update_work will then assign a pointer to the begin
which will be used for an nntp upload.
on nntp_done, the list is decreased by one member
*/
- static Needed n;
+ Needed n;
char buf[2048];
struct stat sb;
- for (int i=1;i<=_parts;i++)
- {
- n.partno = i;
- g_snprintf(buf,sizeof(buf),"%s/%s.%d",
- file::get_uulib_path().c_str(),
- _basename.c_str(), i);
- n.filename = buf;
- stat(buf, &sb);
- n.bytes = sb.st_size;
- _needed.push_back (n);
- }
- init_steps (_parts);
+ for (int i=1; i<=_total_parts; ++i)
+ {
+ n.partno = i;
+ g_snprintf(buf,sizeof(buf),"%s/%s.%d",
+ file::get_uulib_path().c_str(),
+ _basename.c_str(), i);
+ n.filename = buf;
+ stat(buf, &sb);
+ n.bytes = sb.st_size;
+ _needed.push_back (n);
+ }
+
+ init_steps (_total_parts);
set_step (0);
}
}
diff --git a/pan/tasks/task-upload.h b/pan/tasks/task-upload.h
index 17ffaff..7a7b1fd 100644
--- a/pan/tasks/task-upload.h
+++ b/pan/tasks/task-upload.h
@@ -25,14 +25,14 @@
#define _TaskUpload_h_
#include <pan/general/worker-pool.h>
+#include <pan/general/locking.h>
#include <pan/data/article.h>
#include <pan/data/article-cache.h>
#include <pan/data/data.h>
-#include <pan/data/file-queue.h>
#include <pan/data/xref.h>
#include <pan/tasks/nntp.h>
#include <pan/tasks/task.h>
-#include <deque>
+#include <set>
namespace pan
{
@@ -46,7 +46,17 @@ namespace pan
private NNTP::Listener,
private WorkerPool::Worker::Listener
{
- public: // life cycle
+ public:
+
+ struct Needed {
+ std::string filename;
+ unsigned long bytes;
+ int partno;
+ NNTP* nntp;
+ Needed (): nntp(0) {}
+ };
+
+ typedef std::deque<Needed> needed_t;
enum EncodeMode
{
@@ -55,18 +65,24 @@ namespace pan
PLAIN
};
- TaskUpload ( const FileQueue::FileData & file_data,
+ // life cycle
+ TaskUpload ( const std::string & filename,
const Quark & server,
- std::string groups,
+ quarks_t & groups,
std::string subject,
std::string author,
- Progress::Listener * listener=0,
- TaskUpload::EncodeMode enc = YENC);
+ needed_t & todo,
+ Progress::Listener * listener= 0,
+ TaskUpload::EncodeMode enc= YENC);
virtual ~TaskUpload ();
public: // Task subclass
unsigned long get_bytes_remaining () const;
void stop ();
+ const std::string& basename() { return _basename; }
+ const std::string& filename() { return _filename; }
+ const std::string& subject () { return _subject; }
+ unsigned long get_byte_count() { return _bytes; }
/** only call this for tasks in the NEED_DECODE state
* attempts to acquire the saver thread and start saving
@@ -91,25 +107,22 @@ namespace pan
private: // implementation
friend class Encoder;
+ friend class NZB;
Encoder * _encoder;
bool _encoder_has_run;
- const FileQueue::FileData _file_data;
- const std::string _basename;
+ std::string _filename;
+ std::string _basename;
TaskUpload::EncodeMode _encode_mode;
- std::string _groups, _subject, _author;
- int _parts; // filled in by encoder
+ quarks_t _groups;
+ std::string _subject, _author;
+ int _total_parts; // filled in by encoder
+ unsigned long _bytes;
Mutex mut;
private:
- struct Needed {
- std::string filename;
- unsigned long bytes;
- int partno;
- NNTP* nntp;
- Needed (): nntp(0), partno(0) {}
- };
- typedef std::deque<Needed> needed_t;
- needed_t _needed;
+ needed_t _needed;
+ needed_t _extern;
+ std::set<int> _parts;
void update_work (NNTP * checkin_pending = 0);
};
diff --git a/pan/usenet-utils/message-check.cc b/pan/usenet-utils/message-check.cc
index 7174818..84f610f 100644
--- a/pan/usenet-utils/message-check.cc
+++ b/pan/usenet-utils/message-check.cc
@@ -267,7 +267,7 @@ namespace
* (2) Replace carriage returns in both the calculated attribution string
* and a temporary copy of the message body, so that we don't have to
* worry whether or not the attribution line's been wrapped.
- *
+ *
* (3) Search for an occurance of the attribution string in the body. If
* it's found, remove it from the temporary copy of the body so that
* it won't affect our line counts.
@@ -420,7 +420,8 @@ MessageCheck :: message_check (const GMimeMessage * message_const,
const StringView & attribution,
const quarks_t & groups_our_server_has,
unique_strings_t & errors,
- Goodness & goodness)
+ Goodness & goodness,
+ bool binpost)
{
goodness.clear ();
errors.clear ();
@@ -445,18 +446,23 @@ MessageCheck :: message_check (const GMimeMessage * message_const,
errors.insert (_("Warning: Most newsgroups frown upon HTML posts."));
goodness.raise_to_warn ();
}
- check_body (errors, goodness, tm, message, body, attribution);
+ if (!binpost)
+ check_body (errors, goodness, tm, message, body, attribution);
g_free (body);
-
+
// check the optional followup-to...
bool followup_to_set (false);
const char * cpch = g_mime_object_get_header ((GMimeObject *) message, "Followup-To");
- if (cpch && *cpch) {
- quarks_t groups;
- get_nntp_rcpts (cpch, groups);
- followup_to_set = !groups.empty();
- check_followup_to (errors, goodness, groups_our_server_has, groups);
- }
+ if (!binpost)
+ {
+ if (cpch && *cpch) {
+ quarks_t groups;
+ get_nntp_rcpts (cpch, groups);
+ followup_to_set = !groups.empty();
+ check_followup_to (errors, goodness, groups_our_server_has, groups);
+ }
+ } else
+ followup_to_set = true;
// check the groups...
size_t group_qty (0);
diff --git a/pan/usenet-utils/message-check.h b/pan/usenet-utils/message-check.h
index 1528f12..8889ee1 100644
--- a/pan/usenet-utils/message-check.h
+++ b/pan/usenet-utils/message-check.h
@@ -58,7 +58,8 @@ namespace pan
const StringView & attribution,
const quarks_t & groups_our_server_has,
unique_strings_t & errors,
- Goodness & goodness);
+ Goodness & goodness,
+ bool binpost = false);
};
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]