[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Re: Problems with pspp on fresh toolchain
From: |
John Darrington |
Subject: |
Re: Re: Problems with pspp on fresh toolchain |
Date: |
Mon, 16 Jan 2012 18:43:41 +0000 |
User-agent: |
Mutt/1.5.18 (2008-05-17) |
[ Adding address@hidden back ]
On Mon, Jan 16, 2012 at 07:21:45PM +0100, Harry Thijssen wrote:
Hi John
Took some time but I displayed the pointer and added more displays in
psppire_output_submit. See the ouput below. I attached the source so you
can see where the displays are placed.
It looks weired to me as if GTK_WINDOW has the problem.
I don't think so. You can leave that call out if you like - it'll generate a
warning - nothing more.
I think the problem is with gtk_window_set_urgency_hint. If you feel game, you
can go into the gtk source and carry on the hunt there.
Either way, I think this should be reported to the Gtk developers.
In the meantime, you can just comment out that line - it's just supposed to
make the output window's icon flash.
J'
See the ugly output
============
address@hidden:/usr/i686-w64-mingw32/sys-root/mingw/bin> wine psppire.exe
(psppire.exe:8): Pango-WARNING **: couldn't load font "MS Shell Dlg
Not-Rotated 8", falling back to "Sans Not-Rotated 8", expect ugly output.
(psppire.exe:8): Pango-WARNING **: couldn't load font "MS Shell Dlg 8",
falling back to "Sans 8", expect ugly output.
(psppire.exe:8): Pango-WARNING **: failed to choose a font, expect ugly
output. engine-type='PangoRenderWin32', script='common'
<1>
<1a>
b: PsppireOutputWindow
<2>
<3>
c: PsppireOutputWindow
d: PsppireOutputWindow
(psppire.exe:8): Pango-WARNING **: couldn't load font "MS Shell Dlg Italic
Not-Rotated 8", falling back to "Sans Italic Not-Rotated 8", expect ugly
output.
e: PsppireOutputWindow
f: PsppireOutputWindow
g: PsppireOutputWindow
h: PsppireOutputWindow
i: PsppireOutputWindow
fixme:win:FlashWindowEx 0xcfefdc
wine: Unhandled page fault on write access to 0x0000001c at address
0x1239590 (thread 0009), starting debugger...
Unhandled exception: page fault on write access to 0x0000001c in 32-bit
code (0x01239590).
Register dump:
CS:0073 SS:007b DS:007b ES:007b FS:0033 GS:003b
EIP:01239590 ESP:00cff004 EBP:00000001 EFLAGS:00010202( R- -- I - - -
)
EAX:00000001 EBX:011e12d8 ECX:00000000 EDX:00000000
ESI:00f01e5c EDI:00000000
Stack dump:
0x00cff004: 00000001 01239dd0 6c3685f5 00171038
0x00cff014: 010cc050 00000013 010e1528 011e11b8
0x00cff024: 010cc050 00cff088 00425b33 011e11b8
0x00cff034: 00000001 00000039 010dad58 00000001
0x00cff044: 010a1940 00000002 00000006 ffffffff
0x00cff054: 00cff2ac 00000006 004ed0e4 00000006
Backtrace:
0x01239590: addb %bh,0x1b(%eax)
Modules:
Module Address Debug info Name (126 modules)
PE 230000- 271000 Deferred libgdk_pixbuf-2.0-0
PE 400000- af7000 Deferred psppire
PE d00000- 109e000 Deferred libgtk-win32-2.0-0
PE 617c0000-6180d000 Deferred libjasper-1
PE 61cc0000-61ce2000 Deferred libintl-8
[...]
==============
2012/1/15 John Darrington <address@hidden>
> On Sun, Jan 15, 2012 at 01:41:59PM +0100, Harry Thijssen wrote:
> 2012/1/15 John Darrington <address@hidden>
>
> > My GTK2 version is 2.24.8-1.7
> >
> > Did your old tool chain use a different version?
> >
>
> Yes. It is really old. 2.20.1-5.3
> BTW with version between these 2 I had problems that the output was
not
> correctly displayed. Now it looks good when the problem line is
> removed.
>
>
>
> > I presume pod->viewer points to a valid GtkWindow. If it didn't
then
> > lots of other things would be going wrong.
> >
>
> How can I check this pointer?
>
> Try adding the line g_print ("%s\n", G_OBJECT_TYPE_NAME (pod->viewer));
>
> >
> > Make sure that everything else works ok.
> >
>
> Everything opening an output window crashes. So there is not much I
can
> use. With the latest replacement I could also use the other
> functionality.
>
> I meant when you remove this problem line, does everything else work ok?
>
>
> --
> PGP Public key ID: 1024D/2DE827B3
> fingerprint = 8797 A26D 0854 2EAB 0285 A290 8A67 719C 2DE8 27B3
> See http://keys.gnupg.net or any PGP keyserver for public key.
>
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.9 (GNU/Linux)
>
> iD8DBQFPEuFjimdxnC3oJ7MRAtvVAKCKE/IDJKtyfTrZop2h4c/8ax3lTgCeOa5A
> 5uBrlckTI9O+Fl99u4RPMLQ=
> =KOTU
> -----END PGP SIGNATURE-----
>
>
/* PSPPIRE - a graphical user interface for PSPP.
Copyright (C) 2008, 2009, 2010, 2011, 2012 Free Software Foundation
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <errno.h>
#include <gtk/gtk.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "libpspp/cast.h"
#include "libpspp/message.h"
#include "libpspp/string-map.h"
#include "output/cairo.h"
#include "output/chart-item.h"
#include "output/driver-provider.h"
#include "output/message-item.h"
#include "output/output-item.h"
#include "output/tab.h"
#include "output/table-item.h"
#include "output/text-item.h"
#include "ui/gui/help-menu.h"
#include "ui/gui/builder-wrapper.h"
#include "ui/gui/psppire-output-window.h"
#include "gl/error.h"
#include "gl/tmpdir.h"
#include "gl/xalloc.h"
#include "helper.h"
#include <gettext.h>
#define _(msgid) gettext (msgid)
#define N_(msgid) msgid
enum
{
COL_TITLE, /* Table title. */
COL_ADDR, /* Pointer to the table */
COL_Y, /* Y position of top of title. */
N_COLS
};
static void psppire_output_window_base_finalize (PsppireOutputWindowClass
*, gpointer);
static void psppire_output_window_base_init (PsppireOutputWindowClass
*class);
static void psppire_output_window_class_init (PsppireOutputWindowClass
*class);
static void psppire_output_window_init (PsppireOutputWindow
*window);
static void psppire_output_window_style_set (GtkWidget *window, GtkStyle
*prev);
GType
psppire_output_window_get_type (void)
{
static GType psppire_output_window_type = 0;
if (!psppire_output_window_type)
{
static const GTypeInfo psppire_output_window_info =
{
sizeof (PsppireOutputWindowClass),
(GBaseInitFunc) psppire_output_window_base_init,
(GBaseFinalizeFunc) psppire_output_window_base_finalize,
(GClassInitFunc)psppire_output_window_class_init,
(GClassFinalizeFunc) NULL,
NULL,
sizeof (PsppireOutputWindow),
0,
(GInstanceInitFunc) psppire_output_window_init,
};
psppire_output_window_type =
g_type_register_static (PSPPIRE_TYPE_WINDOW, "PsppireOutputWindow",
&psppire_output_window_info, 0);
}
return psppire_output_window_type;
}
static GObjectClass *parent_class;
static void
psppire_output_window_finalize (GObject *object)
{
string_map_destroy (&PSPPIRE_OUTPUT_WINDOW(object)->render_opts);
if (G_OBJECT_CLASS (parent_class)->finalize)
(*G_OBJECT_CLASS (parent_class)->finalize) (object);
}
static void
psppire_output_window_dispose (GObject *obj)
{
PsppireOutputWindow *viewer = PSPPIRE_OUTPUT_WINDOW (obj);
size_t i;
for (i = 0; i < viewer->n_items; i++)
output_item_unref (viewer->items[i]);
free (viewer->items);
viewer->items = NULL;
viewer->n_items = viewer->allocated_items = 0;
if (viewer->print_settings != NULL)
g_object_unref (viewer->print_settings);
/* Chain up to the parent class */
G_OBJECT_CLASS (parent_class)->dispose (obj);
}
static void
psppire_output_window_class_init (PsppireOutputWindowClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
parent_class = g_type_class_peek_parent (class);
object_class->dispose = psppire_output_window_dispose;
GTK_WIDGET_CLASS (object_class)->style_set =
psppire_output_window_style_set;
}
static void
psppire_output_window_base_init (PsppireOutputWindowClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
object_class->finalize = psppire_output_window_finalize;
}
static void
psppire_output_window_base_finalize (PsppireOutputWindowClass *class,
gpointer class_data)
{
}
/* Output driver class. */
struct psppire_output_driver
{
struct output_driver driver;
PsppireOutputWindow *viewer;
struct xr_driver *xr;
int font_height;
};
static struct output_driver_class psppire_output_class;
static struct psppire_output_driver *
psppire_output_cast (struct output_driver *driver)
{
assert (driver->class == &psppire_output_class);
return UP_CAST (driver, struct psppire_output_driver, driver);
}
static void on_dwgarea_realize (GtkWidget *widget, gpointer data);
static gboolean
expose_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer
data)
{
PsppireOutputWindow *viewer = PSPPIRE_OUTPUT_WINDOW (data);
struct xr_rendering *r = g_object_get_data (G_OBJECT (widget),
"rendering");
cairo_t *cr = gdk_cairo_create (widget->window);
const GtkStyle *style = gtk_widget_get_style (GTK_WIDGET (viewer));
PangoFontDescription *font_desc;
char *font_name;
gchar *fgc =
gdk_color_to_string (&style->text[gtk_widget_get_state (GTK_WIDGET
(widget))]);
string_map_replace (&viewer->render_opts, "foreground-color", fgc);
free (fgc);
/* Use GTK+ default font as proportional font. */
font_name = pango_font_description_to_string (style->font_desc);
string_map_replace (&viewer->render_opts, "prop-font", font_name);
g_free (font_name);
/* Derived emphasized font from proportional font. */
font_desc = pango_font_description_copy (style->font_desc);
pango_font_description_set_style (font_desc, PANGO_STYLE_ITALIC);
font_name = pango_font_description_to_string (font_desc);
string_map_replace (&viewer->render_opts, "emph-font", font_name);
g_free (font_name);
pango_font_description_free (font_desc);
xr_rendering_apply_options (r, &viewer->render_opts);
xr_rendering_draw (r, cr, event->area.x, event->area.y,
event->area.width, event->area.height);
cairo_destroy (cr);
return TRUE;
}
static void
psppire_output_submit (struct output_driver *this,
const struct output_item *item)
{
struct psppire_output_driver *pod = psppire_output_cast (this);
PsppireOutputWindow *viewer;
GtkWidget *drawing_area;
struct xr_rendering *r;
struct string title;
GtkTreeStore *store;
GtkTreePath *path;
GtkTreeIter iter;
cairo_t *cr;
int tw, th;
/* g_print ("a: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
*/
g_print ("<1>\n");
if (pod->viewer == NULL)
{
g_print ("<1a>\n");
pod->viewer = PSPPIRE_OUTPUT_WINDOW (psppire_output_window_new ());
gtk_widget_show_all (GTK_WIDGET (pod->viewer));
pod->viewer->driver = pod;
}
viewer = pod->viewer;
g_print ("b: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
g_print ("<2>\n");
if (viewer->n_items >= viewer->allocated_items)
viewer->items = x2nrealloc (viewer->items, &viewer->allocated_items,
sizeof *viewer->items);
viewer->items[viewer->n_items++] = output_item_ref (item);
g_print ("<3>\n");
if (is_text_item (item))
{
const struct text_item *text_item = to_text_item (item);
enum text_item_type type = text_item_get_type (text_item);
const char *text = text_item_get_text (text_item);
if (type == TEXT_ITEM_COMMAND_CLOSE)
{
viewer->in_command = false;
return;
}
else if (text[0] == '\0')
return;
}
g_print ("c: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
cr = gdk_cairo_create (GTK_WIDGET (pod->viewer)->window);
if (pod->xr == NULL)
{
const GtkStyle *style = gtk_widget_get_style (GTK_WIDGET (viewer));
struct text_item *text_item;
PangoFontDescription *font_desc;
char *font_name;
int font_width;
gchar *fgc = gdk_color_to_string (&style->text[gtk_widget_get_state
(GTK_WIDGET (viewer))]);
string_map_insert (&pod->viewer->render_opts, "foreground-color",
fgc);
g_free (fgc);
font_name = pango_font_description_to_string (style->font_desc);
string_map_insert (&pod->viewer->render_opts, "prop-font",
font_name);
g_free (font_name);
font_desc = pango_font_description_copy (style->font_desc);
pango_font_description_set_style (font_desc, PANGO_STYLE_ITALIC);
font_name = pango_font_description_to_string (font_desc);
string_map_insert (&pod->viewer->render_opts, "emph-font",
font_name);
g_free (font_name);
pango_font_description_free (font_desc);
string_map_insert (&pod->viewer->render_opts, "paper-size",
"300x200000mm");
string_map_insert (&pod->viewer->render_opts, "left-margin", "0");
string_map_insert (&pod->viewer->render_opts, "right-margin", "0");
string_map_insert (&pod->viewer->render_opts, "top-margin", "0");
string_map_insert (&pod->viewer->render_opts, "bottom-margin", "0");
g_print ("d: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
pod->xr = xr_driver_create (cr, &pod->viewer->render_opts);
text_item = text_item_create (TEXT_ITEM_PARAGRAPH, "X");
r = xr_rendering_create (pod->xr, text_item_super (text_item), cr);
xr_rendering_measure (r, &font_width, &pod->font_height);
text_item_unref (text_item);
}
else
g_print ("d: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
pod->viewer->y += pod->font_height / 2;
r = xr_rendering_create (pod->xr, item, cr);
g_print ("e: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
if (r == NULL)
goto done;
xr_rendering_measure (r, &tw, &th);
drawing_area = gtk_drawing_area_new ();
g_object_set_data (G_OBJECT (drawing_area), "rendering", r);
g_signal_connect (drawing_area, "realize",
G_CALLBACK (on_dwgarea_realize), pod->viewer);
g_signal_connect (drawing_area, "expose_event",
G_CALLBACK (expose_event_callback), pod->viewer);
gtk_widget_set_size_request (drawing_area, tw, th);
g_print ("f: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
gtk_layout_put (pod->viewer->output, drawing_area, 0, pod->viewer->y);
gtk_widget_show (drawing_area);
if (!is_text_item (item)
|| text_item_get_type (to_text_item (item)) != TEXT_ITEM_SYNTAX
|| !viewer->in_command)
{
store = GTK_TREE_STORE (gtk_tree_view_get_model (viewer->overview));
ds_init_empty (&title);
if (is_text_item (item)
&& text_item_get_type (to_text_item (item)) ==
TEXT_ITEM_COMMAND_OPEN)
{
gtk_tree_store_append (store, &iter, NULL);
viewer->cur_command = iter;
viewer->in_command = true;
}
else
{
GtkTreeIter *p = viewer->in_command ? &viewer->cur_command :
NULL;
gtk_tree_store_append (store, &iter, p);
}
ds_clear (&title);
if (is_text_item (item))
ds_put_cstr (&title, text_item_get_text (to_text_item (item)));
else if (is_message_item (item))
{
const struct message_item *msg_item = to_message_item (item);
const struct msg *msg = message_item_get_msg (msg_item);
ds_put_format (&title, "%s: %s", _("Message"),
msg_severity_to_string (msg->severity));
}
else if (is_table_item (item))
{
const char *caption = table_item_get_caption (to_table_item
(item));
if (caption != NULL)
ds_put_format (&title, "Table: %s", caption);
else
ds_put_cstr (&title, "Table");
}
else if (is_chart_item (item))
{
const char *s = chart_item_get_title (to_chart_item (item));
if (s != NULL)
ds_put_format (&title, "Chart: %s", s);
else
ds_put_cstr (&title, "Chart");
}
gtk_tree_store_set (store, &iter,
COL_TITLE, ds_cstr (&title),
COL_ADDR, item,
COL_Y, viewer->y,
-1);
ds_destroy (&title);
path = gtk_tree_model_get_path (GTK_TREE_MODEL (store), &iter);
gtk_tree_view_expand_row (viewer->overview, path, TRUE);
gtk_tree_path_free (path);
}
g_print ("g: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
if (pod->viewer->max_width < tw)
pod->viewer->max_width = tw;
pod->viewer->y += th;
g_print ("h: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
gtk_layout_set_size (pod->viewer->output,
pod->viewer->max_width, pod->viewer->y);
g_print ("i: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
gtk_window_set_urgency_hint (GTK_WINDOW (pod->viewer), TRUE);
g_print ("j: %s\n", G_OBJECT_TYPE_NAME (pod->viewer));
/*
gtk_window_set_urgency_hint (NULL, TRUE);
*/
done:
cairo_destroy (cr);
}
static struct output_driver_class psppire_output_class =
{
"PSPPIRE", /* name */
NULL, /* destroy */
psppire_output_submit, /* submit */
NULL, /* flush */
};
void
psppire_output_window_setup (void)
{
struct psppire_output_driver *pod;
struct output_driver *d;
pod = xzalloc (sizeof *pod);
d = &pod->driver;
output_driver_init (d, &psppire_output_class, "PSPPIRE",
SETTINGS_DEVICE_UNFILTERED);
output_driver_register (d);
}
/* Callback for the "delete" action (clicking the x on the top right
hand corner of the window) */
static gboolean
on_delete (GtkWidget *w, GdkEvent *event, gpointer user_data)
{
PsppireOutputWindow *ow = PSPPIRE_OUTPUT_WINDOW (user_data);
gtk_widget_destroy (GTK_WIDGET (ow));
ow->driver->viewer = NULL;
return FALSE;
}
static void
cancel_urgency (GtkWindow *window, gpointer data)
{
gtk_window_set_urgency_hint (window, FALSE);
}
static void
on_row_activate (GtkTreeView *overview,
GtkTreePath *path,
GtkTreeViewColumn *column,
PsppireOutputWindow *window)
{
GtkTreeModel *model;
GtkTreeIter iter;
GtkAdjustment *vadj;
GValue value = {0};
double y, min, max;
model = gtk_tree_view_get_model (overview);
if (!gtk_tree_model_get_iter (model, &iter, path))
return;
gtk_tree_model_get_value (model, &iter, COL_Y, &value);
y = g_value_get_long (&value);
g_value_unset (&value);
vadj = gtk_layout_get_vadjustment (window->output);
min = vadj->lower;
max = vadj->upper - vadj->page_size;
if (y < min)
y = min;
else if (y > max)
y = max;
gtk_adjustment_set_value (vadj, y);
}
static void psppire_output_window_print (PsppireOutputWindow *window);
static void
export_output (PsppireOutputWindow *window, struct string_map *options,
const char *format)
{
struct output_driver *driver;
size_t i;
string_map_insert (options, "format", format);
driver = output_driver_create (options);
if (driver == NULL)
return;
for (i = 0; i < window->n_items; i++)
driver->class->submit (driver, window->items[i]);
output_driver_destroy (driver);
}
struct file_types
{
const gchar *label;
const gchar *ext;
};
enum
{
FT_AUTO = 0,
FT_PDF,
FT_HTML,
FT_ODT,
FT_TXT,
FT_PS,
FT_CSV,
n_FT
};
#define N_EXTENSIONS (n_FT - 1)
struct file_types ft[n_FT] = {
{N_("Infer file type from extension"), NULL},
{N_("PDF (*.pdf)"), ".pdf"},
{N_("HTML (*.html)"), ".html"},
{N_("OpenDocument (*.odt)"), ".odt"},
{N_("Text (*.txt)"), ".txt"},
{N_("PostScript (*.ps)"), ".ps"},
{N_("Comma-Separated Values (*.csv)"), ".csv"}
};
static void
on_combo_change (GtkFileChooser *chooser)
{
gboolean sensitive = FALSE;
GtkWidget *combo = gtk_file_chooser_get_extra_widget (chooser);
int x = 0;
gchar *fn = gtk_file_chooser_get_filename (chooser);
if (combo && gtk_widget_get_realized (combo))
x = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
if (fn == NULL)
{
sensitive = FALSE;
}
else
{
gint i;
if ( x != 0 )
sensitive = TRUE;
for (i = 1 ; i < N_EXTENSIONS ; ++i)
{
if ( g_str_has_suffix (fn, ft[i].ext))
{
sensitive = TRUE;
break;
}
}
}
g_free (fn);
gtk_dialog_set_response_sensitive (GTK_DIALOG (chooser),
GTK_RESPONSE_ACCEPT, sensitive);
}
static void
on_file_chooser_change (GObject *w, GParamSpec *pspec, gpointer data)
{
GtkFileChooser *chooser = data;
const gchar *name = g_param_spec_get_name (pspec);
if ( ! gtk_widget_get_realized (GTK_WIDGET (chooser)))
return;
/* Ignore this one. It causes recursion. */
if ( 0 == strcmp ("tooltip-text", name))
return;
on_combo_change (chooser);
}
/* Recursively descend all the children of W, connecting
to their "notify" signal */
static void
iterate_widgets (GtkWidget *w, gpointer data)
{
if ( GTK_IS_CONTAINER (w))
gtk_container_forall (GTK_CONTAINER (w), iterate_widgets, data);
else
g_signal_connect (w, "notify", G_CALLBACK (on_file_chooser_change),
data);
}
static GtkListStore *
create_file_type_list (void)
{
int i;
GtkTreeIter iter;
GtkListStore *list = gtk_list_store_new (2, G_TYPE_STRING,
G_TYPE_STRING);
for (i = 0 ; i < n_FT ; ++i)
{
gtk_list_store_append (list, &iter);
gtk_list_store_set (list, &iter,
0, gettext (ft[i].label),
1, ft[i].ext,
-1);
}
return list;
}
static void
psppire_output_window_export (PsppireOutputWindow *window)
{
gint response;
GtkWidget *combo;
GtkListStore *list;
GtkFileChooser *chooser;
GtkWidget *dialog = gtk_file_chooser_dialog_new (_("Export Output"),
GTK_WINDOW (window),
GTK_FILE_CHOOSER_ACTION_SAVE,
GTK_STOCK_CANCEL,
GTK_RESPONSE_CANCEL,
GTK_STOCK_SAVE,
GTK_RESPONSE_ACCEPT,
NULL);
g_object_set (dialog, "local-only", FALSE, NULL);
chooser = GTK_FILE_CHOOSER (dialog);
list = create_file_type_list ();
combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (list));
{
/* Create text cell renderer */
GtkCellRenderer *cell = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), cell, FALSE );
gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (combo), cell, "text",
0);
}
g_signal_connect_swapped (combo, "changed", G_CALLBACK
(on_combo_change), chooser);
gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
gtk_file_chooser_set_extra_widget (chooser, combo);
/* This kludge is necessary because there is no signal to tell us
when the candidate filename of a GtkFileChooser has changed */
gtk_container_forall (GTK_CONTAINER (dialog), iterate_widgets, dialog);
gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE);
response = gtk_dialog_run (GTK_DIALOG (dialog));
if ( response == GTK_RESPONSE_ACCEPT )
{
int file_type = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
char *filename = gtk_file_chooser_get_filename (chooser);
struct string_map options;
g_return_if_fail (filename);
if (file_type == FT_AUTO)
{
gint i;
for (i = 1 ; i < N_EXTENSIONS ; ++i)
{
if ( g_str_has_suffix (filename, ft[i].ext))
{
file_type = i;
break;
}
}
}
string_map_init (&options);
string_map_insert (&options, "output-file", filename);
switch (file_type)
{
case FT_PDF:
export_output (window, &options, "pdf");
break;
case FT_HTML:
export_output (window, &options, "html");
break;
case FT_ODT:
export_output (window, &options, "odt");
break;
case FT_PS:
export_output (window, &options, "ps");
break;
case FT_CSV:
export_output (window, &options, "csv");
break;
case FT_TXT:
string_map_insert (&options, "headers", "false");
string_map_insert (&options, "paginate", "false");
string_map_insert (&options, "squeeze", "true");
string_map_insert (&options, "emphasis", "none");
string_map_insert (&options, "charts", "none");
string_map_insert (&options, "top-margin", "0");
string_map_insert (&options, "bottom-margin", "0");
export_output (window, &options, "txt");
break;
default:
g_assert_not_reached ();
}
string_map_destroy (&options);
free (filename);
}
gtk_widget_destroy (dialog);
}
enum {
SELECT_FMT_NULL,
SELECT_FMT_TEXT,
SELECT_FMT_UTF8,
SELECT_FMT_HTML,
SELECT_FMT_ODT
};
static void
clipboard_get_cb (GtkClipboard *clipboard,
GtkSelectionData *selection_data,
guint info,
gpointer data)
{
PsppireOutputWindow *window = data;
gsize length;
gchar *text = NULL;
struct output_driver *driver = NULL;
char dirname[PATH_MAX], *filename;
struct string_map options;
GtkTreeSelection *sel = gtk_tree_view_get_selection (window->overview);
GtkTreeModel *model = gtk_tree_view_get_model (window->overview);
GList *rows = gtk_tree_selection_get_selected_rows (sel, &model);
GList *n = rows;
if ( n == NULL)
return;
if (path_search (dirname, sizeof dirname, NULL, NULL, true)
|| mkdtemp (dirname) == NULL)
{
error (0, errno, _("failed to create temporary directory"));
return;
}
filename = xasprintf ("%s/clip.tmp", dirname);
string_map_init (&options);
string_map_insert (&options, "output-file", filename);
switch (info)
{
case SELECT_FMT_UTF8:
string_map_insert (&options, "box", "unicode");
/* fall-through */
case SELECT_FMT_TEXT:
string_map_insert (&options, "format", "txt");
break;
case SELECT_FMT_HTML:
string_map_insert (&options, "format", "html");
string_map_insert (&options, "borders", "false");
string_map_insert (&options, "css", "false");
break;
case SELECT_FMT_ODT:
string_map_insert (&options, "format", "odt");
break;
default:
g_warning ("unsupported clip target\n");
goto finish;
break;
}
driver = output_driver_create (&options);
if (driver == NULL)
goto finish;
while (n)
{
GtkTreePath *path = n->data ;
GtkTreeIter iter;
struct output_item *item ;
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get (model, &iter, COL_ADDR, &item, -1);
driver->class->submit (driver, item);
n = n->next;
}
if ( driver->class->flush)
driver->class->flush (driver);
/* Some drivers (eg: the odt one) don't write anything until they
are closed */
output_driver_destroy (driver);
driver = NULL;
if ( g_file_get_contents (filename, &text, &length, NULL) )
{
gtk_selection_data_set (selection_data, selection_data->target,
8,
(const guchar *) text, length);
}
finish:
if (driver != NULL)
output_driver_destroy (driver);
g_free (text);
unlink (filename);
free (filename);
rmdir (dirname);
g_list_free (rows);
}
static void
clipboard_clear_cb (GtkClipboard *clipboard,
gpointer data)
{
}
static const GtkTargetEntry targets[] = {
{ "STRING", 0, SELECT_FMT_TEXT },
{ "TEXT", 0, SELECT_FMT_TEXT },
{ "COMPOUND_TEXT", 0, SELECT_FMT_TEXT },
{ "text/plain", 0, SELECT_FMT_TEXT },
{ "UTF8_STRING", 0, SELECT_FMT_UTF8 },
{ "text/plain;charset=utf-8", 0, SELECT_FMT_UTF8 },
{ "text/html", 0, SELECT_FMT_HTML },
{ "application/vnd.oasis.opendocument.text", 0, SELECT_FMT_ODT }
};
static void
on_copy (PsppireOutputWindow *window)
{
{
GtkClipboard *clipboard =
gtk_widget_get_clipboard (GTK_WIDGET (window),
GDK_SELECTION_CLIPBOARD);
if (!gtk_clipboard_set_with_data (clipboard, targets,
G_N_ELEMENTS (targets),
clipboard_get_cb, clipboard_clear_cb,
window))
clipboard_clear_cb (clipboard, window);
}
}
static void
on_selection_change (GtkTreeSelection *sel, GtkAction *copy_action)
{
/* The Copy action is available only if there is something selected */
gtk_action_set_sensitive (copy_action,
gtk_tree_selection_count_selected_rows (sel) > 0);
}
static void
on_select_all (PsppireOutputWindow *window)
{
GtkTreeSelection *sel = gtk_tree_view_get_selection (window->overview);
gtk_tree_view_expand_all (window->overview);
gtk_tree_selection_select_all (sel);
}
static void
copy_base_to_bg (GtkWidget *dest, GtkWidget *src)
{
int i;
for (i = 0; i < 5; ++i)
{
GdkColor *col = >k_widget_get_style (src)->base[i];
gtk_widget_modify_bg (dest, i, col);
col = >k_widget_get_style (src)->text[i];
gtk_widget_modify_fg (dest, i, col);
}
}
static void
on_dwgarea_realize (GtkWidget *dwg_area, gpointer data)
{
GtkWidget *viewer = GTK_WIDGET (data);
copy_base_to_bg (dwg_area, viewer);
}
static void
psppire_output_window_style_set (GtkWidget *w, GtkStyle *prev)
{
GtkWidget *op = GTK_WIDGET (PSPPIRE_OUTPUT_WINDOW (w)->output);
/* Copy the base style from the parent widget to the container and
all its children.
We do this, because the container's primary purpose is to
display text. This way psppire appears to follow the chosen
gnome theme.
*/
copy_base_to_bg (op, w);
gtk_container_foreach (GTK_CONTAINER (op), (GtkCallback) copy_base_to_bg,
PSPPIRE_OUTPUT_WINDOW (w)->output);
/* Chain up to the parent class */
GTK_WIDGET_CLASS (parent_class)->style_set (w, prev);
}
static void
psppire_output_window_init (PsppireOutputWindow *window)
{
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
GtkBuilder *xml;
GtkAction *copy_action;
GtkAction *select_all_action;
GtkTreeSelection *sel;
string_map_init (&window->render_opts);
xml = builder_new ("output-viewer.ui");
copy_action = get_action_assert (xml, "edit_copy");
select_all_action = get_action_assert (xml, "edit_select-all");
gtk_action_set_sensitive (copy_action, FALSE);
g_signal_connect_swapped (copy_action, "activate", G_CALLBACK (on_copy),
window);
g_signal_connect_swapped (select_all_action, "activate", G_CALLBACK
(on_select_all), window);
gtk_widget_reparent (get_widget_assert (xml, "vbox1"), GTK_WIDGET
(window));
window->output = GTK_LAYOUT (get_widget_assert (xml, "output"));
window->y = 0;
window->overview = GTK_TREE_VIEW (get_widget_assert (xml, "overview"));
sel = gtk_tree_view_get_selection (window->overview);
gtk_tree_selection_set_mode (sel, GTK_SELECTION_MULTIPLE);
g_signal_connect (sel, "changed", G_CALLBACK (on_selection_change),
copy_action);
gtk_tree_view_set_model (window->overview,
GTK_TREE_MODEL (gtk_tree_store_new (
N_COLS,
G_TYPE_STRING, /* COL_TITLE
*/
G_TYPE_POINTER, /* COL_ADDR */
G_TYPE_LONG))); /* COL_Y */
window->in_command = false;
window->items = NULL;
window->n_items = window->allocated_items = 0;
column = gtk_tree_view_column_new ();
gtk_tree_view_append_column (GTK_TREE_VIEW (window->overview), column);
renderer = gtk_cell_renderer_text_new ();
gtk_tree_view_column_pack_start (column, renderer, TRUE);
gtk_tree_view_column_add_attribute (column, renderer, "text", COL_TITLE);
g_signal_connect (GTK_TREE_VIEW (window->overview),
"row-activated", G_CALLBACK (on_row_activate), window);
connect_help (xml);
g_signal_connect (window,
"focus-in-event",
G_CALLBACK (cancel_urgency),
NULL);
g_signal_connect (get_action_assert (xml,"windows_minimise-all"),
"activate",
G_CALLBACK (psppire_window_minimise_all),
NULL);
{
GtkUIManager *uim = GTK_UI_MANAGER (get_object_assert (xml,
"uimanager1", GTK_TYPE_UI_MANAGER));
merge_help_menu (uim);
PSPPIRE_WINDOW (window)->menu =
GTK_MENU_SHELL (gtk_ui_manager_get_widget
(uim,"/ui/menubar/windows_menuitem/windows_minimise-all")->parent);
}
g_signal_connect_swapped (get_action_assert (xml, "file_export"),
"activate",
G_CALLBACK (psppire_output_window_export),
window);
g_signal_connect_swapped (get_action_assert (xml, "file_print"),
"activate",
G_CALLBACK (psppire_output_window_print),
window);
g_object_unref (xml);
g_signal_connect (window, "delete-event",
G_CALLBACK (on_delete), window);
}
GtkWidget*
psppire_output_window_new (void)
{
return GTK_WIDGET (g_object_new (psppire_output_window_get_type (),
/* TRANSLATORS: This will form a filename.
Please avoid whitespace. */
"filename", _("Output"),
"description", _("Output Viewer"),
NULL));
}
static void
create_xr_print_driver (GtkPrintContext *context, PsppireOutputWindow
*window)
{
struct string_map options;
GtkPageSetup *page_setup;
double width, height;
double left_margin;
double right_margin;
double top_margin;
double bottom_margin;
page_setup = gtk_print_context_get_page_setup (context);
width = gtk_page_setup_get_paper_width (page_setup, GTK_UNIT_MM);
height = gtk_page_setup_get_paper_height (page_setup, GTK_UNIT_MM);
left_margin = gtk_page_setup_get_left_margin (page_setup, GTK_UNIT_MM);
right_margin = gtk_page_setup_get_right_margin (page_setup, GTK_UNIT_MM);
top_margin = gtk_page_setup_get_top_margin (page_setup, GTK_UNIT_MM);
bottom_margin = gtk_page_setup_get_bottom_margin (page_setup,
GTK_UNIT_MM);
string_map_init (&options);
string_map_insert_nocopy (&options, xstrdup ("paper-size"),
xasprintf("%.2fx%.2fmm", width, height));
string_map_insert_nocopy (&options, xstrdup ("left-margin"),
xasprintf ("%.2fmm", left_margin));
string_map_insert_nocopy (&options, xstrdup ("right-margin"),
xasprintf ("%.2fmm", right_margin));
string_map_insert_nocopy (&options, xstrdup ("top-margin"),
xasprintf ("%.2fmm", top_margin));
string_map_insert_nocopy (&options, xstrdup ("bottom-margin"),
xasprintf ("%.2fmm", bottom_margin));
window->print_xrd =
xr_driver_create (gtk_print_context_get_cairo_context (context),
&options);
string_map_destroy (&options);
}
static gboolean
paginate (GtkPrintOperation *operation,
GtkPrintContext *context,
PsppireOutputWindow *window)
{
if (window->paginated)
{
/* Sometimes GTK+ emits this signal again even after pagination is
complete. Don't let that screw up printing. */
return TRUE;
}
else if ( window->print_item < window->n_items )
{
xr_driver_output_item (window->print_xrd,
window->items[window->print_item++]);
while (xr_driver_need_new_page (window->print_xrd))
{
xr_driver_next_page (window->print_xrd, NULL);
window->print_n_pages ++;
}
return FALSE;
}
else
{
gtk_print_operation_set_n_pages (operation, window->print_n_pages);
/* Re-create the driver to do the real printing. */
xr_driver_destroy (window->print_xrd);
create_xr_print_driver (context, window);
window->print_item = 0;
window->paginated = TRUE;
return TRUE;
}
}
static void
begin_print (GtkPrintOperation *operation,
GtkPrintContext *context,
PsppireOutputWindow *window)
{
create_xr_print_driver (context, window);
window->print_item = 0;
window->print_n_pages = 1;
window->paginated = FALSE;
}
static void
end_print (GtkPrintOperation *operation,
GtkPrintContext *context,
PsppireOutputWindow *window)
{
xr_driver_destroy (window->print_xrd);
}
static void
draw_page (GtkPrintOperation *operation,
GtkPrintContext *context,
gint page_number,
PsppireOutputWindow *window)
{
xr_driver_next_page (window->print_xrd,
gtk_print_context_get_cairo_context (context));
while (!xr_driver_need_new_page (window->print_xrd)
&& window->print_item < window->n_items)
xr_driver_output_item (window->print_xrd, window->items
[window->print_item++]);
}
static void
psppire_output_window_print (PsppireOutputWindow *window)
{
GtkPrintOperationResult res;
GtkPrintOperation *print = gtk_print_operation_new ();
if (window->print_settings != NULL)
gtk_print_operation_set_print_settings (print, window->print_settings);
g_signal_connect (print, "begin_print", G_CALLBACK (begin_print),
window);
g_signal_connect (print, "end_print", G_CALLBACK (end_print),
window);
g_signal_connect (print, "paginate", G_CALLBACK (paginate),
window);
g_signal_connect (print, "draw_page", G_CALLBACK (draw_page),
window);
res = gtk_print_operation_run (print,
GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
GTK_WINDOW (window), NULL);
if (res == GTK_PRINT_OPERATION_RESULT_APPLY)
{
if (window->print_settings != NULL)
g_object_unref (window->print_settings);
window->print_settings = g_object_ref
(gtk_print_operation_get_print_settings (print));
}
g_object_unref (print);
}
--
PGP Public key ID: 1024D/2DE827B3
fingerprint = 8797 A26D 0854 2EAB 0285 A290 8A67 719C 2DE8 27B3
See http://keys.gnupg.net or any PGP keyserver for public key.
signature.asc
Description: Digital signature
- Re: Re: Problems with pspp on fresh toolchain, (continued)
- Re: Re: Problems with pspp on fresh toolchain, Harry Thijssen, 2012/01/14
- Re: Re: Problems with pspp on fresh toolchain, John Darrington, 2012/01/14
- Re: Re: Problems with pspp on fresh toolchain, Harry Thijssen, 2012/01/14
- Re: Re: Problems with pspp on fresh toolchain, John Darrington, 2012/01/15
- Re: Re: Problems with pspp on fresh toolchain, Harry Thijssen, 2012/01/15
- Re: Re: Problems with pspp on fresh toolchain, John Darrington, 2012/01/15
- Re: Re: Problems with pspp on fresh toolchain, Harry Thijssen, 2012/01/15
- Re: Re: Problems with pspp on fresh toolchain, John Darrington, 2012/01/15
- Re: Re: Problems with pspp on fresh toolchain, Harry Thijssen, 2012/01/15
- Re: Re: Problems with pspp on fresh toolchain, John Darrington, 2012/01/15
- Message not available
- Re: Re: Problems with pspp on fresh toolchain,
John Darrington <=
- Re: Re: Re: Problems with pspp on fresh toolchain, harry . thijssen, 2012/01/16