export.cpp revision 081a843d20a46d9526f6be83a913635cf5717188
0N/A/** @file
3261N/A * @brief PNG export dialog
0N/A */
0N/A/* Authors:
0N/A * Lauris Kaplinski <lauris@kaplinski.com>
0N/A * bulia byak <buliabyak@users.sf.net>
2362N/A * Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
0N/A *
2362N/A * Copyright (C) 1999-2007 Authors
0N/A * Copyright (C) 2001-2002 Ximian, Inc.
0N/A *
0N/A * Released under GNU GPL, read the file 'COPYING' for more information
0N/A */
0N/A
0N/A#ifdef HAVE_CONFIG_H
0N/A# include "config.h"
0N/A#endif
0N/A
0N/A// This has to be included prior to anything that includes setjmp.h, it croaks otherwise
0N/A#include <png.h>
2362N/A
2362N/A#include <gtk/gtk.h>
2362N/A#include <gtkmm/box.h>
0N/A#include <gtkmm/buttonbox.h>
0N/A#include <gtkmm/label.h>
0N/A#include <gtkmm/widget.h>
0N/A#include <gtkmm/togglebutton.h>
0N/A#include <gtkmm/entry.h>
0N/A#include <gtkmm/image.h>
0N/A#include <gtkmm/stockid.h>
0N/A#include <gtkmm/stock.h>
0N/A#ifdef WITH_GNOME_VFS
0N/A# include <libgnomevfs/gnome-vfs-init.h> // gnome_vfs_initialized
0N/A#endif
0N/A
0N/A#include <glibmm/i18n.h>
0N/A#include "helper/unit-menu.h"
0N/A#include "helper/units.h"
0N/A#include "unit-constants.h"
0N/A#include "helper/window.h"
0N/A#include "inkscape-private.h"
0N/A#include "document.h"
0N/A#include "desktop-handles.h"
0N/A#include "sp-item.h"
0N/A#include "selection.h"
0N/A#include "file.h"
0N/A#include "macros.h"
0N/A#include "sp-namedview.h"
0N/A#include "selection-chemistry.h"
0N/A
0N/A#include "dialog-events.h"
243N/A#include "preferences.h"
0N/A#include "verbs.h"
0N/A#include "interface.h"
0N/A
0N/A#include "extension/output.h"
0N/A#include "extension/db.h"
0N/A
0N/A#include "io/sys.h"
0N/A
0N/A#include "helper/png-write.h"
0N/A
0N/A#ifdef WIN32
0N/A#include <windows.h>
0N/A#include <COMMDLG.h>
0N/A#include <gdk/gdkwin32.h>
886N/A#endif
0N/A
0N/A#define SP_EXPORT_MIN_SIZE 1.0
886N/A
0N/A#define DPI_BASE PX_PER_IN
0N/A
0N/A#define EXPORT_COORD_PRECISION 3
0N/A
0N/A#define MIN_ONSCREEN_DISTANCE 50
1686N/A
1686N/Astatic void sp_export_area_toggled ( GtkToggleButton *tb, GtkObject *base );
1686N/Astatic void sp_export_export_clicked ( GtkButton *button, GtkObject *base );
0N/Astatic void sp_export_browse_clicked ( GtkButton *button, gpointer userdata );
0N/A
430N/Astatic void sp_export_area_x_value_changed ( GtkAdjustment *adj,
430N/A GtkObject *base);
430N/A
0N/Astatic void sp_export_area_y_value_changed ( GtkAdjustment *adj,
430N/A GtkObject *base);
1696N/A
0N/Astatic void sp_export_area_width_value_changed ( GtkAdjustment *adj,
0N/A GtkObject *base);
0N/A
0N/Astatic void sp_export_area_height_value_changed ( GtkAdjustment *adj,
0N/A GtkObject *base);
0N/A
0N/Astatic void sp_export_bitmap_width_value_changed ( GtkAdjustment *adj,
0N/A GtkObject *base);
0N/A
0N/Astatic void sp_export_bitmap_height_value_changed ( GtkAdjustment *adj,
1724N/A GtkObject *base);
1724N/A
1724N/Astatic void sp_export_xdpi_value_changed ( GtkAdjustment *adj,
1724N/A GtkObject *base);
1724N/A
1724N/Astatic void sp_export_selection_changed ( Inkscape::Application *inkscape,
1724N/A Inkscape::Selection *selection,
1724N/A GtkObject *base);
1724N/Astatic void sp_export_selection_modified ( Inkscape::Application *inkscape,
1724N/A Inkscape::Selection *selection,
1724N/A guint flags,
0N/A GtkObject *base );
0N/A
0N/Astatic void sp_export_set_area (GtkObject *base, double x0, double y0, double x1, double y1);
0N/Astatic void sp_export_value_set (GtkObject *base, const gchar *key, double val);
0N/Astatic void sp_export_value_set_px (GtkObject *base, const gchar *key, double val);
0N/Astatic float sp_export_value_get ( GtkObject *base, const gchar *key );
0N/Astatic float sp_export_value_get_px ( GtkObject *base, const gchar *key );
0N/A
0N/Astatic void sp_export_filename_modified (GtkObject * object, gpointer data);
0N/Astatic inline void sp_export_find_default_selection(GtkWidget * dlg);
0N/Astatic void sp_export_detect_size(GtkObject * base);
0N/A
0N/Astatic Glib::ustring const prefs_path = "/dialogs/export/";
0N/A
0N/A// these all need to be reinitialized to their defaults during dialog_destroy
0N/Astatic GtkWidget *dlg = NULL;
0N/Astatic win_data wd;
0N/Astatic gint x = -1000, y = -1000, w = 0, h = 0; // impossible original values to make sure they are read from prefs
0N/Astatic gchar * original_name = NULL;
0N/Astatic gchar * doc_export_name = NULL;
0N/Astatic bool was_empty = TRUE;
0N/A
0N/A/** What type of button is being pressed */
0N/Aenum selection_type {
0N/A SELECTION_PAGE = 0, /**< Export the whole page */
0N/A SELECTION_DRAWING, /**< Export everything drawn on the page */
0N/A SELECTION_SELECTION, /**< Export everything that is selected */
0N/A SELECTION_CUSTOM, /**< Allows the user to set the region exported */
0N/A SELECTION_NUMBER_OF /**< A counter for the number of these guys */
0N/A};
0N/A
0N/A/** A list of strings that is used both in the preferences, and in the
0N/A data fields to describe the various values of \c selection_type. */
0N/Astatic const char * selection_names[SELECTION_NUMBER_OF] = {
0N/A "page", "drawing", "selection", "custom"};
0N/A
0N/A/** The names on the buttons for the various selection types. */
0N/Astatic const char * selection_labels[SELECTION_NUMBER_OF] = {
0N/A N_("_Page"), N_("_Drawing"), N_("_Selection"), N_("_Custom")};
0N/A
0N/Astatic void
0N/Asp_export_dialog_destroy ( GtkObject */*object*/, gpointer /*data*/ )
0N/A{
0N/A sp_signal_disconnect_by_data (INKSCAPE, dlg);
0N/A
0N/A wd.win = dlg = NULL;
0N/A wd.stop = 0;
0N/A x = -1000; y = -1000; w = 0; h = 0;
0N/A g_free(original_name);
0N/A original_name = NULL;
0N/A g_free(doc_export_name);
0N/A doc_export_name = NULL;
0N/A was_empty = TRUE;
0N/A
0N/A return;
0N/A} // end of sp_export_dialog_destroy()
0N/A
0N/A/// Called when dialog is closed or inkscape is shut down.
0N/Astatic bool
0N/Asp_export_dialog_delete ( GtkObject */*object*/, GdkEvent */*event*/, gpointer /*data*/ )
0N/A{
0N/A
0N/A gtk_window_get_position ((GtkWindow *) dlg, &x, &y);
0N/A gtk_window_get_size ((GtkWindow *) dlg, &w, &h);
0N/A
0N/A if (x<0) x=0;
0N/A if (y<0) y=0;
0N/A
0N/A Inkscape::Preferences *prefs = Inkscape::Preferences::get();
0N/A prefs->setInt(prefs_path + "x", x);
0N/A prefs->setInt(prefs_path + "y", y);
0N/A prefs->setInt(prefs_path + "w", w);
0N/A prefs->setInt(prefs_path + "h", h);
0N/A
0N/A return FALSE; // which means, go ahead and destroy it
0N/A
0N/A} // end of sp_export_dialog_delete()
0N/A
0N/A/**
0N/A \brief Creates a new spin button for the export dialog
0N/A \param key The name of the spin button
0N/A \param val A default value for the spin button
0N/A \param min Minimum value for the spin button
1696N/A \param max Maximum value for the spin button
1696N/A \param step The step size for the spin button
1696N/A \param page Size of the page increment
1696N/A \param us Unit selector that effects this spin button
0N/A \param t Table to put the spin button in
0N/A \param x X location in the table \c t to start with
0N/A \param y Y location in the table \c t to start with
0N/A \param ll Text to put on the left side of the spin button (optional)
0N/A \param lr Text to put on the right side of the spin button (optional)
0N/A \param digits Number of digits to display after the decimal
0N/A \param sensitive Whether the spin button is sensitive or not
0N/A \param cb Callback for when this spin button is changed (optional)
0N/A \param dlg Export dialog the spin button is being placed in
0N/A
0N/A*/
0N/Astatic void
0N/Asp_export_spinbutton_new ( gchar const *key, float val, float min, float max,
0N/A float step, float page, GtkWidget *us,
0N/A GtkWidget *t, int x, int y,
0N/A const gchar *ll, const gchar *lr,
0N/A int digits, unsigned int sensitive,
0N/A GCallback cb, GtkWidget *dlg )
0N/A{
0N/A GtkObject *adj = gtk_adjustment_new( val, min, max, step, page, 0 );
0N/A gtk_object_set_data( adj, "key", const_cast<gchar *>(key) );
0N/A gtk_object_set_data( GTK_OBJECT (dlg), (const gchar *)key, adj );
0N/A
0N/A if (us) {
0N/A sp_unit_selector_add_adjustment ( SP_UNIT_SELECTOR (us),
0N/A GTK_ADJUSTMENT (adj) );
0N/A }
0N/A
0N/A int pos = 0;
0N/A
0N/A GtkWidget *l = NULL;
0N/A
0N/A if (ll) {
0N/A
0N/A l = gtk_label_new_with_mnemonic ((const gchar *)ll);
0N/A gtk_misc_set_alignment (GTK_MISC (l), 1.0, 0.5);
0N/A gtk_table_attach ( GTK_TABLE (t), l, x + pos, x + pos + 1, y, y + 1,
0N/A (GtkAttachOptions)0, (GtkAttachOptions)0, 0, 0 );
0N/A gtk_widget_set_sensitive (l, sensitive);
0N/A pos += 1;
0N/A
0N/A }
0N/A
0N/A GtkWidget *sb = gtk_spin_button_new (GTK_ADJUSTMENT (adj), 1.0, digits);
0N/A gtk_table_attach ( GTK_TABLE (t), sb, x + pos, x + pos + 1, y, y + 1,
0N/A (GtkAttachOptions)0, (GtkAttachOptions)0, 0, 0 );
0N/A gtk_widget_set_size_request (sb, 80, -1);
0N/A gtk_widget_set_sensitive (sb, sensitive);
0N/A pos += 1;
0N/A
0N/A if (ll) { gtk_label_set_mnemonic_widget (GTK_LABEL(l), sb); }
0N/A
0N/A if (lr) {
0N/A
0N/A l = gtk_label_new_with_mnemonic ((const gchar *)lr);
0N/A gtk_misc_set_alignment (GTK_MISC (l), 0.0, 0.5);
0N/A gtk_table_attach ( GTK_TABLE (t), l, x + pos, x + pos + 1, y, y + 1,
0N/A (GtkAttachOptions)0, (GtkAttachOptions)0, 0, 0 );
0N/A gtk_widget_set_sensitive (l, sensitive);
0N/A pos += 1;
0N/A
0N/A gtk_label_set_mnemonic_widget (GTK_LABEL(l), sb);
0N/A }
0N/A
0N/A if (cb)
0N/A gtk_signal_connect (adj, "value_changed", cb, dlg);
0N/A
0N/A return;
0N/A} // end of sp_export_spinbutton_new()
0N/A
0N/A
0N/Astatic Gtk::VBox *
0N/Asp_export_dialog_area_box (GtkWidget * dlg)
0N/A{
0N/A Gtk::VBox* vb = new Gtk::VBox(false, 3);
0N/A
0N/A Gtk::Label* lbl = new Gtk::Label(_("<big><b>Export area</b></big>"), Gtk::ALIGN_LEFT);
0N/A lbl->set_use_markup(true);
0N/A vb->pack_start(*lbl);
0N/A
0N/A /* Units box */
0N/A Gtk::HBox* unitbox = new Gtk::HBox(false, 0);
0N/A /* gets added to the vbox later, but the unit selector is needed
0N/A earlier than that */
0N/A
0N/A Gtk::Widget* us = Glib::wrap(sp_unit_selector_new (SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE));
0N/A SPDesktop *desktop = SP_ACTIVE_DESKTOP;
0N/A if (desktop)
0N/A sp_unit_selector_set_unit (SP_UNIT_SELECTOR(us->gobj()), sp_desktop_namedview(desktop)->doc_units);
0N/A unitbox->pack_end(*us, false, false, 0);
0N/A Gtk::Label* l = new Gtk::Label(_("Units:"));
0N/A unitbox->pack_end(*l, false, false, 3);
0N/A gtk_object_set_data (GTK_OBJECT (dlg), "units", us->gobj());
0N/A
0N/A Gtk::HBox* togglebox = new Gtk::HBox(true, 0);
0N/A
0N/A Gtk::ToggleButton* b;
0N/A for (int i = 0; i < SELECTION_NUMBER_OF; i++) {
0N/A b = new Gtk::ToggleButton(_(selection_labels[i]), true);
0N/A b->set_data("key", GINT_TO_POINTER(i));
0N/A gtk_object_set_data (GTK_OBJECT (dlg), selection_names[i], b->gobj());
0N/A togglebox->pack_start(*b, false, true, 0);
0N/A gtk_signal_connect ( GTK_OBJECT (b->gobj()), "clicked",
0N/A GTK_SIGNAL_FUNC (sp_export_area_toggled), dlg );
0N/A }
0N/A
0N/A g_signal_connect ( G_OBJECT (INKSCAPE), "change_selection",
0N/A G_CALLBACK (sp_export_selection_changed), dlg );
0N/A g_signal_connect ( G_OBJECT (INKSCAPE), "modify_selection",
0N/A G_CALLBACK (sp_export_selection_modified), dlg );
0N/A g_signal_connect ( G_OBJECT (INKSCAPE), "activate_desktop",
0N/A G_CALLBACK (sp_export_selection_changed), dlg );
0N/A
0N/A Gtk::Table* t = new Gtk::Table(2, 6, FALSE);
0N/A t->set_row_spacings (4);
0N/A t->set_col_spacings (4);
0N/A
0N/A sp_export_spinbutton_new ( "x0", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, us->gobj(),
0N/A GTK_WIDGET(t->gobj()), 0, 0, _("_x0:"), NULL, EXPORT_COORD_PRECISION, 1,
0N/A G_CALLBACK ( sp_export_area_x_value_changed),
0N/A dlg );
1053N/A
0N/A sp_export_spinbutton_new ( "x1", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, us->gobj(),
0N/A GTK_WIDGET(t->gobj()), 2, 0, _("x_1:"), NULL, EXPORT_COORD_PRECISION, 1,
0N/A G_CALLBACK (sp_export_area_x_value_changed),
0N/A dlg );
0N/A
0N/A sp_export_spinbutton_new ( "width", 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0,
0N/A us->gobj(), GTK_WIDGET(t->gobj()), 4, 0, _("Wid_th:"), NULL, EXPORT_COORD_PRECISION, 1,
0N/A G_CALLBACK
0N/A (sp_export_area_width_value_changed),
0N/A dlg );
0N/A
0N/A sp_export_spinbutton_new ( "y0", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, us->gobj(),
0N/A GTK_WIDGET(t->gobj()), 0, 1, _("_y0:"), NULL, EXPORT_COORD_PRECISION, 1,
0N/A G_CALLBACK (sp_export_area_y_value_changed),
0N/A dlg );
0N/A
0N/A sp_export_spinbutton_new ( "y1", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, us->gobj(),
0N/A GTK_WIDGET(t->gobj()), 2, 1, _("y_1:"), NULL, EXPORT_COORD_PRECISION, 1,
0N/A G_CALLBACK (sp_export_area_y_value_changed),
0N/A dlg );
0N/A
0N/A sp_export_spinbutton_new ( "height", 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0,
0N/A us->gobj(), GTK_WIDGET(t->gobj()), 4, 1, _("Hei_ght:"), NULL, EXPORT_COORD_PRECISION, 1,
0N/A G_CALLBACK (sp_export_area_height_value_changed),
0N/A dlg );
0N/A
0N/A vb->pack_start(*togglebox, false, false, 3);
0N/A vb->pack_start(*t, false, false, 0);
0N/A vb->pack_start(*unitbox, false, false, 0);
0N/A
0N/A return vb;
0N/A} // end of sp_export_dialog_area_box
0N/A
0N/A
0N/Agchar* create_filepath_from_id (const gchar *id, const gchar *file_entry_text) {
0N/A
0N/A if (id == NULL) /* This should never happen */
0N/A id = "bitmap";
0N/A
0N/A gchar * directory = NULL;
0N/A
0N/A if (directory == NULL && file_entry_text != NULL && file_entry_text[0] != '\0') {
0N/A // std::cout << "Directory from dialog" << std::endl;
0N/A directory = g_dirname(file_entry_text);
0N/A }
0N/A
0N/A if (directory == NULL) {
0N/A /* Grab document directory */
0N/A if (SP_DOCUMENT_URI(SP_ACTIVE_DOCUMENT)) {
0N/A // std::cout << "Directory from document" << std::endl;
0N/A directory = g_dirname(SP_DOCUMENT_URI(SP_ACTIVE_DOCUMENT));
555N/A }
0N/A }
0N/A
0N/A if (directory == NULL) {
0N/A // std::cout << "Home Directory" << std::endl;
0N/A directory = homedir_path(NULL);
0N/A }
0N/A
0N/A gchar * id_ext = g_strconcat(id, ".png", NULL);
0N/A gchar *filename = g_build_filename(directory, id_ext, NULL);
0N/A g_free(directory);
0N/A g_free(id_ext);
0N/A return filename;
0N/A}
0N/A
0N/Astatic void
0N/Abatch_export_clicked (GtkWidget *widget, GtkObject *base)
0N/A{
0N/A Gtk::Widget *vb_singleexport = (Gtk::Widget *)gtk_object_get_data(base, "vb_singleexport");
0N/A if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(widget))) {
0N/A vb_singleexport->set_sensitive(false);
0N/A } else {
0N/A vb_singleexport->set_sensitive(true);
0N/A }
0N/A}
0N/A
0N/Avoid
0N/Asp_export_dialog (void)
0N/A{
0N/A Inkscape::Preferences *prefs = Inkscape::Preferences::get();
0N/A if (!dlg) {
0N/A
0N/A gchar title[500];
0N/A sp_ui_dialog_title_string (Inkscape::Verb::get(SP_VERB_FILE_EXPORT), title);
0N/A
0N/A dlg = sp_window_new (title, TRUE);
0N/A
0N/A if (x == -1000 || y == -1000) {
0N/A x = prefs->getInt(prefs_path + "x", 0);
0N/A y = prefs->getInt(prefs_path + "y", 0);
0N/A }
0N/A
0N/A if (w ==0 || h == 0) {
0N/A w = prefs->getInt(prefs_path + "w", 0);
0N/A h = prefs->getInt(prefs_path + "h", 0);
0N/A }
0N/A
0N/A// if (x<0) x=0;
0N/A// if (y<0) y=0;
0N/A
0N/A if (w && h) gtk_window_resize ((GtkWindow *) dlg, w, h);
0N/A if (x >= 0 && y >= 0 && (x < (gdk_screen_width()-MIN_ONSCREEN_DISTANCE)) && (y < (gdk_screen_height()-MIN_ONSCREEN_DISTANCE)))
0N/A gtk_window_move ((GtkWindow *) dlg, x, y);
0N/A else
0N/A gtk_window_set_position(GTK_WINDOW(dlg), GTK_WIN_POS_CENTER);
0N/A sp_transientize (dlg);
0N/A wd.win = dlg;
0N/A wd.stop = 0;
0N/A
0N/A g_signal_connect ( G_OBJECT (INKSCAPE), "activate_desktop",
0N/A G_CALLBACK (sp_transientize_callback), &wd);
0N/A
0N/A gtk_signal_connect ( GTK_OBJECT (dlg), "event",
0N/A GTK_SIGNAL_FUNC (sp_dialog_event_handler), dlg);
0N/A
0N/A gtk_signal_connect ( GTK_OBJECT (dlg), "destroy",
0N/A G_CALLBACK (sp_export_dialog_destroy), dlg);
0N/A
0N/A gtk_signal_connect ( GTK_OBJECT (dlg), "delete_event",
0N/A G_CALLBACK (sp_export_dialog_delete), dlg);
0N/A
0N/A g_signal_connect ( G_OBJECT (INKSCAPE), "shut_down",
0N/A G_CALLBACK (sp_export_dialog_delete), dlg);
0N/A
0N/A g_signal_connect ( G_OBJECT (INKSCAPE), "dialogs_hide",
0N/A G_CALLBACK (sp_dialog_hide), dlg);
0N/A
0N/A g_signal_connect ( G_OBJECT (INKSCAPE), "dialogs_unhide",
0N/A G_CALLBACK (sp_dialog_unhide), dlg);
0N/A
0N/A GtkTooltips *tt = gtk_tooltips_new();
0N/A
0N/A Gtk::VBox *vb = new Gtk::VBox(false, 3);
0N/A vb->set_border_width(3);
0N/A gtk_container_add (GTK_CONTAINER (dlg), GTK_WIDGET(vb->gobj()));
0N/A
0N/A Gtk::VBox *vb_singleexport = new Gtk::VBox(false, 0);
0N/A vb_singleexport->set_border_width(0);
0N/A vb->pack_start(*vb_singleexport);
0N/A gtk_object_set_data(GTK_OBJECT(dlg), "vb_singleexport", vb_singleexport);
0N/A
0N/A /* Export area frame */
0N/A {
0N/A Gtk::VBox *area_box = sp_export_dialog_area_box(dlg);
0N/A area_box->set_border_width(3);
0N/A vb_singleexport->pack_start(*area_box, false, false, 0);
0N/A }
0N/A
0N/A /* Bitmap size frame */
0N/A {
0N/A Gtk::VBox *size_box = new Gtk::VBox(false, 3);
0N/A size_box->set_border_width(3);
0N/A
0N/A Gtk::Label* lbl = new Gtk::Label(_("<big><b>Bitmap size</b></big>"), Gtk::ALIGN_LEFT);
0N/A lbl->set_use_markup(true);
0N/A size_box->pack_start(*lbl, false, false, 0);
0N/A const int rows = 2;
0N/A const int cols = 5;
0N/A const bool homogeneous = false;
0N/A Gtk::Table *t = new Gtk::Table(rows, cols, homogeneous);
0N/A t->set_row_spacings (4);
0N/A t->set_col_spacings (4);
0N/A size_box->pack_start(*t);
0N/A
0N/A sp_export_spinbutton_new ( "bmwidth", 16.0, 1.0, 1000000.0, 1.0, 10.0,
0N/A NULL, GTK_WIDGET(t->gobj()), 0, 0,
0N/A _("_Width:"), _("pixels at"), 0, 1,
0N/A G_CALLBACK
0N/A (sp_export_bitmap_width_value_changed),
0N/A dlg );
0N/A
0N/A sp_export_spinbutton_new ( "xdpi",
0N/A prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE),
0N/A 0.01, 100000.0, 0.1, 1.0, NULL, GTK_WIDGET(t->gobj()), 3, 0,
0N/A NULL, _("dp_i"), 2, 1,
0N/A G_CALLBACK (sp_export_xdpi_value_changed),
0N/A dlg );
0N/A
0N/A sp_export_spinbutton_new ( "bmheight", 16.0, 1.0, 1000000.0, 1.0, 10.0,
0N/A NULL, GTK_WIDGET(t->gobj()), 0, 1,
0N/A _("_Height:"), _("pixels at"), 0, 1,
0N/A G_CALLBACK
0N/A (sp_export_bitmap_height_value_changed),
0N/A dlg );
0N/A
0N/A /** \todo
0N/A * Needs fixing: there's no way to set ydpi currently, so we use
0N/A * the defaultxdpi value here, too...
0N/A */
0N/A sp_export_spinbutton_new ( "ydpi", prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE),
0N/A 0.01, 100000.0, 0.1, 1.0, NULL, GTK_WIDGET(t->gobj()), 3, 1,
0N/A NULL, _("dpi"), 2, 0, NULL, dlg );
0N/A
0N/A vb_singleexport->pack_start(*size_box);
0N/A }
0N/A
0N/A /* File entry */
0N/A {
0N/A Gtk::VBox* file_box = new Gtk::VBox(false, 3);
0N/A file_box->set_border_width(3);
0N/A
0N/A // true = has mnemonic
0N/A Gtk::Label *flabel = new Gtk::Label(_("<big><b>_Filename</b></big>"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, true);
0N/A flabel->set_use_markup(true);
0N/A file_box->pack_start(*flabel, false, false, 0);
0N/A
0N/A Gtk::Entry *fe = new Gtk::Entry();
0N/A
0N/A /*
0N/A * set the default filename to be that of the current path + document
0N/A * with .png extension
0N/A *
0N/A * One thing to notice here is that this filename may get
0N/A * overwritten, but it won't happen here. The filename gets
0N/A * written into the text field, but then the button to select
0N/A * the area gets set. In that code the filename can be changed
0N/A * if there are some with presidence in the document. So, while
0N/A * this code sets the name first, it may not be the one users
0N/A * really see.
0N/A */
0N/A if (SP_ACTIVE_DOCUMENT && SP_DOCUMENT_URI (SP_ACTIVE_DOCUMENT))
0N/A {
0N/A gchar *name;
0N/A SPDocument * doc = SP_ACTIVE_DOCUMENT;
0N/A const gchar *uri = SP_DOCUMENT_URI (doc);
0N/A const gchar *text_extension = get_file_save_extension (Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS).c_str();
0N/A Inkscape::Extension::Output * oextension = NULL;
0N/A
0N/A if (text_extension != NULL) {
0N/A oextension = dynamic_cast<Inkscape::Extension::Output *>(Inkscape::Extension::db.get(text_extension));
0N/A }
0N/A
0N/A if (oextension != NULL) {
0N/A gchar * old_extension = oextension->get_extension();
0N/A if (g_str_has_suffix(uri, old_extension)) {
0N/A gchar * uri_copy;
0N/A gchar * extension_point;
0N/A gchar * final_name;
0N/A
0N/A uri_copy = g_strdup(uri);
0N/A extension_point = g_strrstr(uri_copy, old_extension);
0N/A extension_point[0] = '\0';
0N/A
0N/A final_name = g_strconcat(uri_copy, ".png", NULL);
0N/A fe->set_text(final_name);
0N/A
0N/A g_free(final_name);
0N/A g_free(uri_copy);
0N/A }
0N/A } else {
0N/A name = g_strconcat(uri, ".png", NULL);
0N/A fe->set_text(name);
0N/A g_free(name);
0N/A }
0N/A
0N/A doc_export_name = g_strdup(fe->get_text().c_str());
0N/A }
0N/A g_signal_connect ( G_OBJECT (fe->gobj()), "changed",
0N/A G_CALLBACK (sp_export_filename_modified), dlg);
0N/A
0N/A Gtk::HBox *hb = new Gtk::HBox(FALSE, 5);
0N/A
0N/A {
0N/A // true = has mnemonic
0N/A Gtk::Button *b = new Gtk::Button();
0N/A
0N/A Gtk::HBox* pixlabel = new Gtk::HBox(false, 3);
0N/A Gtk::Image *im = new Gtk::Image(Gtk::StockID(Gtk::Stock::INDEX),
0N/A Gtk::ICON_SIZE_BUTTON);
0N/A pixlabel->pack_start(*im);
0N/A
0N/A Gtk::Label *l = new Gtk::Label();
0N/A l->set_markup_with_mnemonic(_("_Browse..."));
0N/A pixlabel->pack_start(*l);
0N/A
0N/A b->add(*pixlabel);
0N/A
0N/A hb->pack_end (*b, false, false, 4);
0N/A g_signal_connect ( G_OBJECT (b->gobj()), "clicked",
0N/A G_CALLBACK (sp_export_browse_clicked), NULL );
0N/A }
0N/A
0N/A hb->pack_start (*fe, true, true, 0);
0N/A file_box->add(*hb);
0N/A gtk_object_set_data (GTK_OBJECT (dlg), "filename", fe->gobj());
0N/A gtk_object_set_data (GTK_OBJECT (dlg), "filename-modified", (gpointer)FALSE);
0N/A original_name = g_strdup(fe->get_text().c_str());
0N/A // pressing enter in the filename field is the same as clicking export:
0N/A g_signal_connect ( G_OBJECT (fe->gobj()), "activate",
0N/A G_CALLBACK (sp_export_export_clicked), dlg );
0N/A // focus is in the filename initially:
0N/A fe->grab_focus();
0N/A
0N/A // mnemonic in frame label moves focus to filename:
0N/A flabel->set_mnemonic_widget(*fe);
0N/A
0N/A vb_singleexport->pack_start(*file_box);
0N/A }
0N/A
0N/A {
0N/A Gtk::HBox* batch_box = new Gtk::HBox(FALSE, 5);
0N/A GtkWidget *be = gtk_check_button_new_with_label(_("Batch export all selected objects"));
0N/A gtk_widget_set_sensitive(GTK_WIDGET(be), TRUE);
0N/A gtk_object_set_data(GTK_OBJECT(dlg), "batch_checkbox", be);
0N/A batch_box->pack_start(*Glib::wrap(be), false, false);
0N/A gtk_tooltips_set_tip(tt, be, _("Export each selected object into its own PNG file, using export hints if any (caution, overwrites without asking!)"), NULL);
0N/A batch_box->show_all();
0N/A g_signal_connect(G_OBJECT(be), "toggled", GTK_SIGNAL_FUNC(batch_export_clicked), dlg);
0N/A vb->pack_start(*batch_box);
0N/A }
0N/A
0N/A {
0N/A Gtk::HBox* hide_box = new Gtk::HBox(FALSE, 5);
0N/A GtkWidget *he = gtk_check_button_new_with_label(_("Hide all except selected"));
0N/A gtk_widget_set_sensitive(GTK_WIDGET(he), TRUE);
0N/A gtk_object_set_data(GTK_OBJECT(dlg), "hide_checkbox", he);
0N/A hide_box->pack_start(*Glib::wrap(he), false, false);
0N/A gtk_tooltips_set_tip(tt, he, _("In the exported image, hide all objects except those that are selected"), NULL);
0N/A hide_box->show_all();
0N/A vb->pack_start(*hide_box);
0N/A }
0N/A
0N/A /* Buttons */
0N/A Gtk::HButtonBox* bb = new Gtk::HButtonBox(Gtk::BUTTONBOX_END);
0N/A bb->set_border_width(3);
0N/A
0N/A {
0N/A Gtk::Button *b = new Gtk::Button();
0N/A Gtk::HBox* image_label = new Gtk::HBox(false, 3);
0N/A Gtk::Image *im = new Gtk::Image(Gtk::StockID(Gtk::Stock::APPLY),
0N/A Gtk::ICON_SIZE_BUTTON);
0N/A image_label->pack_start(*im);
0N/A
0N/A Gtk::Label *l = new Gtk::Label();
0N/A l->set_markup_with_mnemonic(_("_Export"));
0N/A image_label->pack_start(*l);
0N/A
0N/A b->add(*image_label);
0N/A gtk_tooltips_set_tip (tt, GTK_WIDGET(b->gobj()), _("Export the bitmap file with these settings"), NULL);
541N/A gtk_signal_connect ( GTK_OBJECT (b->gobj()), "clicked",
541N/A GTK_SIGNAL_FUNC (sp_export_export_clicked), dlg );
541N/A bb->pack_end(*b, false, false, 0);
541N/A }
541N/A
541N/A vb->pack_end(*bb, false, false, 0);
541N/A vb->show_all();
541N/A
541N/A } // end of if (!dlg)
541N/A
541N/A sp_export_find_default_selection(dlg);
541N/A
541N/A gtk_window_present ((GtkWindow *) dlg);
541N/A
541N/A return;
100N/A} // end of sp_export_dialog()
100N/A
0N/Astatic void
0N/Asp_export_update_checkbuttons (GtkObject *base)
0N/A{
0N/A gint num = g_slist_length((GSList *) sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList());
0N/A GtkWidget *be = (GtkWidget *)gtk_object_get_data(base, "batch_checkbox");
0N/A GtkWidget *he = (GtkWidget *)gtk_object_get_data(base, "hide_checkbox");
0N/A if (num >= 2) {
0N/A gtk_widget_set_sensitive (be, true);
0N/A gtk_button_set_label (GTK_BUTTON(be), g_strdup_printf (ngettext("Batch export %d selected object","Batch export %d selected objects",num), num));
0N/A } else {
0N/A gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(be), FALSE);
0N/A gtk_widget_set_sensitive (be, FALSE);
0N/A }
0N/A if (num > 0) {
0N/A gtk_widget_set_sensitive (he, true);
0N/A } else {
0N/A gtk_widget_set_sensitive (he, false);
0N/A }
0N/A}
0N/A
0N/Astatic inline void
0N/Asp_export_find_default_selection(GtkWidget * dlg)
0N/A{
0N/A selection_type key = SELECTION_NUMBER_OF;
0N/A
0N/A if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) {
0N/A key = SELECTION_SELECTION;
0N/A }
0N/A
0N/A /* Try using the preferences */
0N/A if (key == SELECTION_NUMBER_OF) {
0N/A Inkscape::Preferences *prefs = Inkscape::Preferences::get();
0N/A int i = SELECTION_NUMBER_OF;
0N/A
0N/A Glib::ustring what = prefs->getString("/dialogs/export/exportarea/value");
0N/A
0N/A if (!what.empty()) {
0N/A for (i = 0; i < SELECTION_NUMBER_OF; i++) {
0N/A if (what == selection_names[i]) {
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A
0N/A key = (selection_type)i;
0N/A }
0N/A
0N/A if (key == SELECTION_NUMBER_OF) {
0N/A key = SELECTION_SELECTION;
0N/A }
0N/A
0N/A GtkWidget *button = (GtkWidget *)g_object_get_data(G_OBJECT(dlg),
0N/A selection_names[key]);
0N/A gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
0N/A
0N/A sp_export_update_checkbuttons (GTK_OBJECT(dlg));
0N/A}
0N/A
0N/A
0N/A/**
0N/A * \brief If selection changed or a different document activated, we must
0N/A * recalculate any chosen areas
0N/A *
0N/A */
0N/Astatic void
0N/Asp_export_selection_changed ( Inkscape::Application *inkscape,
0N/A Inkscape::Selection *selection,
0N/A GtkObject *base )
0N/A{
0N/A selection_type current_key;
0N/A current_key = (selection_type)(GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(base), "selection-type")));
0N/A
0N/A if ((current_key == SELECTION_DRAWING || current_key == SELECTION_PAGE) &&
0N/A (sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false &&
0N/A was_empty) {
0N/A gtk_toggle_button_set_active
0N/A ( GTK_TOGGLE_BUTTON ( gtk_object_get_data (base, selection_names[SELECTION_SELECTION])),
0N/A TRUE );
0N/A }
0N/A was_empty = (sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty();
0N/A
0N/A current_key = (selection_type)(GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(base), "selection-type")));
0N/A
0N/A if (inkscape &&
0N/A SP_IS_INKSCAPE (inkscape) &&
0N/A selection &&
0N/A SELECTION_CUSTOM != current_key) {
0N/A GtkToggleButton * button;
0N/A button = (GtkToggleButton *)gtk_object_get_data(base, selection_names[current_key]);
0N/A sp_export_area_toggled(button, base);
0N/A }
0N/A
0N/A sp_export_update_checkbuttons (base);
0N/A}
0N/A
0N/Astatic void
0N/Asp_export_selection_modified ( Inkscape::Application */*inkscape*/,
0N/A Inkscape::Selection */*selection*/,
0N/A guint /*flags*/,
0N/A GtkObject *base )
0N/A{
0N/A selection_type current_key;
886N/A current_key = (selection_type)(GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(base), "selection-type")));
886N/A
0N/A switch (current_key) {
0N/A case SELECTION_DRAWING:
0N/A if ( SP_ACTIVE_DESKTOP ) {
0N/A SPDocument *doc;
886N/A doc = sp_desktop_document (SP_ACTIVE_DESKTOP);
886N/A Geom::OptRect bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc)));
886N/A if (bbox) {
886N/A sp_export_set_area (base, bbox->min()[Geom::X],
886N/A bbox->min()[Geom::Y],
886N/A bbox->max()[Geom::X],
886N/A bbox->max()[Geom::Y]);
886N/A }
886N/A }
0N/A break;
0N/A case SELECTION_SELECTION:
0N/A if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) {
0N/A NRRect bbox;
0N/A (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds(&bbox);
0N/A sp_export_set_area (base, bbox.x0, bbox.y0, bbox.x1, bbox.y1);
0N/A }
0N/A break;
0N/A default:
0N/A /* Do nothing for page or for custom */
0N/A break;
0N/A }
0N/A
0N/A return;
0N/A}
0N/A
0N/A/// Called when one of the selection buttons was toggled.
0N/Astatic void
0N/Asp_export_area_toggled (GtkToggleButton *tb, GtkObject *base)
0N/A{
0N/A if (gtk_object_get_data (base, "update"))
0N/A return;
0N/A
0N/A selection_type key, old_key;
1045N/A key = (selection_type)(GPOINTER_TO_INT(gtk_object_get_data (GTK_OBJECT (tb), "key")));
1045N/A old_key = (selection_type)(GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(base), "selection-type")));
1045N/A
1045N/A /* Ignore all "turned off" events unless we're the only active button */
1045N/A if (!gtk_toggle_button_get_active (tb) ) {
1045N/A
1045N/A /* Don't let the current selection be deactived - but rerun the
886N/A activate to allow the user to renew the values */
886N/A if (key == old_key) {
1045N/A gtk_toggle_button_set_active ( tb, TRUE );
1045N/A }
1045N/A
1045N/A return;
1045N/A }
1045N/A
1045N/A /* Turn off the currently active button unless it's us */
1045N/A gtk_object_set_data(GTK_OBJECT(base), "selection-type", (gpointer)key);
1045N/A
886N/A if (old_key != key) {
886N/A gtk_toggle_button_set_active
886N/A ( GTK_TOGGLE_BUTTON ( gtk_object_get_data (base, selection_names[old_key])),
886N/A FALSE );
886N/A }
886N/A
886N/A if ( SP_ACTIVE_DESKTOP )
886N/A {
886N/A SPDocument *doc;
886N/A Geom::OptRect bbox;
886N/A doc = sp_desktop_document (SP_ACTIVE_DESKTOP);
886N/A
886N/A /* Notice how the switch is used to 'fall through' here to get
886N/A various backups. If you modify this without noticing you'll
886N/A probabaly screw something up. */
886N/A switch (key) {
886N/A case SELECTION_SELECTION:
886N/A if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false)
886N/A {
886N/A bbox = sp_desktop_selection (SP_ACTIVE_DESKTOP)->bounds();
886N/A /* Only if there is a selection that we can set
886N/A do we break, otherwise we fall through to the
886N/A drawing */
886N/A // std::cout << "Using selection: SELECTION" << std::endl;
886N/A key = SELECTION_SELECTION;
886N/A break;
886N/A }
886N/A case SELECTION_DRAWING:
1053N/A /** \todo
1053N/A * This returns wrong values if the document has a viewBox.
1053N/A */
1053N/A bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc)));
1053N/A /* If the drawing is valid, then we'll use it and break
1053N/A otherwise we drop through to the page settings */
1058N/A if (bbox) {
1058N/A // std::cout << "Using selection: DRAWING" << std::endl;
1058N/A key = SELECTION_DRAWING;
1058N/A break;
1058N/A }
1058N/A case SELECTION_PAGE:
1066N/A bbox = Geom::Rect(Geom::Point(0.0, 0.0),
1976N/A Geom::Point(sp_document_width(doc), sp_document_height(doc)));
1066N/A
1066N/A // std::cout << "Using selection: PAGE" << std::endl;
1338N/A key = SELECTION_PAGE;
1338N/A break;
1338N/A case SELECTION_CUSTOM:
1338N/A default:
1338N/A break;
1338N/A } // switch
1338N/A
1338N/A // remember area setting
1338N/A Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1338N/A prefs->setString("/dialogs/export/exportarea/value", selection_names[key]);
1338N/A
1976N/A if ( key != SELECTION_CUSTOM && bbox ) {
1976N/A sp_export_set_area (base, bbox->min()[Geom::X],
1976N/A bbox->min()[Geom::Y],
1976N/A bbox->max()[Geom::X],
1976N/A bbox->max()[Geom::Y]);
1976N/A }
1976N/A
1976N/A } // end of if ( SP_ACTIVE_DESKTOP )
1976N/A
1976N/A
1976N/A if (SP_ACTIVE_DESKTOP && !gtk_object_get_data(GTK_OBJECT(base), "filename-modified")) {
1976N/A GtkWidget * file_entry;
1976N/A const gchar * filename = NULL;
1976N/A float xdpi = 0.0, ydpi = 0.0;
1976N/A
1976N/A file_entry = (GtkWidget *)gtk_object_get_data (base, "filename");
1976N/A
1976N/A switch (key) {
1976N/A case SELECTION_PAGE:
1976N/A case SELECTION_DRAWING: {
1976N/A SPDocument * doc = SP_ACTIVE_DOCUMENT;
1976N/A sp_document_get_export_hints (doc, &filename, &xdpi, &ydpi);
1976N/A
1976N/A if (filename == NULL) {
1976N/A if (doc_export_name != NULL) {
1976N/A filename = g_strdup(doc_export_name);
1976N/A } else {
1976N/A filename = g_strdup("");
1976N/A }
1976N/A }
1976N/A break;
1976N/A }
1976N/A case SELECTION_SELECTION:
1976N/A if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) {
1976N/A
1976N/A sp_selection_get_export_hints (sp_desktop_selection(SP_ACTIVE_DESKTOP), &filename, &xdpi, &ydpi);
1976N/A
1976N/A /* If we still don't have a filename -- let's build
1976N/A one that's nice */
1976N/A if (filename == NULL) {
1976N/A const gchar * id = NULL;
1976N/A const GSList * reprlst = sp_desktop_selection(SP_ACTIVE_DESKTOP)->reprList();
1976N/A for(; reprlst != NULL; reprlst = reprlst->next) {
1976N/A Inkscape::XML::Node * repr = (Inkscape::XML::Node *)reprlst->data;
1976N/A if (repr->attribute("id")) {
1976N/A id = repr->attribute("id");
1976N/A break;
1976N/A }
1976N/A }
1976N/A
1976N/A filename = create_filepath_from_id (id, gtk_entry_get_text(GTK_ENTRY(file_entry)));
1976N/A }
1976N/A }
1976N/A break;
1976N/A case SELECTION_CUSTOM:
1976N/A default:
1976N/A break;
1976N/A }
1976N/A
1976N/A if (filename != NULL) {
1976N/A g_free(original_name);
1976N/A original_name = g_strdup(filename);
1976N/A gtk_entry_set_text(GTK_ENTRY(file_entry), filename);
1976N/A }
1976N/A
886N/A if (xdpi != 0.0) {
886N/A sp_export_value_set(base, "xdpi", xdpi);
886N/A }
0N/A
0N/A /* These can't be separate, and setting x sets y, so for
0N/A now setting this is disabled. Hopefully it won't be in
0N/A the future */
0N/A if (FALSE && ydpi != 0.0) {
0N/A sp_export_value_set(base, "ydpi", ydpi);
0N/A }
0N/A }
0N/A
0N/A return;
0N/A} // end of sp_export_area_toggled()
0N/A
0N/A/// Called when dialog is deleted
0N/Astatic gint
0N/Asp_export_progress_delete ( GtkWidget */*widget*/, GdkEvent */*event*/, GObject *base )
0N/A{
0N/A g_object_set_data (base, "cancel", (gpointer) 1);
0N/A return TRUE;
0N/A} // end of sp_export_progress_delete()
0N/A
0N/A/// Called when progress is cancelled
0N/Astatic void
0N/Asp_export_progress_cancel ( GtkWidget */*widget*/, GObject *base )
0N/A{
0N/A g_object_set_data (base, "cancel", (gpointer) 1);
0N/A} // end of sp_export_progress_cancel()
0N/A
0N/A/// Called for every progress iteration
0N/Astatic unsigned int
0N/Asp_export_progress_callback (float value, void *data)
0N/A{
0N/A GtkWidget *prg;
0N/A int evtcount;
541N/A
0N/A if (g_object_get_data ((GObject *) data, "cancel"))
0N/A return FALSE;
0N/A
0N/A prg = (GtkWidget *) g_object_get_data ((GObject *) data, "progress");
0N/A gtk_progress_bar_set_fraction ((GtkProgressBar *) prg, value);
0N/A
0N/A evtcount = 0;
0N/A while ((evtcount < 16) && gdk_events_pending ()) {
0N/A gtk_main_iteration_do (FALSE);
0N/A evtcount += 1;
0N/A }
0N/A
0N/A gtk_main_iteration_do (FALSE);
0N/A
0N/A return TRUE;
0N/A
541N/A} // end of sp_export_progress_callback()
0N/A
0N/AGtkWidget *
0N/Acreate_progress_dialog (GtkObject *base, gchar *progress_text) {
0N/A GtkWidget *dlg, *prg, *btn; /* progressbar-stuff */
0N/A
0N/A dlg = gtk_dialog_new ();
0N/A gtk_window_set_title (GTK_WINDOW (dlg), _("Export in progress"));
0N/A prg = gtk_progress_bar_new ();
0N/A sp_transientize (dlg);
0N/A gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE);
0N/A g_object_set_data ((GObject *) base, "progress", prg);
0N/A
0N/A gtk_progress_bar_set_text ((GtkProgressBar *) prg, progress_text);
0N/A
0N/A gtk_progress_bar_set_orientation ( (GtkProgressBar *) prg,
0N/A GTK_PROGRESS_LEFT_TO_RIGHT);
0N/A gtk_box_pack_start ((GtkBox *) ((GtkDialog *) dlg)->vbox,
0N/A prg, FALSE, FALSE, 4 );
0N/A btn = gtk_dialog_add_button ( GTK_DIALOG (dlg),
0N/A GTK_STOCK_CANCEL,
0N/A GTK_RESPONSE_CANCEL );
0N/A
0N/A g_signal_connect ( (GObject *) dlg, "delete_event",
0N/A (GCallback) sp_export_progress_delete, base);
0N/A g_signal_connect ( (GObject *) btn, "clicked",
0N/A (GCallback) sp_export_progress_cancel, base);
0N/A gtk_window_set_modal ((GtkWindow *) dlg, TRUE);
0N/A gtk_widget_show_all (dlg);
0N/A
0N/A return dlg;
0N/A}
0N/A
0N/A// FIXME: Some lib function should be available to do this ...
0N/Astatic gchar *
0N/Afilename_add_extension (const gchar *filename, const gchar *extension)
0N/A{
0N/A const gchar *dot;
0N/A
0N/A dot = strrchr (filename, '.');
0N/A if ( !dot )
0N/A return g_strconcat (filename, ".", extension, NULL);
0N/A {
0N/A if (dot[1] == '\0')
0N/A return g_strconcat (filename, extension, NULL);
0N/A else
0N/A {
0N/A if (g_strcasecmp (dot + 1, extension) == 0)
0N/A return g_strdup (filename);
0N/A else
0N/A {
0N/A return g_strconcat (filename, ".", extension, NULL);
0N/A }
0N/A }
0N/A }
0N/A}
0N/A
0N/A/// Called when export button is clicked
0N/Astatic void
0N/Asp_export_export_clicked (GtkButton */*button*/, GtkObject *base)
0N/A{
0N/A if (!SP_ACTIVE_DESKTOP) return;
0N/A
0N/A SPNamedView *nv = sp_desktop_namedview(SP_ACTIVE_DESKTOP);
0N/A
0N/A GtkWidget *be = (GtkWidget *)gtk_object_get_data(base, "batch_checkbox");
0N/A GtkWidget *he = (GtkWidget *)gtk_object_get_data(base, "hide_checkbox");
0N/A bool hide = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (he));
0N/A if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (be))) {
0N/A // Batch export of selected objects
0N/A
0N/A gint num = g_slist_length((GSList *) sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList());
0N/A gint n = 0;
0N/A
0N/A if (num < 1)
0N/A return;
0N/A
0N/A gchar *progress_text = g_strdup_printf (_("Exporting %d files"), num);
0N/A GtkWidget *prog_dlg = create_progress_dialog (base, progress_text);
0N/A g_free (progress_text);
0N/A
0N/A for (GSList *i = (GSList *) sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList();
0N/A i != NULL;
0N/A i = i->next) {
0N/A SPItem *item = (SPItem *) i->data;
0N/A // retrieve export filename hint
0N/A const gchar *fn = SP_OBJECT_REPR(item)->attribute("inkscape:export-filename");
0N/A if (!fn) {
0N/A fn = create_filepath_from_id (SP_OBJECT_ID(item), NULL);
0N/A }
0N/A
0N/A // retrieve export dpi hints
0N/A const gchar *dpi_hint = SP_OBJECT_REPR(item)->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now
0N/A gdouble dpi = 0.0;
0N/A if (dpi_hint) {
0N/A dpi = atof(dpi_hint);
0N/A }
0N/A if (dpi == 0.0) {
0N/A dpi = DPI_BASE;
0N/A }
0N/A
0N/A Geom::OptRect area;
0N/A sp_item_invoke_bbox(item, area, sp_item_i2d_affine((SPItem *) item), TRUE);
0N/A if (area) {
0N/A gint width = (gint) (area->width() * dpi / PX_PER_IN + 0.5);
0N/A gint height = (gint) (area->height() * dpi / PX_PER_IN + 0.5);
0N/A
0N/A if (width > 1 && height > 1) {
0N/A /* Do export */
0N/A if (!sp_export_png_file (sp_desktop_document (SP_ACTIVE_DESKTOP), fn,
0N/A *area, width, height, dpi, dpi,
0N/A nv->pagecolor,
0N/A NULL, NULL, TRUE, // overwrite without asking
0N/A hide ? (GSList *) sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList() : NULL
1053N/A )) {
0N/A gchar * error;
0N/A gchar * safeFile = Inkscape::IO::sanitizeString(fn);
0N/A error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile);
0N/A sp_ui_error_dialog(error);
1053N/A g_free(safeFile);
1053N/A g_free(error);
1053N/A }
1053N/A }
0N/A }
1219N/A n++;
1219N/A sp_export_progress_callback((float)n/num, base);
1219N/A }
1219N/A
1219N/A gtk_widget_destroy (prog_dlg);
1219N/A g_object_set_data (G_OBJECT (base), "cancel", (gpointer) 0);
1219N/A
1219N/A } else {
1219N/A
1219N/A GtkWidget *fe = (GtkWidget *)gtk_object_get_data(base, "filename");
1219N/A gchar const *filename = gtk_entry_get_text(GTK_ENTRY(fe));
1219N/A
1219N/A float const x0 = sp_export_value_get_px(base, "x0");
1219N/A float const y0 = sp_export_value_get_px(base, "y0");
1219N/A float const x1 = sp_export_value_get_px(base, "x1");
1219N/A float const y1 = sp_export_value_get_px(base, "y1");
1219N/A float const xdpi = sp_export_value_get(base, "xdpi");
0N/A float const ydpi = sp_export_value_get(base, "ydpi");
0N/A unsigned long int const width = int(sp_export_value_get(base, "bmwidth") + 0.5);
0N/A unsigned long int const height = int(sp_export_value_get(base, "bmheight") + 0.5);
0N/A
0N/A if (filename == NULL || *filename == '\0') {
0N/A sp_ui_error_dialog(_("You have to enter a filename"));
0N/A return;
0N/A }
0N/A
0N/A if (!((x1 > x0) && (y1 > y0) && (width > 0) && (height > 0))) {
0N/A sp_ui_error_dialog (_("The chosen area to be exported is invalid"));
0N/A return;
0N/A }
0N/A
0N/A gchar *dirname = g_path_get_dirname(filename);
0N/A if ( dirname == NULL
0N/A || !Inkscape::IO::file_test(dirname, (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) )
212N/A {
0N/A gchar *safeDir = Inkscape::IO::sanitizeString(dirname);
0N/A gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"),
0N/A safeDir);
0N/A sp_ui_error_dialog(error);
0N/A g_free(safeDir);
0N/A g_free(error);
0N/A g_free(dirname);
0N/A return;
0N/A }
0N/A g_free(dirname);
0N/A
0N/A // make sure that .png is the extension of the file:
0N/A gchar * filename_ext = filename_add_extension(filename, "png");
0N/A gtk_entry_set_text(GTK_ENTRY(fe), filename_ext);
0N/A
0N/A gchar *fn = g_path_get_basename (filename_ext);
0N/A
0N/A gchar *progress_text = g_strdup_printf (_("Exporting %s (%lu x %lu)"), fn, width, height);
0N/A g_free (fn);
0N/A GtkWidget *prog_dlg = create_progress_dialog (base, progress_text);
0N/A g_free (progress_text);
0N/A
0N/A /* Do export */
0N/A if (!sp_export_png_file (sp_desktop_document (SP_ACTIVE_DESKTOP), filename_ext,
0N/A Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)), width, height, xdpi, ydpi,
0N/A nv->pagecolor,
0N/A sp_export_progress_callback, base, FALSE,
0N/A hide ? (GSList *) sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList() : NULL
0N/A )) {
0N/A gchar * error;
0N/A gchar * safeFile = Inkscape::IO::sanitizeString(filename);
0N/A error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile);
0N/A sp_ui_error_dialog(error);
0N/A g_free(safeFile);
0N/A g_free(error);
0N/A }
0N/A
0N/A /* Reset the filename so that it can be changed again by changing
0N/A selections and all that */
0N/A g_free(original_name);
0N/A original_name = g_strdup(filename_ext);
0N/A gtk_object_set_data (GTK_OBJECT (base), "filename-modified", (gpointer)FALSE);
0N/A
0N/A gtk_widget_destroy (prog_dlg);
0N/A g_object_set_data (G_OBJECT (base), "cancel", (gpointer) 0);
0N/A
0N/A /* Setup the values in the document */
0N/A switch ((selection_type)(GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(base), "selection-type")))) {
0N/A case SELECTION_PAGE:
0N/A case SELECTION_DRAWING: {
0N/A SPDocument * doc = SP_ACTIVE_DOCUMENT;
0N/A Inkscape::XML::Node * repr = sp_document_repr_root(doc);
0N/A bool modified = false;
0N/A const gchar * temp_string;
0N/A
0N/A bool saved = sp_document_get_undo_sensitive(doc);
0N/A sp_document_set_undo_sensitive(doc, false);
0N/A
0N/A temp_string = repr->attribute("inkscape:export-filename");
0N/A if (temp_string == NULL || strcmp(temp_string, filename_ext)) {
0N/A repr->setAttribute("inkscape:export-filename", filename_ext);
0N/A modified = true;
0N/A }
0N/A temp_string = repr->attribute("inkscape:export-xdpi");
0N/A if (temp_string == NULL || xdpi != atof(temp_string)) {
0N/A sp_repr_set_svg_double(repr, "inkscape:export-xdpi", xdpi);
0N/A modified = true;
0N/A }
0N/A temp_string = repr->attribute("inkscape:export-ydpi");
0N/A if (temp_string == NULL || xdpi != atof(temp_string)) {
0N/A sp_repr_set_svg_double(repr, "inkscape:export-ydpi", ydpi);
0N/A modified = true;
0N/A }
0N/A sp_document_set_undo_sensitive(doc, saved);
0N/A
0N/A if (modified) {
0N/A doc->setModifiedSinceSave();
0N/A }
0N/A break;
0N/A }
0N/A case SELECTION_SELECTION: {
0N/A const GSList * reprlst;
0N/A SPDocument * doc = SP_ACTIVE_DOCUMENT;
0N/A bool modified = false;
0N/A
0N/A bool saved = sp_document_get_undo_sensitive(doc);
0N/A sp_document_set_undo_sensitive(doc, false);
0N/A reprlst = sp_desktop_selection(SP_ACTIVE_DESKTOP)->reprList();
0N/A
0N/A for(; reprlst != NULL; reprlst = reprlst->next) {
0N/A Inkscape::XML::Node * repr = (Inkscape::XML::Node *)reprlst->data;
0N/A const gchar * temp_string;
0N/A
0N/A if (repr->attribute("id") == NULL ||
0N/A !(g_strrstr(filename_ext, repr->attribute("id")) != NULL &&
0N/A (!SP_DOCUMENT_URI(SP_ACTIVE_DOCUMENT) ||
243N/A strcmp(g_dirname(filename), g_dirname(SP_DOCUMENT_URI(SP_ACTIVE_DOCUMENT))) == 0))) {
0N/A temp_string = repr->attribute("inkscape:export-filename");
0N/A if (temp_string == NULL || strcmp(temp_string, filename_ext)) {
0N/A repr->setAttribute("inkscape:export-filename", filename_ext);
0N/A modified = true;
0N/A }
0N/A }
0N/A temp_string = repr->attribute("inkscape:export-xdpi");
0N/A if (temp_string == NULL || xdpi != atof(temp_string)) {
0N/A sp_repr_set_svg_double(repr, "inkscape:export-xdpi", xdpi);
0N/A modified = true;
0N/A }
0N/A temp_string = repr->attribute("inkscape:export-ydpi");
0N/A if (temp_string == NULL || xdpi != atof(temp_string)) {
0N/A sp_repr_set_svg_double(repr, "inkscape:export-ydpi", ydpi);
0N/A modified = true;
0N/A }
0N/A }
0N/A sp_document_set_undo_sensitive(doc, saved);
0N/A
0N/A if (modified) {
0N/A doc->setModifiedSinceSave();
0N/A }
0N/A break;
0N/A }
0N/A default:
0N/A break;
0N/A }
0N/A
0N/A g_free (filename_ext);
0N/A
0N/A }
0N/A
0N/A} // end of sp_export_export_clicked()
0N/A
0N/A/// Called when Browse button is clicked
0N/A/// @todo refactor this code to use ui/dialogs/filedialog.cpp
0N/Astatic void
0N/Asp_export_browse_clicked (GtkButton */*button*/, gpointer /*userdata*/)
0N/A{
0N/A GtkWidget *fs, *fe;
0N/A const gchar *filename;
0N/A
0N/A fs = gtk_file_chooser_dialog_new (_("Select a filename for exporting"),
0N/A (GtkWindow*)dlg,
0N/A GTK_FILE_CHOOSER_ACTION_SAVE,
0N/A GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
0N/A GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
0N/A NULL );
0N/A
0N/A#ifdef WITH_GNOME_VFS
0N/A if (gnome_vfs_initialized()) {
0N/A gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(fs), false);
0N/A }
0N/A#endif
0N/A
0N/A fe = (GtkWidget *)g_object_get_data (G_OBJECT (dlg), "filename");
0N/A
0N/A sp_transientize (fs);
0N/A
0N/A gtk_window_set_modal(GTK_WINDOW (fs), true);
0N/A
0N/A filename = gtk_entry_get_text (GTK_ENTRY (fe));
0N/A
0N/A if (*filename == '\0') {
0N/A filename = create_filepath_from_id(NULL, NULL);
0N/A }
0N/A
0N/A gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (fs), filename);
0N/A
0N/A#ifdef WIN32
0N/A // code in this section is borrowed from ui/dialogs/filedialogimpl-win32.cpp
0N/A OPENFILENAMEW opf;
0N/A WCHAR* filter_string = (WCHAR*)g_utf8_to_utf16("PNG\0*.png\0\0", 12, NULL, NULL, NULL);
0N/A WCHAR* title_string = (WCHAR*)g_utf8_to_utf16(_("Select a filename for exporting"), -1, NULL, NULL, NULL);
0N/A WCHAR* extension_string = (WCHAR*)g_utf8_to_utf16("*.png", -1, NULL, NULL, NULL);
0N/A // Copy the selected file name, converting from UTF-8 to UTF-16
0N/A WCHAR _filename[_MAX_PATH + 1];
0N/A memset(_filename, 0, sizeof(_filename));
0N/A gunichar2* utf16_path_string = g_utf8_to_utf16(filename, -1, NULL, NULL, NULL);
0N/A wcsncpy(_filename, (wchar_t*)utf16_path_string, _MAX_PATH);
0N/A g_free(utf16_path_string);
0N/A
0N/A opf.hwndOwner = (HWND)(GDK_WINDOW_HWND(GTK_WIDGET(dlg)->window));
0N/A opf.lpstrFilter = filter_string;
0N/A opf.lpstrCustomFilter = 0;
0N/A opf.nMaxCustFilter = 0L;
0N/A opf.nFilterIndex = 1L;
0N/A opf.lpstrFile = _filename;
0N/A opf.nMaxFile = _MAX_PATH;
0N/A opf.lpstrFileTitle = NULL;
0N/A opf.nMaxFileTitle=0;
0N/A opf.lpstrInitialDir = 0;
0N/A opf.lpstrTitle = title_string;
0N/A opf.nFileOffset = 0;
0N/A opf.nFileExtension = 2;
0N/A opf.lpstrDefExt = extension_string;
0N/A opf.lpfnHook = NULL;
0N/A opf.lCustData = 0;
0N/A opf.Flags = OFN_PATHMUSTEXIST;
0N/A opf.lStructSize = sizeof(OPENFILENAMEW);
0N/A if (GetSaveFileNameW(&opf) != 0)
0N/A {
0N/A // Copy the selected file name, converting from UTF-16 to UTF-8
0N/A gchar *utf8string = g_utf16_to_utf8((const gunichar2*)opf.lpstrFile, _MAX_PATH, NULL, NULL, NULL);
0N/A gtk_entry_set_text (GTK_ENTRY (fe), utf8string);
0N/A g_object_set_data (G_OBJECT (dlg), "filename", fe);
0N/A g_free(utf8string);
0N/A
0N/A }
0N/A g_free(extension_string);
0N/A g_free(title_string);
0N/A g_free(filter_string);
0N/A#else
0N/A if (gtk_dialog_run (GTK_DIALOG (fs)) == GTK_RESPONSE_ACCEPT)
0N/A {
0N/A gchar *file;
0N/A
0N/A file = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (fs));
0N/A
0N/A gchar * utf8file = g_filename_to_utf8( file, -1, NULL, NULL, NULL );
0N/A gtk_entry_set_text (GTK_ENTRY (fe), utf8file);
0N/A
0N/A g_object_set_data (G_OBJECT (dlg), "filename", fe);
0N/A
0N/A g_free(utf8file);
0N/A g_free(file);
0N/A }
0N/A#endif
0N/A
0N/A gtk_widget_destroy (fs);
0N/A
0N/A return;
0N/A} // end of sp_export_browse_clicked()
0N/A
0N/A// TODO: Move this to nr-rect-fns.h.
0N/Astatic bool
0N/Asp_export_bbox_equal(Geom::Rect const &one, Geom::Rect const &two)
0N/A{
0N/A double const epsilon = pow(10.0, -EXPORT_COORD_PRECISION);
0N/A return (
0N/A (fabs(one.min()[Geom::X] - two.min()[Geom::X]) < epsilon) &&
0N/A (fabs(one.min()[Geom::Y] - two.min()[Geom::Y]) < epsilon) &&
0N/A (fabs(one.max()[Geom::X] - two.max()[Geom::X]) < epsilon) &&
0N/A (fabs(one.max()[Geom::Y] - two.max()[Geom::Y]) < epsilon)
0N/A );
0N/A}
0N/A
0N/A/**
0N/A \brief This function is used to detect the current selection setting
0N/A based on the values in the x0, y0, x1 and y0 fields.
0N/A \param base The export dialog itself
0N/A
0N/A One of the most confusing parts of this function is why the array
0N/A is built at the beginning. What needs to happen here is that we
0N/A should always check the current selection to see if it is the valid
0N/A one. While this is a performance improvement it is also a usability
0N/A one during the cases where things like selections and drawings match
0N/A size. This way buttons change less 'randomly' (atleast in the eyes
0N/A of the user). To do this an array is built where the current selection
0N/A type is placed first, and then the others in an order from smallest
0N/A to largest (this can be configured by reshuffling \c test_order).
0N/A
0N/A All of the values in this function are rounded to two decimal places
0N/A because that is what is shown to the user. While everything is kept
0N/A more accurate than that, the user can't control more acurrate than
0N/A that, so for this to work for them - it needs to check on that level
0N/A of accuracy.
0N/A
0N/A \todo finish writing this up
0N/A*/
0N/Astatic void
0N/Asp_export_detect_size(GtkObject * base) {
0N/A static const selection_type test_order[SELECTION_NUMBER_OF] = {SELECTION_SELECTION, SELECTION_DRAWING, SELECTION_PAGE, SELECTION_CUSTOM};
0N/A selection_type this_test[SELECTION_NUMBER_OF + 1];
0N/A selection_type key = SELECTION_NUMBER_OF;
0N/A
0N/A Geom::Point x(sp_export_value_get_px (base, "x0"),
0N/A sp_export_value_get_px (base, "y0"));
0N/A Geom::Point y(sp_export_value_get_px (base, "x1"),
0N/A sp_export_value_get_px (base, "y1"));
0N/A Geom::Rect current_bbox(x, y);
0N/A //std::cout << "Current " << current_bbox;
0N/A
0N/A this_test[0] = (selection_type)(GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(base), "selection-type")));
0N/A for (int i = 0; i < SELECTION_NUMBER_OF; i++) {
0N/A this_test[i + 1] = test_order[i];
0N/A }
0N/A
872N/A for (int i = 0;
0N/A i < SELECTION_NUMBER_OF + 1 &&
0N/A key == SELECTION_NUMBER_OF &&
0N/A SP_ACTIVE_DESKTOP != NULL;
0N/A i++) {
0N/A // std::cout << "Looking at: " << selection_names[this_test[i]] << std::endl;
0N/A switch (this_test[i]) {
0N/A case SELECTION_SELECTION:
0N/A if ((sp_desktop_selection(SP_ACTIVE_DESKTOP))->isEmpty() == false) {
0N/A Geom::OptRect bbox = (sp_desktop_selection (SP_ACTIVE_DESKTOP))->bounds();
0N/A
0N/A //std::cout << "Selection " << bbox;
0N/A if ( bbox && sp_export_bbox_equal(*bbox,current_bbox)) {
0N/A key = SELECTION_SELECTION;
0N/A }
0N/A }
0N/A break;
0N/A case SELECTION_DRAWING: {
0N/A SPDocument *doc = sp_desktop_document (SP_ACTIVE_DESKTOP);
0N/A
0N/A Geom::OptRect bbox = sp_item_bbox_desktop (SP_ITEM (SP_DOCUMENT_ROOT (doc)));
0N/A
0N/A // std::cout << "Drawing " << bbox2;
0N/A if ( bbox && sp_export_bbox_equal(*bbox,current_bbox) ) {
0N/A key = SELECTION_DRAWING;
0N/A }
0N/A break;
0N/A }
0N/A
0N/A case SELECTION_PAGE: {
0N/A SPDocument *doc;
0N/A
0N/A doc = sp_desktop_document (SP_ACTIVE_DESKTOP);
0N/A
0N/A Geom::Point x(0.0, 0.0);
0N/A Geom::Point y(sp_document_width(doc),
0N/A sp_document_height(doc));
218N/A Geom::Rect bbox(x, y);
218N/A
218N/A // std::cout << "Page " << bbox;
218N/A if (sp_export_bbox_equal(bbox,current_bbox)) {
0N/A key = SELECTION_PAGE;
0N/A }
0N/A
0N/A break;
218N/A }
0N/A default:
0N/A break;
0N/A }
872N/A }
0N/A // std::cout << std::endl;
0N/A
0N/A if (key == SELECTION_NUMBER_OF) {
0N/A key = SELECTION_CUSTOM;
0N/A }
0N/A
0N/A /* We're now using a custom size, not a fixed one */
0N/A /* printf("Detecting state: %s\n", selection_names[key]); */
0N/A selection_type old = (selection_type)(GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(base), "selection-type")));
0N/A gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(gtk_object_get_data(base, selection_names[old])), FALSE);
0N/A gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(gtk_object_get_data(base, selection_names[key])), TRUE);
0N/A gtk_object_set_data(GTK_OBJECT(base), "selection-type", (gpointer)key);
0N/A
0N/A return;
0N/A} /* sp_export_detect_size */
0N/A
0N/A/// Called when area x0 value is changed
0N/Astatic void
0N/Asp_export_area_x_value_changed (GtkAdjustment *adj, GtkObject *base)
0N/A{
0N/A float x0, x1, xdpi, width;
0N/A
0N/A if (gtk_object_get_data (base, "update"))
0N/A return;
0N/A
0N/A if (sp_unit_selector_update_test ((SPUnitSelector *)gtk_object_get_data
0N/A (base, "units")))
0N/A {
0N/A return;
0N/A }
0N/A
0N/A gtk_object_set_data ( base, "update", GUINT_TO_POINTER (TRUE) );
0N/A
0N/A x0 = sp_export_value_get_px (base, "x0");
0N/A x1 = sp_export_value_get_px (base, "x1");
0N/A xdpi = sp_export_value_get (base, "xdpi");
0N/A
0N/A width = floor ((x1 - x0) * xdpi / DPI_BASE + 0.5);
0N/A
0N/A if (width < SP_EXPORT_MIN_SIZE) {
0N/A const gchar *key;
0N/A width = SP_EXPORT_MIN_SIZE;
0N/A key = (const gchar *)gtk_object_get_data (GTK_OBJECT (adj), "key");
0N/A
0N/A if (!strcmp (key, "x0")) {
0N/A x1 = x0 + width * DPI_BASE / xdpi;
0N/A sp_export_value_set_px (base, "x1", x1);
0N/A } else {
0N/A x0 = x1 - width * DPI_BASE / xdpi;
0N/A sp_export_value_set_px (base, "x0", x0);
0N/A }
0N/A }
0N/A
0N/A sp_export_value_set_px (base, "width", x1 - x0);
0N/A sp_export_value_set (base, "bmwidth", width);
0N/A
0N/A sp_export_detect_size(base);
0N/A
0N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (FALSE));
0N/A
0N/A return;
0N/A} // end of sp_export_area_x_value_changed()
0N/A
0N/A/// Called when area y0 value is changed.
0N/Astatic void
0N/Asp_export_area_y_value_changed (GtkAdjustment *adj, GtkObject *base)
0N/A{
0N/A float y0, y1, ydpi, height;
0N/A
0N/A if (gtk_object_get_data (base, "update"))
1724N/A return;
1724N/A
1724N/A if (sp_unit_selector_update_test ((SPUnitSelector *)gtk_object_get_data
1724N/A (base, "units")))
0N/A {
0N/A return;
0N/A }
1724N/A
0N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (TRUE));
0N/A
0N/A y0 = sp_export_value_get_px (base, "y0");
0N/A y1 = sp_export_value_get_px (base, "y1");
0N/A ydpi = sp_export_value_get (base, "ydpi");
0N/A
0N/A height = floor ((y1 - y0) * ydpi / DPI_BASE + 0.5);
0N/A
0N/A if (height < SP_EXPORT_MIN_SIZE) {
0N/A const gchar *key;
0N/A height = SP_EXPORT_MIN_SIZE;
0N/A key = (const gchar *)gtk_object_get_data (GTK_OBJECT (adj), "key");
0N/A if (!strcmp (key, "y0")) {
0N/A y1 = y0 + height * DPI_BASE / ydpi;
0N/A sp_export_value_set_px (base, "y1", y1);
0N/A } else {
0N/A y0 = y1 - height * DPI_BASE / ydpi;
0N/A sp_export_value_set_px (base, "y0", y0);
872N/A }
0N/A }
0N/A
0N/A sp_export_value_set_px (base, "height", y1 - y0);
0N/A sp_export_value_set (base, "bmheight", height);
0N/A
0N/A sp_export_detect_size(base);
0N/A
0N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (FALSE));
0N/A
0N/A return;
0N/A} // end of sp_export_area_y_value_changed()
0N/A
0N/A/// Called when x1-x0 or area width is changed
0N/Astatic void
0N/Asp_export_area_width_value_changed (GtkAdjustment */*adj*/, GtkObject *base)
0N/A{
0N/A float x0, x1, xdpi, width, bmwidth;
0N/A
0N/A if (gtk_object_get_data (base, "update"))
0N/A return;
0N/A
0N/A if (sp_unit_selector_update_test ((SPUnitSelector *)gtk_object_get_data
0N/A (base, "units"))) {
0N/A return;
0N/A }
0N/A
0N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (TRUE));
0N/A
0N/A x0 = sp_export_value_get_px (base, "x0");
0N/A x1 = sp_export_value_get_px (base, "x1");
0N/A xdpi = sp_export_value_get (base, "xdpi");
0N/A width = sp_export_value_get_px (base, "width");
0N/A bmwidth = floor (width * xdpi / DPI_BASE + 0.5);
0N/A
0N/A if (bmwidth < SP_EXPORT_MIN_SIZE) {
0N/A
0N/A bmwidth = SP_EXPORT_MIN_SIZE;
0N/A width = bmwidth * DPI_BASE / xdpi;
0N/A sp_export_value_set_px (base, "width", width);
0N/A }
0N/A
0N/A sp_export_value_set_px (base, "x1", x0 + width);
0N/A sp_export_value_set (base, "bmwidth", bmwidth);
0N/A
0N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (FALSE));
0N/A
0N/A return;
0N/A} // end of sp_export_area_width_value_changed()
0N/A
0N/A/// Called when y1-y0 or area height is changed.
0N/Astatic void
0N/Asp_export_area_height_value_changed (GtkAdjustment */*adj*/, GtkObject *base)
0N/A{
0N/A
0N/A float y0, y1, ydpi, height, bmheight;
0N/A
0N/A if (gtk_object_get_data (base, "update"))
0N/A return;
0N/A
0N/A if (sp_unit_selector_update_test ((SPUnitSelector *)gtk_object_get_data
0N/A (base, "units"))) {
0N/A return;
0N/A }
0N/A
218N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (TRUE));
218N/A
0N/A y0 = sp_export_value_get_px (base, "y0");
0N/A y1 = sp_export_value_get_px (base, "y1");
0N/A ydpi = sp_export_value_get (base, "ydpi");
872N/A height = sp_export_value_get_px (base, "height");
0N/A bmheight = floor (height * ydpi / DPI_BASE + 0.5);
0N/A
0N/A if (bmheight < SP_EXPORT_MIN_SIZE) {
0N/A bmheight = SP_EXPORT_MIN_SIZE;
0N/A height = bmheight * DPI_BASE / ydpi;
0N/A sp_export_value_set_px (base, "height", height);
0N/A }
0N/A
0N/A sp_export_value_set_px (base, "y1", y0 + height);
0N/A sp_export_value_set (base, "bmheight", bmheight);
0N/A
0N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (FALSE));
0N/A
0N/A return;
0N/A} // end of sp_export_area_height_value_changed()
0N/A
0N/A/**
0N/A \brief A function to set the ydpi
0N/A \param base The export dialog
0N/A
0N/A This function grabs all of the y values and then figures out the
0N/A new bitmap size based on the changing dpi value. The dpi value is
0N/A gotten from the xdpi setting as these can not currently be independent.
0N/A*/
0N/Astatic void
0N/Asp_export_set_image_y (GtkObject *base)
0N/A{
0N/A float y0, y1, xdpi;
0N/A
0N/A y0 = sp_export_value_get_px (base, "y0");
0N/A y1 = sp_export_value_get_px (base, "y1");
0N/A xdpi = sp_export_value_get (base, "xdpi");
0N/A
0N/A sp_export_value_set (base, "ydpi", xdpi);
243N/A sp_export_value_set (base, "bmheight", (y1 - y0) * xdpi / DPI_BASE);
0N/A
0N/A return;
0N/A} // end of sp_export_set_image_y()
0N/A
0N/A/**
0N/A \brief A function to set the xdpi
0N/A \param base The export dialog
0N/A
0N/A This function grabs all of the x values and then figures out the
0N/A new bitmap size based on the changing dpi value. The dpi value is
0N/A gotten from the xdpi setting as these can not currently be independent.
0N/A*/
0N/Astatic void
0N/Asp_export_set_image_x (GtkObject *base)
0N/A{
0N/A float x0, x1, xdpi;
0N/A
0N/A x0 = sp_export_value_get_px (base, "x0");
0N/A x1 = sp_export_value_get_px (base, "x1");
0N/A xdpi = sp_export_value_get (base, "xdpi");
0N/A
0N/A sp_export_value_set (base, "ydpi", xdpi);
0N/A sp_export_value_set (base, "bmwidth", (x1 - x0) * xdpi / DPI_BASE);
0N/A
0N/A return;
0N/A} // end of sp_export_set_image_x()
0N/A
0N/A/// Called when pixel width is changed
0N/Astatic void
0N/Asp_export_bitmap_width_value_changed (GtkAdjustment */*adj*/, GtkObject *base)
0N/A{
0N/A float x0, x1, bmwidth, xdpi;
0N/A
0N/A if (gtk_object_get_data (base, "update"))
0N/A return;
0N/A
0N/A if (sp_unit_selector_update_test ((SPUnitSelector *)gtk_object_get_data
0N/A (base, "units"))) {
0N/A return;
0N/A }
0N/A
0N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (TRUE));
0N/A
0N/A x0 = sp_export_value_get_px (base, "x0");
0N/A x1 = sp_export_value_get_px (base, "x1");
0N/A bmwidth = sp_export_value_get (base, "bmwidth");
0N/A
0N/A if (bmwidth < SP_EXPORT_MIN_SIZE) {
0N/A bmwidth = SP_EXPORT_MIN_SIZE;
0N/A sp_export_value_set (base, "bmwidth", bmwidth);
0N/A }
0N/A
0N/A xdpi = bmwidth * DPI_BASE / (x1 - x0);
0N/A sp_export_value_set (base, "xdpi", xdpi);
243N/A
0N/A sp_export_set_image_y (base);
0N/A
0N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (FALSE));
0N/A
0N/A return;
0N/A} // end of sp_export_bitmap_width_value_changed()
0N/A
0N/A/// Called when pixel height is changed
0N/Astatic void
0N/Asp_export_bitmap_height_value_changed (GtkAdjustment */*adj*/, GtkObject *base)
0N/A{
0N/A float y0, y1, bmheight, xdpi;
0N/A
0N/A if (gtk_object_get_data (base, "update"))
0N/A return;
0N/A
0N/A if (sp_unit_selector_update_test ((SPUnitSelector *)gtk_object_get_data
0N/A (base, "units"))) {
0N/A return;
0N/A }
0N/A
0N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (TRUE));
0N/A
0N/A y0 = sp_export_value_get_px (base, "y0");
0N/A y1 = sp_export_value_get_px (base, "y1");
0N/A bmheight = sp_export_value_get (base, "bmheight");
0N/A
0N/A if (bmheight < SP_EXPORT_MIN_SIZE) {
0N/A bmheight = SP_EXPORT_MIN_SIZE;
0N/A sp_export_value_set (base, "bmheight", bmheight);
0N/A }
0N/A
0N/A xdpi = bmheight * DPI_BASE / (y1 - y0);
0N/A sp_export_value_set (base, "xdpi", xdpi);
0N/A
0N/A sp_export_set_image_x (base);
0N/A
0N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (FALSE));
0N/A
0N/A return;
0N/A} // end of sp_export_bitmap_width_value_changed()
0N/A
0N/A/**
0N/A \brief A function to adjust the bitmap width when the xdpi value changes
0N/A \param adj The adjustment that was changed
0N/A \param base The export dialog itself
0N/A
0N/A The first thing this function checks is to see if we are doing an
0N/A update. If we are, this function just returns because there is another
0N/A instance of it that will handle everything for us. If there is a
0N/A units change, we also assume that everyone is being updated appropriately
0N/A and there is nothing for us to do.
0N/A
0N/A If we're the highest level function, we set the update flag, and
0N/A continue on our way.
0N/A
0N/A All of the values are grabbed using the \c sp_export_value_get functions
0N/A (call to the _pt ones for x0 and x1 but just standard for xdpi). The
0N/A xdpi value is saved in the preferences for the next time the dialog
243N/A is opened. (does the selection dpi need to be set here?)
0N/A
0N/A A check is done to to ensure that we aren't outputing an invalid width,
0N/A this is set by SP_EXPORT_MIN_SIZE. If that is the case the dpi is
0N/A changed to make it valid.
0N/A
0N/A After all of this the bitmap width is changed.
0N/A
0N/A We also change the ydpi. This is a temporary hack as these can not
0N/A currently be independent. This is likely to change in the future.
0N/A*/
0N/Avoid
0N/Asp_export_xdpi_value_changed (GtkAdjustment */*adj*/, GtkObject *base)
0N/A{
0N/A float x0, x1, xdpi, bmwidth;
0N/A
0N/A if (gtk_object_get_data (base, "update"))
0N/A return;
0N/A
0N/A if (sp_unit_selector_update_test ((SPUnitSelector *)gtk_object_get_data
1724N/A (base, "units"))) {
1724N/A return;
1724N/A }
1724N/A
0N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (TRUE));
0N/A
0N/A x0 = sp_export_value_get_px (base, "x0");
0N/A x1 = sp_export_value_get_px (base, "x1");
1724N/A xdpi = sp_export_value_get (base, "xdpi");
0N/A
0N/A // remember xdpi setting
0N/A Inkscape::Preferences *prefs = Inkscape::Preferences::get();
0N/A prefs->setDouble("/dialogs/export/defaultxdpi/value", xdpi);
0N/A
0N/A bmwidth = (x1 - x0) * xdpi / DPI_BASE;
0N/A
0N/A if (bmwidth < SP_EXPORT_MIN_SIZE) {
0N/A bmwidth = SP_EXPORT_MIN_SIZE;
0N/A if (x1 != x0)
0N/A xdpi = bmwidth * DPI_BASE / (x1 - x0);
0N/A else
0N/A xdpi = DPI_BASE;
0N/A sp_export_value_set (base, "xdpi", xdpi);
0N/A }
0N/A
0N/A sp_export_value_set (base, "bmwidth", bmwidth);
0N/A
0N/A sp_export_set_image_y (base);
0N/A
0N/A gtk_object_set_data (base, "update", GUINT_TO_POINTER (FALSE));
0N/A
0N/A return;
0N/A} // end of sp_export_xdpi_value_changed()
0N/A
0N/A
0N/A/**
555N/A \brief A function to change the area that is used for the exported
0N/A bitmap.
555N/A \param base This is the export dialog
0N/A \param x0 Horizontal upper left hand corner of the picture in points
0N/A \param y0 Vertical upper left hand corner of the picture in points
0N/A \param x1 Horizontal lower right hand corner of the picture in points
0N/A \param y1 Vertical lower right hand corner of the picture in points
0N/A
0N/A This function just calls \c sp_export_value_set_px for each of the
0N/A parameters that is passed in. This allows for setting them all in
0N/A one convient area.
0N/A
0N/A Update is set to suspend all of the other test running while all the
0N/A values are being set up. This allows for a performance increase, but
0N/A it also means that the wrong type won't be detected with only some of
0N/A the values set. After all the values are set everyone is told that
0N/A there has been an update.
0N/A*/
0N/Astatic void
0N/Asp_export_set_area ( GtkObject *base, double x0, double y0, double x1, double y1 )
0N/A{
0N/A gtk_object_set_data ( base, "update", GUINT_TO_POINTER (TRUE) );
0N/A sp_export_value_set_px (base, "x1", x1);
0N/A sp_export_value_set_px (base, "y1", y1);
0N/A sp_export_value_set_px (base, "x0", x0);
0N/A sp_export_value_set_px (base, "y0", y0);
0N/A gtk_object_set_data ( base, "update", GUINT_TO_POINTER (FALSE) );
0N/A
0N/A sp_export_area_x_value_changed ((GtkAdjustment *)gtk_object_get_data (base, "x1"), base);
0N/A sp_export_area_y_value_changed ((GtkAdjustment *)gtk_object_get_data (base, "y1"), base);
0N/A
0N/A return;
0N/A}
0N/A
0N/A/**
0N/A \brief Sets the value of an adjustment
0N/A \param base The export dialog
0N/A \param key Which adjustment to set
0N/A \param val What value to set it to
0N/A
0N/A This function finds the adjustment using the data stored in the
0N/A export dialog. After finding the adjustment it then sets
0N/A the value of it.
0N/A*/
0N/Astatic void
0N/Asp_export_value_set ( GtkObject *base, const gchar *key, double val )
1724N/A{
1724N/A GtkAdjustment *adj;
1724N/A
1724N/A adj = (GtkAdjustment *)gtk_object_get_data (base, key);
0N/A
0N/A gtk_adjustment_set_value (adj, val);
1724N/A}
0N/A
0N/A/**
0N/A \brief A function to set a value using the units points
0N/A \param base The export dialog
0N/A \param key Which value should be set
0N/A \param val What the value should be in points
0N/A
0N/A This function first gets the adjustment for the key that is passed
0N/A in. It then figures out what units are currently being used in the
0N/A dialog. After doing all of that, it then converts the incoming
0N/A value and sets the adjustment.
555N/A*/
0N/Astatic void
0N/Asp_export_value_set_px (GtkObject *base, const gchar *key, double val)
0N/A{
0N/A const SPUnit *unit = sp_unit_selector_get_unit ((SPUnitSelector *)gtk_object_get_data (base, "units") );
0N/A
0N/A sp_export_value_set (base, key, sp_pixels_get_units (val, *unit));
0N/A
0N/A return;
0N/A}
0N/A
0N/A/**
0N/A \brief Get the value of an adjustment in the export dialog
0N/A \param base The export dialog
0N/A \param key Which adjustment is being looked for
0N/A \return The value in the specified adjustment
0N/A
0N/A This function gets the adjustment from the data field in the export
0N/A dialog. It then grabs the value from the adjustment.
0N/A*/
0N/Astatic float
0N/Asp_export_value_get ( GtkObject *base, const gchar *key )
0N/A{
0N/A GtkAdjustment *adj;
0N/A
0N/A adj = (GtkAdjustment *)gtk_object_get_data (base, key);
0N/A
0N/A return adj->value;
0N/A}
0N/A
0N/A/**
0N/A \brief Grabs a value in the export dialog and converts the unit
0N/A to points
0N/A \param base The export dialog
0N/A \param key Which value should be returned
0N/A \return The value in the adjustment in points
0N/A
0N/A This function, at its most basic, is a call to \c sp_export_value_get
0N/A to get the value of the adjustment. It then finds the units that
0N/A are being used by looking at the "units" attribute of the export
0N/A dialog. Using that it converts the returned value into points.
0N/A*/
0N/Astatic float
0N/Asp_export_value_get_px ( GtkObject *base, const gchar *key )
0N/A{
0N/A float value = sp_export_value_get(base, key);
0N/A const SPUnit *unit = sp_unit_selector_get_unit ((SPUnitSelector *)gtk_object_get_data (base, "units"));
0N/A
0N/A return sp_units_get_pixels (value, *unit);
0N/A} // end of sp_export_value_get_px()
0N/A
0N/A/**
0N/A \brief This function is called when the filename is changed by
0N/A anyone. It resets the virgin bit.
0N/A \param object Text entry box
0N/A \param data The export dialog
0N/A \return None
0N/A
0N/A This function gets called when the text area is modified. It is
0N/A looking for the case where the text area is modified from its
0N/A original value. In that case it sets the "filename-modified" bit
0N/A to TRUE. If the text dialog returns back to the original text, the
0N/A bit gets reset. This should stop simple mistakes.
0N/A*/
0N/Astatic void
0N/Asp_export_filename_modified (GtkObject * object, gpointer data)
0N/A{
0N/A GtkWidget * text_entry = (GtkWidget *)object;
0N/A GtkWidget * export_dialog = (GtkWidget *)data;
0N/A
0N/A if (!strcmp(original_name, gtk_entry_get_text(GTK_ENTRY(text_entry)))) {
0N/A gtk_object_set_data (GTK_OBJECT (export_dialog), "filename-modified", (gpointer)FALSE);
0N/A// printf("Modified: FALSE\n");
0N/A } else {
0N/A gtk_object_set_data (GTK_OBJECT (export_dialog), "filename-modified", (gpointer)TRUE);
0N/A// printf("Modified: TRUE\n");
0N/A }
0N/A
0N/A return;
0N/A} // end sp_export_filename_modified
0N/A
0N/A/*
0N/A Local Variables:
0N/A mode:c++
0N/A c-file-style:"stroustrup"
0N/A c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
0N/A indent-tabs-mode:nil
0N/A fill-column:99
0N/A End:
0N/A*/
0N/A// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
0N/A