From 0f0ea450b06280d2fb5d20f61e6015d8a10a2d87 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Fri, 4 Jun 2021 13:15:12 +0530 Subject: [PATCH 01/40] Prototype using glade --- share/ui/dialog-export.glade | 822 +++++++++++++++++++++++++++++++++++ src/ui/dialog/export.cpp | 525 ++++++---------------- 2 files changed, 964 insertions(+), 383 deletions(-) create mode 100644 share/ui/dialog-export.glade diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade new file mode 100644 index 0000000000..51da57a668 --- /dev/null +++ b/share/ui/dialog-export.glade @@ -0,0 +1,822 @@ + + + + + + True + False + vertical + + + True + True + False + + + True + False + 4 + 4 + vertical + + + True + False + False + True + expand + + + Document + True + True + False + False + + + True + True + 3 + + + + + Page + True + True + False + False + radiobutton1 + + + True + True + 3 + + + + + Selection + True + True + False + False + radiobutton1 + + + True + True + 3 + + + + + Custom + True + True + False + False + radiobutton1 + + + True + True + 3 + + + + + False + True + 0 + + + + + True + False + True + 7 + + + True + False + 10 + Top + 0 + + + + + + 0 + 0 + + + + + True + False + 10 + Bottom + 0 + + + 0 + 1 + + + + + True + False + 10 + Height + 0 + + + 0 + 2 + + + + + True + False + 10 + Left + 0 + + + 2 + 0 + + + + + True + False + 10 + Right + 0 + + + 2 + 1 + + + + + True + False + 10 + Width + 0 + + + 2 + 2 + + + + + True + True + True + 0.000 + number + 3 + True + True + if-valid + + + 1 + 0 + + + + + True + True + True + 0.000 + number + 3 + True + True + if-valid + + + 3 + 0 + + + + + True + True + 0.000 + number + 3 + True + True + if-valid + + + 1 + 1 + + + + + True + True + 0.000 + number + 3 + True + True + if-valid + + + 3 + 1 + + + + + True + True + 0.000 + number + 3 + True + True + if-valid + + + 1 + 2 + + + + + True + True + 500 + 0.000 + number + 1 + 3 + True + True + + + 3 + 2 + + + + + False + True + 10 + 1 + + + + + True + False + + + Show Export Area On Canvas + True + True + False + True + 6 + True + + + True + True + 0 + + + + + True + False + + + True + False + 10 + Units + 0 + + + False + True + 0 + + + + + True + False + on + True + 0 + + mm + px + + + + True + False + 4 + mm + False + + + + + True + True + 1 + + + + + False + True + 1 + + + + + False + True + 2 + + + + + True + False + 7 + 7 + True + + + False + True + 3 + + + + + True + False + + + True + False + vertical + + + True + False + + + True + False + 10 + 5 + Image Size + 0 + + + 0 + 0 + 2 + + + + + True + False + 0 + 5 + DPI + 0 + + + 2 + 0 + + + + + True + False + 10 + H + 0 + + + 0 + 1 + + + + + True + False + 10 + W + 0 + + + 0 + 3 + + + + + True + True + center + + + 1 + 1 + + + + + True + True + center + + + 1 + 3 + + + + + True + True + center + + + 2 + 1 + + + + + True + True + 6 + + + 1 + 2 + + + + + + + + + + + + + + False + True + 0 + + + + + True + False + 10 + vertical + True + + + Hide All Except Selected + True + True + False + False + 0 + True + + + True + True + 0 + + + + + Preview + True + True + False + False + 0 + True + + + True + True + 1 + + + + + True + True + 1 + + + + + True + True + 0 + + + + + 150 + 150 + True + False + gtk-missing-image + 6 + + + False + True + 1 + + + + + False + True + 4 + + + + + True + False + 10 + 10 + + + False + True + 5 + + + + + True + True + + + True + False + vertical + + + checkbutton + True + True + False + True + + + False + True + 0 + + + + + checkbutton + True + True + False + True + + + False + True + 1 + + + + + checkbutton + True + True + False + True + + + False + True + 2 + + + + + + + True + False + 10 + Advanced + + + + + True + True + 5 + 6 + + + + + True + False + 10 + 10 + + + True + True + 7 + + + + + True + False + 5 + 10 + + + True + False + 10 + Filename + 0 + + + 0 + 0 + + + + + True + False + 10 + Extension + 0 + + + 1 + 0 + + + + + True + True + + + 0 + 1 + + + + + True + False + True + 1 + + Png + svg + + + + True + False + 0 + Png + False + + + + + 1 + 1 + + + + + True + False + gtk-justify-fill + + + 2 + 1 + + + + + + + + False + True + 8 + + + + + 1 + + + + + True + False + Single Image + right + + + False + + + + + True + False + vertical + + + + + + + + + + + + 1 + + + + + True + False + Batch Export + right + + + 1 + False + + + + + False + True + 0 + + + + diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 5799169f31..93783a02c3 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -76,6 +76,8 @@ using Inkscape::Util::unit_table; +void make_group(Glib::RefPtr builder); + namespace { class MessageCleaner @@ -147,270 +149,27 @@ static const char * selection_labels[SELECTION_NUMBER_OF] = { }; Export::Export() - : DialogBase("/dialogs/export/", "Export") - , current_key(SELECTION_PAGE) - , manual_key(SELECTION_PAGE) - , original_name() - , doc_export_name() - , filename_modified(false) - , update_flag(false) - , togglebox(Gtk::ORIENTATION_HORIZONTAL, 0) - , area_box(Gtk::ORIENTATION_VERTICAL, 3) - , singleexport_box(Gtk::ORIENTATION_VERTICAL, 0) - , size_box(Gtk::ORIENTATION_VERTICAL, 3) - , file_box(Gtk::ORIENTATION_VERTICAL, 3) - , unitbox(Gtk::ORIENTATION_HORIZONTAL, 0) - , unit_selector() - , units_label(_("Units:")) - , filename_box(Gtk::ORIENTATION_HORIZONTAL, 5) - , browse_label(_("_Export As..."), true) - , browse_image() - , batch_box(Gtk::ORIENTATION_HORIZONTAL, 5) - , batch_export(_("B_atch export all selected objects")) - , interlacing(_("Use interlacing")) - , bitdepth_label(_("Bit depth")) - , bitdepth_cb() - , zlib_label(_("Compression")) - , zlib_compression() - , pHYs_label(_("pHYs dpi")) - , pHYs_sb(pHYs_adj, 1.0, 2) - , antialiasing_label(_("Antialiasing")) - , antialiasing_cb() - , hide_box(Gtk::ORIENTATION_HORIZONTAL, 3) - , hide_export(_("Hide all except selected")) - , closeWhenDone(_("Close when complete")) - , button_box(Gtk::ORIENTATION_HORIZONTAL, 3) - , _prog() - , prog_dlg(nullptr) - , interrupted(false) - , prefs(nullptr) - , selectChangedConn() - , subselChangedConn() - , selectModifiedConn() + : DialogBase("/dialogs/export/", "Export"), + selectChangedConn(), + subselChangedConn(), + selectModifiedConn() { - batch_export.set_use_underline(); - batch_export.set_tooltip_text(_("Export each selected object into its own PNG file, using export hints if any (caution, overwrites without asking!)")); - hide_export.set_use_underline(); - hide_export.set_tooltip_text(_("In the exported image, hide all objects except those that are selected")); - interlacing.set_use_underline(); - interlacing.set_tooltip_text(_("Enables ADAM7 interlacing for PNG output. This results in slightly larger image files, but big images can already be displayed (slightly blurry) while still loading.")); - closeWhenDone.set_use_underline(); - closeWhenDone.set_tooltip_text(_("Once the export completes, close this dialog")); - prefs = Inkscape::Preferences::get(); - - singleexport_box.set_border_width(0); - - /* Export area frame */ - { - Gtk::Label* lbl = new Gtk::Label(_("Export area"), Gtk::ALIGN_START); - lbl->set_use_markup(true); - area_box.pack_start(*lbl); - - /* Units box */ - /* gets added to the vbox later, but the unit selector is needed - earlier than that */ - unit_selector.setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); - - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (desktop) { - unit_selector.setUnit(desktop->getNamedView()->display_units->abbr); - } - unitChangedConn = unit_selector.signal_changed().connect(sigc::mem_fun(*this, &Export::onUnitChanged)); - unitbox.pack_end(unit_selector, false, false, 0); - unitbox.pack_end(units_label, false, false, 3); - - for (int i = 0; i < SELECTION_NUMBER_OF; i++) { - selectiontype_buttons[i] = new Gtk::RadioButton(_(selection_labels[i]), true); - if (i > 0) { - Gtk::RadioButton::Group group = selectiontype_buttons[0]->get_group(); - selectiontype_buttons[i]->set_group(group); - } - selectiontype_buttons[i]->set_mode(false); - togglebox.pack_start(*selectiontype_buttons[i], false, true, 0); - selectiontype_buttons[i]->signal_clicked().connect(sigc::mem_fun(*this, &Export::onAreaTypeToggled)); - } - - auto t = new Gtk::Grid(); - t->set_row_spacing(4); - t->set_column_spacing(4); - - SPDocument *doc; - doc = SP_ACTIVE_DESKTOP->getDocument(); - - x0_adj = createSpinbutton("x0", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, t, 0, 0, _("_x0:"), "", - EXPORT_COORD_PRECISION, 1, &Export::onAreaX0Change); - - x1_adj = createSpinbutton("x1", doc->getWidth().value("mm"), -1000000.0, 1000000.0, 0.1, 1.0, t, 0, 1, - _("x_1:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaX1Change); - - width_adj = createSpinbutton("width", doc->getWidth().value("mm"), 0.0, PNG_UINT_31_MAX, 0.1, 1.0, t, 0, 2, - _("Wid_th:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaWidthChange); - - y0_adj = createSpinbutton("y0", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, t, 2, 0, _("_y0:"), "", - EXPORT_COORD_PRECISION, 1, &Export::onAreaY0Change); - - y1_adj = createSpinbutton("y1", doc->getHeight().value("mm"), -1000000.0, 1000000.0, 0.1, 1.0, t, 2, 1, - _("y_1:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaY1Change); - - height_adj = createSpinbutton("height", doc->getHeight().value("mm"), 0.0, PNG_UINT_31_MAX, 0.1, 1.0, t, 2, 2, - _("Hei_ght:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaHeightChange); - - area_box.pack_start(togglebox, false, false, 3); - area_box.pack_start(*t, false, false, 0); - area_box.pack_start(unitbox, false, false, 0); - - area_box.set_border_width(3); - singleexport_box.pack_start(area_box, false, false, 0); - - } // end of area box - - /* Bitmap size frame */ - { - SPDocument *doc; - doc = SP_ACTIVE_DESKTOP->getDocument(); - - size_box.set_border_width(3); - bm_label = new Gtk::Label(_("Image size"), Gtk::ALIGN_START); - bm_label->set_use_markup(true); - size_box.pack_start(*bm_label, false, false, 0); - - auto t = new Gtk::Grid(); - t->set_row_spacing(4); - t->set_column_spacing(4); - - size_box.pack_start(*t); - - bmwidth_adj = createSpinbutton("bmwidth", doc->getWidth().value("px"), 1.0, 1000000.0, 1.0, 10.0, t, 0, 0, - _("_Width:"), _("pixels at"), 0, 1, &Export::onBitmapWidthChange); - - xdpi_adj = createSpinbutton("xdpi", prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), 0.01, - 100000.0, 0.1, 1.0, t, 3, 0, "", _("dp_i"), 2, 1, &Export::onExportXdpiChange); + std::string gladefile = get_filename_string(Inkscape::IO::Resource::UIS, "dialog-export.glade"); + Glib::RefPtr builder; - bmheight_adj = createSpinbutton("bmheight", doc->getHeight().value("px"), 1.0, 1000000.0, 1.0, 10.0, t, 0, 1, - _("_Height:"), _("pixels at"), 0, 1, &Export::onBitmapHeightChange); - - /** TODO - * There's no way to set ydpi currently, so we use the defaultxdpi value here, too... - */ - ydpi_adj = createSpinbutton ( "ydpi", prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), - 0.01, 100000.0, 0.1, 1.0, t, 3, 1, - "", _("dpi"), 2, 0, nullptr ); - - singleexport_box.pack_start(size_box, Gtk::PACK_SHRINK); - } - - /* File entry */ - { - file_box.set_border_width(3); - flabel = new Gtk::Label(_("_Filename"), Gtk::ALIGN_START, Gtk::ALIGN_CENTER, true); - flabel->set_use_markup(true); - file_box.pack_start(*flabel, false, false, 0); - - set_default_filename(); - - filename_box.pack_start (filename_entry, true, true, 0); - - Gtk::Box* browser_im_label = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 3); - browse_image.set_from_icon_name("folder", Gtk::ICON_SIZE_BUTTON); - browser_im_label->pack_start(browse_image); - browser_im_label->pack_start(browse_label); - browse_button.add(*browser_im_label); - filename_box.pack_end (browse_button, false, false); - filename_box.pack_end(export_button, false, false); - - file_box.add(filename_box); - - original_name = filename_entry.get_text(); - - // focus is in the filename initially: - filename_entry.grab_focus(); - - // mnemonic in frame label moves focus to filename: - flabel->set_mnemonic_widget(filename_entry); + try { + builder = Gtk::Builder::create_from_file(gladefile); + } catch (const Glib::Error &ex) { + g_error("Glade file loading failed for boot screen"); + return; } - - batch_export.set_sensitive(true); - batch_box.pack_start(batch_export, false, false, 3); - - hide_export.set_sensitive(true); - hide_export.set_active (prefs->getBool("/dialogs/export/hideexceptselected/value", false)); - hide_box.pack_start(hide_export, false, false, 3); - - - /* Export Button row */ - export_button.set_label(_("_Export")); - export_button.set_use_underline(); - export_button.set_tooltip_text (_("Export the bitmap file with these settings")); - - button_box.set_border_width(3); - button_box.pack_start(closeWhenDone, true, true, 0); - - /*Advanced*/ - Gtk::Label *label_advanced = Gtk::manage(new Gtk::Label(_("Advanced"),true)); - expander.set_label_widget(*label_advanced); - expander.set_vexpand(false); - const char* const modes_list[]={"Gray_1", "Gray_2","Gray_4","Gray_8","Gray_16","RGB_8","RGB_16","GrayAlpha_8","GrayAlpha_16","RGBA_8","RGBA_16"}; - for(auto i : modes_list) - bitdepth_cb.append(i); - bitdepth_cb.set_active_text("RGBA_8"); - bitdepth_cb.set_hexpand(); - const char* const zlist[]={"Z_NO_COMPRESSION","Z_BEST_SPEED","2","3","4","5","Z_DEFAULT_COMPRESSION","7","8","Z_BEST_COMPRESSION"}; - for(auto i : zlist) - zlib_compression.append(i); - zlib_compression.set_active_text("Z_DEFAULT_COMPRESSION"); - pHYs_adj = Gtk::Adjustment::create(0, 0, 100000, 0.1, 1.0, 0); - pHYs_sb.set_adjustment(pHYs_adj); - pHYs_sb.set_width_chars(7); - pHYs_sb.set_tooltip_text( _("Will force-set the physical dpi for the png file. Set this to 72 if you're planning to work on your png with Photoshop") ); - zlib_compression.set_hexpand(); - const char* const antialising_list[] = {"CAIRO_ANTIALIAS_NONE","CAIRO_ANTIALIAS_FAST","CAIRO_ANTIALIAS_GOOD (default)","CAIRO_ANTIALIAS_BEST"}; - for(auto i : antialising_list) - antialiasing_cb.append(i); - antialiasing_cb.set_active_text(antialising_list[2]); - bitdepth_label.set_halign(Gtk::ALIGN_START); - zlib_label.set_halign(Gtk::ALIGN_START); - pHYs_label.set_halign(Gtk::ALIGN_START); - antialiasing_label.set_halign(Gtk::ALIGN_START); - auto table = new Gtk::Grid(); - expander.add(*table); - table->set_border_width(4); - table->attach(interlacing,0,0,1,1); - table->attach(bitdepth_label,0,1,1,1); - table->attach(bitdepth_cb,1,1,1,1); - table->attach(zlib_label,0,2,1,1); - table->attach(zlib_compression,1,2,1,1); - table->attach(pHYs_label,0,3,1,1); - table->attach(pHYs_sb,1,3,1,1); - table->attach(antialiasing_label,0,4,1,1); - table->attach(antialiasing_cb,1,4,1,1); - table->show(); - - /* Main dialog */ - set_spacing(0); - pack_start(singleexport_box, Gtk::PACK_SHRINK); - pack_start(file_box, Gtk::PACK_SHRINK); - pack_start(batch_box, Gtk::PACK_SHRINK); - pack_start(hide_box, Gtk::PACK_SHRINK); - pack_start(button_box, Gtk::PACK_SHRINK); - pack_start(expander, Gtk::PACK_SHRINK); - pack_end(_prog, Gtk::PACK_SHRINK); - - /* Signal handlers */ - filename_entry.signal_changed().connect( sigc::mem_fun(*this, &Export::onFilenameModified) ); - // pressing enter in the filename field is the same as clicking export: - filename_entry.signal_activate().connect(sigc::mem_fun(*this, &Export::onExport) ); - browse_button.signal_clicked().connect(sigc::mem_fun(*this, &Export::onBrowse)); - batch_export.signal_clicked().connect(sigc::mem_fun(*this, &Export::onBatchClicked)); - export_button.signal_clicked().connect(sigc::mem_fun(*this, &Export::onExport)); - hide_export.signal_clicked().connect(sigc::mem_fun(*this, &Export::onHideExceptSelected)); - + Gtk::Box *contents; + builder->get_widget("contents", contents); + add(*contents); show_all_children(); - setExporting(false); - - findDefaultSelection(); - refreshArea(); } + Export::~Export () { selectModifiedConn.disconnect(); @@ -723,131 +482,131 @@ void Export::onAreaTypeToggled() { /// Area type changed, unit changed, initialization void Export::refreshArea () { - if ( SP_ACTIVE_DESKTOP ) - { - SPDocument *doc; - Geom::OptRect bbox; - bbox = Geom::Rect(Geom::Point(0.0, 0.0),Geom::Point(0.0, 0.0)); - doc = SP_ACTIVE_DESKTOP->getDocument(); - - /* Notice how the switch is used to 'fall through' here to get - various backups. If you modify this without noticing you'll - probably screw something up. */ - switch (current_key) { - case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) - { - bbox = SP_ACTIVE_DESKTOP->getSelection()->visualBounds(); - /* Only if there is a selection that we can set - do we break, otherwise we fall through to the - drawing */ - // std::cout << "Using selection: SELECTION" << std::endl; - current_key = SELECTION_SELECTION; - break; - } - case SELECTION_DRAWING: - if (manual_key == SELECTION_DRAWING || manual_key == SELECTION_SELECTION) { - /** \todo - * This returns wrong values if the document has a viewBox. - */ - bbox = doc->getRoot()->desktopVisualBounds(); - /* If the drawing is valid, then we'll use it and break - otherwise we drop through to the page settings */ - if (bbox) { - // std::cout << "Using selection: DRAWING" << std::endl; - current_key= SELECTION_DRAWING; - break; - } - } - case SELECTION_PAGE: - if (manual_key == SELECTION_PAGE){ - bbox = Geom::Rect(Geom::Point(0.0, 0.0), - Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); - - // std::cout << "Using selection: PAGE" << std::endl; - current_key= SELECTION_PAGE; - break; - } - case SELECTION_CUSTOM: - current_key = SELECTION_CUSTOM; - default: - break; - } // switch - - // remember area setting - prefs->setString("/dialogs/export/exportarea/value", selection_names[current_key]); - - if ( current_key != SELECTION_CUSTOM && bbox ) { - setArea ( bbox->min()[Geom::X], - bbox->min()[Geom::Y], - bbox->max()[Geom::X], - bbox->max()[Geom::Y]); - } - - } // end of if ( SP_ACTIVE_DESKTOP ) - - if (SP_ACTIVE_DESKTOP && !filename_modified) { - - Glib::ustring filename; - float xdpi = 0.0, ydpi = 0.0; - - switch (current_key) { - case SELECTION_PAGE: - case SELECTION_DRAWING: { - SPDocument * doc = SP_ACTIVE_DOCUMENT; - sp_document_get_export_hints (doc, filename, &xdpi, &ydpi); - - if (filename.empty()) { - if (!doc_export_name.empty()) { - filename = doc_export_name; - } - } - break; - } - case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { - - SP_ACTIVE_DESKTOP->getSelection()->getExportHints(filename, &xdpi, &ydpi); - - /* If we still don't have a filename -- let's build - one that's nice */ - if (filename.empty()) { - const gchar * id = "object"; - auto reprlst = SP_ACTIVE_DESKTOP->getSelection()->xmlNodes(); - for(auto i=reprlst.begin(); reprlst.end() != i; ++i) { - Inkscape::XML::Node * repr = *i; - if (repr->attribute("id")) { - id = repr->attribute("id"); - break; - } - } - - filename = create_filepath_from_id (id, filename_entry.get_text()); - } - } - break; - case SELECTION_CUSTOM: - default: - break; - } - - if (!filename.empty()) { - original_name = filename; - filename_entry.set_text(filename); - filename_entry.set_position(filename.length()); - } - - if (xdpi != 0.0) { - setValue(xdpi_adj, xdpi); - } - - /* These can't be separate, and setting x sets y, so for - now setting this is disabled. Hopefully it won't be in - the future */ - if (FALSE && ydpi != 0.0) { - setValue(ydpi_adj, ydpi); - } - } + // if ( SP_ACTIVE_DESKTOP ) + // { + // SPDocument *doc; + // Geom::OptRect bbox; + // bbox = Geom::Rect(Geom::Point(0.0, 0.0),Geom::Point(0.0, 0.0)); + // doc = SP_ACTIVE_DESKTOP->getDocument(); + + // /* Notice how the switch is used to 'fall through' here to get + // various backups. If you modify this without noticing you'll + // probably screw something up. */ + // switch (current_key) { + // case SELECTION_SELECTION: + // if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) + // { + // bbox = SP_ACTIVE_DESKTOP->getSelection()->visualBounds(); + // /* Only if there is a selection that we can set + // do we break, otherwise we fall through to the + // drawing */ + // // std::cout << "Using selection: SELECTION" << std::endl; + // current_key = SELECTION_SELECTION; + // break; + // } + // case SELECTION_DRAWING: + // if (manual_key == SELECTION_DRAWING || manual_key == SELECTION_SELECTION) { + // /** \todo + // * This returns wrong values if the document has a viewBox. + // */ + // bbox = doc->getRoot()->desktopVisualBounds(); + // /* If the drawing is valid, then we'll use it and break + // otherwise we drop through to the page settings */ + // if (bbox) { + // // std::cout << "Using selection: DRAWING" << std::endl; + // current_key= SELECTION_DRAWING; + // break; + // } + // } + // case SELECTION_PAGE: + // if (manual_key == SELECTION_PAGE){ + // bbox = Geom::Rect(Geom::Point(0.0, 0.0), + // Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); + + // // std::cout << "Using selection: PAGE" << std::endl; + // current_key= SELECTION_PAGE; + // break; + // } + // case SELECTION_CUSTOM: + // current_key = SELECTION_CUSTOM; + // default: + // break; + // } // switch + + // // remember area setting + // prefs->setString("/dialogs/export/exportarea/value", selection_names[current_key]); + + // if ( current_key != SELECTION_CUSTOM && bbox ) { + // setArea ( bbox->min()[Geom::X], + // bbox->min()[Geom::Y], + // bbox->max()[Geom::X], + // bbox->max()[Geom::Y]); + // } + + // } // end of if ( SP_ACTIVE_DESKTOP ) + + // if (SP_ACTIVE_DESKTOP && !filename_modified) { + + // Glib::ustring filename; + // float xdpi = 0.0, ydpi = 0.0; + + // switch (current_key) { + // case SELECTION_PAGE: + // case SELECTION_DRAWING: { + // SPDocument * doc = SP_ACTIVE_DOCUMENT; + // sp_document_get_export_hints (doc, filename, &xdpi, &ydpi); + + // if (filename.empty()) { + // if (!doc_export_name.empty()) { + // filename = doc_export_name; + // } + // } + // break; + // } + // case SELECTION_SELECTION: + // if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { + + // SP_ACTIVE_DESKTOP->getSelection()->getExportHints(filename, &xdpi, &ydpi); + + // /* If we still don't have a filename -- let's build + // one that's nice */ + // if (filename.empty()) { + // const gchar * id = "object"; + // auto reprlst = SP_ACTIVE_DESKTOP->getSelection()->xmlNodes(); + // for(auto i=reprlst.begin(); reprlst.end() != i; ++i) { + // Inkscape::XML::Node * repr = *i; + // if (repr->attribute("id")) { + // id = repr->attribute("id"); + // break; + // } + // } + + // filename = create_filepath_from_id (id, filename_entry.get_text()); + // } + // } + // break; + // case SELECTION_CUSTOM: + // default: + // break; + // } + + // if (!filename.empty()) { + // original_name = filename; + // filename_entry.set_text(filename); + // filename_entry.set_position(filename.length()); + // } + + // if (xdpi != 0.0) { + // setValue(xdpi_adj, xdpi); + // } + + // /* These can't be separate, and setting x sets y, so for + // now setting this is disabled. Hopefully it won't be in + // the future */ + // if (FALSE && ydpi != 0.0) { + // setValue(ydpi_adj, ydpi); + // } + // } return; } // end of sp_export_area_toggled() -- GitLab From 3e2108f2ec030d69414f33d6b71502fd0a70ea98 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Fri, 4 Jun 2021 19:35:25 +0530 Subject: [PATCH 02/40] Scrolled with fixed header and footer --- share/ui/dialog-export.glade | 1262 ++++++++++++++++++---------------- src/ui/dialog/export.cpp | 2 +- 2 files changed, 675 insertions(+), 589 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 51da57a668..2fbcf3c084 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -2,10 +2,15 @@ + + 10 + 1 + True False vertical + True True @@ -19,18 +24,19 @@ 4 vertical - + True False False True expand - + Document True True False + True False @@ -46,7 +52,7 @@ True False False - radiobutton1 + radiobutton2 True @@ -61,7 +67,7 @@ True False False - radiobutton1 + radiobutton2 True @@ -76,7 +82,7 @@ True False False - radiobutton1 + radiobutton2 True @@ -92,676 +98,756 @@ - - True - False - True - 7 - - - True - False - 10 - Top - 0 - - - - - - 0 - 0 - - - - - True - False - 10 - Bottom - 0 - - - 0 - 1 - - - - - True - False - 10 - Height - 0 - - - 0 - 2 - - - - - True - False - 10 - Left - 0 - - - 2 - 0 - - - - - True - False - 10 - Right - 0 - - - 2 - 1 - - - - - True - False - 10 - Width - 0 - - - 2 - 2 - - - - - True - True - True - 0.000 - number - 3 - True - True - if-valid - - - 1 - 0 - - - - - True - True - True - 0.000 - number - 3 - True - True - if-valid - - - 3 - 0 - - - - - True - True - 0.000 - number - 3 - True - True - if-valid - - - 1 - 1 - - - - - True - True - 0.000 - number - 3 - True - True - if-valid - - - 3 - 1 - - - - - True - True - 0.000 - number - 3 - True - True - if-valid - - - 1 - 2 - - - - - True - True - 500 - 0.000 - number - 1 - 3 - True - True - - - 3 - 2 - - - - - False - True - 10 - 1 - - - - + True - False - - - Show Export Area On Canvas - True - True - False - True - 6 - True - - - True - True - 0 - - - - - True - False - - - True - False - 10 - Units - 0 - - - False - True - 0 - - - - - True - False - on - True - 0 - - mm - px - - - - True - False - 4 - mm - False - - - - - True - True - 1 - - - - - False - True - 1 - - - - - False - True - 2 - - - - - True - False - 7 - 7 - True - - - False - True - 3 - - - - - True - False + True + True + never + always + in + True - + True False - vertical + natural - + True False + 4 + 4 + vertical - + True False - 10 - 5 - Image Size - 0 + True + 7 + + + True + False + 10 + Top + 0 + + + + + + 0 + 0 + + + + + True + False + 10 + Bottom + 0 + + + 0 + 1 + + + + + True + False + 10 + Height + 0 + + + 0 + 2 + + + + + True + False + 10 + Left + 0 + + + 2 + 0 + + + + + True + False + 10 + Right + 0 + + + 2 + 1 + + + + + True + False + 10 + Width + 0 + + + 2 + 2 + + + + + True + True + True + 78 + 0.000 + True + False + 1 + 1 + number + 29.170000000000002 + 3 + True + True + True + if-valid + + + 1 + 0 + + + + + True + True + True + 0.000 + number + 3 + True + True + if-valid + + + 3 + 0 + + + + + True + True + 0.000 + number + 3 + True + True + if-valid + + + 1 + 1 + + + + + True + True + 0.000 + number + 3 + True + True + if-valid + + + 3 + 1 + + + + + True + True + 0.000 + number + 3 + True + True + if-valid + + + 1 + 2 + + + + + True + True + 500 + 0.000 + number + 1 + 3 + True + True + + + 3 + 2 + + - 0 - 0 - 2 + False + True + 10 + 0 - + True False - 0 - 5 - DPI - 0 + + + Show Export Area On Canvas + True + True + False + True + True + + + True + True + 0 + + + + + True + False + + + True + False + 10 + Units + 0 + + + False + True + 0 + + + + + True + False + on + True + 0 + + mm + px + + + + True + False + 4 + mm + False + + + + + True + True + 1 + + + + + False + True + 1 + + - 2 - 0 + False + True + 1 - + True False - 10 - H - 0 + 7 + 7 + True - 0 - 1 + False + True + 3 - + True False - 10 - W - 0 + + + True + False + vertical + + + True + False + + + True + False + 10 + 5 + Image Size + 0 + + + 0 + 0 + 2 + + + + + True + False + 0 + 5 + DPI + 0 + + + 2 + 0 + + + + + True + False + 10 + H + 0 + + + 0 + 1 + + + + + True + False + 10 + W + 0 + + + 0 + 3 + + + + + True + True + center + + + 1 + 1 + + + + + True + True + center + + + 1 + 3 + + + + + True + True + center + + + 2 + 1 + + + + + True + True + 6 + + + 1 + 2 + + + + + True + True + 0.12 + adjustment1 + 2 + 0.12 + + + 2 + 3 + + + + + + + + + + + False + True + 0 + + + + + True + False + 10 + vertical + True + + + Hide All Except Selected + True + True + False + False + 0 + True + + + True + True + 0 + + + + + Preview + True + True + False + False + 0 + True + + + True + True + 1 + + + + + True + True + 1 + + + + + True + True + 0 + + + + + 150 + 150 + True + False + gtk-missing-image + 6 + + + False + True + 1 + + - 0 - 3 - - - - - True - True - center - - - 1 - 1 + False + True + 4 - + True - True - center + False + 10 + 10 - 1 - 3 + False + True + 5 - + True True - center + + + True + False + vertical + + + checkbutton + True + True + False + True + + + False + True + 0 + + + + + checkbutton + True + True + False + True + + + False + True + 1 + + + + + checkbutton + True + True + False + True + + + False + True + 2 + + + + + + + True + False + 10 + Advanced + + - 2 - 1 + True + True + 5 + 6 - + True - True - 6 - - - 1 - 2 - - - - - - - - - - - - - - False - True - 0 - - - - - True - False - 10 - vertical - True - - - Hide All Except Selected - True - True - False - False - 0 - True + False + 10 + 10 True True - 0 + 7 - - Preview + True - True - False - False - 0 - True + False + 5 + 10 + + + True + False + 10 + Filename + 0 + + + 0 + 0 + + + + + True + False + 10 + Extension + 0 + + + 1 + 0 + + + + + True + True + + + 0 + 1 + + + + + True + False + True + 1 + + Png + svg + + + + True + False + 0 + Png + False + + + + + 1 + 1 + + + + + True + False + gtk-justify-fill + + + 2 + 1 + + + + + - True + False True - 1 + 8 + + + - - True - True - 1 - - - - - True - True - 0 - - - - - 150 - 150 - True - False - gtk-missing-image - 6 - - - False - True - 1 - - - - - False - True - 4 - - - - - True - False - 10 - 10 - - - False - True - 5 - - - - - True - True - - - True - False - vertical - - - checkbutton - True - True - False - True - - - False - True - 0 - - - - - checkbutton - True - True - False - True - - - False - True - 1 - - - - - checkbutton - True - True - False - True - - - False - True - 2 - - - - True - False - 10 - Advanced - - True True - 5 - 6 - - - - - True - False - 10 - 10 - - - True - True - 7 + 1 - + True False - 5 - 10 - - - True - False - 10 - Filename - 0 - - - 0 - 0 - - - - - True - False - 10 - Extension - 0 - - - 1 - 0 - - + False + True + expand - + + Export True True + True + half - 0 - 1 - - - - - True - False - True - 1 - - Png - svg - - - - True - False - 0 - Png - False - - - - - 1 - 1 - - - - - True - False - gtk-justify-fill - - - 2 - 1 + True + True + 3 - - - False True - 8 + 2 diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 93783a02c3..a2dd591417 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -160,7 +160,7 @@ Export::Export() try { builder = Gtk::Builder::create_from_file(gladefile); } catch (const Glib::Error &ex) { - g_error("Glade file loading failed for boot screen"); + g_error("Glade file loading failed for export screen"); return; } Gtk::Box *contents; -- GitLab From 5ad3c09cf9e45aaac6bd7531bd75de325bdaccd7 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Wed, 9 Jun 2021 18:56:15 +0530 Subject: [PATCH 03/40] added remove scroll function --- share/ui/dialog-export.glade | 1802 +++++++++++++++++++------------ src/ui/dialog/export-old.cpp | 1933 ++++++++++++++++++++++++++++++++++ src/ui/dialog/export-old.h | 371 +++++++ src/ui/dialog/export.cpp | 1660 +---------------------------- src/ui/dialog/export.h | 363 +------ 5 files changed, 3528 insertions(+), 2601 deletions(-) create mode 100644 src/ui/dialog/export-old.cpp create mode 100644 src/ui/dialog/export-old.h diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 2fbcf3c084..c77717ed90 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -6,543 +6,424 @@ 10 1 - + + + image/png + image/jpeg + image/svg+xml + + + + False + dialog + + + + + + False + vertical + 2 + + + False + end + + + Select + True + True + True + + + True + True + 0 + + + + + False + False + 0 + + + + + True + False + save + export_filter + False + + + False + True + 1 + + + + + + + + + + + + + Hello + + + + True False + False vertical True - + True - True + False + False False - + True False - 4 - 4 + False vertical - - - True - False - False - True - expand - - - Document - True - True - False - True - False - - - True - True - 3 - - - - - Page - True - True - False - False - radiobutton2 - - - True - True - 3 - - - - - Selection - True - True - False - False - radiobutton2 - - - True - True - 3 - - - - - Custom - True - True - False - False - radiobutton2 - - - True - True - 3 - - - - - False - True - 0 - - + 5 + 300 True True + False True never always - in True True False + False natural + none - + True False - 4 - 4 - vertical + 5 + 10 - + True False + Left + True + 0 + + + 1 + 1 + + + + + True + True True - 7 - - - True - False - 10 - Top - 0 - - - - - - 0 - 0 - - - - - True - False - 10 - Bottom - 0 - - - 0 - 1 - - - - - True - False - 10 - Height - 0 - - - 0 - 2 - - - - - True - False - 10 - Left - 0 - - - 2 - 0 - - - - - True - False - 10 - Right - 0 - - - 2 - 1 - - - - - True - False - 10 - Width - 0 - - - 2 - 2 - - - - - True - True - True - 78 - 0.000 - True - False - 1 - 1 - number - 29.170000000000002 - 3 - True - True - True - if-valid - - - 1 - 0 - - - - - True - True - True - 0.000 - number - 3 - True - True - if-valid - - - 3 - 0 - - - - - True - True - 0.000 - number - 3 - True - True - if-valid - - - 1 - 1 - - - - - True - True - 0.000 - number - 3 - True - True - if-valid - - - 3 - 1 - - - - - True - True - 0.000 - number - 3 - True - True - if-valid - - - 1 - 2 - - - - - True - True - 500 - 0.000 - number - 1 - 3 - True - True - - - 3 - 2 - - + False - False - True - 10 - 0 + 2 + 1 - + + True + True + True + + + 2 + 2 + + + + + True + True + True + + + 5 + 1 + + + + + True + True + True + + + 5 + 2 + + + + True False - - - Show Export Area On Canvas - True - True - False - True - True - - - True - True - 0 - - - - - True - False - - - True - False - 10 - Units - 0 - - - False - True - 0 - - - - - True - False - on - True - 0 - - mm - px - - - - True - False - 4 - mm - False - - - - - True - True - 1 - - - - - False - True - 1 - - + Right + True + 0 - False - True - 1 + 4 + 1 - + True False - 7 - 7 - True + Bottom + True + 0 - False - True - 3 + 4 + 2 - + True False - - + Top + True + 0 + + + 1 + 2 + + + + + True + False + Width + True + 0 + + + 1 + 3 + + + + + True + True + True + + + 2 + 3 + + + + + True + True + True + + + 5 + 3 + + + + + True + False + Height + True + 0 + + + 4 + 3 + + + + + True + False + 5 + 5 + Image Size + 0 + + + + + + 1 + 5 + 2 + + + + + True + False + Width + True + 0 + + + 1 + 6 + + + + + True + False + Height + True + 0 + + + 4 + 6 + + + + + True + True + True + + + 5 + 6 + + + + + True + True + True + + + 2 + 6 + + + + + True + False + DPI + True + 0 + + + 1 + 7 + + + + + True + False + px + True + 0 + + + + + + + + + 3 + 6 + + + + + True + False + px + True + 0 + + + + + + + + + 6 + 6 + + + + + True + True + center + True + + + 2 + 7 + + + + + True + False + + + Show Export Area On Canvas + True + True + False + True + + + False + True + 0 + + + + True False - vertical + end + True + 5 - + True False - - - True - False - 10 - 5 - Image Size - 0 - - - 0 - 0 - 2 - - - - - True - False - 0 - 5 - DPI - 0 - - - 2 - 0 - - - - - True - False - 10 - H - 0 - - - 0 - 1 - - - - - True - False - 10 - W - 0 - - - 0 - 3 - - - - - True - True - center - - - 1 - 1 - - - - - True - True - center - - - 1 - 3 - - - - - True - True - center - - - 2 - 1 - - - - - True - True - 6 - - - 1 - 2 - - - - - True - True - 0.12 - adjustment1 - 2 - 0.12 - - - 2 - 3 - - - - - - - - + Units + True + 0 False @@ -551,52 +432,581 @@ - + True False + 1 + + mm + px + + + + False + True + 1 + + + + + False + True + 2 + + + + + 1 + 4 + 5 + + + + + True + False + vertical + + + Hide All Except Selected + True + True + False + True + + + False + True + 0 + + + + + Preview + True + True + False + True + + + False + True + 1 + + + + + 1 + 8 + 2 + 3 + + + + + True + True + 10 + 10 + True + + + True + False + 5 + + + checkbutton + True + True + False + 20 10 - vertical - True + True + + + 0 + 0 + + + + + checkbutton + True + True + False + 20 + True + + + 0 + 1 + + + + + + + True + False + 10 + Advance + True + + + + + 1 + 11 + 5 + + + + + True + False + False + 5 + True + expand + + + Document + True + False + False + True + False + + + True + True + 3 + + + + + Page + True + False + False + False + si_s_document + + + True + True + 3 + + + + + Selection + True + False + False + False + si_s_document + + + True + True + 3 + + + + + Custom + True + False + False + False + si_s_document + + + True + True + 3 + + + + + 0 + 0 + 8 + + + + + True + False + vertical + + + 150 + 150 + True + False + 150 + face-smile + 6 + + + False + True + 0 + + + + + 3 + 7 + 4 + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + 0 + + + + + True + False + 10 + + + True + True + True + folder-open + Filename + + + 0 + 0 + + + + + True + False + center + 1 + + svg + png + + + + 1 + 0 + + + + + Export + True + True + True + end + + + 2 + 0 + + + + + False + True + 1 + + + + + + + + 1 + + + + + True + False + False + Single Image + right + + + False + + + + + True + False + False + vertical + + + 300 + True + True + True + never + always + False + True + + + True + False + none + + + True + False + vertical + 10 + 10 + + + 150 + True + True + True + never + in + + + True + False + + + True + False + True + 10 + 10 + 10 + none + + + 50 + 50 + True + True + + + True + False + 50 + face-glasses + + + + + + + 100 + 80 + True + True + + + True + False + 50 + face-glasses + + + + + + + 100 + 80 + True + True + + + True + False + 50 + face-glasses + + + + - - Hide All Except Selected + + 100 + 80 True True - False - False - 0 - True + + + True + False + 50 + face-glasses + + - - True - True - 0 - - - Preview + + 100 + 80 True True - False - False - 0 - True + + + True + False + 50 + face-glasses + + - - True - True - 1 - - - True - True - 1 - + + + + 1 + 1 + 8 + + + + + True + False + True + expand + + + Selection + True + False + False + True + False + True True @@ -604,75 +1014,93 @@ - - 150 - 150 + + Layers True False - gtk-missing-image - 6 + False + True + False + radiobutton2 - False + True True 1 - False - True - 4 + 0 + 0 + 10 - + + Preview + True + True + False + True + + + 1 + 2 + 2 + + + + True False - 10 - 10 + 5 Items + + + 8 + 2 + + + + + Hide All Except Selected + True + True + False + True - False - True - 5 + 1 + 5 + 4 True True + 10 + 10 + 5 + True - + True False - vertical - - - checkbutton - True - True - False - True - - - False - True - 0 - - + 10 + 5 checkbutton True True False + 10 True - False - True - 1 + 0 + 0 @@ -684,9 +1112,8 @@ True - False - True - 2 + 0 + 1 @@ -695,122 +1122,156 @@ True False - 10 - Advanced + 5 + Advance + True - True - True - 5 - 6 - - - - - True - False - 10 - 10 - - - True - True - 7 + 1 + 6 + 4 - + True - False - 5 - 10 - - - True - False - 10 - Filename - 0 - - - 0 - 0 - - - - - True - False - 10 - Extension - 0 - - - 1 - 0 - + True + liststore1 + False + False + + - - True - True + + autosize + Prefix + True - - 0 - 1 - - - True - False - True - 1 - - Png - svg - - - - True - False - 0 - Png - False - - + + autosize + Scale + True - - 1 - 1 - - - True - False - gtk-justify-fill + + autosize + Format + True - - 2 - 1 - - - - - False - True - 8 + 1 + 3 + 4 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -819,35 +1280,49 @@ True True - 1 + 0 - + True False - False - True - expand + 5 + 5 + 10 + + + True + True + True + folder-open + Filename + + + 0 + 0 + + Export True True True - half - True - True - 3 + 2 + 0 + + + False True - 2 + 1 @@ -859,36 +1334,7 @@ True False - Single Image - right - - - False - - - - - True - False - vertical - - - - - - - - - - - - 1 - - - - - True - False + False Batch Export right diff --git a/src/ui/dialog/export-old.cpp b/src/ui/dialog/export-old.cpp new file mode 100644 index 0000000000..d7c03bb08c --- /dev/null +++ b/src/ui/dialog/export-old.cpp @@ -0,0 +1,1933 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Authors: + * Lauris Kaplinski + * bulia byak + * Johan Engelen + * Peter Bostrom + * Jon A. Cruz + * Abhishek Sharma + * Kris De Gussem + * + * Copyright (C) 1999-2007, 2012 Authors + * Copyright (C) 2001-2002 Ximian, Inc. + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +// This has to be included prior to anything that includes setjmp.h, it croaks otherwise +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "document-undo.h" +#include "document.h" +#include "file.h" +#include "inkscape.h" +#include "inkscape-window.h" +#include "preferences.h" +#include "selection-chemistry.h" + +// required to set status message after export +#include "desktop.h" +#include "message-stack.h" + +#include "helper/png-write.h" + +#include "io/resource.h" +#include "io/sys.h" + +#include "object/sp-namedview.h" +#include "object/sp-root.h" + +#include "ui/dialog-events.h" +#include "ui/interface.h" +#include "ui/widget/unit-menu.h" +#include "ui/widget/scrollprotected.h" +#include "ui/dialog/dialog-notebook.h" +#include "ui/dialog/filedialog.h" + +#include "extension/db.h" + +#ifdef _WIN32 +#include +#include +#include +#include +#endif + +#define SP_EXPORT_MIN_SIZE 1.0 + +#define DPI_BASE Inkscape::Util::Quantity::convert(1, "in", "px") + +#define EXPORT_COORD_PRECISION 3 + +#include "export.h" + +using Inkscape::Util::unit_table; + +namespace { + +class MessageCleaner +{ +public: + MessageCleaner(Inkscape::MessageId messageId, SPDesktop *desktop) : + _desktop(desktop), + _messageId(messageId) + { + } + + ~MessageCleaner() + { + if (_messageId && _desktop) { + _desktop->messageStack()->cancel(_messageId); + } + } + +private: + MessageCleaner(MessageCleaner const &other) = delete; + MessageCleaner &operator=(MessageCleaner const &other) = delete; + + SPDesktop *_desktop; + Inkscape::MessageId _messageId; +}; + +} // namespace + +namespace Inkscape { +namespace UI { +namespace Dialog { + +class ExportProgressDialog : public Gtk::Dialog { + private: + Gtk::ProgressBar *_progress = nullptr; + Export *_export_panel = nullptr; + int _current = 0; + int _total = 0; + + public: + ExportProgressDialog(const Glib::ustring &title, bool modal = false) + : Gtk::Dialog(title, modal) + {} + + inline void set_export_panel(const decltype(_export_panel) export_panel) { _export_panel = export_panel; } + inline decltype(_export_panel) get_export_panel() const { return _export_panel; } + + inline void set_progress(const decltype(_progress) progress) { _progress = progress; } + inline decltype(_progress) get_progress() const { return _progress; } + + inline void set_current(const int current) { _current = current; } + inline int get_current() const { return _current; } + + inline void set_total(const int total) { _total = total; } + inline int get_total() const { return _total; } +}; + +static std::string create_filepath_from_id(Glib::ustring, const Glib::ustring &); + +/** A list of strings that is used both in the preferences, and in the + data fields to describe the various values of \c selection_type. */ +static const char * selection_names[SELECTION_NUMBER_OF] = { + "page", "drawing", "selection", "custom" +}; + +/** The names on the buttons for the various selection types. */ +static const char * selection_labels[SELECTION_NUMBER_OF] = { + N_("_Page"), N_("_Drawing"), N_("_Selection"), N_("_Custom") +}; + +Export::Export() + : DialogBase("/dialogs/export/", "Export") + , current_key(SELECTION_PAGE) + , manual_key(SELECTION_PAGE) + , original_name() + , doc_export_name() + , filename_modified(false) + , update_flag(false) + , togglebox(Gtk::ORIENTATION_HORIZONTAL, 0) + , area_box(Gtk::ORIENTATION_VERTICAL, 3) + , singleexport_box(Gtk::ORIENTATION_VERTICAL, 0) + , size_box(Gtk::ORIENTATION_VERTICAL, 3) + , file_box(Gtk::ORIENTATION_VERTICAL, 3) + , unitbox(Gtk::ORIENTATION_HORIZONTAL, 0) + , unit_selector() + , units_label(_("Units:")) + , filename_box(Gtk::ORIENTATION_HORIZONTAL, 5) + , browse_label(_("_Export As..."), true) + , browse_image() + , batch_box(Gtk::ORIENTATION_HORIZONTAL, 5) + , batch_export(_("B_atch export all selected objects")) + , interlacing(_("Use interlacing")) + , bitdepth_label(_("Bit depth")) + , bitdepth_cb() + , zlib_label(_("Compression")) + , zlib_compression() + , pHYs_label(_("pHYs dpi")) + , pHYs_sb(pHYs_adj, 1.0, 2) + , antialiasing_label(_("Antialiasing")) + , antialiasing_cb() + , hide_box(Gtk::ORIENTATION_HORIZONTAL, 3) + , hide_export(_("Hide all except selected")) + , closeWhenDone(_("Close when complete")) + , button_box(Gtk::ORIENTATION_HORIZONTAL, 3) + , _prog() + , prog_dlg(nullptr) + , interrupted(false) + , prefs(nullptr) + , selectChangedConn() + , subselChangedConn() + , selectModifiedConn() +{ + batch_export.set_use_underline(); + batch_export.set_tooltip_text(_("Export each selected object into its own PNG file, using export hints if any (caution, overwrites without asking!)")); + hide_export.set_use_underline(); + hide_export.set_tooltip_text(_("In the exported image, hide all objects except those that are selected")); + interlacing.set_use_underline(); + interlacing.set_tooltip_text(_("Enables ADAM7 interlacing for PNG output. This results in slightly larger image files, but big images can already be displayed (slightly blurry) while still loading.")); + closeWhenDone.set_use_underline(); + closeWhenDone.set_tooltip_text(_("Once the export completes, close this dialog")); + prefs = Inkscape::Preferences::get(); + + singleexport_box.set_border_width(0); + + /* Export area frame */ + { + Gtk::Label* lbl = new Gtk::Label(_("Export area"), Gtk::ALIGN_START); + lbl->set_use_markup(true); + area_box.pack_start(*lbl); + + /* Units box */ + /* gets added to the vbox later, but the unit selector is needed + earlier than that */ + unit_selector.setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); + + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + unit_selector.setUnit(desktop->getNamedView()->display_units->abbr); + } + unitChangedConn = unit_selector.signal_changed().connect(sigc::mem_fun(*this, &Export::onUnitChanged)); + unitbox.pack_end(unit_selector, false, false, 0); + unitbox.pack_end(units_label, false, false, 3); + + for (int i = 0; i < SELECTION_NUMBER_OF; i++) { + selectiontype_buttons[i] = new Gtk::RadioButton(_(selection_labels[i]), true); + if (i > 0) { + Gtk::RadioButton::Group group = selectiontype_buttons[0]->get_group(); + selectiontype_buttons[i]->set_group(group); + } + selectiontype_buttons[i]->set_mode(false); + togglebox.pack_start(*selectiontype_buttons[i], false, true, 0); + selectiontype_buttons[i]->signal_clicked().connect(sigc::mem_fun(*this, &Export::onAreaTypeToggled)); + } + + auto t = new Gtk::Grid(); + t->set_row_spacing(4); + t->set_column_spacing(4); + + SPDocument *doc; + doc = SP_ACTIVE_DESKTOP->getDocument(); + + x0_adj = createSpinbutton("x0", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, t, 0, 0, _("_x0:"), "", + EXPORT_COORD_PRECISION, 1, &Export::onAreaX0Change); + + x1_adj = createSpinbutton("x1", doc->getWidth().value("mm"), -1000000.0, 1000000.0, 0.1, 1.0, t, 0, 1, + _("x_1:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaX1Change); + + width_adj = createSpinbutton("width", doc->getWidth().value("mm"), 0.0, PNG_UINT_31_MAX, 0.1, 1.0, t, 0, 2, + _("Wid_th:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaWidthChange); + + y0_adj = createSpinbutton("y0", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, t, 2, 0, _("_y0:"), "", + EXPORT_COORD_PRECISION, 1, &Export::onAreaY0Change); + + y1_adj = createSpinbutton("y1", doc->getHeight().value("mm"), -1000000.0, 1000000.0, 0.1, 1.0, t, 2, 1, + _("y_1:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaY1Change); + + height_adj = createSpinbutton("height", doc->getHeight().value("mm"), 0.0, PNG_UINT_31_MAX, 0.1, 1.0, t, 2, 2, + _("Hei_ght:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaHeightChange); + + area_box.pack_start(togglebox, false, false, 3); + area_box.pack_start(*t, false, false, 0); + area_box.pack_start(unitbox, false, false, 0); + + area_box.set_border_width(3); + singleexport_box.pack_start(area_box, false, false, 0); + + } // end of area box + + /* Bitmap size frame */ + { + SPDocument *doc; + doc = SP_ACTIVE_DESKTOP->getDocument(); + + size_box.set_border_width(3); + bm_label = new Gtk::Label(_("Image size"), Gtk::ALIGN_START); + bm_label->set_use_markup(true); + size_box.pack_start(*bm_label, false, false, 0); + + auto t = new Gtk::Grid(); + t->set_row_spacing(4); + t->set_column_spacing(4); + + size_box.pack_start(*t); + + bmwidth_adj = createSpinbutton("bmwidth", doc->getWidth().value("px"), 1.0, 1000000.0, 1.0, 10.0, t, 0, 0, + _("_Width:"), _("pixels at"), 0, 1, &Export::onBitmapWidthChange); + + xdpi_adj = createSpinbutton("xdpi", prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), 0.01, + 100000.0, 0.1, 1.0, t, 3, 0, "", _("dp_i"), 2, 1, &Export::onExportXdpiChange); + + bmheight_adj = createSpinbutton("bmheight", doc->getHeight().value("px"), 1.0, 1000000.0, 1.0, 10.0, t, 0, 1, + _("_Height:"), _("pixels at"), 0, 1, &Export::onBitmapHeightChange); + + /** TODO + * There's no way to set ydpi currently, so we use the defaultxdpi value here, too... + */ + ydpi_adj = createSpinbutton ( "ydpi", prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), + 0.01, 100000.0, 0.1, 1.0, t, 3, 1, + "", _("dpi"), 2, 0, nullptr ); + + singleexport_box.pack_start(size_box, Gtk::PACK_SHRINK); + } + + /* File entry */ + { + file_box.set_border_width(3); + flabel = new Gtk::Label(_("_Filename"), Gtk::ALIGN_START, Gtk::ALIGN_CENTER, true); + flabel->set_use_markup(true); + file_box.pack_start(*flabel, false, false, 0); + + set_default_filename(); + + filename_box.pack_start (filename_entry, true, true, 0); + + Gtk::Box* browser_im_label = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 3); + browse_image.set_from_icon_name("folder", Gtk::ICON_SIZE_BUTTON); + browser_im_label->pack_start(browse_image); + browser_im_label->pack_start(browse_label); + browse_button.add(*browser_im_label); + filename_box.pack_end (browse_button, false, false); + filename_box.pack_end(export_button, false, false); + + file_box.add(filename_box); + + original_name = filename_entry.get_text(); + + // focus is in the filename initially: + filename_entry.grab_focus(); + + // mnemonic in frame label moves focus to filename: + flabel->set_mnemonic_widget(filename_entry); + } + + batch_export.set_sensitive(true); + batch_box.pack_start(batch_export, false, false, 3); + + hide_export.set_sensitive(true); + hide_export.set_active (prefs->getBool("/dialogs/export/hideexceptselected/value", false)); + hide_box.pack_start(hide_export, false, false, 3); + + + /* Export Button row */ + export_button.set_label(_("_Export")); + export_button.set_use_underline(); + export_button.set_tooltip_text (_("Export the bitmap file with these settings")); + + button_box.set_border_width(3); + button_box.pack_start(closeWhenDone, true, true, 0); + + /*Advanced*/ + Gtk::Label *label_advanced = Gtk::manage(new Gtk::Label(_("Advanced"),true)); + expander.set_label_widget(*label_advanced); + expander.set_vexpand(false); + const char* const modes_list[]={"Gray_1", "Gray_2","Gray_4","Gray_8","Gray_16","RGB_8","RGB_16","GrayAlpha_8","GrayAlpha_16","RGBA_8","RGBA_16"}; + for(auto i : modes_list) + bitdepth_cb.append(i); + bitdepth_cb.set_active_text("RGBA_8"); + bitdepth_cb.set_hexpand(); + const char* const zlist[]={"Z_NO_COMPRESSION","Z_BEST_SPEED","2","3","4","5","Z_DEFAULT_COMPRESSION","7","8","Z_BEST_COMPRESSION"}; + for(auto i : zlist) + zlib_compression.append(i); + zlib_compression.set_active_text("Z_DEFAULT_COMPRESSION"); + pHYs_adj = Gtk::Adjustment::create(0, 0, 100000, 0.1, 1.0, 0); + pHYs_sb.set_adjustment(pHYs_adj); + pHYs_sb.set_width_chars(7); + pHYs_sb.set_tooltip_text( _("Will force-set the physical dpi for the png file. Set this to 72 if you're planning to work on your png with Photoshop") ); + zlib_compression.set_hexpand(); + const char* const antialising_list[] = {"CAIRO_ANTIALIAS_NONE","CAIRO_ANTIALIAS_FAST","CAIRO_ANTIALIAS_GOOD (default)","CAIRO_ANTIALIAS_BEST"}; + for(auto i : antialising_list) + antialiasing_cb.append(i); + antialiasing_cb.set_active_text(antialising_list[2]); + bitdepth_label.set_halign(Gtk::ALIGN_START); + zlib_label.set_halign(Gtk::ALIGN_START); + pHYs_label.set_halign(Gtk::ALIGN_START); + antialiasing_label.set_halign(Gtk::ALIGN_START); + auto table = new Gtk::Grid(); + expander.add(*table); + table->set_border_width(4); + table->attach(interlacing,0,0,1,1); + table->attach(bitdepth_label,0,1,1,1); + table->attach(bitdepth_cb,1,1,1,1); + table->attach(zlib_label,0,2,1,1); + table->attach(zlib_compression,1,2,1,1); + table->attach(pHYs_label,0,3,1,1); + table->attach(pHYs_sb,1,3,1,1); + table->attach(antialiasing_label,0,4,1,1); + table->attach(antialiasing_cb,1,4,1,1); + table->show(); + + /* Main dialog */ + set_spacing(0); + pack_start(singleexport_box, Gtk::PACK_SHRINK); + pack_start(file_box, Gtk::PACK_SHRINK); + pack_start(batch_box, Gtk::PACK_SHRINK); + pack_start(hide_box, Gtk::PACK_SHRINK); + pack_start(button_box, Gtk::PACK_SHRINK); + pack_start(expander, Gtk::PACK_SHRINK); + pack_end(_prog, Gtk::PACK_SHRINK); + + /* Signal handlers */ + filename_entry.signal_changed().connect( sigc::mem_fun(*this, &Export::onFilenameModified) ); + // pressing enter in the filename field is the same as clicking export: + filename_entry.signal_activate().connect(sigc::mem_fun(*this, &Export::onExport) ); + browse_button.signal_clicked().connect(sigc::mem_fun(*this, &Export::onBrowse)); + batch_export.signal_clicked().connect(sigc::mem_fun(*this, &Export::onBatchClicked)); + export_button.signal_clicked().connect(sigc::mem_fun(*this, &Export::onExport)); + hide_export.signal_clicked().connect(sigc::mem_fun(*this, &Export::onHideExceptSelected)); + + show_all_children(); + setExporting(false); + + findDefaultSelection(); + refreshArea(); +} + +Export::~Export () +{ + selectModifiedConn.disconnect(); + subselChangedConn.disconnect(); + selectChangedConn.disconnect(); +} + +void Export::setDesktop(SPDesktop *desktop) +{ +#if 0 + { + { + selectModifiedConn.disconnect(); + subselChangedConn.disconnect(); + selectChangedConn.disconnect(); + } + if (desktop && desktop->selection) { + + selectChangedConn = desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &Export::onSelectionChanged))); + subselChangedConn = desktop->connectToolSubselectionChanged(sigc::hide(sigc::mem_fun(*this, &Export::onSelectionChanged))); + + //// Must check flags, so can't call widget_setup() directly. + selectModifiedConn = desktop->selection->connectModified(sigc::hide<0>(sigc::mem_fun(*this, &Export::onSelectionModified))); + } + } +#endif +} + +void Export::update() +{ + if (!_app) { + std::cerr << "Export::update(): _app is null" << std::endl; + return; + } + + onSelectionChanged(); + onSelectionModified(0); +#if 0 + setDesktop(getDesktop()); +#endif +} + +/* + * set the default filename to be that of the current path + document + * with .png extension + * + * One thing to notice here is that this filename may get + * overwritten, but it won't happen here. The filename gets + * written into the text field, but then the button to select + * the area gets set. In that code the filename can be changed + * if there are some with presidence in the document. So, while + * this code sets the name first, it may not be the one users + * really see. + */ +void Export::set_default_filename () { + + if ( SP_ACTIVE_DOCUMENT && SP_ACTIVE_DOCUMENT->getDocumentFilename() ) + { + SPDocument * doc = SP_ACTIVE_DOCUMENT; + const gchar *filename = doc->getDocumentFilename(); + auto &&text_extension = get_file_save_extension(Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS); + Inkscape::Extension::Output * oextension = nullptr; + + if (!text_extension.empty()) { + oextension = dynamic_cast(Inkscape::Extension::db.get(text_extension.c_str())); + } + + if (oextension != nullptr) { + gchar * old_extension = oextension->get_extension(); + if (g_str_has_suffix(filename, old_extension)) { + gchar * filename_copy; + gchar * extension_point; + gchar * final_name; + + filename_copy = g_strdup(filename); + extension_point = g_strrstr(filename_copy, old_extension); + extension_point[0] = '\0'; + + final_name = g_strconcat(filename_copy, ".png", NULL); + filename_entry.set_text(final_name); + filename_entry.set_position(strlen(final_name)); + + g_free(final_name); + g_free(filename_copy); + } + } else { + gchar *name = g_strconcat(filename, ".png", NULL); + filename_entry.set_text(name); + filename_entry.set_position(strlen(name)); + + g_free(name); + } + + doc_export_name = filename_entry.get_text(); + } + else if ( SP_ACTIVE_DOCUMENT ) + { + Glib::ustring filename = create_filepath_from_id (_("bitmap"), filename_entry.get_text()); + filename_entry.set_text(filename); + filename_entry.set_position(filename.length()); + + doc_export_name = filename_entry.get_text(); + } +} + +Glib::RefPtr Export::createSpinbutton( gchar const * /*key*/, + double val, double min, double max, double step, double page, + Gtk::Grid *t, int x, int y, + const Glib::ustring& ll, const Glib::ustring& lr, + int digits, unsigned int sensitive, + void (Export::*cb)() ) +{ + auto adj = Gtk::Adjustment::create(val, min, max, step, page, 0); + + int pos = 0; + Gtk::Label *l = nullptr; + + if (!ll.empty()) { + l = new Gtk::Label(ll,true); + l->set_halign(Gtk::ALIGN_END); + l->set_valign(Gtk::ALIGN_CENTER); + l->set_hexpand(); + t->attach(*l, x + pos, y, 1, 1); + l->set_sensitive(sensitive); + pos++; + } + + auto sb = new Inkscape::UI::Widget::ScrollProtected(adj, 1.0, digits); + sb->set_hexpand(); + t->attach(*sb, x + pos, y, 1, 1); + + sb->set_width_chars(7); + sb->set_sensitive (sensitive); + pos++; + + if (l) { + l->set_mnemonic_widget(*sb); + } + + if (!lr.empty()) { + l = new Gtk::Label(lr,true); + l->set_halign(Gtk::ALIGN_START); + l->set_valign(Gtk::ALIGN_CENTER); + l->set_hexpand(); + t->attach(*l, x + pos, y, 1, 1); + l->set_sensitive (sensitive); + pos++; + l->set_mnemonic_widget (*sb); + } + + if (cb) { + adj->signal_value_changed().connect( sigc::mem_fun(*this, cb) ); + } + + return adj; +} // end of createSpinbutton() + + +std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_entry_text) +{ + if (id.empty()) + { /* This should never happen */ + id = "bitmap"; + } + + std::string directory; + + if (!file_entry_text.empty()) { + directory = Glib::path_get_dirname(Glib::filename_from_utf8(file_entry_text)); + } + + if (directory.empty()) { + /* Grab document directory */ + const gchar* docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); + if (docFilename) { + directory = Glib::path_get_dirname(docFilename); + } + } + + if (directory.empty()) { + directory = Inkscape::IO::Resource::homedir_path(nullptr); + } + + return Glib::build_filename(directory, Glib::filename_from_utf8(id) + ".png"); +} + +void Export::onBatchClicked () +{ + if (batch_export.get_active()) { + singleexport_box.set_sensitive(false); + } else { + singleexport_box.set_sensitive(true); + } +} + +void Export::updateCheckbuttons () +{ + gint num = (gint) boost::distance(SP_ACTIVE_DESKTOP->getSelection()->items()); + if (num >= 2) { + batch_export.set_sensitive(true); + } else { + batch_export.set_active (false); + batch_export.set_sensitive(false); + } + gchar *l = g_strdup_printf(ngettext("B_atch export %d selected object","B_atch export %d selected objects",num), num); + batch_export.set_label(l); + g_free(l); + + //hide_export.set_sensitive (num > 0); +} + +inline void Export::findDefaultSelection() +{ + selection_type key = SELECTION_NUMBER_OF; + + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { + key = SELECTION_SELECTION; + } + + /* Try using the preferences */ + if (key == SELECTION_NUMBER_OF) { + + int i = SELECTION_NUMBER_OF; + + Glib::ustring what = prefs->getString("/dialogs/export/exportarea/value"); + + if (!what.empty()) { + for (i = 0; i < SELECTION_NUMBER_OF; i++) { + if (what == selection_names[i]) { + break; + } + } + } + + key = (selection_type)i; + } + + if (key == SELECTION_NUMBER_OF) { + key = SELECTION_PAGE; + } + + current_key = key; + selectiontype_buttons[current_key]->set_active(true); + updateCheckbuttons (); +} + + +/** + * If selection changed and "Export area" is set to "Selection" + * recalculate bounds when the selection changes + */ +void Export::onSelectionChanged() +{ + Inkscape::Selection *selection = SP_ACTIVE_DESKTOP->getSelection(); + if (manual_key != SELECTION_CUSTOM && selection) { + current_key = SELECTION_SELECTION; + refreshArea(); + } + + updateCheckbuttons(); +} + +void Export::onSelectionModified ( guint /*flags*/ ) +{ + Inkscape::Selection * Sel; + switch (current_key) { + case SELECTION_DRAWING: + if ( SP_ACTIVE_DESKTOP ) { + SPDocument *doc; + doc = SP_ACTIVE_DESKTOP->getDocument(); + Geom::OptRect bbox = doc->getRoot()->desktopVisualBounds(); + if (bbox) { + setArea ( bbox->left(), + bbox->top(), + bbox->right(), + bbox->bottom()); + } + } + break; + case SELECTION_SELECTION: + Sel = SP_ACTIVE_DESKTOP->getSelection(); + if (Sel->isEmpty() == false) { + Geom::OptRect bbox = Sel->visualBounds(); + if (bbox) + { + setArea ( bbox->left(), + bbox->top(), + bbox->right(), + bbox->bottom()); + } + } + break; + default: + /* Do nothing for page or for custom */ + break; + } + + return; +} + +/// Called when one of the selection buttons was toggled. +void Export::onAreaTypeToggled() { + if (update_flag) { + return; + } + + /* Find which button is active */ + selection_type key = current_key; + for (int i = 0; i < SELECTION_NUMBER_OF; i++) { + if (selectiontype_buttons[i]->get_active()) { + key = (selection_type)i; + } + } + manual_key = current_key = key; + + refreshArea(); +} + +/// Called when area needs to be refreshed +/// Area type changed, unit changed, initialization +void Export::refreshArea () +{ + if ( SP_ACTIVE_DESKTOP ) + { + SPDocument *doc; + Geom::OptRect bbox; + bbox = Geom::Rect(Geom::Point(0.0, 0.0),Geom::Point(0.0, 0.0)); + doc = SP_ACTIVE_DESKTOP->getDocument(); + + /* Notice how the switch is used to 'fall through' here to get + various backups. If you modify this without noticing you'll + probably screw something up. */ + switch (current_key) { + case SELECTION_SELECTION: + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) + { + bbox = SP_ACTIVE_DESKTOP->getSelection()->visualBounds(); + /* Only if there is a selection that we can set + do we break, otherwise we fall through to the + drawing */ + // std::cout << "Using selection: SELECTION" << std::endl; + current_key = SELECTION_SELECTION; + break; + } + case SELECTION_DRAWING: + if (manual_key == SELECTION_DRAWING || manual_key == SELECTION_SELECTION) { + /** \todo + * This returns wrong values if the document has a viewBox. + */ + bbox = doc->getRoot()->desktopVisualBounds(); + /* If the drawing is valid, then we'll use it and break + otherwise we drop through to the page settings */ + if (bbox) { + // std::cout << "Using selection: DRAWING" << std::endl; + current_key= SELECTION_DRAWING; + break; + } + } + case SELECTION_PAGE: + if (manual_key == SELECTION_PAGE){ + bbox = Geom::Rect(Geom::Point(0.0, 0.0), + Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); + + // std::cout << "Using selection: PAGE" << std::endl; + current_key= SELECTION_PAGE; + break; + } + case SELECTION_CUSTOM: + current_key = SELECTION_CUSTOM; + default: + break; + } // switch + + // remember area setting + prefs->setString("/dialogs/export/exportarea/value", selection_names[current_key]); + + if ( current_key != SELECTION_CUSTOM && bbox ) { + setArea ( bbox->min()[Geom::X], + bbox->min()[Geom::Y], + bbox->max()[Geom::X], + bbox->max()[Geom::Y]); + } + + } // end of if ( SP_ACTIVE_DESKTOP ) + + if (SP_ACTIVE_DESKTOP && !filename_modified) { + + Glib::ustring filename; + float xdpi = 0.0, ydpi = 0.0; + + switch (current_key) { + case SELECTION_PAGE: + case SELECTION_DRAWING: { + SPDocument * doc = SP_ACTIVE_DOCUMENT; + sp_document_get_export_hints (doc, filename, &xdpi, &ydpi); + + if (filename.empty()) { + if (!doc_export_name.empty()) { + filename = doc_export_name; + } + } + break; + } + case SELECTION_SELECTION: + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { + + SP_ACTIVE_DESKTOP->getSelection()->getExportHints(filename, &xdpi, &ydpi); + + /* If we still don't have a filename -- let's build + one that's nice */ + if (filename.empty()) { + const gchar * id = "object"; + auto reprlst = SP_ACTIVE_DESKTOP->getSelection()->xmlNodes(); + for(auto i=reprlst.begin(); reprlst.end() != i; ++i) { + Inkscape::XML::Node * repr = *i; + if (repr->attribute("id")) { + id = repr->attribute("id"); + break; + } + } + + filename = create_filepath_from_id (id, filename_entry.get_text()); + } + } + break; + case SELECTION_CUSTOM: + default: + break; + } + + if (!filename.empty()) { + original_name = filename; + filename_entry.set_text(filename); + filename_entry.set_position(filename.length()); + } + + if (xdpi != 0.0) { + setValue(xdpi_adj, xdpi); + } + + /* These can't be separate, and setting x sets y, so for + now setting this is disabled. Hopefully it won't be in + the future */ + if (FALSE && ydpi != 0.0) { + setValue(ydpi_adj, ydpi); + } + } + + return; +} // end of sp_export_area_toggled() + +/// Called when dialog is deleted +bool Export::onProgressDelete (GdkEventAny * /*event*/) +{ + interrupted = true; + return TRUE; +} // end of sp_export_progress_delete() + + +/// Called when progress is cancelled +void Export::onProgressCancel () +{ + interrupted = true; +} // end of sp_export_progress_cancel() + + +/// Called for every progress iteration +unsigned int Export::onProgressCallback(float value, void *dlg) +{ + auto dlg2 = reinterpret_cast(dlg); + + auto self = dlg2->get_export_panel(); + if (self->interrupted) + return FALSE; + + auto current = dlg2->get_current(); + auto total = dlg2->get_total(); + if (total > 0) { + double completed = current; + completed /= static_cast(total); + + value = completed + (value / static_cast(total)); + } + + auto prg = dlg2->get_progress(); + prg->set_fraction(value); + + if (self) { + self->_prog.set_fraction(value); + } + + int evtcount = 0; + while ((evtcount < 16) && gdk_events_pending()) { + Gtk::Main::iteration(false); + evtcount += 1; + } + + Gtk::Main::iteration(false); + return TRUE; +} // end of sp_export_progress_callback() + +void Export::setExporting(bool exporting, Glib::ustring const &text) +{ + if (exporting) { + _prog.set_text(text); + _prog.set_fraction(0.0); + _prog.set_sensitive(true); + + export_button.set_sensitive(false); + } else { + _prog.set_text(""); + _prog.set_fraction(0.0); + _prog.set_sensitive(false); + + export_button.set_sensitive(true); + } +} + +ExportProgressDialog * +Export::create_progress_dialog(Glib::ustring progress_text) +{ + auto dlg = new ExportProgressDialog(_("Export in progress"), true); + dlg->set_transient_for( *(INKSCAPE.active_desktop()->getToplevel()) ); + + Gtk::ProgressBar *prg = new Gtk::ProgressBar (); + prg->set_text(progress_text); + dlg->set_progress(prg); + auto CA = dlg->get_content_area(); + CA->pack_start(*prg, FALSE, FALSE, 4); + + Gtk::Button* btn = dlg->add_button (_("_Cancel"),Gtk::RESPONSE_CANCEL ); + + btn->signal_clicked().connect( sigc::mem_fun(*this, &Export::onProgressCancel) ); + dlg->signal_delete_event().connect( sigc::mem_fun(*this, &Export::onProgressDelete) ); + + dlg->show_all (); + return dlg; +} + +static std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename) +{ + std::string path; + //Make relative paths go from the document location, if possible: + if (!Glib::path_is_absolute(filename) && doc->getDocumentFilename()) { + auto dirname = Glib::path_get_dirname(doc->getDocumentFilename()); + if (!dirname.empty()) { + path = Glib::build_filename(dirname, filename); + } + } + if (path.empty()) { + path = filename; + } + return path; +} + +// Called when unit is changed +void Export::onUnitChanged() +{ + refreshArea(); +} + +void Export::onHideExceptSelected () +{ + prefs->setBool("/dialogs/export/hideexceptselected/value", hide_export.get_active()); +} + +/// Called when export button is clicked +void Export::onExport () +{ + _export_raster(nullptr); +} + +void Export::_export_raster(Inkscape::Extension::Output *extension) +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (!desktop) return; + + SPNamedView *nv = desktop->getNamedView(); + SPDocument *doc = desktop->getDocument(); + + bool exportSuccessful = false; + + bool hide = hide_export.get_active (); + + // Advanced parameters + bool do_interlace = (interlacing.get_active()); + float pHYs = 0; + int zlib = zlib_compression.get_active_row_number() ; + int colortypes[] = {0,0,0,0,0,2,2,4,4,6,6}; //keep in sync with modes_list in Export constructor. values are from libpng doc. + int bitdepths[] = {1,2,4,8,16,8,16,8,16,8,16}; + int color_type = colortypes[bitdepth_cb.get_active_row_number()] ; + int bit_depth = bitdepths[bitdepth_cb.get_active_row_number()] ; + int antialiasing = antialiasing_cb.get_active_row_number(); + + + if (batch_export.get_active ()) { + // Batch export of selected objects + + gint num = (gint) boost::distance(desktop->getSelection()->items()); + gint n = 0; + + if (num < 1) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No items selected.")); + return; + } + + prog_dlg = create_progress_dialog(Glib::ustring::compose(_("Exporting %1 files"), num)); + prog_dlg->set_export_panel(this); + setExporting(true, Glib::ustring::compose(_("Exporting %1 files"), num)); + + gint export_count = 0; + + auto itemlist= desktop->getSelection()->items(); + for(auto i = itemlist.begin();i!=itemlist.end() && !interrupted ;++i){ + SPItem *item = *i; + + prog_dlg->set_current(n); + prog_dlg->set_total(num); + onProgressCallback(0.0, prog_dlg); + + // retrieve export filename hint + const gchar *filename = item->getRepr()->attribute("inkscape:export-filename"); + std::string path; + if (!filename) { + auto id = item->getId(); + if (!id) { + g_warning("object has no id"); + continue; + } + path = create_filepath_from_id(id, filename_entry.get_text()); + } else { + path = absolutize_path_from_document_location(doc, filename); + } + + // retrieve export dpi hints + const gchar *dpi_hint = item->getRepr()->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now + gdouble dpi = 0.0; + if (dpi_hint) { + dpi = g_ascii_strtod(dpi_hint, nullptr); + } + if (dpi == 0.0) { + dpi = getValue(xdpi_adj); + } + pHYs = (pHYs_adj->get_value() > 0.01) ? pHYs_adj->get_value() : dpi; + + Geom::OptRect area = item->documentVisualBounds(); + if (area) { + gint width = (gint) (area->width() * dpi / DPI_BASE + 0.5); + gint height = (gint) (area->height() * dpi / DPI_BASE + 0.5); + + if (width > 1 && height > 1) { + // Do export + gchar * safeFile = Inkscape::IO::sanitizeString(path.c_str()); + MessageCleaner msgCleanup(desktop->messageStack()->pushF(Inkscape::IMMEDIATE_MESSAGE, + _("Exporting file %s..."), safeFile), desktop); + MessageCleaner msgFlashCleanup(desktop->messageStack()->flashF(Inkscape::IMMEDIATE_MESSAGE, + _("Exporting file %s..."), safeFile), desktop); + std::vector x; + std::vector selected(desktop->getSelection()->items().begin(), desktop->getSelection()->items().end()); + if (!sp_export_png_file (doc, path.c_str(), + *area, width, height, pHYs, pHYs, + nv->pagecolor, + onProgressCallback, (void*)prog_dlg, + TRUE, // overwrite without asking + hide ? selected : x, + do_interlace, color_type, bit_depth, zlib, antialiasing + )) { + gchar * error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); + + desktop->messageStack()->flashF(Inkscape::ERROR_MESSAGE, + _("Could not export to filename %s."), safeFile); + + sp_ui_error_dialog(error); + g_free(error); + } else { + ++export_count; // one more item exported successfully + } + g_free(safeFile); + } + } + + n++; + } + + desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, + _("Successfully exported %d files from %d selected items."), export_count, num); + + setExporting(false); + delete prog_dlg; + prog_dlg = nullptr; + interrupted = false; + exportSuccessful = (export_count > 0); + } else { + Glib::ustring filename = filename_entry.get_text(); + + if (filename.empty()) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You have to enter a filename.")); + sp_ui_error_dialog(_("You have to enter a filename")); + return; + } + + float const x0 = getValuePx(x0_adj); + float const y0 = getValuePx(y0_adj); + float const x1 = getValuePx(x1_adj); + float const y1 = getValuePx(y1_adj); + float const xdpi = getValue(xdpi_adj); + float const ydpi = getValue(ydpi_adj); + pHYs = (pHYs_adj->get_value() > 0.01) ? pHYs_adj->get_value() : xdpi; + unsigned long int const width = int(getValue(bmwidth_adj) + 0.5); + unsigned long int const height = int(getValue(bmheight_adj) + 0.5); + + if (!((x1 > x0) && (y1 > y0) && (width > 0) && (height > 0))) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("The chosen area to be exported is invalid.")); + sp_ui_error_dialog(_("The chosen area to be exported is invalid")); + return; + } + + std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(filename)); + + Glib::ustring dirname = Glib::path_get_dirname(path); + if ( dirname.empty() + || !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) ) + { + gchar *safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); + gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), + safeDir); + + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); + sp_ui_error_dialog(error); + + g_free(safeDir); + g_free(error); + return; + } + + auto fn = Glib::path_get_basename(path); + auto area = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * desktop->dt2doc(); + + // Select a raster output extension if not a png file (manual filename) + if (!extension && !Glib::str_has_suffix(filename, ".png")) { + Inkscape::Extension::DB::OutputList extension_list; + Inkscape::Extension::db.get_output_list(extension_list); + for (auto output_ext : extension_list) { + if (output_ext->deactivated() || !output_ext->is_raster()) + continue; + if(Glib::str_has_suffix(path.c_str(), output_ext->get_extension())) { + // Select the extension + extension = output_ext; + break; + } + } + } + + bool overwrite = false; + auto png_filename = std::string(path.c_str()); + if (extension) { + // Select the extension and set the filename to a temporary file + int tempfd_out = Glib::file_open_tmp(png_filename, "ink_ext_"); + // Do the over-write protection now, since the png is just a temp file. + if (!sp_ui_overwrite_file(filename.c_str())) { + return; + } + overwrite = true; + close(tempfd_out); + } + + /* TRANSLATORS: %1 will be the filename, %2 the width, and %3 the height of the image */ + prog_dlg = create_progress_dialog (Glib::ustring::compose(_("Exporting %1 (%2 x %3)"), fn, width, height)); + prog_dlg->set_export_panel(this); + setExporting(true, Glib::ustring::compose(_("Exporting %1 (%2 x %3)"), fn, width, height)); + + prog_dlg->set_current(0); + prog_dlg->set_total(0); + + /* Do export */ + std::vector x; + std::vector selected(desktop->getSelection()->items().begin(), desktop->getSelection()->items().end()); + ExportResult status = sp_export_png_file(desktop->getDocument(), png_filename.c_str(), + area, width, height, pHYs, pHYs, //previously xdpi, ydpi. + nv->pagecolor, + onProgressCallback, (void*)prog_dlg, + overwrite, + hide ? selected : x, + do_interlace, color_type, bit_depth, zlib, antialiasing + ); + if (status == EXPORT_ERROR) { + gchar * safeFile = Inkscape::IO::sanitizeString(path.c_str()); + gchar * error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); + + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); + sp_ui_error_dialog(error); + + g_free(safeFile); + g_free(error); + } else if (status == EXPORT_OK) { + + exportSuccessful = true; + if(extension != nullptr) { + // Remove progress dialog before showing prefs dialog. + delete prog_dlg; + prog_dlg = nullptr; + if(extension->prefs()) { + try { + extension->export_raster(doc, png_filename, path.c_str(), false); + } catch (Inkscape::Extension::Output::save_failed &e) { + exportSuccessful = false; + } + } else { + exportSuccessful = false; + } + } + + if (exportSuccessful) { + auto recentmanager = Gtk::RecentManager::get_default(); + if(recentmanager && Glib::path_is_absolute(path)) { + Glib::ustring uri = Glib::filename_to_uri(path); + recentmanager->add_item(uri); + } + + gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); + desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, _("Drawing exported to %s."), safeFile); + g_free(safeFile); + } + } else { + // Extensions have their own error popup, so this only tracks failures in the png step + desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE, _("Export aborted.")); + } + if (extension != nullptr) { + unlink(png_filename.c_str()); + } + + /* Reset the filename so that it can be changed again by changing + selections and all that */ + original_name = filename; + filename_modified = false; + + setExporting(false); + if(prog_dlg) { + delete prog_dlg; + prog_dlg = nullptr; + } + interrupted = false; + + /* Setup the values in the document */ + switch (current_key) { + case SELECTION_PAGE: + case SELECTION_DRAWING: { + SPDocument * doc = SP_ACTIVE_DOCUMENT; + Inkscape::XML::Node * repr = doc->getReprRoot(); + bool modified = false; + + bool saved = DocumentUndo::getUndoSensitive(doc); + DocumentUndo::setUndoSensitive(doc, false); + + gchar const *temp_string = repr->attribute("inkscape:export-filename"); + if (temp_string == nullptr || (filename != temp_string)) { + repr->setAttribute("inkscape:export-filename", filename); + modified = true; + } + temp_string = repr->attribute("inkscape:export-xdpi"); + if (temp_string == nullptr || xdpi != g_ascii_strtod(temp_string, nullptr)) { + repr->setAttributeSvgDouble("inkscape:export-xdpi", xdpi); + modified = true; + } + temp_string = repr->attribute("inkscape:export-ydpi"); + if (temp_string == nullptr || ydpi != g_ascii_strtod(temp_string, nullptr)) { + repr->setAttributeSvgDouble("inkscape:export-ydpi", ydpi); + modified = true; + } + DocumentUndo::setUndoSensitive(doc, saved); + + if (modified) { + doc->setModifiedSinceSave(); + } + break; + } + case SELECTION_SELECTION: { + SPDocument * doc = SP_ACTIVE_DOCUMENT; + bool modified = false; + + bool saved = DocumentUndo::getUndoSensitive(doc); + DocumentUndo::setUndoSensitive(doc, false); + auto reprlst = desktop->getSelection()->xmlNodes(); + + for(auto i=reprlst.begin(); reprlst.end() != i; ++i) { + Inkscape::XML::Node * repr = *i; + const gchar * temp_string; + Glib::ustring dir = Glib::path_get_dirname(filename.c_str()); + const gchar* docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); + Glib::ustring docdir; + if (docFilename) + { + docdir = Glib::path_get_dirname(docFilename); + } + temp_string = repr->attribute("inkscape:export-filename"); + if (temp_string == nullptr || (filename != temp_string)) { + repr->setAttribute("inkscape:export-filename", filename); + modified = true; + } + + temp_string = repr->attribute("inkscape:export-xdpi"); + if (temp_string == nullptr || xdpi != g_ascii_strtod(temp_string, nullptr)) { + repr->setAttributeSvgDouble("inkscape:export-xdpi", xdpi); + modified = true; + } + temp_string = repr->attribute("inkscape:export-ydpi"); + if (temp_string == nullptr || ydpi != g_ascii_strtod(temp_string, nullptr)) { + repr->setAttributeSvgDouble("inkscape:export-ydpi", ydpi); + modified = true; + } + } + DocumentUndo::setUndoSensitive(doc, saved); + + if (modified) { + doc->setModifiedSinceSave(); + } + break; + } + default: + break; + } + } + + if (exportSuccessful && closeWhenDone.get_active()) { + for (Gtk::Container *parent = get_parent(); parent; parent = parent->get_parent()) { + DialogNotebook *notebook = dynamic_cast(parent); + if (notebook) { + notebook->close_tab_callback(); + break; + } + } + } +} // end of Export::onExport() + +/// Called when Browse button is clicked +void Export::onBrowse () +{ + // Create and show the dialog + Gtk::Window *window = _app->get_active_window(); + std::string filename = Glib::filename_from_utf8(filename_entry.get_text()); + + if (filename.empty()) { + Glib::ustring tmp; + filename = create_filepath_from_id(tmp, tmp); + } + + Inkscape::UI::Dialog::FileSaveDialog *dialog = Inkscape::UI::Dialog::FileSaveDialog::create( + *window, filename, Inkscape::UI::Dialog::RASTER_TYPES, _("Select a filename for exporting"), "", "", + Inkscape::Extension::FILE_SAVE_METHOD_EXPORT); + + if (dialog->show()) { + auto file = dialog->getFilename(); + filename_entry.set_text(Glib::filename_to_utf8(file)); + filename_entry.set_position(-1); + auto selection_type = dialog->getSelectionType(); + //deleting dialog before exporting is important + //proper delete function should be made for dialog IMO + delete dialog; + _export_raster(dynamic_cast(selection_type)); + }else { + delete dialog; + } + +} + +// TODO: Move this to nr-rect-fns.h. +bool Export::bbox_equal(Geom::Rect const &one, Geom::Rect const &two) +{ + double const epsilon = pow(10.0, -EXPORT_COORD_PRECISION); + return ( + (fabs(one.min()[Geom::X] - two.min()[Geom::X]) < epsilon) && + (fabs(one.min()[Geom::Y] - two.min()[Geom::Y]) < epsilon) && + (fabs(one.max()[Geom::X] - two.max()[Geom::X]) < epsilon) && + (fabs(one.max()[Geom::Y] - two.max()[Geom::Y]) < epsilon) + ); +} + +/** + *This function is used to detect the current selection setting + * based on the values in the x0, y0, x1 and y0 fields. + * + * One of the most confusing parts of this function is why the array + * is built at the beginning. What needs to happen here is that we + * should always check the current selection to see if it is the valid + * one. While this is a performance improvement it is also a usability + * one during the cases where things like selections and drawings match + * size. This way buttons change less 'randomly' (at least in the eyes + * of the user). To do this an array is built where the current selection + * type is placed first, and then the others in an order from smallest + * to largest (this can be configured by reshuffling \c test_order). + * + * All of the values in this function are rounded to two decimal places + * because that is what is shown to the user. While everything is kept + * more accurate than that, the user can't control more accurate than + * that, so for this to work for them - it needs to check on that level + * of accuracy. + * + * @todo finish writing this up. + */ +void Export::detectSize() { + static const selection_type test_order[SELECTION_NUMBER_OF] = {SELECTION_SELECTION, SELECTION_DRAWING, SELECTION_PAGE, SELECTION_CUSTOM}; + selection_type this_test[SELECTION_NUMBER_OF + 1]; + selection_type key = SELECTION_NUMBER_OF; + + Geom::Point x(getValuePx(x0_adj), + getValuePx(y0_adj)); + Geom::Point y(getValuePx(x1_adj), + getValuePx(y1_adj)); + Geom::Rect current_bbox(x, y); + + this_test[0] = current_key; + for (int i = 0; i < SELECTION_NUMBER_OF; i++) { + this_test[i + 1] = test_order[i]; + } + + for (int i = 0; + i < SELECTION_NUMBER_OF + 1 && + key == SELECTION_NUMBER_OF && + SP_ACTIVE_DESKTOP != nullptr; + i++) { + switch (this_test[i]) { + case SELECTION_SELECTION: + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { + Geom::OptRect bbox = (SP_ACTIVE_DESKTOP->getSelection())->bounds(SPItem::VISUAL_BBOX); + + if ( bbox && bbox_equal(*bbox,current_bbox)) { + key = SELECTION_SELECTION; + } + } + break; + case SELECTION_DRAWING: { + SPDocument *doc = SP_ACTIVE_DESKTOP->getDocument(); + + Geom::OptRect bbox = doc->getRoot()->desktopVisualBounds(); + + if ( bbox && bbox_equal(*bbox,current_bbox) ) { + key = SELECTION_DRAWING; + } + break; + } + + case SELECTION_PAGE: { + SPDocument *doc; + + doc = SP_ACTIVE_DESKTOP->getDocument(); + + Geom::Point x(0.0, 0.0); + Geom::Point y(doc->getWidth().value("px"), + doc->getHeight().value("px")); + Geom::Rect bbox(x, y); + + if (bbox_equal(bbox,current_bbox)) { + key = SELECTION_PAGE; + } + + break; + } + default: + break; + } + } + // std::cout << std::endl; + + if (key == SELECTION_NUMBER_OF) { + key = SELECTION_CUSTOM; + } + + current_key = key; + selectiontype_buttons[current_key]->set_active(true); + + return; +} /* sp_export_detect_size */ + +/// Called when area x0 value is changed +void Export::areaXChange(Glib::RefPtr& adj) +{ + float x0, x1, xdpi, width; + + if (update_flag) { + return; + } + + update_flag = true; + + x0 = getValuePx(x0_adj); + x1 = getValuePx(x1_adj); + xdpi = getValue(xdpi_adj); + + width = floor ((x1 - x0) * xdpi / DPI_BASE + 0.5); + + if (width < SP_EXPORT_MIN_SIZE) { + width = SP_EXPORT_MIN_SIZE; + + if (adj == x1_adj) { + x1 = x0 + width * DPI_BASE / xdpi; + setValuePx(x1_adj, x1); + } else { + x0 = x1 - width * DPI_BASE / xdpi; + setValuePx(x0_adj, x0); + } + } + + setValuePx(width_adj, x1 - x0); + setValue(bmwidth_adj, width); + + detectSize(); + + update_flag = false; + + return; +} // end of sp_export_area_x_value_changed() + +/// Called when area y0 value is changed. +void Export::areaYChange(Glib::RefPtr& adj) +{ + float y0, y1, ydpi, height; + + if (update_flag) { + return; + } + + update_flag = true; + + y0 = getValuePx(y0_adj); + y1 = getValuePx(y1_adj); + ydpi = getValue(ydpi_adj); + + height = floor ((y1 - y0) * ydpi / DPI_BASE + 0.5); + + if (height < SP_EXPORT_MIN_SIZE) { + height = SP_EXPORT_MIN_SIZE; + if (adj == y1_adj) { + //if (!strcmp (key, "y0")) { + y1 = y0 + height * DPI_BASE / ydpi; + setValuePx(y1_adj, y1); + } else { + y0 = y1 - height * DPI_BASE / ydpi; + setValuePx(y0_adj, y0); + } + } + + setValuePx(height_adj, y1 - y0); + setValue(bmheight_adj, height); + + detectSize(); + + update_flag = false; + + return; +} // end of sp_export_area_y_value_changed() + +/// Called when x1-x0 or area width is changed +void Export::onAreaWidthChange() +{ + if (update_flag) { + return; + } + + update_flag = true; + + float x0 = getValuePx(x0_adj); + float xdpi = getValue(xdpi_adj); + float width = getValuePx(width_adj); + float bmwidth = floor(width * xdpi / DPI_BASE + 0.5); + + if (bmwidth < SP_EXPORT_MIN_SIZE) { + + bmwidth = SP_EXPORT_MIN_SIZE; + width = bmwidth * DPI_BASE / xdpi; + setValuePx(width_adj, width); + } + + setValuePx(x1_adj, x0 + width); + setValue(bmwidth_adj, bmwidth); + + update_flag = false; + + return; +} // end of sp_export_area_width_value_changed() + +/// Called when y1-y0 or area height is changed. +void Export::onAreaHeightChange() +{ + if (update_flag) { + return; + } + + update_flag = true; + + float y0 = getValuePx(y0_adj); + //float y1 = sp_export_value_get_px(y1_adj); + float ydpi = getValue(ydpi_adj); + float height = getValuePx(height_adj); + float bmheight = floor (height * ydpi / DPI_BASE + 0.5); + + if (bmheight < SP_EXPORT_MIN_SIZE) { + bmheight = SP_EXPORT_MIN_SIZE; + height = bmheight * DPI_BASE / ydpi; + setValuePx(height_adj, height); + } + + setValuePx(y1_adj, y0 + height); + setValue(bmheight_adj, bmheight); + + update_flag = false; + + return; +} // end of sp_export_area_height_value_changed() + +/** + * A function to set the ydpi. + * @param base The export dialog. + * + * This function grabs all of the y values and then figures out the + * new bitmap size based on the changing dpi value. The dpi value is + * gotten from the xdpi setting as these can not currently be independent. + */ +void Export::setImageY() +{ + float y0, y1, xdpi; + + y0 = getValuePx(y0_adj); + y1 = getValuePx(y1_adj); + xdpi = getValue(xdpi_adj); + + setValue(ydpi_adj, xdpi); + setValue(bmheight_adj, (y1 - y0) * xdpi / DPI_BASE); + + return; +} // end of setImageY() + +/** + * A function to set the xdpi. + * + * This function grabs all of the x values and then figures out the + * new bitmap size based on the changing dpi value. The dpi value is + * gotten from the xdpi setting as these can not currently be independent. + * + */ +void Export::setImageX() +{ + float x0, x1, xdpi; + + x0 = getValuePx(x0_adj); + x1 = getValuePx(x1_adj); + xdpi = getValue(xdpi_adj); + + setValue(ydpi_adj, xdpi); + setValue(bmwidth_adj, (x1 - x0) * xdpi / DPI_BASE); + + return; +} // end of setImageX() + +/// Called when pixel width is changed +void Export::onBitmapWidthChange () +{ + float x0, x1, bmwidth, xdpi; + + if (update_flag) { + return; + } + + update_flag = true; + + x0 = getValuePx(x0_adj); + x1 = getValuePx(x1_adj); + bmwidth = getValue(bmwidth_adj); + + if (bmwidth < SP_EXPORT_MIN_SIZE) { + bmwidth = SP_EXPORT_MIN_SIZE; + setValue(bmwidth_adj, bmwidth); + } + + xdpi = bmwidth * DPI_BASE / (x1 - x0); + setValue(xdpi_adj, xdpi); + + setImageY (); + + update_flag = false; + + return; +} // end of sp_export_bitmap_width_value_changed() + +/// Called when pixel height is changed +void Export::onBitmapHeightChange () +{ + float y0, y1, bmheight, xdpi; + + if (update_flag) { + return; + } + + update_flag = true; + + y0 = getValuePx(y0_adj); + y1 = getValuePx(y1_adj); + bmheight = getValue(bmheight_adj); + + if (bmheight < SP_EXPORT_MIN_SIZE) { + bmheight = SP_EXPORT_MIN_SIZE; + setValue(bmheight_adj, bmheight); + } + + xdpi = bmheight * DPI_BASE / (y1 - y0); + setValue(xdpi_adj, xdpi); + + setImageX (); + + update_flag = false; + + return; +} // end of sp_export_bitmap_width_value_changed() + +/** + * A function to adjust the bitmap width when the xdpi value changes. + * + * The first thing this function checks is to see if we are doing an + * update. If we are, this function just returns because there is another + * instance of it that will handle everything for us. If there is a + * units change, we also assume that everyone is being updated appropriately + * and there is nothing for us to do. + * + * If we're the highest level function, we set the update flag, and + * continue on our way. + * + * All of the values are grabbed using the \c sp_export_value_get functions + * (call to the _pt ones for x0 and x1 but just standard for xdpi). The + * xdpi value is saved in the preferences for the next time the dialog + * is opened. (does the selection dpi need to be set here?) + * + * A check is done to to ensure that we aren't outputting an invalid width, + * this is set by SP_EXPORT_MIN_SIZE. If that is the case the dpi is + * changed to make it valid. + * + * After all of this the bitmap width is changed. + * + * We also change the ydpi. This is a temporary hack as these can not + * currently be independent. This is likely to change in the future. + * + */ +void Export::onExportXdpiChange() +{ + float x0, x1, xdpi, bmwidth; + + if (update_flag) { + return; + } + + update_flag = true; + + x0 = getValuePx(x0_adj); + x1 = getValuePx(x1_adj); + xdpi = getValue(xdpi_adj); + + // remember xdpi setting + prefs->setDouble("/dialogs/export/defaultxdpi/value", xdpi); + + bmwidth = (x1 - x0) * xdpi / DPI_BASE; + + if (bmwidth < SP_EXPORT_MIN_SIZE) { + bmwidth = SP_EXPORT_MIN_SIZE; + if (x1 != x0) + xdpi = bmwidth * DPI_BASE / (x1 - x0); + else + xdpi = DPI_BASE; + setValue(xdpi_adj, xdpi); + } + + setValue(bmwidth_adj, bmwidth); + + setImageY (); + + update_flag = false; + + return; +} // end of sp_export_xdpi_value_changed() + + +/** + * A function to change the area that is used for the exported. + * bitmap. + * + * This function just calls \c sp_export_value_set_px for each of the + * parameters that is passed in. This allows for setting them all in + * one convenient area. + * + * Update is set to suspend all of the other test running while all the + * values are being set up. This allows for a performance increase, but + * it also means that the wrong type won't be detected with only some of + * the values set. After all the values are set everyone is told that + * there has been an update. + * + * @param x0 Horizontal upper left hand corner of the picture in points. + * @param y0 Vertical upper left hand corner of the picture in points. + * @param x1 Horizontal lower right hand corner of the picture in points. + * @param y1 Vertical lower right hand corner of the picture in points. + */ +void Export::setArea( double x0, double y0, double x1, double y1 ) +{ + update_flag = true; + setValuePx(x1_adj, x1); + setValuePx(y1_adj, y1); + setValuePx(x0_adj, x0); + setValuePx(y0_adj, y0); + update_flag = false; + + areaXChange (x1_adj); + areaYChange (y1_adj); + + return; +} + +/** + * Sets the value of an adjustment. + * + * @param adj The adjustment widget + * @param val What value to set it to. + */ +void Export::setValue(Glib::RefPtr& adj, double val ) +{ + if (adj) { + adj->set_value(val); + } +} + +/** + * A function to set a value using the units points. + * + * This function first gets the adjustment for the key that is passed + * in. It then figures out what units are currently being used in the + * dialog. After doing all of that, it then converts the incoming + *value and sets the adjustment. + * + * @param adj The adjustment widget + * @param val What the value should be in points. + */ +void Export::setValuePx(Glib::RefPtr& adj, double val) +{ + Unit const *unit = unit_selector.getUnit(); + + setValue(adj, Inkscape::Util::Quantity::convert(val, "px", unit)); + + return; +} + +/** + * Get the value of an adjustment in the export dialog. + * + * This function gets the adjustment from the data field in the export + * dialog. It then grabs the value from the adjustment. + * + * @param adj The adjustment widget + * + * @return The value in the specified adjustment. + */ +float Export::getValue(Glib::RefPtr& adj) +{ + if (!adj) { + g_message("sp_export_value_get : adj is NULL"); + return 0.0; + } + return adj->get_value(); +} + +/** + * Grabs a value in the export dialog and converts the unit + * to points. + * + * This function, at its most basic, is a call to \c sp_export_value_get + * to get the value of the adjustment. It then finds the units that + * are being used by looking at the "units" attribute of the export + * dialog. Using that it converts the returned value into points. + * + * @param adj The adjustment widget + * + * @return The value in the adjustment in points. + */ +float Export::getValuePx(Glib::RefPtr& adj) +{ + float value = getValue( adj); + Unit const *unit = unit_selector.getUnit(); + + return Inkscape::Util::Quantity::convert(value, unit, "px"); +} // end of sp_export_value_get_px() + +/** + * This function is called when the filename is changed by + * anyone. It resets the virgin bit. + * + * This function gets called when the text area is modified. It is + * looking for the case where the text area is modified from its + * original value. In that case it sets the "filename-modified" bit + * to TRUE. If the text dialog returns back to the original text, the + * bit gets reset. This should stop simple mistakes. + */ +void Export::onFilenameModified() +{ + if (original_name == filename_entry.get_text()) { + filename_modified = false; + } else { + filename_modified = true; + } + + return; +} // end sp_export_filename_modified + +} +} +} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/export-old.h b/src/ui/dialog/export-old.h new file mode 100644 index 0000000000..7379508351 --- /dev/null +++ b/src/ui/dialog/export-old.h @@ -0,0 +1,371 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Authors: + * Lauris Kaplinski + * bulia byak + * Johan Engelen + * + * Copyright (C) 1999-2007 Authors + * Copyright (C) 2001-2002 Ximian, Inc. + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SP_EXPORT_H +#define SP_EXPORT_H + +#include +#include +#include +#include +#include +#include +#include + +#include "extension/output.h" +#include "ui/dialog/dialog-base.h" +#include "ui/widget/scrollprotected.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { + +class ExportProgressDialog; + +/** What type of button is being pressed */ +enum selection_type { + SELECTION_PAGE = 0, /**< Export the whole page */ + SELECTION_DRAWING, /**< Export everything drawn on the page */ + SELECTION_SELECTION, /**< Export everything that is selected */ + SELECTION_CUSTOM, /**< Allows the user to set the region exported */ + SELECTION_NUMBER_OF /**< A counter for the number of these guys */ +}; + +/** + * A dialog widget to export to various image formats such as bitmap and png. + * + * Creates a dialog window for exporting an image to a bitmap if one doesn't already exist and + * shows it to the user. If the dialog has already been created, it simply shows the window. + * + */ +class Export : public DialogBase +{ +public: + Export (); + ~Export () override; + + static Export &getInstance() { + return *new Export(); + } + +private: + + /** + * A function to set the xdpi. + * + * This function grabs all of the x values and then figures out the + * new bitmap size based on the changing dpi value. The dpi value is + * gotten from the xdpi setting as these can not currently be independent. + * + */ + void setImageX(); + + /** + * A function to set the ydpi. + * + * This function grabs all of the y values and then figures out the + * new bitmap size based on the changing dpi value. The dpi value is + * gotten from the xdpi setting as these can not currently be independent. + */ + void setImageY(); + bool bbox_equal(Geom::Rect const &one, Geom::Rect const &two); + void updateCheckbuttons (); + inline void findDefaultSelection(); + void detectSize(); + void setArea ( double x0, double y0, double x1, double y1); + /* + * Getter/setter style functions for the spinbuttons + */ + void setValue(Glib::RefPtr& adj, double val); + void setValuePx(Glib::RefPtr& adj, double val); + float getValue(Glib::RefPtr& adj); + float getValuePx(Glib::RefPtr& adj); + + /** + * Helper function to create, style and pack spinbuttons for the export dialog. + * + * Creates a new spin button for the export dialog. + * @param key The name of the spin button + * @param val A default value for the spin button + * @param min Minimum value for the spin button + * @param max Maximum value for the spin button + * @param step The step size for the spin button + * @param page Size of the page increment + * @param t Table to put the spin button in + * @param x X location in the table \c t to start with + * @param y Y location in the table \c t to start with + * @param ll Text to put on the left side of the spin button (optional) + * @param lr Text to put on the right side of the spin button (optional) + * @param digits Number of digits to display after the decimal + * @param sensitive Whether the spin button is sensitive or not + * @param cb Callback for when this spin button is changed (optional) + * + * No unit_selector is stored in the created spinbutton, relies on external unit management + */ + Glib::RefPtr createSpinbutton( gchar const *key, + double val, double min, double max, double step, double page, + Gtk::Grid *t, int x, int y, + const Glib::ustring& ll, const Glib::ustring& lr, + int digits, unsigned int sensitive, + void (Export::*cb)() ); + + /** + * One of the area select radio buttons was pressed + */ + void onAreaTypeToggled(); + void refreshArea(); + + /** + * Export button callback + */ + void onExport (); + void _export_raster(Inkscape::Extension::Output *extension); + + /** + * File Browse button callback + */ + void onBrowse (); + + /** + * Area X value changed callback + */ + void onAreaX0Change() { + areaXChange(x0_adj); + } ; + void onAreaX1Change() { + areaXChange(x1_adj); + } ; + void areaXChange(Glib::RefPtr& adj); + + /** + * Area Y value changed callback + */ + void onAreaY0Change() { + areaYChange(y0_adj); + } ; + void onAreaY1Change() { + areaYChange(y1_adj); + } ; + void areaYChange(Glib::RefPtr& adj); + + /** + * Unit changed callback + */ + void onUnitChanged(); + + /** + * Hide except selected callback + */ + void onHideExceptSelected (); + + /** + * Area width value changed callback + */ + void onAreaWidthChange (); + + /** + * Area height value changed callback + */ + void onAreaHeightChange (); + + /** + * Bitmap width value changed callback + */ + void onBitmapWidthChange (); + + /** + * Bitmap height value changed callback + */ + void onBitmapHeightChange (); + + /** + * Export xdpi value changed callback + */ + void onExportXdpiChange (); + + /** + * Batch export callback + */ + void onBatchClicked (); + + /** + * Inkscape selection change callback + */ + void onSelectionChanged (); + void onSelectionModified (guint flags); + + /** + * Filename modified callback + */ + void onFilenameModified (); + + /** + * Can be invoked for setting the desktop. Currently not used. + */ + void setDesktop(SPDesktop *desktop); + + /** + * Update active window. + */ + void update() override; + + /** + * Creates progress dialog for batch exporting. + * + * @param progress_text Text to be shown in the progress bar + */ + ExportProgressDialog * create_progress_dialog(Glib::ustring progress_text); + + /** + * Callback to be used in for loop to update the progress bar. + * + * @param value number between 0 and 1 indicating the fraction of progress (0.17 = 17 % progress) + * @param dlg void pointer to the Gtk::Dialog progress dialog + */ + static unsigned int onProgressCallback(float value, void *dlg); + + /** + * Callback for pressing the cancel button. + */ + void onProgressCancel (); + + /** + * Callback invoked on closing the progress dialog. + */ + bool onProgressDelete (GdkEventAny *event); + + /** + * Handles state changes as exporting starts or stops. + */ + void setExporting(bool exporting, Glib::ustring const &text = ""); + + /* + * Utility filename and path functions + */ + void set_default_filename (); + + /* + * Currently selected export area type + * can be changed by code + */ + selection_type current_key; + /* + * Manually selected export area type(only changed by buttons) + */ + selection_type manual_key; + /* + * Original name for the export object + */ + Glib::ustring original_name; + Glib::ustring doc_export_name; + /* + * Was the Original name modified + */ + bool filename_modified; + + /* + * Flag to stop simultaneous updates + */ + bool update_flag; + + /* Area selection radio buttons */ + Gtk::Box togglebox; + Gtk::RadioButton *selectiontype_buttons[SELECTION_NUMBER_OF]; + + Gtk::Box area_box; + Gtk::Box singleexport_box; + + /* Custom size widgets */ + Glib::RefPtr x0_adj; + Glib::RefPtr x1_adj; + Glib::RefPtr y0_adj; + Glib::RefPtr y1_adj; + Glib::RefPtr width_adj; + Glib::RefPtr height_adj; + + /* Bitmap size widgets */ + Glib::RefPtr bmwidth_adj; + Glib::RefPtr bmheight_adj; + Glib::RefPtr xdpi_adj; + Glib::RefPtr ydpi_adj; + + Gtk::Box size_box; + Gtk::Label* bm_label; + + Gtk::Box file_box; + Gtk::Label *flabel; + Gtk::Entry filename_entry; + + /* Unit selector widgets */ + Gtk::Box unitbox; + Inkscape::UI::Widget::UnitMenu unit_selector; + Gtk::Label units_label; + + /* Filename widgets */ + Gtk::Box filename_box; + Gtk::Button browse_button; + Gtk::Label browse_label; + Gtk::Image browse_image; + + Gtk::Box batch_box; + Gtk::CheckButton batch_export; + + Gtk::Box hide_box; + Gtk::CheckButton hide_export; + + Gtk::CheckButton closeWhenDone; + + /* Advanced */ + Gtk::Expander expander; + Gtk::CheckButton interlacing; + Gtk::Label bitdepth_label; + Inkscape::UI::Widget::ScrollProtected bitdepth_cb; + Gtk::Label zlib_label; + Inkscape::UI::Widget::ScrollProtected zlib_compression; + Gtk::Label pHYs_label; + Glib::RefPtr pHYs_adj; + Inkscape::UI::Widget::ScrollProtected pHYs_sb; + Gtk::Label antialiasing_label; + Inkscape::UI::Widget::ScrollProtected antialiasing_cb; + + /* Export Button widgets */ + Gtk::Box button_box; + Gtk::Button export_button; + + Gtk::ProgressBar _prog; + + ExportProgressDialog *prog_dlg; + bool interrupted; // indicates whether export needs to be interrupted (read: user pressed cancel in the progress dialog) + + Inkscape::Preferences *prefs; + sigc::connection selectChangedConn; + sigc::connection subselChangedConn; + sigc::connection selectModifiedConn; + sigc::connection unitChangedConn; + +}; + +} +} +} +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index a2dd591417..15b4c257c1 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -14,148 +14,24 @@ * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ -// This has to be included prior to anything that includes setjmp.h, it croaks otherwise -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "document-undo.h" -#include "document.h" -#include "file.h" -#include "inkscape.h" -#include "inkscape-window.h" -#include "preferences.h" -#include "selection-chemistry.h" - -// required to set status message after export -#include "desktop.h" -#include "message-stack.h" +#include "export.h" -#include "helper/png-write.h" +#include #include "io/resource.h" -#include "io/sys.h" - -#include "object/sp-namedview.h" -#include "object/sp-root.h" - -#include "ui/dialog-events.h" -#include "ui/interface.h" -#include "ui/widget/unit-menu.h" -#include "ui/widget/scrollprotected.h" -#include "ui/dialog/dialog-notebook.h" -#include "ui/dialog/filedialog.h" - -#include "extension/db.h" #ifdef _WIN32 -#include -#include -#include -#include -#endif - -#define SP_EXPORT_MIN_SIZE 1.0 - -#define DPI_BASE Inkscape::Util::Quantity::convert(1, "in", "px") - -#define EXPORT_COORD_PRECISION 3 - -#include "export.h" - -using Inkscape::Util::unit_table; -void make_group(Glib::RefPtr builder); - -namespace { - -class MessageCleaner -{ -public: - MessageCleaner(Inkscape::MessageId messageId, SPDesktop *desktop) : - _desktop(desktop), - _messageId(messageId) - { - } - - ~MessageCleaner() - { - if (_messageId && _desktop) { - _desktop->messageStack()->cancel(_messageId); - } - } - -private: - MessageCleaner(MessageCleaner const &other) = delete; - MessageCleaner &operator=(MessageCleaner const &other) = delete; - - SPDesktop *_desktop; - Inkscape::MessageId _messageId; -}; - -} // namespace +#endif namespace Inkscape { namespace UI { namespace Dialog { -class ExportProgressDialog : public Gtk::Dialog { - private: - Gtk::ProgressBar *_progress = nullptr; - Export *_export_panel = nullptr; - int _current = 0; - int _total = 0; - - public: - ExportProgressDialog(const Glib::ustring &title, bool modal = false) - : Gtk::Dialog(title, modal) - {} - - inline void set_export_panel(const decltype(_export_panel) export_panel) { _export_panel = export_panel; } - inline decltype(_export_panel) get_export_panel() const { return _export_panel; } - - inline void set_progress(const decltype(_progress) progress) { _progress = progress; } - inline decltype(_progress) get_progress() const { return _progress; } - - inline void set_current(const int current) { _current = current; } - inline int get_current() const { return _current; } - - inline void set_total(const int total) { _total = total; } - inline int get_total() const { return _total; } -}; - -static std::string create_filepath_from_id(Glib::ustring, const Glib::ustring &); - -/** A list of strings that is used both in the preferences, and in the - data fields to describe the various values of \c selection_type. */ -static const char * selection_names[SELECTION_NUMBER_OF] = { - "page", "drawing", "selection", "custom" -}; - -/** The names on the buttons for the various selection types. */ -static const char * selection_labels[SELECTION_NUMBER_OF] = { - N_("_Page"), N_("_Drawing"), N_("_Selection"), N_("_Custom") -}; - Export::Export() - : DialogBase("/dialogs/export/", "Export"), - selectChangedConn(), - subselChangedConn(), - selectModifiedConn() + : DialogBase("/dialogs/export/", "Export") { std::string gladefile = get_filename_string(Inkscape::IO::Resource::UIS, "dialog-export.glade"); - Glib::RefPtr builder; try { builder = Gtk::Builder::create_from_file(gladefile); @@ -163,1512 +39,89 @@ Export::Export() g_error("Glade file loading failed for export screen"); return; } - Gtk::Box *contents; - builder->get_widget("contents", contents); - add(*contents); + builder->get_widget("Export Dialog Box", container); + add(*container); show_all_children(); + initialise_all(); + removeScrollEvent(dynamic_cast(left_sb)); + export_notebook->signal_map().connect(sigc::mem_fun(*this, &Export::onNotebookVisible)); } +Export::~Export() {} -Export::~Export () -{ - selectModifiedConn.disconnect(); - subselChangedConn.disconnect(); - selectChangedConn.disconnect(); -} - -void Export::setDesktop(SPDesktop *desktop) +void Export::initialise_all() { -#if 0 - { + if (builder) { + // Notebook Start { - selectModifiedConn.disconnect(); - subselChangedConn.disconnect(); - selectChangedConn.disconnect(); - } - if (desktop && desktop->selection) { - - selectChangedConn = desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &Export::onSelectionChanged))); - subselChangedConn = desktop->connectToolSubselectionChanged(sigc::hide(sigc::mem_fun(*this, &Export::onSelectionChanged))); - - //// Must check flags, so can't call widget_setup() directly. - selectModifiedConn = desktop->selection->connectModified(sigc::hide<0>(sigc::mem_fun(*this, &Export::onSelectionModified))); - } - } -#endif -} - -void Export::update() -{ -} - -/* - * set the default filename to be that of the current path + document - * with .png extension - * - * One thing to notice here is that this filename may get - * overwritten, but it won't happen here. The filename gets - * written into the text field, but then the button to select - * the area gets set. In that code the filename can be changed - * if there are some with presidence in the document. So, while - * this code sets the name first, it may not be the one users - * really see. - */ -void Export::set_default_filename () { - - if ( SP_ACTIVE_DOCUMENT && SP_ACTIVE_DOCUMENT->getDocumentFilename() ) - { - SPDocument * doc = SP_ACTIVE_DOCUMENT; - const gchar *filename = doc->getDocumentFilename(); - auto &&text_extension = get_file_save_extension(Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS); - Inkscape::Extension::Output * oextension = nullptr; - - if (!text_extension.empty()) { - oextension = dynamic_cast(Inkscape::Extension::db.get(text_extension.c_str())); - } - - if (oextension != nullptr) { - gchar * old_extension = oextension->get_extension(); - if (g_str_has_suffix(filename, old_extension)) { - gchar * filename_copy; - gchar * extension_point; - gchar * final_name; - - filename_copy = g_strdup(filename); - extension_point = g_strrstr(filename_copy, old_extension); - extension_point[0] = '\0'; - - final_name = g_strconcat(filename_copy, ".png", nullptr); - filename_entry.set_text(final_name); - filename_entry.set_position(strlen(final_name)); - - g_free(final_name); - g_free(filename_copy); - } - } else { - gchar *name = g_strconcat(filename, ".png", nullptr); - filename_entry.set_text(name); - filename_entry.set_position(strlen(name)); - - g_free(name); - } - - doc_export_name = filename_entry.get_text(); - } - else if ( SP_ACTIVE_DOCUMENT ) - { - Glib::ustring filename = create_filepath_from_id (_("bitmap"), filename_entry.get_text()); - filename_entry.set_text(filename); - filename_entry.set_position(filename.length()); - - doc_export_name = filename_entry.get_text(); - } -} - -Glib::RefPtr Export::createSpinbutton( gchar const * /*key*/, - double val, double min, double max, double step, double page, - Gtk::Grid *t, int x, int y, - const Glib::ustring& ll, const Glib::ustring& lr, - int digits, unsigned int sensitive, - void (Export::*cb)() ) -{ - auto adj = Gtk::Adjustment::create(val, min, max, step, page, 0); - - int pos = 0; - Gtk::Label *l = nullptr; - - if (!ll.empty()) { - l = new Gtk::Label(ll,true); - l->set_halign(Gtk::ALIGN_END); - l->set_valign(Gtk::ALIGN_CENTER); - l->set_hexpand(); - t->attach(*l, x + pos, y, 1, 1); - l->set_sensitive(sensitive); - pos++; - } - - auto sb = new Inkscape::UI::Widget::ScrollProtected(adj, 1.0, digits); - sb->set_hexpand(); - t->attach(*sb, x + pos, y, 1, 1); - - sb->set_width_chars(7); - sb->set_sensitive (sensitive); - pos++; - - if (l) { - l->set_mnemonic_widget(*sb); - } - - if (!lr.empty()) { - l = new Gtk::Label(lr,true); - l->set_halign(Gtk::ALIGN_START); - l->set_valign(Gtk::ALIGN_CENTER); - l->set_hexpand(); - t->attach(*l, x + pos, y, 1, 1); - l->set_sensitive (sensitive); - pos++; - l->set_mnemonic_widget (*sb); - } - - if (cb) { - adj->signal_value_changed().connect( sigc::mem_fun(*this, cb) ); - } - - return adj; -} // end of createSpinbutton() - - -std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_entry_text) -{ - if (id.empty()) - { /* This should never happen */ - id = "bitmap"; - } - - std::string directory; - - if (!file_entry_text.empty()) { - directory = Glib::path_get_dirname(Glib::filename_from_utf8(file_entry_text)); - } - - if (directory.empty()) { - /* Grab document directory */ - const gchar* docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); - if (docFilename) { - directory = Glib::path_get_dirname(docFilename); - } - } - - if (directory.empty()) { - directory = Inkscape::IO::Resource::homedir_path(nullptr); - } - - return Glib::build_filename(directory, Glib::filename_from_utf8(id) + ".png"); -} - -void Export::onBatchClicked () -{ - if (batch_export.get_active()) { - singleexport_box.set_sensitive(false); - } else { - singleexport_box.set_sensitive(true); - } -} - -void Export::updateCheckbuttons () -{ - gint num = (gint) boost::distance(SP_ACTIVE_DESKTOP->getSelection()->items()); - if (num >= 2) { - batch_export.set_sensitive(true); - } else { - batch_export.set_active (false); - batch_export.set_sensitive(false); - } - gchar *l = g_strdup_printf(ngettext("B_atch export %d selected object","B_atch export %d selected objects",num), num); - batch_export.set_label(l); - g_free(l); - - //hide_export.set_sensitive (num > 0); -} - -inline void Export::findDefaultSelection() -{ - selection_type key = SELECTION_NUMBER_OF; - - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { - key = SELECTION_SELECTION; - } - - /* Try using the preferences */ - if (key == SELECTION_NUMBER_OF) { - - int i = SELECTION_NUMBER_OF; - - Glib::ustring what = prefs->getString("/dialogs/export/exportarea/value"); + builder->get_widget("Export Notebook", export_notebook); + // Single Image Start + { + builder->get_widget("Single Image", single_image); - if (!what.empty()) { - for (i = 0; i < SELECTION_NUMBER_OF; i++) { - if (what == selection_names[i]) { - break; - } - } - } + builder->get_widget("si_s_document", select_document); + builder->get_widget("si_s_page", select_page); + builder->get_widget("si_s_selection", select_selection); + builder->get_widget("si_s_custom", select_custom); - key = (selection_type)i; - } + builder->get_widget("si_left_sb", left_sb); + builder->get_widget("si_right_sb", right_sb); + builder->get_widget("si_top_sb", top_sb); + builder->get_widget("si_bottom_sb", bottom_sb); + builder->get_widget("si_height_sb", height_sb); + builder->get_widget("si_width_sb", width_sb); - if (key == SELECTION_NUMBER_OF) { - key = SELECTION_PAGE; - } + builder->get_widget("si_img_height_sb", img_height_sb); + builder->get_widget("si_img_width_sb", img_width_sb); + builder->get_widget("si_dpi_sb", dpi_sb); - current_key = key; - selectiontype_buttons[current_key]->set_active(true); - updateCheckbuttons (); -} + builder->get_widget("si_show_export_area", show_export_area); + builder->get_widget("si_units", units); + builder->get_widget("si_hide_all", hide_all); + builder->get_widget("si_preview_box", si_preview_box); + builder->get_widget("si_show_preview", si_show_preview); -/** - * If selection changed and "Export area" is set to "Selection" - * recalculate bounds when the selection changes - */ -void Export::onSelectionChanged() -{ - Inkscape::Selection *selection = SP_ACTIVE_DESKTOP->getSelection(); - if (manual_key != SELECTION_CUSTOM && selection) { - current_key = SELECTION_SELECTION; - refreshArea(); - } + builder->get_widget("si_extention", extension); + builder->get_widget("si_filename", filename); + builder->get_widget("si_export", si_export); + } // Single Image End - updateCheckbuttons(); -} - -void Export::onSelectionModified ( guint /*flags*/ ) -{ - Inkscape::Selection * Sel; - switch (current_key) { - case SELECTION_DRAWING: - if ( SP_ACTIVE_DESKTOP ) { - SPDocument *doc; - doc = SP_ACTIVE_DESKTOP->getDocument(); - Geom::OptRect bbox = doc->getRoot()->desktopVisualBounds(); - if (bbox) { - setArea ( bbox->left(), - bbox->top(), - bbox->right(), - bbox->bottom()); - } - } - break; - case SELECTION_SELECTION: - Sel = SP_ACTIVE_DESKTOP->getSelection(); - if (Sel->isEmpty() == false) { - Geom::OptRect bbox = Sel->visualBounds(); - if (bbox) + // Batch Export Start { - setArea ( bbox->left(), - bbox->top(), - bbox->right(), - bbox->bottom()); - } - } - break; - default: - /* Do nothing for page or for custom */ - break; - } - - return; -} - -/// Called when one of the selection buttons was toggled. -void Export::onAreaTypeToggled() { - if (update_flag) { - return; - } + builder->get_widget("Batch Export", batch_export); + } // Batch Export End - /* Find which button is active */ - selection_type key = current_key; - for (int i = 0; i < SELECTION_NUMBER_OF; i++) { - if (selectiontype_buttons[i]->get_active()) { - key = (selection_type)i; - } + } // Notebook End } - manual_key = current_key = key; - - refreshArea(); -} - -/// Called when area needs to be refreshed -/// Area type changed, unit changed, initialization -void Export::refreshArea () -{ - // if ( SP_ACTIVE_DESKTOP ) - // { - // SPDocument *doc; - // Geom::OptRect bbox; - // bbox = Geom::Rect(Geom::Point(0.0, 0.0),Geom::Point(0.0, 0.0)); - // doc = SP_ACTIVE_DESKTOP->getDocument(); - - // /* Notice how the switch is used to 'fall through' here to get - // various backups. If you modify this without noticing you'll - // probably screw something up. */ - // switch (current_key) { - // case SELECTION_SELECTION: - // if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) - // { - // bbox = SP_ACTIVE_DESKTOP->getSelection()->visualBounds(); - // /* Only if there is a selection that we can set - // do we break, otherwise we fall through to the - // drawing */ - // // std::cout << "Using selection: SELECTION" << std::endl; - // current_key = SELECTION_SELECTION; - // break; - // } - // case SELECTION_DRAWING: - // if (manual_key == SELECTION_DRAWING || manual_key == SELECTION_SELECTION) { - // /** \todo - // * This returns wrong values if the document has a viewBox. - // */ - // bbox = doc->getRoot()->desktopVisualBounds(); - // /* If the drawing is valid, then we'll use it and break - // otherwise we drop through to the page settings */ - // if (bbox) { - // // std::cout << "Using selection: DRAWING" << std::endl; - // current_key= SELECTION_DRAWING; - // break; - // } - // } - // case SELECTION_PAGE: - // if (manual_key == SELECTION_PAGE){ - // bbox = Geom::Rect(Geom::Point(0.0, 0.0), - // Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); - - // // std::cout << "Using selection: PAGE" << std::endl; - // current_key= SELECTION_PAGE; - // break; - // } - // case SELECTION_CUSTOM: - // current_key = SELECTION_CUSTOM; - // default: - // break; - // } // switch - - // // remember area setting - // prefs->setString("/dialogs/export/exportarea/value", selection_names[current_key]); - - // if ( current_key != SELECTION_CUSTOM && bbox ) { - // setArea ( bbox->min()[Geom::X], - // bbox->min()[Geom::Y], - // bbox->max()[Geom::X], - // bbox->max()[Geom::Y]); - // } - - // } // end of if ( SP_ACTIVE_DESKTOP ) - - // if (SP_ACTIVE_DESKTOP && !filename_modified) { - - // Glib::ustring filename; - // float xdpi = 0.0, ydpi = 0.0; - - // switch (current_key) { - // case SELECTION_PAGE: - // case SELECTION_DRAWING: { - // SPDocument * doc = SP_ACTIVE_DOCUMENT; - // sp_document_get_export_hints (doc, filename, &xdpi, &ydpi); - - // if (filename.empty()) { - // if (!doc_export_name.empty()) { - // filename = doc_export_name; - // } - // } - // break; - // } - // case SELECTION_SELECTION: - // if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { - - // SP_ACTIVE_DESKTOP->getSelection()->getExportHints(filename, &xdpi, &ydpi); - - // /* If we still don't have a filename -- let's build - // one that's nice */ - // if (filename.empty()) { - // const gchar * id = "object"; - // auto reprlst = SP_ACTIVE_DESKTOP->getSelection()->xmlNodes(); - // for(auto i=reprlst.begin(); reprlst.end() != i; ++i) { - // Inkscape::XML::Node * repr = *i; - // if (repr->attribute("id")) { - // id = repr->attribute("id"); - // break; - // } - // } - - // filename = create_filepath_from_id (id, filename_entry.get_text()); - // } - // } - // break; - // case SELECTION_CUSTOM: - // default: - // break; - // } - - // if (!filename.empty()) { - // original_name = filename; - // filename_entry.set_text(filename); - // filename_entry.set_position(filename.length()); - // } - - // if (xdpi != 0.0) { - // setValue(xdpi_adj, xdpi); - // } - - // /* These can't be separate, and setting x sets y, so for - // now setting this is disabled. Hopefully it won't be in - // the future */ - // if (FALSE && ydpi != 0.0) { - // setValue(ydpi_adj, ydpi); - // } - // } - return; -} // end of sp_export_area_toggled() - -/// Called when dialog is deleted -bool Export::onProgressDelete (GdkEventAny * /*event*/) -{ - interrupted = true; - return TRUE; -} // end of sp_export_progress_delete() - - -/// Called when progress is cancelled -void Export::onProgressCancel () -{ - interrupted = true; -} // end of sp_export_progress_cancel() - - -/// Called for every progress iteration -unsigned int Export::onProgressCallback(float value, void *dlg) -{ - auto dlg2 = reinterpret_cast(dlg); - - auto self = dlg2->get_export_panel(); - if (self->interrupted) - return FALSE; - - auto current = dlg2->get_current(); - auto total = dlg2->get_total(); - if (total > 0) { - double completed = current; - completed /= static_cast(total); - - value = completed + (value / static_cast(total)); - } - - auto prg = dlg2->get_progress(); - prg->set_fraction(value); - - if (self) { - self->_prog.set_fraction(value); - } - - int evtcount = 0; - while ((evtcount < 16) && gdk_events_pending()) { - Gtk::Main::iteration(false); - evtcount += 1; - } - - Gtk::Main::iteration(false); - return TRUE; -} // end of sp_export_progress_callback() - -void Export::setExporting(bool exporting, Glib::ustring const &text) -{ - if (exporting) { - _prog.set_text(text); - _prog.set_fraction(0.0); - _prog.set_sensitive(true); - - export_button.set_sensitive(false); - } else { - _prog.set_text(""); - _prog.set_fraction(0.0); - _prog.set_sensitive(false); - - export_button.set_sensitive(true); - } -} - -ExportProgressDialog * -Export::create_progress_dialog(Glib::ustring progress_text) -{ - auto dlg = new ExportProgressDialog(_("Export in progress"), true); - dlg->set_transient_for( *(INKSCAPE.active_desktop()->getToplevel()) ); - - Gtk::ProgressBar *prg = new Gtk::ProgressBar (); - prg->set_text(progress_text); - dlg->set_progress(prg); - auto CA = dlg->get_content_area(); - CA->pack_start(*prg, FALSE, FALSE, 4); - - Gtk::Button* btn = dlg->add_button (_("_Cancel"),Gtk::RESPONSE_CANCEL ); - - btn->signal_clicked().connect( sigc::mem_fun(*this, &Export::onProgressCancel) ); - dlg->signal_delete_event().connect( sigc::mem_fun(*this, &Export::onProgressDelete) ); - - dlg->show_all (); - return dlg; -} - -static std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename) -{ - std::string path; - //Make relative paths go from the document location, if possible: - if (!Glib::path_is_absolute(filename) && doc->getDocumentFilename()) { - auto dirname = Glib::path_get_dirname(doc->getDocumentFilename()); - if (!dirname.empty()) { - path = Glib::build_filename(dirname, filename); - } - } - if (path.empty()) { - path = filename; - } - return path; -} - -// Called when unit is changed -void Export::onUnitChanged() -{ - refreshArea(); -} - -void Export::onHideExceptSelected () -{ - prefs->setBool("/dialogs/export/hideexceptselected/value", hide_export.get_active()); -} - -/// Called when export button is clicked -void Export::onExport () -{ - _export_raster(nullptr); -} - -void Export::_export_raster(Inkscape::Extension::Output *extension) -{ - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) return; - - SPNamedView *nv = desktop->getNamedView(); - SPDocument *doc = desktop->getDocument(); - - bool exportSuccessful = false; - - bool hide = hide_export.get_active (); - - // Advanced parameters - bool do_interlace = (interlacing.get_active()); - float pHYs = 0; - int zlib = zlib_compression.get_active_row_number() ; - int colortypes[] = {0,0,0,0,0,2,2,4,4,6,6}; //keep in sync with modes_list in Export constructor. values are from libpng doc. - int bitdepths[] = {1,2,4,8,16,8,16,8,16,8,16}; - int color_type = colortypes[bitdepth_cb.get_active_row_number()] ; - int bit_depth = bitdepths[bitdepth_cb.get_active_row_number()] ; - int antialiasing = antialiasing_cb.get_active_row_number(); - - - if (batch_export.get_active ()) { - // Batch export of selected objects - - gint num = (gint) boost::distance(desktop->getSelection()->items()); - gint n = 0; - - if (num < 1) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No items selected.")); - return; - } - - prog_dlg = create_progress_dialog(Glib::ustring::compose(_("Exporting %1 files"), num)); - prog_dlg->set_export_panel(this); - setExporting(true, Glib::ustring::compose(_("Exporting %1 files"), num)); - - gint export_count = 0; - - auto itemlist= desktop->getSelection()->items(); - for(auto i = itemlist.begin();i!=itemlist.end() && !interrupted ;++i){ - SPItem *item = *i; - - prog_dlg->set_current(n); - prog_dlg->set_total(num); - onProgressCallback(0.0, prog_dlg); - - // retrieve export filename hint - const gchar *filename = item->getRepr()->attribute("inkscape:export-filename"); - std::string path; - if (!filename) { - auto id = item->getId(); - if (!id) { - g_warning("object has no id"); - continue; - } - path = create_filepath_from_id(id, filename_entry.get_text()); - } else { - path = absolutize_path_from_document_location(doc, filename); - } - - // retrieve export dpi hints - const gchar *dpi_hint = item->getRepr()->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now - gdouble dpi = 0.0; - if (dpi_hint) { - dpi = g_ascii_strtod(dpi_hint, nullptr); - } - if (dpi == 0.0) { - dpi = getValue(xdpi_adj); - } - pHYs = (pHYs_adj->get_value() > 0.01) ? pHYs_adj->get_value() : dpi; - - Geom::OptRect area = item->documentVisualBounds(); - if (area) { - gint width = (gint) (area->width() * dpi / DPI_BASE + 0.5); - gint height = (gint) (area->height() * dpi / DPI_BASE + 0.5); - - if (width > 1 && height > 1) { - // Do export - gchar * safeFile = Inkscape::IO::sanitizeString(path.c_str()); - MessageCleaner msgCleanup(desktop->messageStack()->pushF(Inkscape::IMMEDIATE_MESSAGE, - _("Exporting file %s..."), safeFile), desktop); - MessageCleaner msgFlashCleanup(desktop->messageStack()->flashF(Inkscape::IMMEDIATE_MESSAGE, - _("Exporting file %s..."), safeFile), desktop); - std::vector x; - std::vector selected(desktop->getSelection()->items().begin(), desktop->getSelection()->items().end()); - if (!sp_export_png_file (doc, path.c_str(), - *area, width, height, pHYs, pHYs, - nv->pagecolor, - onProgressCallback, (void*)prog_dlg, - TRUE, // overwrite without asking - hide ? selected : x, - do_interlace, color_type, bit_depth, zlib, antialiasing - )) { - gchar * error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); - - desktop->messageStack()->flashF(Inkscape::ERROR_MESSAGE, - _("Could not export to filename %s."), safeFile); - - sp_ui_error_dialog(error); - g_free(error); - } else { - ++export_count; // one more item exported successfully - } - g_free(safeFile); - } - } - - n++; - } - - desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, - _("Successfully exported %d files from %d selected items."), export_count, num); - - setExporting(false); - delete prog_dlg; - prog_dlg = nullptr; - interrupted = false; - exportSuccessful = (export_count > 0); - } else { - Glib::ustring filename = filename_entry.get_text(); - - if (filename.empty()) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You have to enter a filename.")); - sp_ui_error_dialog(_("You have to enter a filename")); - return; - } - - float const x0 = getValuePx(x0_adj); - float const y0 = getValuePx(y0_adj); - float const x1 = getValuePx(x1_adj); - float const y1 = getValuePx(y1_adj); - float const xdpi = getValue(xdpi_adj); - float const ydpi = getValue(ydpi_adj); - pHYs = (pHYs_adj->get_value() > 0.01) ? pHYs_adj->get_value() : xdpi; - unsigned long int const width = int(getValue(bmwidth_adj) + 0.5); - unsigned long int const height = int(getValue(bmheight_adj) + 0.5); - - if (!((x1 > x0) && (y1 > y0) && (width > 0) && (height > 0))) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("The chosen area to be exported is invalid.")); - sp_ui_error_dialog(_("The chosen area to be exported is invalid")); - return; - } - - std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(filename)); - - Glib::ustring dirname = Glib::path_get_dirname(path); - if ( dirname.empty() - || !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) ) - { - gchar *safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); - gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), - safeDir); - - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); - sp_ui_error_dialog(error); - - g_free(safeDir); - g_free(error); - return; - } - - auto fn = Glib::path_get_basename(path); - auto area = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * desktop->dt2doc(); - - // Select a raster output extension if not a png file (manual filename) - if (!extension && !Glib::str_has_suffix(filename, ".png")) { - Inkscape::Extension::DB::OutputList extension_list; - Inkscape::Extension::db.get_output_list(extension_list); - for (auto output_ext : extension_list) { - if (output_ext->deactivated() || !output_ext->is_raster()) - continue; - if(Glib::str_has_suffix(path.c_str(), output_ext->get_extension())) { - // Select the extension - extension = output_ext; - break; - } - } - } - - bool overwrite = false; - auto png_filename = std::string(path.c_str()); - if (extension) { - // Select the extension and set the filename to a temporary file - int tempfd_out = Glib::file_open_tmp(png_filename, "ink_ext_"); - // Do the over-write protection now, since the png is just a temp file. - if (!sp_ui_overwrite_file(filename.c_str())) { - return; - } - overwrite = true; - close(tempfd_out); - } - - /* TRANSLATORS: %1 will be the filename, %2 the width, and %3 the height of the image */ - prog_dlg = create_progress_dialog (Glib::ustring::compose(_("Exporting %1 (%2 x %3)"), fn, width, height)); - prog_dlg->set_export_panel(this); - setExporting(true, Glib::ustring::compose(_("Exporting %1 (%2 x %3)"), fn, width, height)); - - prog_dlg->set_current(0); - prog_dlg->set_total(0); - - /* Do export */ - std::vector x; - std::vector selected(desktop->getSelection()->items().begin(), desktop->getSelection()->items().end()); - ExportResult status = sp_export_png_file(desktop->getDocument(), png_filename.c_str(), - area, width, height, pHYs, pHYs, //previously xdpi, ydpi. - nv->pagecolor, - onProgressCallback, (void*)prog_dlg, - overwrite, - hide ? selected : x, - do_interlace, color_type, bit_depth, zlib, antialiasing - ); - if (status == EXPORT_ERROR) { - gchar * safeFile = Inkscape::IO::sanitizeString(path.c_str()); - gchar * error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); - - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); - sp_ui_error_dialog(error); - - g_free(safeFile); - g_free(error); - } else if (status == EXPORT_OK) { - - exportSuccessful = true; - if(extension != nullptr) { - // Remove progress dialog before showing prefs dialog. - delete prog_dlg; - prog_dlg = nullptr; - if(extension->prefs()) { - try { - extension->export_raster(doc, png_filename, path.c_str(), false); - } catch (Inkscape::Extension::Output::save_failed &e) { - exportSuccessful = false; - } - } else { - exportSuccessful = false; - } - } - - if (exportSuccessful) { - auto recentmanager = Gtk::RecentManager::get_default(); - if(recentmanager && Glib::path_is_absolute(path)) { - Glib::ustring uri = Glib::filename_to_uri(path); - recentmanager->add_item(uri); - } - - gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); - desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, _("Drawing exported to %s."), safeFile); - g_free(safeFile); - } - } else { - // Extensions have their own error popup, so this only tracks failures in the png step - desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE, _("Export aborted.")); - } - if (extension != nullptr) { - unlink(png_filename.c_str()); - } - - /* Reset the filename so that it can be changed again by changing - selections and all that */ - original_name = filename; - filename_modified = false; - - setExporting(false); - if(prog_dlg) { - delete prog_dlg; - prog_dlg = nullptr; - } - interrupted = false; - - /* Setup the values in the document */ - switch (current_key) { - case SELECTION_PAGE: - case SELECTION_DRAWING: { - SPDocument * doc = SP_ACTIVE_DOCUMENT; - Inkscape::XML::Node * repr = doc->getReprRoot(); - bool modified = false; - - bool saved = DocumentUndo::getUndoSensitive(doc); - DocumentUndo::setUndoSensitive(doc, false); - - gchar const *temp_string = repr->attribute("inkscape:export-filename"); - if (temp_string == nullptr || (filename != temp_string)) { - repr->setAttribute("inkscape:export-filename", filename); - modified = true; - } - temp_string = repr->attribute("inkscape:export-xdpi"); - if (temp_string == nullptr || xdpi != g_ascii_strtod(temp_string, nullptr)) { - repr->setAttributeSvgDouble("inkscape:export-xdpi", xdpi); - modified = true; - } - temp_string = repr->attribute("inkscape:export-ydpi"); - if (temp_string == nullptr || ydpi != g_ascii_strtod(temp_string, nullptr)) { - repr->setAttributeSvgDouble("inkscape:export-ydpi", ydpi); - modified = true; - } - DocumentUndo::setUndoSensitive(doc, saved); - - if (modified) { - doc->setModifiedSinceSave(); - } - break; - } - case SELECTION_SELECTION: { - SPDocument * doc = SP_ACTIVE_DOCUMENT; - bool modified = false; - - bool saved = DocumentUndo::getUndoSensitive(doc); - DocumentUndo::setUndoSensitive(doc, false); - auto reprlst = desktop->getSelection()->xmlNodes(); - - for(auto i=reprlst.begin(); reprlst.end() != i; ++i) { - Inkscape::XML::Node * repr = *i; - const gchar * temp_string; - Glib::ustring dir = Glib::path_get_dirname(filename.c_str()); - const gchar* docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); - Glib::ustring docdir; - if (docFilename) - { - docdir = Glib::path_get_dirname(docFilename); - } - temp_string = repr->attribute("inkscape:export-filename"); - if (temp_string == nullptr || (filename != temp_string)) { - repr->setAttribute("inkscape:export-filename", filename); - modified = true; - } - - temp_string = repr->attribute("inkscape:export-xdpi"); - if (temp_string == nullptr || xdpi != g_ascii_strtod(temp_string, nullptr)) { - repr->setAttributeSvgDouble("inkscape:export-xdpi", xdpi); - modified = true; - } - temp_string = repr->attribute("inkscape:export-ydpi"); - if (temp_string == nullptr || ydpi != g_ascii_strtod(temp_string, nullptr)) { - repr->setAttributeSvgDouble("inkscape:export-ydpi", ydpi); - modified = true; - } - } - DocumentUndo::setUndoSensitive(doc, saved); - - if (modified) { - doc->setModifiedSinceSave(); - } - break; - } - default: - break; - } - } - - if (exportSuccessful && closeWhenDone.get_active()) { - for (Gtk::Container *parent = get_parent(); parent; parent = parent->get_parent()) { - DialogNotebook *notebook = dynamic_cast(parent); - if (notebook) { - notebook->close_tab_callback(); - break; - } - } - } -} // end of Export::onExport() - -/// Called when Browse button is clicked -void Export::onBrowse () -{ - // Create and show the dialog - Gtk::Window *window = getApp()->get_active_window(); - std::string filename = Glib::filename_from_utf8(filename_entry.get_text()); - - if (filename.empty()) { - Glib::ustring tmp; - filename = create_filepath_from_id(tmp, tmp); - } - - Inkscape::UI::Dialog::FileSaveDialog *dialog = Inkscape::UI::Dialog::FileSaveDialog::create( - *window, filename, Inkscape::UI::Dialog::RASTER_TYPES, _("Select a filename for exporting"), "", "", - Inkscape::Extension::FILE_SAVE_METHOD_EXPORT); - - if (dialog->show()) { - auto file = dialog->getFilename(); - filename_entry.set_text(Glib::filename_to_utf8(file)); - filename_entry.set_position(-1); - auto selection_type = dialog->getSelectionType(); - //deleting dialog before exporting is important - //proper delete function should be made for dialog IMO - delete dialog; - _export_raster(dynamic_cast(selection_type)); - }else { - delete dialog; - } - -} - -// TODO: Move this to nr-rect-fns.h. -bool Export::bbox_equal(Geom::Rect const &one, Geom::Rect const &two) -{ - double const epsilon = pow(10.0, -EXPORT_COORD_PRECISION); - return ( - (fabs(one.min()[Geom::X] - two.min()[Geom::X]) < epsilon) && - (fabs(one.min()[Geom::Y] - two.min()[Geom::Y]) < epsilon) && - (fabs(one.max()[Geom::X] - two.max()[Geom::X]) < epsilon) && - (fabs(one.max()[Geom::Y] - two.max()[Geom::Y]) < epsilon) - ); } /** - *This function is used to detect the current selection setting - * based on the values in the x0, y0, x1 and y0 fields. - * - * One of the most confusing parts of this function is why the array - * is built at the beginning. What needs to happen here is that we - * should always check the current selection to see if it is the valid - * one. While this is a performance improvement it is also a usability - * one during the cases where things like selections and drawings match - * size. This way buttons change less 'randomly' (at least in the eyes - * of the user). To do this an array is built where the current selection - * type is placed first, and then the others in an order from smallest - * to largest (this can be configured by reshuffling \c test_order). - * - * All of the values in this function are rounded to two decimal places - * because that is what is shown to the user. While everything is kept - * more accurate than that, the user can't control more accurate than - * that, so for this to work for them - it needs to check on that level - * of accuracy. - * - * @todo finish writing this up. + * Set current page based on preference/last visited page */ -void Export::detectSize() { - static const selection_type test_order[SELECTION_NUMBER_OF] = {SELECTION_SELECTION, SELECTION_DRAWING, SELECTION_PAGE, SELECTION_CUSTOM}; - selection_type this_test[SELECTION_NUMBER_OF + 1]; - selection_type key = SELECTION_NUMBER_OF; - - Geom::Point x(getValuePx(x0_adj), - getValuePx(y0_adj)); - Geom::Point y(getValuePx(x1_adj), - getValuePx(y1_adj)); - Geom::Rect current_bbox(x, y); - - this_test[0] = current_key; - for (int i = 0; i < SELECTION_NUMBER_OF; i++) { - this_test[i + 1] = test_order[i]; - } - - for (int i = 0; - i < SELECTION_NUMBER_OF + 1 && - key == SELECTION_NUMBER_OF && - SP_ACTIVE_DESKTOP != nullptr; - i++) { - switch (this_test[i]) { - case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { - Geom::OptRect bbox = (SP_ACTIVE_DESKTOP->getSelection())->bounds(SPItem::VISUAL_BBOX); - - if ( bbox && bbox_equal(*bbox,current_bbox)) { - key = SELECTION_SELECTION; - } - } - break; - case SELECTION_DRAWING: { - SPDocument *doc = SP_ACTIVE_DESKTOP->getDocument(); - - Geom::OptRect bbox = doc->getRoot()->desktopVisualBounds(); - - if ( bbox && bbox_equal(*bbox,current_bbox) ) { - key = SELECTION_DRAWING; - } - break; - } - - case SELECTION_PAGE: { - SPDocument *doc; - - doc = SP_ACTIVE_DESKTOP->getDocument(); - - Geom::Point x(0.0, 0.0); - Geom::Point y(doc->getWidth().value("px"), - doc->getHeight().value("px")); - Geom::Rect bbox(x, y); - - if (bbox_equal(bbox,current_bbox)) { - key = SELECTION_PAGE; - } - - break; - } - default: - break; - } - } - // std::cout << std::endl; - - if (key == SELECTION_NUMBER_OF) { - key = SELECTION_CUSTOM; - } - - current_key = key; - selectiontype_buttons[current_key]->set_active(true); - return; -} /* sp_export_detect_size */ - -/// Called when area x0 value is changed -void Export::areaXChange(Glib::RefPtr& adj) +void Export::onNotebookVisible() { - float x0, x1, xdpi, width; - - if (update_flag) { - return; - } - - update_flag = true; - - x0 = getValuePx(x0_adj); - x1 = getValuePx(x1_adj); - xdpi = getValue(xdpi_adj); - - width = floor ((x1 - x0) * xdpi / DPI_BASE + 0.5); - - if (width < SP_EXPORT_MIN_SIZE) { - width = SP_EXPORT_MIN_SIZE; - - if (adj == x1_adj) { - x1 = x0 + width * DPI_BASE / xdpi; - setValuePx(x1_adj, x1); - } else { - x0 = x1 - width * DPI_BASE / xdpi; - setValuePx(x0_adj, x0); - } + if (export_notebook && batch_export) { + auto page_num = export_notebook->page_num(*batch_export); + export_notebook->set_current_page(page_num); } - - setValuePx(width_adj, x1 - x0); - setValue(bmwidth_adj, width); - - detectSize(); - - update_flag = false; - - return; -} // end of sp_export_area_x_value_changed() - -/// Called when area y0 value is changed. -void Export::areaYChange(Glib::RefPtr& adj) -{ - float y0, y1, ydpi, height; - - if (update_flag) { - return; - } - - update_flag = true; - - y0 = getValuePx(y0_adj); - y1 = getValuePx(y1_adj); - ydpi = getValue(ydpi_adj); - - height = floor ((y1 - y0) * ydpi / DPI_BASE + 0.5); - - if (height < SP_EXPORT_MIN_SIZE) { - height = SP_EXPORT_MIN_SIZE; - if (adj == y1_adj) { - //if (!strcmp (key, "y0")) { - y1 = y0 + height * DPI_BASE / ydpi; - setValuePx(y1_adj, y1); - } else { - y0 = y1 - height * DPI_BASE / ydpi; - setValuePx(y0_adj, y0); - } - } - - setValuePx(height_adj, y1 - y0); - setValue(bmheight_adj, height); - - detectSize(); - - update_flag = false; - - return; -} // end of sp_export_area_y_value_changed() - -/// Called when x1-x0 or area width is changed -void Export::onAreaWidthChange() -{ - if (update_flag) { - return; - } - - update_flag = true; - - float x0 = getValuePx(x0_adj); - float xdpi = getValue(xdpi_adj); - float width = getValuePx(width_adj); - float bmwidth = floor(width * xdpi / DPI_BASE + 0.5); - - if (bmwidth < SP_EXPORT_MIN_SIZE) { - - bmwidth = SP_EXPORT_MIN_SIZE; - width = bmwidth * DPI_BASE / xdpi; - setValuePx(width_adj, width); - } - - setValuePx(x1_adj, x0 + width); - setValue(bmwidth_adj, bmwidth); - - update_flag = false; - - return; -} // end of sp_export_area_width_value_changed() - -/// Called when y1-y0 or area height is changed. -void Export::onAreaHeightChange() -{ - if (update_flag) { - return; - } - - update_flag = true; - - float y0 = getValuePx(y0_adj); - //float y1 = sp_export_value_get_px(y1_adj); - float ydpi = getValue(ydpi_adj); - float height = getValuePx(height_adj); - float bmheight = floor (height * ydpi / DPI_BASE + 0.5); - - if (bmheight < SP_EXPORT_MIN_SIZE) { - bmheight = SP_EXPORT_MIN_SIZE; - height = bmheight * DPI_BASE / ydpi; - setValuePx(height_adj, height); - } - - setValuePx(y1_adj, y0 + height); - setValue(bmheight_adj, bmheight); - - update_flag = false; - - return; -} // end of sp_export_area_height_value_changed() - -/** - * A function to set the ydpi. - * @param base The export dialog. - * - * This function grabs all of the y values and then figures out the - * new bitmap size based on the changing dpi value. The dpi value is - * gotten from the xdpi setting as these can not currently be independent. - */ -void Export::setImageY() -{ - float y0, y1, xdpi; - - y0 = getValuePx(y0_adj); - y1 = getValuePx(y1_adj); - xdpi = getValue(xdpi_adj); - - setValue(ydpi_adj, xdpi); - setValue(bmheight_adj, (y1 - y0) * xdpi / DPI_BASE); - - return; -} // end of setImageY() - -/** - * A function to set the xdpi. - * - * This function grabs all of the x values and then figures out the - * new bitmap size based on the changing dpi value. The dpi value is - * gotten from the xdpi setting as these can not currently be independent. - * - */ -void Export::setImageX() -{ - float x0, x1, xdpi; - - x0 = getValuePx(x0_adj); - x1 = getValuePx(x1_adj); - xdpi = getValue(xdpi_adj); - - setValue(ydpi_adj, xdpi); - setValue(bmwidth_adj, (x1 - x0) * xdpi / DPI_BASE); - - return; -} // end of setImageX() - -/// Called when pixel width is changed -void Export::onBitmapWidthChange () -{ - float x0, x1, bmwidth, xdpi; - - if (update_flag) { - return; - } - - update_flag = true; - - x0 = getValuePx(x0_adj); - x1 = getValuePx(x1_adj); - bmwidth = getValue(bmwidth_adj); - - if (bmwidth < SP_EXPORT_MIN_SIZE) { - bmwidth = SP_EXPORT_MIN_SIZE; - setValue(bmwidth_adj, bmwidth); - } - - xdpi = bmwidth * DPI_BASE / (x1 - x0); - setValue(xdpi_adj, xdpi); - - setImageY (); - - update_flag = false; - - return; -} // end of sp_export_bitmap_width_value_changed() - -/// Called when pixel height is changed -void Export::onBitmapHeightChange () -{ - float y0, y1, bmheight, xdpi; - - if (update_flag) { - return; - } - - update_flag = true; - - y0 = getValuePx(y0_adj); - y1 = getValuePx(y1_adj); - bmheight = getValue(bmheight_adj); - - if (bmheight < SP_EXPORT_MIN_SIZE) { - bmheight = SP_EXPORT_MIN_SIZE; - setValue(bmheight_adj, bmheight); - } - - xdpi = bmheight * DPI_BASE / (y1 - y0); - setValue(xdpi_adj, xdpi); - - setImageX (); - - update_flag = false; - - return; -} // end of sp_export_bitmap_width_value_changed() - -/** - * A function to adjust the bitmap width when the xdpi value changes. - * - * The first thing this function checks is to see if we are doing an - * update. If we are, this function just returns because there is another - * instance of it that will handle everything for us. If there is a - * units change, we also assume that everyone is being updated appropriately - * and there is nothing for us to do. - * - * If we're the highest level function, we set the update flag, and - * continue on our way. - * - * All of the values are grabbed using the \c sp_export_value_get functions - * (call to the _pt ones for x0 and x1 but just standard for xdpi). The - * xdpi value is saved in the preferences for the next time the dialog - * is opened. (does the selection dpi need to be set here?) - * - * A check is done to to ensure that we aren't outputting an invalid width, - * this is set by SP_EXPORT_MIN_SIZE. If that is the case the dpi is - * changed to make it valid. - * - * After all of this the bitmap width is changed. - * - * We also change the ydpi. This is a temporary hack as these can not - * currently be independent. This is likely to change in the future. - * - */ -void Export::onExportXdpiChange() -{ - float x0, x1, xdpi, bmwidth; - - if (update_flag) { - return; - } - - update_flag = true; - - x0 = getValuePx(x0_adj); - x1 = getValuePx(x1_adj); - xdpi = getValue(xdpi_adj); - - // remember xdpi setting - prefs->setDouble("/dialogs/export/defaultxdpi/value", xdpi); - - bmwidth = (x1 - x0) * xdpi / DPI_BASE; - - if (bmwidth < SP_EXPORT_MIN_SIZE) { - bmwidth = SP_EXPORT_MIN_SIZE; - if (x1 != x0) - xdpi = bmwidth * DPI_BASE / (x1 - x0); - else - xdpi = DPI_BASE; - setValue(xdpi_adj, xdpi); - } - - setValue(bmwidth_adj, bmwidth); - - setImageY (); - - update_flag = false; - - return; -} // end of sp_export_xdpi_value_changed() - - -/** - * A function to change the area that is used for the exported. - * bitmap. - * - * This function just calls \c sp_export_value_set_px for each of the - * parameters that is passed in. This allows for setting them all in - * one convenient area. - * - * Update is set to suspend all of the other test running while all the - * values are being set up. This allows for a performance increase, but - * it also means that the wrong type won't be detected with only some of - * the values set. After all the values are set everyone is told that - * there has been an update. - * - * @param x0 Horizontal upper left hand corner of the picture in points. - * @param y0 Vertical upper left hand corner of the picture in points. - * @param x1 Horizontal lower right hand corner of the picture in points. - * @param y1 Vertical lower right hand corner of the picture in points. - */ -void Export::setArea( double x0, double y0, double x1, double y1 ) -{ - update_flag = true; - setValuePx(x1_adj, x1); - setValuePx(y1_adj, y1); - setValuePx(x0_adj, x0); - setValuePx(y0_adj, y0); - update_flag = false; - - areaXChange (x1_adj); - areaYChange (y1_adj); - return; } -/** - * Sets the value of an adjustment. - * - * @param adj The adjustment widget - * @param val What value to set it to. - */ -void Export::setValue(Glib::RefPtr& adj, double val ) -{ - if (adj) { - adj->set_value(val); +void Export::removeScrollEvent(Gtk::Widget* widget){ + if(widget){ + Gdk::EventMask event_masks = widget->get_events(); + Gdk::EventMask new_masks = event_masks & ~Gdk::EventMask::SCROLL_MASK; + widget->set_events(new_masks); } -} - -/** - * A function to set a value using the units points. - * - * This function first gets the adjustment for the key that is passed - * in. It then figures out what units are currently being used in the - * dialog. After doing all of that, it then converts the incoming - *value and sets the adjustment. - * - * @param adj The adjustment widget - * @param val What the value should be in points. - */ -void Export::setValuePx(Glib::RefPtr& adj, double val) -{ - Unit const *unit = unit_selector.getUnit(); - - setValue(adj, Inkscape::Util::Quantity::convert(val, "px", unit)); - return; } -/** - * Get the value of an adjustment in the export dialog. - * - * This function gets the adjustment from the data field in the export - * dialog. It then grabs the value from the adjustment. - * - * @param adj The adjustment widget - * - * @return The value in the specified adjustment. - */ -float Export::getValue(Glib::RefPtr& adj) -{ - if (!adj) { - g_message("sp_export_value_get : adj is NULL"); - return 0.0; - } - return adj->get_value(); -} - -/** - * Grabs a value in the export dialog and converts the unit - * to points. - * - * This function, at its most basic, is a call to \c sp_export_value_get - * to get the value of the adjustment. It then finds the units that - * are being used by looking at the "units" attribute of the export - * dialog. Using that it converts the returned value into points. - * - * @param adj The adjustment widget - * - * @return The value in the adjustment in points. - */ -float Export::getValuePx(Glib::RefPtr& adj) -{ - float value = getValue( adj); - Unit const *unit = unit_selector.getUnit(); - - return Inkscape::Util::Quantity::convert(value, unit, "px"); -} // end of sp_export_value_get_px() - -/** - * This function is called when the filename is changed by - * anyone. It resets the virgin bit. - * - * This function gets called when the text area is modified. It is - * looking for the case where the text area is modified from its - * original value. In that case it sets the "filename-modified" bit - * to TRUE. If the text dialog returns back to the original text, the - * bit gets reset. This should stop simple mistakes. - */ -void Export::onFilenameModified() -{ - if (original_name == filename_entry.get_text()) { - filename_modified = false; - } else { - filename_modified = true; - } - - return; -} // end sp_export_filename_modified - -} -} -} +} // namespace Dialog +} // namespace UI +} // namespace Inkscape /* Local Variables: @@ -1680,3 +133,4 @@ void Export::onFilenameModified() End: */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 7379508351..cd8c270140 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -13,17 +13,9 @@ #ifndef SP_EXPORT_H #define SP_EXPORT_H -#include -#include -#include -#include -#include -#include -#include +#include -#include "extension/output.h" #include "ui/dialog/dialog-base.h" -#include "ui/widget/scrollprotected.h" namespace Inkscape { namespace UI { @@ -31,15 +23,6 @@ namespace Dialog { class ExportProgressDialog; -/** What type of button is being pressed */ -enum selection_type { - SELECTION_PAGE = 0, /**< Export the whole page */ - SELECTION_DRAWING, /**< Export everything drawn on the page */ - SELECTION_SELECTION, /**< Export everything that is selected */ - SELECTION_CUSTOM, /**< Allows the user to set the region exported */ - SELECTION_NUMBER_OF /**< A counter for the number of these guys */ -}; - /** * A dialog widget to export to various image formats such as bitmap and png. * @@ -50,313 +33,53 @@ enum selection_type { class Export : public DialogBase { public: - Export (); - ~Export () override; + Export(); + ~Export() override; - static Export &getInstance() { - return *new Export(); - } + static Export &getInstance() { return *new Export(); } private: - - /** - * A function to set the xdpi. - * - * This function grabs all of the x values and then figures out the - * new bitmap size based on the changing dpi value. The dpi value is - * gotten from the xdpi setting as these can not currently be independent. - * - */ - void setImageX(); - - /** - * A function to set the ydpi. - * - * This function grabs all of the y values and then figures out the - * new bitmap size based on the changing dpi value. The dpi value is - * gotten from the xdpi setting as these can not currently be independent. - */ - void setImageY(); - bool bbox_equal(Geom::Rect const &one, Geom::Rect const &two); - void updateCheckbuttons (); - inline void findDefaultSelection(); - void detectSize(); - void setArea ( double x0, double y0, double x1, double y1); - /* - * Getter/setter style functions for the spinbuttons - */ - void setValue(Glib::RefPtr& adj, double val); - void setValuePx(Glib::RefPtr& adj, double val); - float getValue(Glib::RefPtr& adj); - float getValuePx(Glib::RefPtr& adj); - - /** - * Helper function to create, style and pack spinbuttons for the export dialog. - * - * Creates a new spin button for the export dialog. - * @param key The name of the spin button - * @param val A default value for the spin button - * @param min Minimum value for the spin button - * @param max Maximum value for the spin button - * @param step The step size for the spin button - * @param page Size of the page increment - * @param t Table to put the spin button in - * @param x X location in the table \c t to start with - * @param y Y location in the table \c t to start with - * @param ll Text to put on the left side of the spin button (optional) - * @param lr Text to put on the right side of the spin button (optional) - * @param digits Number of digits to display after the decimal - * @param sensitive Whether the spin button is sensitive or not - * @param cb Callback for when this spin button is changed (optional) - * - * No unit_selector is stored in the created spinbutton, relies on external unit management - */ - Glib::RefPtr createSpinbutton( gchar const *key, - double val, double min, double max, double step, double page, - Gtk::Grid *t, int x, int y, - const Glib::ustring& ll, const Glib::ustring& lr, - int digits, unsigned int sensitive, - void (Export::*cb)() ); - - /** - * One of the area select radio buttons was pressed - */ - void onAreaTypeToggled(); - void refreshArea(); - - /** - * Export button callback - */ - void onExport (); - void _export_raster(Inkscape::Extension::Output *extension); - - /** - * File Browse button callback - */ - void onBrowse (); - - /** - * Area X value changed callback - */ - void onAreaX0Change() { - areaXChange(x0_adj); - } ; - void onAreaX1Change() { - areaXChange(x1_adj); - } ; - void areaXChange(Glib::RefPtr& adj); - - /** - * Area Y value changed callback - */ - void onAreaY0Change() { - areaYChange(y0_adj); - } ; - void onAreaY1Change() { - areaYChange(y1_adj); - } ; - void areaYChange(Glib::RefPtr& adj); - - /** - * Unit changed callback - */ - void onUnitChanged(); - - /** - * Hide except selected callback - */ - void onHideExceptSelected (); - - /** - * Area width value changed callback - */ - void onAreaWidthChange (); - - /** - * Area height value changed callback - */ - void onAreaHeightChange (); - - /** - * Bitmap width value changed callback - */ - void onBitmapWidthChange (); - - /** - * Bitmap height value changed callback - */ - void onBitmapHeightChange (); - - /** - * Export xdpi value changed callback - */ - void onExportXdpiChange (); - - /** - * Batch export callback - */ - void onBatchClicked (); - - /** - * Inkscape selection change callback - */ - void onSelectionChanged (); - void onSelectionModified (guint flags); - - /** - * Filename modified callback - */ - void onFilenameModified (); - - /** - * Can be invoked for setting the desktop. Currently not used. - */ - void setDesktop(SPDesktop *desktop); - - /** - * Update active window. - */ - void update() override; - - /** - * Creates progress dialog for batch exporting. - * - * @param progress_text Text to be shown in the progress bar - */ - ExportProgressDialog * create_progress_dialog(Glib::ustring progress_text); - - /** - * Callback to be used in for loop to update the progress bar. - * - * @param value number between 0 and 1 indicating the fraction of progress (0.17 = 17 % progress) - * @param dlg void pointer to the Gtk::Dialog progress dialog - */ - static unsigned int onProgressCallback(float value, void *dlg); - - /** - * Callback for pressing the cancel button. - */ - void onProgressCancel (); - - /** - * Callback invoked on closing the progress dialog. - */ - bool onProgressDelete (GdkEventAny *event); - - /** - * Handles state changes as exporting starts or stops. - */ - void setExporting(bool exporting, Glib::ustring const &text = ""); - - /* - * Utility filename and path functions - */ - void set_default_filename (); - - /* - * Currently selected export area type - * can be changed by code - */ - selection_type current_key; - /* - * Manually selected export area type(only changed by buttons) - */ - selection_type manual_key; - /* - * Original name for the export object - */ - Glib::ustring original_name; - Glib::ustring doc_export_name; - /* - * Was the Original name modified - */ - bool filename_modified; - - /* - * Flag to stop simultaneous updates - */ - bool update_flag; - - /* Area selection radio buttons */ - Gtk::Box togglebox; - Gtk::RadioButton *selectiontype_buttons[SELECTION_NUMBER_OF]; - - Gtk::Box area_box; - Gtk::Box singleexport_box; - - /* Custom size widgets */ - Glib::RefPtr x0_adj; - Glib::RefPtr x1_adj; - Glib::RefPtr y0_adj; - Glib::RefPtr y1_adj; - Glib::RefPtr width_adj; - Glib::RefPtr height_adj; - - /* Bitmap size widgets */ - Glib::RefPtr bmwidth_adj; - Glib::RefPtr bmheight_adj; - Glib::RefPtr xdpi_adj; - Glib::RefPtr ydpi_adj; - - Gtk::Box size_box; - Gtk::Label* bm_label; - - Gtk::Box file_box; - Gtk::Label *flabel; - Gtk::Entry filename_entry; - - /* Unit selector widgets */ - Gtk::Box unitbox; - Inkscape::UI::Widget::UnitMenu unit_selector; - Gtk::Label units_label; - - /* Filename widgets */ - Gtk::Box filename_box; - Gtk::Button browse_button; - Gtk::Label browse_label; - Gtk::Image browse_image; - - Gtk::Box batch_box; - Gtk::CheckButton batch_export; - - Gtk::Box hide_box; - Gtk::CheckButton hide_export; - - Gtk::CheckButton closeWhenDone; - - /* Advanced */ - Gtk::Expander expander; - Gtk::CheckButton interlacing; - Gtk::Label bitdepth_label; - Inkscape::UI::Widget::ScrollProtected bitdepth_cb; - Gtk::Label zlib_label; - Inkscape::UI::Widget::ScrollProtected zlib_compression; - Gtk::Label pHYs_label; - Glib::RefPtr pHYs_adj; - Inkscape::UI::Widget::ScrollProtected pHYs_sb; - Gtk::Label antialiasing_label; - Inkscape::UI::Widget::ScrollProtected antialiasing_cb; - - /* Export Button widgets */ - Gtk::Box button_box; - Gtk::Button export_button; - - Gtk::ProgressBar _prog; - - ExportProgressDialog *prog_dlg; - bool interrupted; // indicates whether export needs to be interrupted (read: user pressed cancel in the progress dialog) - - Inkscape::Preferences *prefs; - sigc::connection selectChangedConn; - sigc::connection subselChangedConn; - sigc::connection selectModifiedConn; - sigc::connection unitChangedConn; + // builder and its object ( in order ) + Glib::RefPtr builder; + Gtk::Box *container = nullptr; + Gtk::Notebook *export_notebook = nullptr; + + Gtk::Box *single_image = nullptr; + Gtk::RadioButton *select_document = nullptr; + Gtk::RadioButton *select_page = nullptr; + Gtk::RadioButton *select_selection = nullptr; + Gtk::RadioButton *select_custom = nullptr; + Gtk::SpinButton *left_sb = nullptr; + Gtk::SpinButton *right_sb = nullptr; + Gtk::SpinButton *top_sb = nullptr; + Gtk::SpinButton *bottom_sb = nullptr; + Gtk::SpinButton *height_sb = nullptr; + Gtk::SpinButton *width_sb = nullptr; + Gtk::SpinButton *img_height_sb = nullptr; + Gtk::SpinButton *img_width_sb = nullptr; + Gtk::SpinButton *dpi_sb = nullptr; + Gtk::CheckButton *show_export_area = nullptr; + Gtk::ComboBoxText *units = nullptr; + Gtk::CheckButton *hide_all = nullptr; + Gtk::Box *si_preview_box = nullptr; + Gtk::CheckButton *si_show_preview = nullptr; + Gtk::ComboBoxText *extension = nullptr; + Gtk::Entry *filename = nullptr; + Gtk::Button *si_export = nullptr; + + Gtk::Box *batch_export = nullptr; + + // Initialise all objects from builder + void initialise_all(); + + //signals callback + void removeScrollEvent(Gtk::Widget* widget); + void onNotebookVisible(); }; - -} -} -} +} // namespace Dialog +} // namespace UI +} // namespace Inkscape #endif /* -- GitLab From 86e6776db696ca5e1ff445ecdab7607aa76f22b8 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Thu, 10 Jun 2021 12:44:49 +0530 Subject: [PATCH 04/40] Last commit before dropping glade --- src/ui/dialog/export.cpp | 23 +++++++++++++++++++++-- src/ui/dialog/export.h | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 15b4c257c1..80ad53d7fc 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -43,7 +43,7 @@ Export::Export() add(*container); show_all_children(); initialise_all(); - removeScrollEvent(dynamic_cast(left_sb)); + removeScrollEvents(); export_notebook->signal_map().connect(sigc::mem_fun(*this, &Export::onNotebookVisible)); } @@ -113,9 +113,28 @@ void Export::onNotebookVisible() void Export::removeScrollEvent(Gtk::Widget* widget){ if(widget){ Gdk::EventMask event_masks = widget->get_events(); - Gdk::EventMask new_masks = event_masks & ~Gdk::EventMask::SCROLL_MASK; + Gdk::EventMask new_masks = event_masks & ~(Gdk::EventMask::SCROLL_MASK | ~Gdk::EventMask::SMOOTH_SCROLL_MASK); widget->set_events(new_masks); + std::cout << "Removed\n"; + }else{ + std::cout << "Not Removed\n"; } + std::cout.flush(); + return; +} + +void Export::removeScrollEvents(){ + removeScrollEvent(dynamic_cast(left_sb)); + removeScrollEvent(dynamic_cast(right_sb)); + removeScrollEvent(dynamic_cast(top_sb)); + removeScrollEvent(dynamic_cast(bottom_sb)); + removeScrollEvent(dynamic_cast(height_sb)); + removeScrollEvent(dynamic_cast(width_sb)); + removeScrollEvent(dynamic_cast(units)); + removeScrollEvent(dynamic_cast(extension)); + removeScrollEvent(dynamic_cast(img_height_sb)); + removeScrollEvent(dynamic_cast(img_width_sb)); + return; } diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index cd8c270140..02298b63f3 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -74,6 +74,7 @@ private: //signals callback void removeScrollEvent(Gtk::Widget* widget); + void removeScrollEvents(); void onNotebookVisible(); }; -- GitLab From 3720ffe1fe1751beb598a3af765f55654f8d73e1 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Thu, 10 Jun 2021 22:15:24 +0530 Subject: [PATCH 05/40] Shifted from Glade --- share/ui/#dialog-export.glade# | 1271 ++++++++++++++++++++++++++++++++ share/ui/dialog-export.glade | 144 ++-- src/ui/dialog/export.cpp | 263 ++++--- src/ui/dialog/export.h | 83 ++- 4 files changed, 1550 insertions(+), 211 deletions(-) create mode 100644 share/ui/#dialog-export.glade# diff --git a/share/ui/#dialog-export.glade# b/share/ui/#dialog-export.glade# new file mode 100644 index 0000000000..95592f63c8 --- /dev/null +++ b/share/ui/#dialog-export.glade# @@ -0,0 +1,1271 @@ + + + + + + True + False + False + vertical + True + + + True + False + False + False + + + True + False + False + vertical + 5 + + + 300 + True + True + False + True + never + always + True + + + True + False + False + natural + none + + + True + False + 5 + 10 + + + True + False + Left + True + 0 + + + 1 + 1 + + + + + True + True + True + False + + + 2 + 1 + + + + + True + True + True + + + 2 + 2 + + + + + True + True + True + + + 5 + 1 + + + + + True + True + True + + + 5 + 2 + + + + + True + False + Right + True + 0 + + + 4 + 1 + + + + + True + False + Bottom + True + 0 + + + 4 + 2 + + + + + True + False + Top + True + 0 + + + 1 + 2 + + + + + True + False + Width + True + 0 + + + 1 + 3 + + + + + True + True + True + + + 2 + 3 + + + + + True + True + True + + + 5 + 3 + + + + + True + False + Height + True + 0 + + + 4 + 3 + + + + + True + False + 5 + 5 + Image Size + 0 + + + + + + 1 + 5 + 2 + + + + + True + False + Width + True + 0 + + + 1 + 6 + + + + + True + False + Height + True + 0 + + + 4 + 6 + + + + + True + True + True + + + 5 + 6 + + + + + True + True + True + + + 2 + 6 + + + + + True + False + DPI + True + 0 + + + 1 + 7 + + + + + True + False + px + True + 0 + + + + + + + + + 3 + 6 + + + + + True + False + px + True + 0 + + + + + + + + + 6 + 6 + + + + + True + True + center + True + + + 2 + 7 + + + + + True + False + + + Show Export Area On Canvas + True + True + False + True + + + False + True + 0 + + + + + True + False + end + True + 5 + + + True + False + Units + True + 0 + + + False + True + 0 + + + + + True + False + 1 + + mm + px + + + + False + True + 1 + + + + + False + True + 2 + + + + + 1 + 4 + 5 + + + + + True + False + vertical + + + Hide All Except Selected + True + True + False + True + + + False + True + 0 + + + + + Preview + True + True + False + True + + + False + True + 1 + + + + + 1 + 8 + 2 + 3 + + + + + True + True + 10 + 10 + True + + + True + False + 5 + + + checkbutton + True + True + False + 20 + 10 + True + + + 0 + 0 + + + + + checkbutton + True + True + False + 20 + True + + + 0 + 1 + + + + + + + True + False + 10 + Advance + True + + + + + 1 + 11 + 5 + + + + + True + False + False + 5 + True + expand + + + Document + True + False + False + False + True + False + + + True + True + 1 + + + + + Page + True + False + False + False + si_s_document + + + True + True + 3 + + + + + Selection + True + False + False + False + si_s_document + + + True + True + 3 + + + + + Custom + True + False + False + False + si_s_document + + + True + True + 3 + + + + + 0 + 0 + 8 + + + + + True + False + vertical + + + 150 + 150 + True + False + 150 + face-smile + 6 + + + False + True + 0 + + + + + 3 + 7 + 4 + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + 0 + + + + + True + False + 10 + + + True + True + True + folder-open + Filename + + + 0 + 0 + + + + + True + False + center + 1 + + svg + png + + + + 1 + 0 + + + + + Export + True + True + True + end + + + 2 + 0 + + + + + False + True + 1 + + + + + 1 + + + + + True + False + False + Single Image + right + + + False + + + + + True + False + False + vertical + + + 300 + True + True + True + never + always + False + True + + + True + False + none + + + True + False + vertical + 10 + 10 + + + 150 + True + True + True + never + in + + + True + False + + + True + False + True + 10 + 10 + 10 + none + + + 50 + 50 + True + True + + + True + False + 50 + face-glasses + + + + + + + 100 + 80 + True + True + + + True + False + 50 + face-glasses + + + + + + + 100 + 80 + True + True + + + True + False + 50 + face-glasses + + + + + + + 100 + 80 + True + True + + + True + False + 50 + face-glasses + + + + + + + 100 + 80 + True + True + + + True + False + 50 + face-glasses + + + + + + + + + + + 1 + 1 + 8 + + + + + True + False + True + expand + + + Selection + True + False + False + True + False + + + True + True + 0 + + + + + Layers + True + False + False + True + False + radiobutton2 + + + True + True + 1 + + + + + 0 + 0 + 10 + + + + + Preview + True + True + False + True + + + 1 + 2 + 2 + + + + + True + False + 5 Items + + + 8 + 2 + + + + + Hide All Except Selected + True + True + False + True + + + 1 + 5 + 4 + + + + + True + True + 10 + 10 + 5 + True + + + True + False + 10 + 5 + + + checkbutton + True + True + False + 10 + True + + + 0 + 0 + + + + + checkbutton + True + True + False + True + + + 0 + 1 + + + + + + + True + False + 5 + Advance + True + + + + + 1 + 6 + 4 + + + + + True + True + False + False + + + + + + autosize + Prefix + True + + + + + autosize + Scale + True + + + + + autosize + Format + True + + + + + 1 + 3 + 4 + 2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + True + 0 + + + + + True + False + 5 + 5 + 10 + + + True + True + True + folder-open + Filename + + + 0 + 0 + + + + + Export + True + True + True + + + 2 + 0 + + + + + + + + False + True + 1 + + + + + 1 + + + + + True + False + False + Batch Export + right + + + 1 + False + + + + + False + True + 0 + + + + diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index c77717ed90..580dcd5998 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -2,80 +2,6 @@ - - 10 - 1 - - - - image/png - image/jpeg - image/svg+xml - - - - False - dialog - - - - - - False - vertical - 2 - - - False - end - - - Select - True - True - True - - - True - True - 0 - - - - - False - False - 0 - - - - - True - False - save - export_filter - False - - - False - True - 1 - - - - - - - - - - - - - Hello - - - True False @@ -574,6 +500,7 @@ Document True False + False False True False @@ -581,7 +508,7 @@ True True - 3 + 1 @@ -666,13 +593,62 @@ - - - - - - - + + True + False + + + radiobutton + True + True + False + True + False + + + True + True + 0 + + + + + radiobutton + True + True + False + True + False + radiobutton1 + + + True + True + 1 + + + + + radiobutton + True + True + False + True + False + radiobutton1 + + + True + True + 2 + + + + + 3 + 5 + 3 + @@ -832,9 +808,6 @@ 1 - - - 1 @@ -1138,7 +1111,6 @@ True True - liststore1 False False diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 80ad53d7fc..53fbe1fea0 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -30,115 +30,202 @@ namespace Dialog { Export::Export() : DialogBase("/dialogs/export/", "Export") -{ - std::string gladefile = get_filename_string(Inkscape::IO::Resource::UIS, "dialog-export.glade"); + , container(Gtk::ORIENTATION_VERTICAL, 0) + , single_image(Gtk::ORIENTATION_VERTICAL, 0) - try { - builder = Gtk::Builder::create_from_file(gladefile); - } catch (const Glib::Error &ex) { - g_error("Glade file loading failed for export screen"); - return; - } - builder->get_widget("Export Dialog Box", container); - add(*container); +{ + createSingleImage(); + createBatch(); + attachLabels(); + createRadioGroups(); + setupSpinButtons(); + container.pack_start(notebook, true, true); + add(container); show_all_children(); - initialise_all(); - removeScrollEvents(); - export_notebook->signal_map().connect(sigc::mem_fun(*this, &Export::onNotebookVisible)); + + select_page.set_active(); } Export::~Export() {} -void Export::initialise_all() +void Export::createSingleImage() { - if (builder) { - // Notebook Start + notebook.append_page(single_image, "Single Image"); + + { // Setup Scrolled Window + single_image.pack_start(si_scrolled, true, true); + si_scrolled.set_propagate_natural_width(); + si_scrolled.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); + si_scrolled.set_vexpand(); + si_scrolled.add(si_scrolled_grid); + { // Setup Scrolled Grid + + int row = 0; + + si_scrolled_grid.set_column_spacing(10); + si_scrolled_grid.set_row_spacing(5); + + { // Setup selection box + si_scrolled_grid.attach(si_selection_box, 0, row, 8, 1); + si_selection_box.pack_start(select_document, true, true); + si_selection_box.pack_start(select_page, true, true); + si_selection_box.pack_start(select_selection, true, true); + si_selection_box.pack_start(select_custom, true, true); + si_selection_box.set_homogeneous(); + si_selection_box.set_hexpand(); + si_selection_box.set_layout(Gtk::BUTTONBOX_EXPAND); + row = row + 1; + } + {// Setup Corrdinates Box + {auto x0_label = Gtk::make_managed("Left", Gtk::ALIGN_START); + si_scrolled_grid.attach(*x0_label, 1, row, 1, 1); + si_scrolled_grid.attach(x0_sb, 2, row, 1, 1); + + auto x1_label = Gtk::make_managed("Right", Gtk::ALIGN_START); + si_scrolled_grid.attach(*x1_label, 4, row, 1, 1); + si_scrolled_grid.attach(x1_sb, 5, row, 1, 1); + + row = row + 1; + } + { + auto y0_label = Gtk::make_managed("Top", Gtk::ALIGN_START); + si_scrolled_grid.attach(*y0_label, 1, row, 1, 1); + si_scrolled_grid.attach(y0_sb, 2, row, 1, 1); + + auto y1_label = Gtk::make_managed("Bottom", Gtk::ALIGN_START); + si_scrolled_grid.attach(*y1_label, 4, row, 1, 1); + si_scrolled_grid.attach(y1_sb, 5, row, 1, 1); + + row = row + 1; + } { - builder->get_widget("Export Notebook", export_notebook); - // Single Image Start - { - builder->get_widget("Single Image", single_image); - - builder->get_widget("si_s_document", select_document); - builder->get_widget("si_s_page", select_page); - builder->get_widget("si_s_selection", select_selection); - builder->get_widget("si_s_custom", select_custom); - - builder->get_widget("si_left_sb", left_sb); - builder->get_widget("si_right_sb", right_sb); - builder->get_widget("si_top_sb", top_sb); - builder->get_widget("si_bottom_sb", bottom_sb); - builder->get_widget("si_height_sb", height_sb); - builder->get_widget("si_width_sb", width_sb); - - builder->get_widget("si_img_height_sb", img_height_sb); - builder->get_widget("si_img_width_sb", img_width_sb); - builder->get_widget("si_dpi_sb", dpi_sb); - - builder->get_widget("si_show_export_area", show_export_area); - builder->get_widget("si_units", units); - - builder->get_widget("si_hide_all", hide_all); - builder->get_widget("si_preview_box", si_preview_box); - builder->get_widget("si_show_preview", si_show_preview); - - builder->get_widget("si_extention", extension); - builder->get_widget("si_filename", filename); - builder->get_widget("si_export", si_export); - } // Single Image End - - // Batch Export Start - { - builder->get_widget("Batch Export", batch_export); - } // Batch Export End - - } // Notebook End + auto width_label = Gtk::make_managed("Width", Gtk::ALIGN_START); + si_scrolled_grid.attach(*width_label, 1, row, 1, 1); + si_scrolled_grid.attach(width_sb, 2, row, 1, 1); + + auto height_label = Gtk::make_managed("Height", Gtk::ALIGN_START); + si_scrolled_grid.attach(*height_label, 4, row, 1, 1); + si_scrolled_grid.attach(height_sb, 5, row, 1, 1); + + row = row + 1; + } + } + { // Setup Units Box + auto units_box = Gtk::make_managed(); + si_scrolled_grid.attach(*units_box, 1, row, 5, 1); + + units_box->pack_start(show_export_area, true, true, 0); + + unit_selector.setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); + units_box->pack_end(unit_selector, false, false, 0); + + auto unit_label = Gtk::make_managed("Unit", Gtk::ALIGN_START); + units_box->pack_end(*unit_label, false, false, 0); + + units_box->set_spacing(5); + units_box->set_hexpand(); + row = row + 1; + } + { // Setup Image Box + { + auto img_label = Gtk::make_managed("Image Size", Gtk::ALIGN_START); + si_scrolled_grid.attach(*img_label, 1, row, 2, 1); + row = row + 1; + } + { + auto bmwidth_label = Gtk::make_managed("Width", Gtk::ALIGN_START); + si_scrolled_grid.attach(*bmwidth_label, 1, row, 1, 1); + si_scrolled_grid.attach(bmwidth_sb, 2, row, 1, 1); + + auto bmheight_label = Gtk::make_managed("Height", Gtk::ALIGN_START); + si_scrolled_grid.attach(*bmheight_label, 4, row, 1, 1); + si_scrolled_grid.attach(bmheight_sb, 5, row, 1, 1); + + row = row + 1; + } + { + auto dpi_label = Gtk::make_managed("DPI", Gtk::ALIGN_START); + si_scrolled_grid.attach(*dpi_label, 1, row, 1, 1); + si_scrolled_grid.attach(dpi_sb, 2, row, 1, 1); + + row = row + 1; + } + { // Options Box + auto options_box = Gtk::make_managed(Gtk::ORIENTATION_VERTICAL); + si_scrolled_grid.attach(*options_box, 1, row, 2, 3); + options_box->pack_start(hide_all, true, true, 0); + options_box->pack_start(preview, true, true, 0); + options_box->set_spacing(5); + row = row + 3; + } } - return; } +} // namespace Dialog -/** - * Set current page based on preference/last visited page - */ +{ // Setup Bottom Grid + single_image.pack_end(si_bottom_grid, false, true); + si_bottom_grid.attach(si_filename, 0, 0, 1, 1); + si_bottom_grid.attach(si_extention, 1, 0, 1, 1); + si_bottom_grid.attach(si_export, 2, 0, 1, 1); + si_filename.set_hexpand(); +} +} // namespace UI + +void Export::createBatch() +{ + notebook.append_page(batch, "Batch Export"); +} + +void Export::attachLabels() +{ + select_document.set_label("Document"); + select_page.set_label("Page"); + select_selection.set_label("Selection"); + select_custom.set_label("Custom"); + si_export.set_label("Export"); + + show_export_area.set_label("Show Export Area on Canvas"); -void Export::onNotebookVisible() + hide_all.set_label("Hide all except selected"); + preview.set_label("Preview"); +} + +void Export::createRadioGroups() { - if (export_notebook && batch_export) { - auto page_num = export_notebook->page_num(*batch_export); - export_notebook->set_current_page(page_num); + { // single image selection group + auto group = select_document.get_group(); + select_page.set_group(group); + select_selection.set_group(group); + select_custom.set_group(group); } - return; + removeIndicators(); } -void Export::removeScrollEvent(Gtk::Widget* widget){ - if(widget){ - Gdk::EventMask event_masks = widget->get_events(); - Gdk::EventMask new_masks = event_masks & ~(Gdk::EventMask::SCROLL_MASK | ~Gdk::EventMask::SMOOTH_SCROLL_MASK); - widget->set_events(new_masks); - std::cout << "Removed\n"; - }else{ - std::cout << "Not Removed\n"; +void Export::removeIndicators() +{ + { + select_document.set_mode(false); + select_page.set_mode(false); + select_selection.set_mode(false); + select_custom.set_mode(false); } - std::cout.flush(); - return; } -void Export::removeScrollEvents(){ - removeScrollEvent(dynamic_cast(left_sb)); - removeScrollEvent(dynamic_cast(right_sb)); - removeScrollEvent(dynamic_cast(top_sb)); - removeScrollEvent(dynamic_cast(bottom_sb)); - removeScrollEvent(dynamic_cast(height_sb)); - removeScrollEvent(dynamic_cast(width_sb)); - removeScrollEvent(dynamic_cast(units)); - removeScrollEvent(dynamic_cast(extension)); - removeScrollEvent(dynamic_cast(img_height_sb)); - removeScrollEvent(dynamic_cast(img_width_sb)); - - return; +void Export::setupSpinButtons() +{ + { // Coordinate sp + auto adj = Gtk::Adjustment::create(0, 0.0, 1000.0, 0.1, 1.0, 0); + x0_sb.configure(adj,1.0,3); + x0_sb.set_width_chars(7); + x0_sb.set_sensitive (true); + + x1_sb.configure(adj,1.0,3); + x1_sb.set_width_chars(7); + x1_sb.set_sensitive (true); + } } -} // namespace Dialog +} // namespace Inkscape } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 02298b63f3..95ad7e1dab 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -15,6 +15,9 @@ #include +#include "ui/widget/scrollprotected.h" +#include "ui/widget/unit-menu.h" + #include "ui/dialog/dialog-base.h" namespace Inkscape { @@ -39,44 +42,50 @@ public: static Export &getInstance() { return *new Export(); } private: - // builder and its object ( in order ) - Glib::RefPtr builder; - Gtk::Box *container = nullptr; - Gtk::Notebook *export_notebook = nullptr; - - Gtk::Box *single_image = nullptr; - Gtk::RadioButton *select_document = nullptr; - Gtk::RadioButton *select_page = nullptr; - Gtk::RadioButton *select_selection = nullptr; - Gtk::RadioButton *select_custom = nullptr; - Gtk::SpinButton *left_sb = nullptr; - Gtk::SpinButton *right_sb = nullptr; - Gtk::SpinButton *top_sb = nullptr; - Gtk::SpinButton *bottom_sb = nullptr; - Gtk::SpinButton *height_sb = nullptr; - Gtk::SpinButton *width_sb = nullptr; - Gtk::SpinButton *img_height_sb = nullptr; - Gtk::SpinButton *img_width_sb = nullptr; - Gtk::SpinButton *dpi_sb = nullptr; - Gtk::CheckButton *show_export_area = nullptr; - Gtk::ComboBoxText *units = nullptr; - Gtk::CheckButton *hide_all = nullptr; - Gtk::Box *si_preview_box = nullptr; - Gtk::CheckButton *si_show_preview = nullptr; - Gtk::ComboBoxText *extension = nullptr; - Gtk::Entry *filename = nullptr; - Gtk::Button *si_export = nullptr; - - Gtk::Box *batch_export = nullptr; - - // Initialise all objects from builder - void initialise_all(); - - //signals callback - void removeScrollEvent(Gtk::Widget* widget); - void removeScrollEvents(); - void onNotebookVisible(); + Gtk::Box container; + Gtk::Notebook notebook; + Gtk::Box single_image; + Gtk::Box batch; + + + Gtk::ScrolledWindow si_scrolled; + Gtk::Grid si_scrolled_grid; + + Gtk::ButtonBox si_selection_box; + Gtk::RadioButton select_document; + Gtk::RadioButton select_page; + Gtk::RadioButton select_selection; + Gtk::RadioButton select_custom; + + Inkscape::UI::Widget::ScrollProtected x0_sb; + Inkscape::UI::Widget::ScrollProtected x1_sb; + Inkscape::UI::Widget::ScrollProtected y0_sb; + Inkscape::UI::Widget::ScrollProtected y1_sb; + Inkscape::UI::Widget::ScrollProtected width_sb; + Inkscape::UI::Widget::ScrollProtected height_sb; + + Gtk::CheckButton show_export_area; + Inkscape::UI::Widget::UnitMenu unit_selector; + + Inkscape::UI::Widget::ScrollProtected bmwidth_sb; + Inkscape::UI::Widget::ScrollProtected bmheight_sb; + Inkscape::UI::Widget::ScrollProtected dpi_sb; + + Gtk::CheckButton hide_all; + Gtk::CheckButton preview; + + Gtk::Grid si_bottom_grid; + Gtk::Entry si_filename; + Gtk::ComboBoxText si_extention; + Gtk::Button si_export; + + void createSingleImage(); + void createBatch(); + void attachLabels(); + void createRadioGroups(); + void removeIndicators(); + void setupSpinButtons(); }; } // namespace Dialog } // namespace UI -- GitLab From 4cb9ab5ad568e66cf71db483409cb3239569d765 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Sun, 13 Jun 2021 17:06:55 +0530 Subject: [PATCH 06/40] Back to glade Modified scrollprotected and unit-menu for builder derived widgets --- share/ui/#dialog-export.glade# | 1271 ------------------------------- share/ui/dialog-export.glade | 61 +- src/ui/dialog/export.cpp | 242 ++---- src/ui/dialog/export.h | 85 +-- src/ui/widget/scrollprotected.h | 5 + src/ui/widget/unit-menu.h | 5 +- 6 files changed, 114 insertions(+), 1555 deletions(-) delete mode 100644 share/ui/#dialog-export.glade# diff --git a/share/ui/#dialog-export.glade# b/share/ui/#dialog-export.glade# deleted file mode 100644 index 95592f63c8..0000000000 --- a/share/ui/#dialog-export.glade# +++ /dev/null @@ -1,1271 +0,0 @@ - - - - - - True - False - False - vertical - True - - - True - False - False - False - - - True - False - False - vertical - 5 - - - 300 - True - True - False - True - never - always - True - - - True - False - False - natural - none - - - True - False - 5 - 10 - - - True - False - Left - True - 0 - - - 1 - 1 - - - - - True - True - True - False - - - 2 - 1 - - - - - True - True - True - - - 2 - 2 - - - - - True - True - True - - - 5 - 1 - - - - - True - True - True - - - 5 - 2 - - - - - True - False - Right - True - 0 - - - 4 - 1 - - - - - True - False - Bottom - True - 0 - - - 4 - 2 - - - - - True - False - Top - True - 0 - - - 1 - 2 - - - - - True - False - Width - True - 0 - - - 1 - 3 - - - - - True - True - True - - - 2 - 3 - - - - - True - True - True - - - 5 - 3 - - - - - True - False - Height - True - 0 - - - 4 - 3 - - - - - True - False - 5 - 5 - Image Size - 0 - - - - - - 1 - 5 - 2 - - - - - True - False - Width - True - 0 - - - 1 - 6 - - - - - True - False - Height - True - 0 - - - 4 - 6 - - - - - True - True - True - - - 5 - 6 - - - - - True - True - True - - - 2 - 6 - - - - - True - False - DPI - True - 0 - - - 1 - 7 - - - - - True - False - px - True - 0 - - - - - - - - - 3 - 6 - - - - - True - False - px - True - 0 - - - - - - - - - 6 - 6 - - - - - True - True - center - True - - - 2 - 7 - - - - - True - False - - - Show Export Area On Canvas - True - True - False - True - - - False - True - 0 - - - - - True - False - end - True - 5 - - - True - False - Units - True - 0 - - - False - True - 0 - - - - - True - False - 1 - - mm - px - - - - False - True - 1 - - - - - False - True - 2 - - - - - 1 - 4 - 5 - - - - - True - False - vertical - - - Hide All Except Selected - True - True - False - True - - - False - True - 0 - - - - - Preview - True - True - False - True - - - False - True - 1 - - - - - 1 - 8 - 2 - 3 - - - - - True - True - 10 - 10 - True - - - True - False - 5 - - - checkbutton - True - True - False - 20 - 10 - True - - - 0 - 0 - - - - - checkbutton - True - True - False - 20 - True - - - 0 - 1 - - - - - - - True - False - 10 - Advance - True - - - - - 1 - 11 - 5 - - - - - True - False - False - 5 - True - expand - - - Document - True - False - False - False - True - False - - - True - True - 1 - - - - - Page - True - False - False - False - si_s_document - - - True - True - 3 - - - - - Selection - True - False - False - False - si_s_document - - - True - True - 3 - - - - - Custom - True - False - False - False - si_s_document - - - True - True - 3 - - - - - 0 - 0 - 8 - - - - - True - False - vertical - - - 150 - 150 - True - False - 150 - face-smile - 6 - - - False - True - 0 - - - - - 3 - 7 - 4 - 4 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - 0 - - - - - True - False - 10 - - - True - True - True - folder-open - Filename - - - 0 - 0 - - - - - True - False - center - 1 - - svg - png - - - - 1 - 0 - - - - - Export - True - True - True - end - - - 2 - 0 - - - - - False - True - 1 - - - - - 1 - - - - - True - False - False - Single Image - right - - - False - - - - - True - False - False - vertical - - - 300 - True - True - True - never - always - False - True - - - True - False - none - - - True - False - vertical - 10 - 10 - - - 150 - True - True - True - never - in - - - True - False - - - True - False - True - 10 - 10 - 10 - none - - - 50 - 50 - True - True - - - True - False - 50 - face-glasses - - - - - - - 100 - 80 - True - True - - - True - False - 50 - face-glasses - - - - - - - 100 - 80 - True - True - - - True - False - 50 - face-glasses - - - - - - - 100 - 80 - True - True - - - True - False - 50 - face-glasses - - - - - - - 100 - 80 - True - True - - - True - False - 50 - face-glasses - - - - - - - - - - - 1 - 1 - 8 - - - - - True - False - True - expand - - - Selection - True - False - False - True - False - - - True - True - 0 - - - - - Layers - True - False - False - True - False - radiobutton2 - - - True - True - 1 - - - - - 0 - 0 - 10 - - - - - Preview - True - True - False - True - - - 1 - 2 - 2 - - - - - True - False - 5 Items - - - 8 - 2 - - - - - Hide All Except Selected - True - True - False - True - - - 1 - 5 - 4 - - - - - True - True - 10 - 10 - 5 - True - - - True - False - 10 - 5 - - - checkbutton - True - True - False - 10 - True - - - 0 - 0 - - - - - checkbutton - True - True - False - True - - - 0 - 1 - - - - - - - True - False - 5 - Advance - True - - - - - 1 - 6 - 4 - - - - - True - True - False - False - - - - - - autosize - Prefix - True - - - - - autosize - Scale - True - - - - - autosize - Format - True - - - - - 1 - 3 - 4 - 2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - 0 - - - - - True - False - 5 - 5 - 10 - - - True - True - True - folder-open - Filename - - - 0 - 0 - - - - - Export - True - True - True - - - 2 - 0 - - - - - - - - False - True - 1 - - - - - 1 - - - - - True - False - False - Batch Export - right - - - 1 - False - - - - - False - True - 0 - - - - diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 580dcd5998..a264d6faad 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -362,10 +362,6 @@ True False 1 - - mm - px - False @@ -593,62 +589,7 @@ - - True - False - - - radiobutton - True - True - False - True - False - - - True - True - 0 - - - - - radiobutton - True - True - False - True - False - radiobutton1 - - - True - True - 1 - - - - - radiobutton - True - True - False - True - False - radiobutton1 - - - True - True - 2 - - - - - 3 - 5 - 3 - + diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 53fbe1fea0..c2b5ba09c7 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -30,202 +30,90 @@ namespace Dialog { Export::Export() : DialogBase("/dialogs/export/", "Export") - , container(Gtk::ORIENTATION_VERTICAL, 0) - , single_image(Gtk::ORIENTATION_VERTICAL, 0) - { - createSingleImage(); - createBatch(); - attachLabels(); - createRadioGroups(); - setupSpinButtons(); - container.pack_start(notebook, true, true); - add(container); + std::string gladefile = get_filename_string(Inkscape::IO::Resource::UIS, "dialog-export.glade"); + + try { + builder = Gtk::Builder::create_from_file(gladefile); + } catch (const Glib::Error &ex) { + g_error("Glade file loading failed for export screen"); + return; + } + builder->get_widget("Export Dialog Box", container); + add(*container); show_all_children(); + initialise_all(); + units->setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); - select_page.set_active(); + export_notebook->signal_map().connect(sigc::mem_fun(*this, &Export::onNotebookVisible)); } Export::~Export() {} -void Export::createSingleImage() +void Export::initialise_all() { - notebook.append_page(single_image, "Single Image"); - - { // Setup Scrolled Window - single_image.pack_start(si_scrolled, true, true); - si_scrolled.set_propagate_natural_width(); - si_scrolled.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); - si_scrolled.set_vexpand(); - si_scrolled.add(si_scrolled_grid); - { // Setup Scrolled Grid - - int row = 0; - - si_scrolled_grid.set_column_spacing(10); - si_scrolled_grid.set_row_spacing(5); - - { // Setup selection box - si_scrolled_grid.attach(si_selection_box, 0, row, 8, 1); - si_selection_box.pack_start(select_document, true, true); - si_selection_box.pack_start(select_page, true, true); - si_selection_box.pack_start(select_selection, true, true); - si_selection_box.pack_start(select_custom, true, true); - si_selection_box.set_homogeneous(); - si_selection_box.set_hexpand(); - si_selection_box.set_layout(Gtk::BUTTONBOX_EXPAND); - row = row + 1; - } - {// Setup Corrdinates Box - {auto x0_label = Gtk::make_managed("Left", Gtk::ALIGN_START); - si_scrolled_grid.attach(*x0_label, 1, row, 1, 1); - si_scrolled_grid.attach(x0_sb, 2, row, 1, 1); - - auto x1_label = Gtk::make_managed("Right", Gtk::ALIGN_START); - si_scrolled_grid.attach(*x1_label, 4, row, 1, 1); - si_scrolled_grid.attach(x1_sb, 5, row, 1, 1); - - row = row + 1; - } - { - auto y0_label = Gtk::make_managed("Top", Gtk::ALIGN_START); - si_scrolled_grid.attach(*y0_label, 1, row, 1, 1); - si_scrolled_grid.attach(y0_sb, 2, row, 1, 1); - - auto y1_label = Gtk::make_managed("Bottom", Gtk::ALIGN_START); - si_scrolled_grid.attach(*y1_label, 4, row, 1, 1); - si_scrolled_grid.attach(y1_sb, 5, row, 1, 1); - - row = row + 1; - } - { - auto width_label = Gtk::make_managed("Width", Gtk::ALIGN_START); - si_scrolled_grid.attach(*width_label, 1, row, 1, 1); - si_scrolled_grid.attach(width_sb, 2, row, 1, 1); - - auto height_label = Gtk::make_managed("Height", Gtk::ALIGN_START); - si_scrolled_grid.attach(*height_label, 4, row, 1, 1); - si_scrolled_grid.attach(height_sb, 5, row, 1, 1); - - row = row + 1; - } - } - { // Setup Units Box - auto units_box = Gtk::make_managed(); - si_scrolled_grid.attach(*units_box, 1, row, 5, 1); - - units_box->pack_start(show_export_area, true, true, 0); - - unit_selector.setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); - units_box->pack_end(unit_selector, false, false, 0); - - auto unit_label = Gtk::make_managed("Unit", Gtk::ALIGN_START); - units_box->pack_end(*unit_label, false, false, 0); - - units_box->set_spacing(5); - units_box->set_hexpand(); - row = row + 1; - } - { // Setup Image Box + if (builder) { + // Notebook Start { - auto img_label = Gtk::make_managed("Image Size", Gtk::ALIGN_START); - si_scrolled_grid.attach(*img_label, 1, row, 2, 1); - row = row + 1; - } - { - auto bmwidth_label = Gtk::make_managed("Width", Gtk::ALIGN_START); - si_scrolled_grid.attach(*bmwidth_label, 1, row, 1, 1); - si_scrolled_grid.attach(bmwidth_sb, 2, row, 1, 1); - - auto bmheight_label = Gtk::make_managed("Height", Gtk::ALIGN_START); - si_scrolled_grid.attach(*bmheight_label, 4, row, 1, 1); - si_scrolled_grid.attach(bmheight_sb, 5, row, 1, 1); - - row = row + 1; - } - { - auto dpi_label = Gtk::make_managed("DPI", Gtk::ALIGN_START); - si_scrolled_grid.attach(*dpi_label, 1, row, 1, 1); - si_scrolled_grid.attach(dpi_sb, 2, row, 1, 1); - - row = row + 1; - } - { // Options Box - auto options_box = Gtk::make_managed(Gtk::ORIENTATION_VERTICAL); - si_scrolled_grid.attach(*options_box, 1, row, 2, 3); - options_box->pack_start(hide_all, true, true, 0); - options_box->pack_start(preview, true, true, 0); - options_box->set_spacing(5); - row = row + 3; - } + builder->get_widget("Export Notebook", export_notebook); + // Single Image Start + { + builder->get_widget("Single Image", single_image); + + builder->get_widget("si_s_document", select_document); + builder->get_widget("si_s_page", select_page); + builder->get_widget("si_s_selection", select_selection); + builder->get_widget("si_s_custom", select_custom); + + builder->get_widget_derived("si_left_sb", left_sb); + builder->get_widget_derived("si_right_sb", right_sb); + builder->get_widget_derived("si_top_sb", top_sb); + builder->get_widget_derived("si_bottom_sb", bottom_sb); + builder->get_widget_derived("si_height_sb", height_sb); + builder->get_widget_derived("si_width_sb", width_sb); + + builder->get_widget_derived("si_img_height_sb", img_height_sb); + builder->get_widget_derived("si_img_width_sb", img_width_sb); + builder->get_widget_derived("si_dpi_sb", dpi_sb); + + builder->get_widget("si_show_export_area", show_export_area); + builder->get_widget_derived("si_units", units); + + builder->get_widget("si_hide_all", hide_all); + builder->get_widget("si_preview_box", si_preview_box); + builder->get_widget("si_show_preview", si_show_preview); + + builder->get_widget("si_extention", extension); + builder->get_widget("si_filename", filename); + builder->get_widget("si_export", si_export); + } // Single Image End + + // Batch Export Start + { + builder->get_widget("Batch Export", batch_export); + } // Batch Export End + + } // Notebook End } + return; } -} // namespace Dialog -{ // Setup Bottom Grid - single_image.pack_end(si_bottom_grid, false, true); - si_bottom_grid.attach(si_filename, 0, 0, 1, 1); - si_bottom_grid.attach(si_extention, 1, 0, 1, 1); - si_bottom_grid.attach(si_export, 2, 0, 1, 1); - si_filename.set_hexpand(); -} -} // namespace UI - -void Export::createBatch() -{ - notebook.append_page(batch, "Batch Export"); -} - -void Export::attachLabels() -{ - select_document.set_label("Document"); - select_page.set_label("Page"); - select_selection.set_label("Selection"); - select_custom.set_label("Custom"); - si_export.set_label("Export"); - - show_export_area.set_label("Show Export Area on Canvas"); - - hide_all.set_label("Hide all except selected"); - preview.set_label("Preview"); -} +/** + * Set current page based on preference/last visited page + */ -void Export::createRadioGroups() +void Export::onNotebookVisible() { - { // single image selection group - auto group = select_document.get_group(); - select_page.set_group(group); - select_selection.set_group(group); - select_custom.set_group(group); + if (export_notebook && batch_export) { + auto page_num = export_notebook->page_num(*batch_export); + export_notebook->set_current_page(page_num); } - removeIndicators(); + return; } -void Export::removeIndicators() -{ - { - select_document.set_mode(false); - select_page.set_mode(false); - select_selection.set_mode(false); - select_custom.set_mode(false); - } -} -void Export::setupSpinButtons() -{ - { // Coordinate sp - auto adj = Gtk::Adjustment::create(0, 0.0, 1000.0, 0.1, 1.0, 0); - x0_sb.configure(adj,1.0,3); - x0_sb.set_width_chars(7); - x0_sb.set_sensitive (true); - - x1_sb.configure(adj,1.0,3); - x1_sb.set_width_chars(7); - x1_sb.set_sensitive (true); - } -} -} // namespace Inkscape +} // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 95ad7e1dab..d34e558678 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -15,10 +15,11 @@ #include +#include "ui/dialog/dialog-base.h" #include "ui/widget/scrollprotected.h" #include "ui/widget/unit-menu.h" -#include "ui/dialog/dialog-base.h" + namespace Inkscape { namespace UI { @@ -42,50 +43,42 @@ public: static Export &getInstance() { return *new Export(); } private: - Gtk::Box container; - Gtk::Notebook notebook; - Gtk::Box single_image; - Gtk::Box batch; - - - Gtk::ScrolledWindow si_scrolled; - Gtk::Grid si_scrolled_grid; - - Gtk::ButtonBox si_selection_box; - Gtk::RadioButton select_document; - Gtk::RadioButton select_page; - Gtk::RadioButton select_selection; - Gtk::RadioButton select_custom; - - Inkscape::UI::Widget::ScrollProtected x0_sb; - Inkscape::UI::Widget::ScrollProtected x1_sb; - Inkscape::UI::Widget::ScrollProtected y0_sb; - Inkscape::UI::Widget::ScrollProtected y1_sb; - Inkscape::UI::Widget::ScrollProtected width_sb; - Inkscape::UI::Widget::ScrollProtected height_sb; - - Gtk::CheckButton show_export_area; - Inkscape::UI::Widget::UnitMenu unit_selector; - - Inkscape::UI::Widget::ScrollProtected bmwidth_sb; - Inkscape::UI::Widget::ScrollProtected bmheight_sb; - Inkscape::UI::Widget::ScrollProtected dpi_sb; - - Gtk::CheckButton hide_all; - Gtk::CheckButton preview; - - Gtk::Grid si_bottom_grid; - Gtk::Entry si_filename; - Gtk::ComboBoxText si_extention; - Gtk::Button si_export; - - - void createSingleImage(); - void createBatch(); - void attachLabels(); - void createRadioGroups(); - void removeIndicators(); - void setupSpinButtons(); + // builder and its object ( in order ) + Glib::RefPtr builder; + Gtk::Box *container = nullptr; + Gtk::Notebook *export_notebook = nullptr; + + Gtk::Box *single_image = nullptr; + Gtk::RadioButton *select_document = nullptr; + Gtk::RadioButton *select_page = nullptr; + Gtk::RadioButton *select_selection = nullptr; + Gtk::RadioButton *select_custom = nullptr; + Inkscape::UI::Widget::ScrollProtected *left_sb = nullptr; + Inkscape::UI::Widget::ScrollProtected *right_sb = nullptr; + Inkscape::UI::Widget::ScrollProtected *top_sb = nullptr; + Inkscape::UI::Widget::ScrollProtected *bottom_sb = nullptr; + Inkscape::UI::Widget::ScrollProtected *height_sb = nullptr; + Inkscape::UI::Widget::ScrollProtected *width_sb = nullptr; + Inkscape::UI::Widget::ScrollProtected *img_height_sb = nullptr; + Inkscape::UI::Widget::ScrollProtected *img_width_sb = nullptr; + Inkscape::UI::Widget::ScrollProtected *dpi_sb = nullptr; + Gtk::CheckButton *show_export_area = nullptr; + Inkscape::UI::Widget::UnitMenu *units = nullptr; + Gtk::CheckButton *hide_all = nullptr; + Gtk::Box *si_preview_box = nullptr; + Gtk::CheckButton *si_show_preview = nullptr; + Gtk::ComboBoxText *extension = nullptr; + Gtk::Entry *filename = nullptr; + Gtk::Button *si_export = nullptr; + + Gtk::Box *batch_export = nullptr; + + // Initialise all objects from builder + void initialise_all(); + + //signals callback + void onNotebookVisible(); + }; } // namespace Dialog } // namespace UI @@ -101,4 +94,4 @@ private: fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/widget/scrollprotected.h b/src/ui/widget/scrollprotected.h index 7dfb5a036f..0be9d8c5a8 100644 --- a/src/ui/widget/scrollprotected.h +++ b/src/ui/widget/scrollprotected.h @@ -10,6 +10,7 @@ * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ +#include #include "scroll-utils.h" namespace Inkscape { @@ -31,6 +32,10 @@ class ScrollProtected : public Base { public: using Base::Base; + using typename Base::BaseObjectType; + ScrollProtected() : Base(){} + ScrollProtected(BaseObjectType* cobject, const Glib::RefPtr& refGlade):Base(cobject){}; + virtual ~ScrollProtected(){}; protected: /** diff --git a/src/ui/widget/unit-menu.h b/src/ui/widget/unit-menu.h index b8e3ab7fab..d3fc497a24 100644 --- a/src/ui/widget/unit-menu.h +++ b/src/ui/widget/unit-menu.h @@ -12,6 +12,7 @@ #define INKSCAPE_UI_WIDGET_UNIT_H #include +#include #include "util/units.h" using namespace Inkscape::Util; @@ -31,7 +32,9 @@ public: * Construct a UnitMenu */ UnitMenu(); - + UnitMenu(BaseObjectType* cobject, const Glib::RefPtr& refGlade):Gtk::ComboBoxText(cobject){ + UnitMenu(); + }; ~UnitMenu() override; /** -- GitLab From c6a5343b0dd53eeb0268980f44bf5bf768ef3feb Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Tue, 15 Jun 2021 15:21:02 +0530 Subject: [PATCH 07/40] Connected Signal Part 1 --- share/ui/dialog-export.glade | 823 +++++++++++++++++------------------ src/ui/dialog/export-old.cpp | 2 +- src/ui/dialog/export-old.h | 2 +- src/ui/dialog/export.cpp | 372 +++++++++++++++- src/ui/dialog/export.h | 91 +++- 5 files changed, 838 insertions(+), 452 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index a264d6faad..ee4bb2d722 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -23,7 +23,6 @@ 5 - 300 True True False @@ -44,19 +43,6 @@ False 5 10 - - - True - False - Left - True - 0 - - - 1 - 1 - - True @@ -64,94 +50,20 @@ True False - - 2 - 1 - - - - - True - True - True - 2 2 - - - True - True - True - - - 5 - 1 - - True True True - - 5 - 2 - - - - - True - False - Right - True - 0 - 4 - 1 - - - - - True - False - Bottom - True - 0 - - - 4 - 2 - - - - - True - False - Top - True - 0 - - - 1 - 2 - - - - - True - False - Width - True - 0 - - - 1 - 3 + 4 @@ -162,7 +74,7 @@ 2 - 3 + 6 @@ -171,22 +83,9 @@ True True - - 5 - 3 - - - - - True - False - Height - True - 0 - 4 - 3 + 6 @@ -203,119 +102,155 @@ 1 - 5 - 2 - - - - - True - False - Width - True - 0 - - - 1 - 6 - - - - - True - False - Height - True - 0 - - - 4 - 6 + 8 + 5 True True + center True - 5 - 6 - - - - - True - True - True - - - 2 - 6 - - - - - True - False - DPI - True - 0 - - - 1 - 7 - - - - - True - False - px - True - 0 - - - - - - - - - 3 - 6 + 4 + 10 - + True False - px - True - 0 - - - - - - + False + 5 + True + expand + + + Document + True + False + False + False + True + False + + + True + True + 1 + + + + + Page + True + False + False + False + si_s_document + + + True + True + 3 + + + + + Selection + True + False + False + False + si_s_document + + + True + True + 3 + + + + + Custom + True + False + False + False + si_s_document + + + True + True + 3 + + - 6 - 6 + 0 + 0 + 7 - + True True - center - True + 10 + 10 + True + + + True + False + 5 + + + checkbutton + True + True + False + 20 + 10 + True + + + 0 + 0 + + + + + checkbutton + True + True + False + 20 + True + + + 0 + 1 + + + + + + + True + False + 10 + Advance + True + + - 2 - 7 + 1 + 14 + 5 @@ -324,7 +259,7 @@ False - Show Export Area On Canvas + Show Export True True False @@ -379,22 +314,48 @@ 1 - 4 + 7 5 - + + True + True + start + True + + + 2 + 12 + + + + + True + True + center + True + + + 2 + 10 + + + + True False - vertical + 20 - - Hide All Except Selected + + 150 + 150 True - True - False - True + False + 150 + face-smile + 6 False @@ -403,189 +364,193 @@ - - Preview - True - True - False - True - - - False - True - 1 - - - - - 1 - 8 - 2 - 3 - - - - - True - True - 10 - 10 - True - - + True False - 5 + center + vertical - - checkbutton + + Preview True True False - 20 - 10 True - 0 - 0 + False + True + 0 - - checkbutton + + Hide All True True False - 20 True - 0 - 1 + False + True + 1 + + True + True + end + 1 + - - - True - False - 10 - Advance - True - - 1 - 11 - 5 + 13 + 5 + + + + + True + False + Left + True + 0 + + + 1 + 2 + + + + + True + False + Top + True + 0 + + + 3 + 2 + + + + + True + False + Right + True + 0 + + + 1 + 4 + + + + + True + False + Bottom + True + 0 + + + 3 + 4 + + + + + True + False + Width + True + 0 + + + 1 + 6 + + + + + True + False + Height + True + 0 + + + 3 + 6 + + + + + True + False + Width +(px) + True + 0 + + + 1 + 10 + + + + + True + False + Height +(px) + True + 0 + + + 3 + 10 + + + + + True + False + DPI + True + 0 + + + 1 + 12 - + True - False - False - 5 - True - expand - - - Document - True - False - False - False - True - False - - - True - True - 1 - - - - - Page - True - False - False - False - si_s_document - - - True - True - 3 - - - - - Selection - True - False - False - False - si_s_document - - - True - True - 3 - - - - - Custom - True - False - False - False - si_s_document - - - True - True - 3 - - + True + True - 0 - 0 - 8 + 4 + 2 - + True - False - vertical - - - 150 - 150 - True - False - 150 - face-smile - 6 - - - False - True - 0 - - + True + True - 3 - 7 - 4 - 4 + 2 + 4 @@ -684,6 +649,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -703,7 +752,7 @@ True - True + False True folder-open Filename @@ -733,8 +782,8 @@ Export True - True - True + False + False end @@ -774,7 +823,6 @@ vertical - 300 True True True @@ -903,7 +951,7 @@ 1 1 - 8 + 5 @@ -947,7 +995,7 @@ 0 0 - 10 + 7 @@ -971,7 +1019,7 @@ 5 Items - 8 + 5 2 @@ -986,7 +1034,7 @@ 1 5 - 4 + 5 @@ -1045,7 +1093,7 @@ 1 6 - 4 + 5 @@ -1082,7 +1130,7 @@ 1 3 - 4 + 5 2 @@ -1128,63 +1176,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/ui/dialog/export-old.cpp b/src/ui/dialog/export-old.cpp index d7c03bb08c..5122b10ce7 100644 --- a/src/ui/dialog/export-old.cpp +++ b/src/ui/dialog/export-old.cpp @@ -1930,4 +1930,4 @@ void Export::onFilenameModified() fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/dialog/export-old.h b/src/ui/dialog/export-old.h index 7379508351..b499e06cfa 100644 --- a/src/ui/dialog/export-old.h +++ b/src/ui/dialog/export-old.h @@ -368,4 +368,4 @@ private: fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index c2b5ba09c7..94f3559e94 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -14,22 +14,33 @@ * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ +// This has to be included prior to anything that includes setjmp.h, it croaks otherwise #include "export.h" #include +#include +#include "inkscape.h" #include "io/resource.h" #ifdef _WIN32 #endif +#define EXPORT_COORD_PRECISION 3 +#define SP_EXPORT_MIN_SIZE 1.0 +#define DPI_BASE Inkscape::Util::Quantity::convert(1, "in", "px") + +using Inkscape::Util::unit_table; namespace Inkscape { namespace UI { namespace Dialog { Export::Export() : DialogBase("/dialogs/export/", "Export") + , selectChangedConn() + , subselChangedConn() + , selectModifiedConn() { std::string gladefile = get_filename_string(Inkscape::IO::Resource::UIS, "dialog-export.glade"); @@ -39,20 +50,40 @@ Export::Export() g_error("Glade file loading failed for export screen"); return; } - builder->get_widget("Export Dialog Box", container); + // initalise all variables from gtk::builder at same place. Makes it easy to sync with glade + initialise_all(); + + // add top level container and show all children. add(*container); show_all_children(); - initialise_all(); - units->setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); - export_notebook->signal_map().connect(sigc::mem_fun(*this, &Export::onNotebookVisible)); + prefs = Inkscape::Preferences::get(); + + // setting up units beforehand is important as we will use it to initialise other values + setupUnits(); + + setupSpinButtons(); + + // Callback when container is dinally mapped on window. All intialisation like set active is done inside it. + container->signal_map().connect(sigc::mem_fun(*this, &Export::onContainerVisible)); + for (auto [key, button] : selection_buttons) { + button->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &Export::onAreaTypeToggle), key)); + } } -Export::~Export() {} +Export::~Export() +{ + selectModifiedConn.disconnect(); + subselChangedConn.disconnect(); + selectChangedConn.disconnect(); +} void Export::initialise_all() { if (builder) { + // Top container + builder->get_widget("Export Dialog Box", container); + // Notebook Start { builder->get_widget("Export Notebook", export_notebook); @@ -60,20 +91,24 @@ void Export::initialise_all() { builder->get_widget("Single Image", single_image); - builder->get_widget("si_s_document", select_document); - builder->get_widget("si_s_page", select_page); - builder->get_widget("si_s_selection", select_selection); - builder->get_widget("si_s_custom", select_custom); + builder->get_widget("si_s_document", selection_buttons[SELECTION_DRAWING]); + selection_names[SELECTION_DRAWING] = "drawing"; + builder->get_widget("si_s_page", selection_buttons[SELECTION_PAGE]); + selection_names[SELECTION_PAGE] = "page"; + builder->get_widget("si_s_selection", selection_buttons[SELECTION_SELECTION]); + selection_names[SELECTION_SELECTION] = "selection"; + builder->get_widget("si_s_custom", selection_buttons[SELECTION_CUSTOM]); + selection_names[SELECTION_CUSTOM] = "custom"; - builder->get_widget_derived("si_left_sb", left_sb); - builder->get_widget_derived("si_right_sb", right_sb); - builder->get_widget_derived("si_top_sb", top_sb); - builder->get_widget_derived("si_bottom_sb", bottom_sb); + builder->get_widget_derived("si_left_sb", x0_sb); + builder->get_widget_derived("si_right_sb", x1_sb); + builder->get_widget_derived("si_top_sb", y0_sb); + builder->get_widget_derived("si_bottom_sb", y1_sb); builder->get_widget_derived("si_height_sb", height_sb); builder->get_widget_derived("si_width_sb", width_sb); - builder->get_widget_derived("si_img_height_sb", img_height_sb); - builder->get_widget_derived("si_img_width_sb", img_width_sb); + builder->get_widget_derived("si_img_height_sb", bmheight_sb); + builder->get_widget_derived("si_img_width_sb", bmwidth_sb); builder->get_widget_derived("si_dpi_sb", dpi_sb); builder->get_widget("si_show_export_area", show_export_area); @@ -98,20 +133,321 @@ void Export::initialise_all() return; } +void Export::setupUnits() +{ + if (units) { + units->setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + units->setUnit(desktop->getNamedView()->display_units->abbr); + } + } +} + +void Export::setupSpinButtons() +{ + setupSpinButton(x0_sb, 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + &Export::onAreaXChange, SPIN_X0); + setupSpinButton(x1_sb, 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + &Export::onAreaXChange, SPIN_X1); + setupSpinButton(y0_sb, 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + &Export::onAreaYChange, SPIN_Y0); + setupSpinButton(y1_sb, 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + &Export::onAreaYChange, SPIN_Y1); + + setupSpinButton(height_sb, 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + &Export::onAreaYChange, SPIN_HEIGHT); + setupSpinButton(width_sb, 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + &Export::onAreaXChange, SPIN_WIDTH); + + setupSpinButton(bmheight_sb, 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, &Export::onDpiChange, SPIN_BMHEIGHT); + setupSpinButton(bmwidth_sb, 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, &Export::onDpiChange, SPIN_BMWIDTH); + setupSpinButton(dpi_sb, 92.0, 0.01, 100000.0, 0.1, 1.0, 2, true, &Export::onDpiChange, SPIN_DPI); +} + +template +void Export::setupSpinButton(Gtk::SpinButton *sb, double val, double min, double max, double step, double page, + int digits, bool sensitive, void (Export::*cb)(T), T param) +{ + if (sb) { + sb->set_digits(digits); + sb->set_increments(step, page); + sb->set_range(min, max); + sb->set_value(val); + sb->set_sensitive(sensitive); + sb->set_width_chars(7); + if (cb) { + auto signal = sb->signal_value_changed().connect(sigc::bind(sigc::mem_fun(*this, cb), param)); + // add signals to list to block all easily + spinButtonConns.push_back(signal); + } + } +} + /** - * Set current page based on preference/last visited page + * UTILS FUNCTIONS */ +float Export::getValuePx(float value) +{ + Unit const *unit = units->getUnit(); + return Inkscape::Util::Quantity::convert(value, unit, "px"); +} + +void Export::setValuePx(Glib::RefPtr &adj, double val) +{ + Unit const *unit = units->getUnit(); + auto value = Inkscape::Util::Quantity::convert(val, "px", unit); + adj->set_value(value); + return; +} + +void Export::areaXChange(sb_type type) +{ + auto x0_adj = x0_sb->get_adjustment(); + auto x1_adj = x1_sb->get_adjustment(); + auto width_adj = width_sb->get_adjustment(); + + float x0, x1, dpi, width, bmwidth; + + // Get all values in px + x0 = getValuePx(x0_adj->get_value()); + x1 = getValuePx(x1_adj->get_value()); + width = getValuePx(width_adj->get_value()); + bmwidth = bmwidth_sb->get_value(); + dpi = dpi_sb->get_value(); + + switch (type) { + case SPIN_X0: + bmwidth = (x1 - x0) * dpi / DPI_BASE; + if (bmwidth < SP_EXPORT_MIN_SIZE) { + x0 = x1 - (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; + } + break; + case SPIN_X1: + bmwidth = (x1 - x0) * dpi / DPI_BASE; + if (bmwidth < SP_EXPORT_MIN_SIZE) { + x1 = x0 + (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; + } + break; + case SPIN_WIDTH: + bmwidth = width * dpi / DPI_BASE; + if (bmwidth < SP_EXPORT_MIN_SIZE) { + width = (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; + } + x1 = x0 + width; + break; + default: + break; + } + + width = x1 - x0; + bmwidth = floor(width * dpi / DPI_BASE + 0.5); + + setValuePx(x0_adj, x0); + setValuePx(x1_adj, x1); + setValuePx(width_adj, width); + bmwidth_sb->set_value(bmwidth); +} + +void Export::areaYChange(sb_type type) +{ + auto y0_adj = y0_sb->get_adjustment(); + auto y1_adj = y1_sb->get_adjustment(); + auto height_adj = height_sb->get_adjustment(); + + float y0, y1, dpi, height, bmheight; + + // Get all values in px + y0 = getValuePx(y0_adj->get_value()); + y1 = getValuePx(y1_adj->get_value()); + height = getValuePx(height_adj->get_value()); + bmheight = bmheight_sb->get_value(); + dpi = dpi_sb->get_value(); + + switch (type) { + case SPIN_Y0: + bmheight = (y1 - y0) * dpi / DPI_BASE; + if (bmheight < SP_EXPORT_MIN_SIZE) { + y0 = y1 - (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; + } + break; + case SPIN_Y1: + bmheight = (y1 - y0) * dpi / DPI_BASE; + if (bmheight < SP_EXPORT_MIN_SIZE) { + y1 = y0 + (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; + } + break; + case SPIN_HEIGHT: + bmheight = height * dpi / DPI_BASE; + if (bmheight < SP_EXPORT_MIN_SIZE) { + height = (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; + } + y1 = y0 + height; + break; + default: + break; + } + + height = y1 - y0; + bmheight = floor(height * dpi / DPI_BASE + 0.5); + + setValuePx(y0_adj, y0); + setValuePx(y1_adj, y1); + setValuePx(height_adj, height); + bmheight_sb->set_value(bmheight); +} -void Export::onNotebookVisible() +void Export::dpiChange(sb_type type) +{ + float dpi, height, width, bmheight, bmwidth; + + // Get all values in px + height = getValuePx(height_sb->get_value()); + width = getValuePx(width_sb->get_value()); + bmheight = bmheight_sb->get_value(); + bmwidth = bmwidth_sb->get_value(); + dpi = dpi_sb->get_value(); + + switch (type) { + case SPIN_BMHEIGHT: + if (bmheight < SP_EXPORT_MIN_SIZE) { + bmheight = SP_EXPORT_MIN_SIZE; + } + dpi = bmheight * DPI_BASE / height; + break; + case SPIN_BMWIDTH: + if (bmwidth < SP_EXPORT_MIN_SIZE) { + bmwidth = SP_EXPORT_MIN_SIZE; + } + dpi = bmwidth * DPI_BASE / width; + break; + case SPIN_DPI: + break; + default: + break; + } + + bmwidth = floor(width * dpi / DPI_BASE + 0.5); + bmheight = floor(height * dpi / DPI_BASE + 0.5); + + bmheight_sb->set_value(bmheight); + bmwidth_sb->set_value(bmwidth); + dpi_sb->set_value(dpi); +} + +void Export::blockSpinConns(bool status = true) +{ + for (auto signal : spinButtonConns) { + if (status) { + signal.block(); + } else { + signal.unblock(); + } + } +} + +void Export::setDefaultNotebookPage() { if (export_notebook && batch_export) { auto page_num = export_notebook->page_num(*batch_export); export_notebook->set_current_page(page_num); } - return; } +void Export::setDefaultSelectionMode() +{ + { // Single Image Selection Mode + + current_key = SELECTION_PAGE; // Page is default key + Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); + for (auto [key, name] : selection_names) { + if (pref_key_name == name) { + current_key = key; + break; + } + } + if (current_key == SELECTION_SELECTION && (SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + current_key = SELECTION_PAGE; + } + selection_buttons[current_key]->set_active(true); + } + + { // Batch Export Selection Mode + } +} + +void Export::setDefaultSpinValues() +{ + blockSpinConns(true); + + blockSpinConns(false); +} +void Export::refreshArea() +{ + SPDocument *doc; + Geom::OptRect bbox; + bbox = Geom::Rect(Geom::Point(0.0, 0.0), Geom::Point(0.0, 0.0)); + doc = SP_ACTIVE_DESKTOP->getDocument(); + + switch (current_key) { + case SELECTION_SELECTION: + break; + case SELECTION_PAGE: + break; + case SELECTION_DRAWING: + break; + case SELECTION_CUSTOM: + break; + default: + break; + } +} + +/** + * SIGNALS + */ + +// Set current page based on preference/last visited page + +void Export::onContainerVisible() +{ + setDefaultNotebookPage(); + setDefaultSelectionMode(); + setDefaultSpinValues(); +} + +void Export::onAreaXChange(sb_type type) +{ + blockSpinConns(true); + areaXChange(type); + blockSpinConns(false); +} +void Export::onAreaYChange(sb_type type) +{ + blockSpinConns(true); + areaYChange(type); + blockSpinConns(false); +} +void Export::onDpiChange(sb_type type) +{ + blockSpinConns(true); + dpiChange(type); + blockSpinConns(false); +} + +void Export::onAreaTypeToggle(selection_mode key) +{ + // Prevent executing function twice + if (!selection_buttons[key]->get_active()) { + return; + } + // If you have reached here means the current key is active one ( not sure if multiple transitions happen but last + // call will change values) + + current_key = key; + refreshArea(); +} } // namespace Dialog } // namespace UI diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index d34e558678..5916656234 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -19,12 +19,31 @@ #include "ui/widget/scrollprotected.h" #include "ui/widget/unit-menu.h" - - namespace Inkscape { namespace UI { namespace Dialog { +enum sb_type +{ + SPIN_X0 = 0, + SPIN_X1, + SPIN_Y0, + SPIN_Y1, + SPIN_WIDTH, + SPIN_HEIGHT, + SPIN_BMWIDTH, + SPIN_BMHEIGHT, + SPIN_DPI +}; + +enum selection_mode +{ + SELECTION_SELECTION = 0, + SELECTION_PAGE, + SELECTION_DRAWING, + SELECTION_CUSTOM +}; + class ExportProgressDialog; /** @@ -49,21 +68,23 @@ private: Gtk::Notebook *export_notebook = nullptr; Gtk::Box *single_image = nullptr; - Gtk::RadioButton *select_document = nullptr; - Gtk::RadioButton *select_page = nullptr; - Gtk::RadioButton *select_selection = nullptr; - Gtk::RadioButton *select_custom = nullptr; - Inkscape::UI::Widget::ScrollProtected *left_sb = nullptr; - Inkscape::UI::Widget::ScrollProtected *right_sb = nullptr; - Inkscape::UI::Widget::ScrollProtected *top_sb = nullptr; - Inkscape::UI::Widget::ScrollProtected *bottom_sb = nullptr; + + std::map selection_buttons; + + Inkscape::UI::Widget::ScrollProtected *x0_sb = nullptr; + Inkscape::UI::Widget::ScrollProtected *x1_sb = nullptr; + Inkscape::UI::Widget::ScrollProtected *y0_sb = nullptr; + Inkscape::UI::Widget::ScrollProtected *y1_sb = nullptr; Inkscape::UI::Widget::ScrollProtected *height_sb = nullptr; Inkscape::UI::Widget::ScrollProtected *width_sb = nullptr; - Inkscape::UI::Widget::ScrollProtected *img_height_sb = nullptr; - Inkscape::UI::Widget::ScrollProtected *img_width_sb = nullptr; + + Inkscape::UI::Widget::ScrollProtected *bmheight_sb = nullptr; + Inkscape::UI::Widget::ScrollProtected *bmwidth_sb = nullptr; Inkscape::UI::Widget::ScrollProtected *dpi_sb = nullptr; + Gtk::CheckButton *show_export_area = nullptr; Inkscape::UI::Widget::UnitMenu *units = nullptr; + Gtk::CheckButton *hide_all = nullptr; Gtk::Box *si_preview_box = nullptr; Gtk::CheckButton *si_show_preview = nullptr; @@ -73,12 +94,50 @@ private: Gtk::Box *batch_export = nullptr; + // Utils Variables + Inkscape::Preferences *prefs = nullptr; + std::map selection_names; + selection_mode current_key; + // Initialise all objects from builder void initialise_all(); - - //signals callback - void onNotebookVisible(); - + // Add units from db + void setupUnits(); + + // change range and callbacks to spinbuttons + void setupSpinButtons(); + template + void setupSpinButton(Gtk::SpinButton *sb, double val, double min, double max, double step, double page, int digits, + bool sensitive, void (Export::*cb)(T), T param); + + // setup default values of widgets + void setDefaultNotebookPage(); + void setDefaultSelectionMode(); + void setDefaultSpinValues(); + + // Utils Functions + void areaXChange(sb_type type); + void areaYChange(sb_type type); + void dpiChange(sb_type type); + float getValuePx(float value); + void setValuePx(Glib::RefPtr &adj, double val); + + void blockSpinConns(bool status); + + void refreshArea(); + + // signals callback + void onContainerVisible(); + void onAreaXChange(sb_type type); + void onAreaYChange(sb_type type); + void onDpiChange(sb_type type); + void onAreaTypeToggle(selection_mode key); + + // signals + sigc::connection selectChangedConn; + sigc::connection subselChangedConn; + sigc::connection selectModifiedConn; + std::vector spinButtonConns; }; } // namespace Dialog } // namespace UI -- GitLab From e19bd08eca94f586fef573f872752ff9e208e0b6 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Tue, 15 Jun 2021 23:20:13 +0530 Subject: [PATCH 08/40] added extention list --- share/ui/dialog-export.glade | 6 +- src/ui/dialog/export.cpp | 227 +++++++++++++++++++++++++++++------ src/ui/dialog/export.h | 23 +++- 3 files changed, 208 insertions(+), 48 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index ee4bb2d722..c4cf8de780 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -767,11 +767,7 @@ True False center - 1 - - svg - png - + 0 1 diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 94f3559e94..9586e4175c 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -20,8 +20,29 @@ #include #include +#include "document-undo.h" +#include "document.h" +#include "file.h" +#include "inkscape-window.h" #include "inkscape.h" +#include "preferences.h" +#include "selection-chemistry.h" + +// required to set status message after export +#include "desktop.h" +#include "extension/db.h" +#include "helper/png-write.h" #include "io/resource.h" +#include "io/sys.h" +#include "message-stack.h" +#include "object/sp-namedview.h" +#include "object/sp-root.h" +#include "ui/dialog-events.h" +#include "ui/dialog/dialog-notebook.h" +#include "ui/dialog/filedialog.h" +#include "ui/interface.h" +#include "ui/widget/scrollprotected.h" +#include "ui/widget/unit-menu.h" #ifdef _WIN32 @@ -63,9 +84,11 @@ Export::Export() setupUnits(); setupSpinButtons(); + setupExtensionList(); // Callback when container is dinally mapped on window. All intialisation like set active is done inside it. container->signal_map().connect(sigc::mem_fun(*this, &Export::onContainerVisible)); + units->signal_changed().connect(sigc::mem_fun(*this, &Export::onUnitChanged)); for (auto [key, button] : selection_buttons) { button->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &Export::onAreaTypeToggle), key)); } @@ -78,6 +101,69 @@ Export::~Export() selectChangedConn.disconnect(); } +void Export::update() +{ + if (!_app) { + std::cerr << "Export::update(): _app is null" << std::endl; + return; + } + + onSelectionChanged(); + onSelectionModified(0); +#if 0 + setDesktop(getDesktop()); +#endif +} + +void Export::onSelectionChanged() +{ + Inkscape::Selection *selection = SP_ACTIVE_DESKTOP->getSelection(); + if (selection->isEmpty()) { + selection_buttons[SELECTION_SELECTION]->set_sensitive(false); + if (current_key == SELECTION_SELECTION) { + selection_buttons[(selection_mode)0]->set_active(true); // This causes refresh area + // return otherwise refreshArea will be called again + return; + } + } else { + selection_buttons[SELECTION_SELECTION]->set_sensitive(true); + } + refreshArea(); +} + +void Export::onSelectionModified(guint /*flags*/) +{ + if (SP_ACTIVE_DESKTOP) { + Geom::OptRect bbox; + + switch (current_key) { + case SELECTION_DRAWING: + SPDocument *doc; + doc = SP_ACTIVE_DESKTOP->getDocument(); + bbox = doc->getRoot()->desktopVisualBounds(); + if (bbox) { + setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); + } + break; + case SELECTION_SELECTION: + Inkscape::Selection *Sel; + Sel = SP_ACTIVE_DESKTOP->getSelection(); + if (Sel->isEmpty() == false) { + bbox = Sel->visualBounds(); + if (bbox) { + setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); + } + } + break; + default: + /* Do nothing for page or for custom */ + break; + } + } + + return; +} + void Export::initialise_all() { if (builder) { @@ -118,7 +204,7 @@ void Export::initialise_all() builder->get_widget("si_preview_box", si_preview_box); builder->get_widget("si_show_preview", si_show_preview); - builder->get_widget("si_extention", extension); + builder->get_widget("si_extention", extension_cb); builder->get_widget("si_filename", filename); builder->get_widget("si_export", si_export); } // Single Image End @@ -144,6 +230,32 @@ void Export::setupUnits() } } +void Export::setupExtensionList() +{ + Inkscape::Extension::DB::OutputList extensions; + Inkscape::Extension::db.get_output_list(extensions); + Glib::ustring extension; + + for (auto omod : extensions) { + // FIXME: would be nice to grey them out instead of not listing them + if (omod->deactivated() || (omod->is_raster() != true)) + continue; + + extension = omod->get_extension(); + extension_cb->append(extension); + extension_list[extension] = omod; + } + + // add extentions manually + Inkscape::Extension::Output *manual_omod; + manual_omod = dynamic_cast(Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_SVG)); + extension = manual_omod->get_extension(); + extension_cb->append(extension); + extension_list[extension] = manual_omod; + + extension_cb->set_active(0); +} + void Export::setupSpinButtons() { setupSpinButton(x0_sb, 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, @@ -348,60 +460,92 @@ void Export::blockSpinConns(bool status = true) void Export::setDefaultNotebookPage() { - if (export_notebook && batch_export) { - auto page_num = export_notebook->page_num(*batch_export); - export_notebook->set_current_page(page_num); - } + // if (export_notebook && batch_export) { + // auto page_num = export_notebook->page_num(*batch_export); + // export_notebook->set_current_page(page_num); + // } } void Export::setDefaultSelectionMode() { - { // Single Image Selection Mode - - current_key = SELECTION_PAGE; // Page is default key - Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); - for (auto [key, name] : selection_names) { - if (pref_key_name == name) { - current_key = key; - break; + if (SP_ACTIVE_DESKTOP) { + { // Single Image Selection Mode + + current_key = (selection_mode)0; // default key + Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); + for (auto [key, name] : selection_names) { + if (pref_key_name == name) { + current_key = key; + break; + } + } + if (current_key == SELECTION_SELECTION && (SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + current_key = (selection_mode)0; + } + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + selection_buttons[SELECTION_SELECTION]->set_sensitive(false); } + selection_buttons[current_key]->set_active(true); } - if (current_key == SELECTION_SELECTION && (SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { - current_key = SELECTION_PAGE; + + { // Batch Export Selection Mode } - selection_buttons[current_key]->set_active(true); } +} - { // Batch Export Selection Mode +void Export::refreshArea() +{ + if (SP_ACTIVE_DESKTOP) { + SPDocument *doc; + Geom::OptRect bbox; + doc = SP_ACTIVE_DESKTOP->getDocument(); + + switch (current_key) { + case SELECTION_SELECTION: + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { + bbox = SP_ACTIVE_DESKTOP->getSelection()->visualBounds(); + break; + } + case SELECTION_DRAWING: + bbox = doc->getRoot()->desktopVisualBounds(); + if (bbox) { + break; + } + case SELECTION_PAGE: + bbox = Geom::Rect(Geom::Point(0.0, 0.0), + Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); + break; + case SELECTION_CUSTOM: + break; + default: + break; + } + if (current_key != SELECTION_CUSTOM && bbox) { + setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); + } } + + // TODO: FilenameModified } -void Export::setDefaultSpinValues() +void Export::setArea(double x0, double y0, double x1, double y1) { blockSpinConns(true); - blockSpinConns(false); -} + auto x0_adj = x0_sb->get_adjustment(); + auto x1_adj = x1_sb->get_adjustment(); + auto y0_adj = y0_sb->get_adjustment(); + auto y1_adj = y1_sb->get_adjustment(); -void Export::refreshArea() -{ - SPDocument *doc; - Geom::OptRect bbox; - bbox = Geom::Rect(Geom::Point(0.0, 0.0), Geom::Point(0.0, 0.0)); - doc = SP_ACTIVE_DESKTOP->getDocument(); + setValuePx(x1_adj, x1); + setValuePx(y1_adj, y1); + setValuePx(x0_adj, x0); + setValuePx(y0_adj, y0); - switch (current_key) { - case SELECTION_SELECTION: - break; - case SELECTION_PAGE: - break; - case SELECTION_DRAWING: - break; - case SELECTION_CUSTOM: - break; - default: - break; - } + areaXChange(SPIN_X1); + areaYChange(SPIN_Y1); + + blockSpinConns(false); } /** @@ -414,7 +558,6 @@ void Export::onContainerVisible() { setDefaultNotebookPage(); setDefaultSelectionMode(); - setDefaultSpinValues(); } void Export::onAreaXChange(sb_type type) @@ -446,6 +589,12 @@ void Export::onAreaTypeToggle(selection_mode key) // call will change values) current_key = key; + prefs->setString("/dialogs/export/exportarea/value", selection_names[current_key]); + refreshArea(); +} + +void Export::onUnitChanged() +{ refreshArea(); } diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 5916656234..0ede2f9e14 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -18,6 +18,8 @@ #include "ui/dialog/dialog-base.h" #include "ui/widget/scrollprotected.h" #include "ui/widget/unit-menu.h" +#include "extension/output.h" + namespace Inkscape { namespace UI { @@ -38,8 +40,8 @@ enum sb_type enum selection_mode { - SELECTION_SELECTION = 0, - SELECTION_PAGE, + SELECTION_PAGE = 0, // Default is alaways placed first + SELECTION_SELECTION, SELECTION_DRAWING, SELECTION_CUSTOM }; @@ -88,7 +90,7 @@ private: Gtk::CheckButton *hide_all = nullptr; Gtk::Box *si_preview_box = nullptr; Gtk::CheckButton *si_show_preview = nullptr; - Gtk::ComboBoxText *extension = nullptr; + Gtk::ComboBoxText *extension_cb = nullptr; Gtk::Entry *filename = nullptr; Gtk::Button *si_export = nullptr; @@ -98,11 +100,13 @@ private: Inkscape::Preferences *prefs = nullptr; std::map selection_names; selection_mode current_key; + std::map extension_list; // Initialise all objects from builder void initialise_all(); // Add units from db void setupUnits(); + void setupExtensionList(); // change range and callbacks to spinbuttons void setupSpinButtons(); @@ -113,7 +117,6 @@ private: // setup default values of widgets void setDefaultNotebookPage(); void setDefaultSelectionMode(); - void setDefaultSpinValues(); // Utils Functions void areaXChange(sb_type type); @@ -125,6 +128,7 @@ private: void blockSpinConns(bool status); void refreshArea(); + void setArea(double x0, double y0, double x1, double y1); // signals callback void onContainerVisible(); @@ -132,6 +136,17 @@ private: void onAreaYChange(sb_type type); void onDpiChange(sb_type type); void onAreaTypeToggle(selection_mode key); + void onUnitChanged(); + /** + * Inkscape selection change callback + */ + void onSelectionChanged(); + void onSelectionModified(guint flags); + + /** + * Update active window. + */ + void update() override; // signals sigc::connection selectChangedConn; -- GitLab From 358c431c6e64d49a6f1d06c602e3ccac30a49be1 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Fri, 18 Jun 2021 15:25:40 +0530 Subject: [PATCH 09/40] Single Image Export Signals Connected --- share/ui/dialog-export.glade | 2 +- src/ui/dialog/export-old.cpp | 819 +++++++++++++++++------------------ src/ui/dialog/export.cpp | 271 +++++++++++- src/ui/dialog/export.h | 21 +- 4 files changed, 667 insertions(+), 446 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index c4cf8de780..513262260c 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -752,7 +752,7 @@ True - False + True True folder-open Filename diff --git a/src/ui/dialog/export-old.cpp b/src/ui/dialog/export-old.cpp index 5122b10ce7..3f70d6d620 100644 --- a/src/ui/dialog/export-old.cpp +++ b/src/ui/dialog/export-old.cpp @@ -15,8 +15,9 @@ */ // This has to be included prior to anything that includes setjmp.h, it croaks otherwise -#include - +#include +#include +#include #include #include #include @@ -25,45 +26,37 @@ #include #include #include - -#include -#include -#include +#include #include "document-undo.h" #include "document.h" #include "file.h" -#include "inkscape.h" #include "inkscape-window.h" +#include "inkscape.h" #include "preferences.h" #include "selection-chemistry.h" // required to set status message after export #include "desktop.h" -#include "message-stack.h" - +#include "extension/db.h" #include "helper/png-write.h" - #include "io/resource.h" #include "io/sys.h" - +#include "message-stack.h" #include "object/sp-namedview.h" #include "object/sp-root.h" - #include "ui/dialog-events.h" -#include "ui/interface.h" -#include "ui/widget/unit-menu.h" -#include "ui/widget/scrollprotected.h" #include "ui/dialog/dialog-notebook.h" #include "ui/dialog/filedialog.h" - -#include "extension/db.h" +#include "ui/interface.h" +#include "ui/widget/scrollprotected.h" +#include "ui/widget/unit-menu.h" #ifdef _WIN32 -#include #include #include #include +#include #endif #define SP_EXPORT_MIN_SIZE 1.0 @@ -81,11 +74,10 @@ namespace { class MessageCleaner { public: - MessageCleaner(Inkscape::MessageId messageId, SPDesktop *desktop) : - _desktop(desktop), - _messageId(messageId) - { - } + MessageCleaner(Inkscape::MessageId messageId, SPDesktop *desktop) + : _desktop(desktop) + , _messageId(messageId) + {} ~MessageCleaner() { @@ -108,43 +100,41 @@ namespace Inkscape { namespace UI { namespace Dialog { -class ExportProgressDialog : public Gtk::Dialog { - private: - Gtk::ProgressBar *_progress = nullptr; - Export *_export_panel = nullptr; - int _current = 0; - int _total = 0; +class ExportProgressDialog : public Gtk::Dialog +{ +private: + Gtk::ProgressBar *_progress = nullptr; + Export *_export_panel = nullptr; + int _current = 0; + int _total = 0; - public: - ExportProgressDialog(const Glib::ustring &title, bool modal = false) - : Gtk::Dialog(title, modal) - {} +public: + ExportProgressDialog(const Glib::ustring &title, bool modal = false) + : Gtk::Dialog(title, modal) + {} - inline void set_export_panel(const decltype(_export_panel) export_panel) { _export_panel = export_panel; } - inline decltype(_export_panel) get_export_panel() const { return _export_panel; } + inline void set_export_panel(const decltype(_export_panel) export_panel) { _export_panel = export_panel; } + inline decltype(_export_panel) get_export_panel() const { return _export_panel; } - inline void set_progress(const decltype(_progress) progress) { _progress = progress; } - inline decltype(_progress) get_progress() const { return _progress; } + inline void set_progress(const decltype(_progress) progress) { _progress = progress; } + inline decltype(_progress) get_progress() const { return _progress; } - inline void set_current(const int current) { _current = current; } - inline int get_current() const { return _current; } + inline void set_current(const int current) { _current = current; } + inline int get_current() const { return _current; } - inline void set_total(const int total) { _total = total; } - inline int get_total() const { return _total; } + inline void set_total(const int total) { _total = total; } + inline int get_total() const { return _total; } }; static std::string create_filepath_from_id(Glib::ustring, const Glib::ustring &); /** A list of strings that is used both in the preferences, and in the data fields to describe the various values of \c selection_type. */ -static const char * selection_names[SELECTION_NUMBER_OF] = { - "page", "drawing", "selection", "custom" -}; +static const char *selection_names[SELECTION_NUMBER_OF] = {"page", "drawing", "selection", "custom"}; /** The names on the buttons for the various selection types. */ -static const char * selection_labels[SELECTION_NUMBER_OF] = { - N_("_Page"), N_("_Drawing"), N_("_Selection"), N_("_Custom") -}; +static const char *selection_labels[SELECTION_NUMBER_OF] = {N_("_Page"), N_("_Drawing"), N_("_Selection"), + N_("_Custom")}; Export::Export() : DialogBase("/dialogs/export/", "Export") @@ -189,11 +179,14 @@ Export::Export() , selectModifiedConn() { batch_export.set_use_underline(); - batch_export.set_tooltip_text(_("Export each selected object into its own PNG file, using export hints if any (caution, overwrites without asking!)")); + batch_export.set_tooltip_text(_("Export each selected object into its own PNG file, using export hints if any " + "(caution, overwrites without asking!)")); hide_export.set_use_underline(); hide_export.set_tooltip_text(_("In the exported image, hide all objects except those that are selected")); interlacing.set_use_underline(); - interlacing.set_tooltip_text(_("Enables ADAM7 interlacing for PNG output. This results in slightly larger image files, but big images can already be displayed (slightly blurry) while still loading.")); + interlacing.set_tooltip_text( + _("Enables ADAM7 interlacing for PNG output. This results in slightly larger image files, but big images can " + "already be displayed (slightly blurry) while still loading.")); closeWhenDone.set_use_underline(); closeWhenDone.set_tooltip_text(_("Once the export completes, close this dialog")); prefs = Inkscape::Preferences::get(); @@ -202,7 +195,7 @@ Export::Export() /* Export area frame */ { - Gtk::Label* lbl = new Gtk::Label(_("Export area"), Gtk::ALIGN_START); + Gtk::Label *lbl = new Gtk::Label(_("Export area"), Gtk::ALIGN_START); lbl->set_use_markup(true); area_box.pack_start(*lbl); @@ -292,9 +285,8 @@ Export::Export() /** TODO * There's no way to set ydpi currently, so we use the defaultxdpi value here, too... */ - ydpi_adj = createSpinbutton ( "ydpi", prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), - 0.01, 100000.0, 0.1, 1.0, t, 3, 1, - "", _("dpi"), 2, 0, nullptr ); + ydpi_adj = createSpinbutton("ydpi", prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), 0.01, + 100000.0, 0.1, 1.0, t, 3, 1, "", _("dpi"), 2, 0, nullptr); singleexport_box.pack_start(size_box, Gtk::PACK_SHRINK); } @@ -308,14 +300,14 @@ Export::Export() set_default_filename(); - filename_box.pack_start (filename_entry, true, true, 0); + filename_box.pack_start(filename_entry, true, true, 0); - Gtk::Box* browser_im_label = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 3); + Gtk::Box *browser_im_label = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 3); browse_image.set_from_icon_name("folder", Gtk::ICON_SIZE_BUTTON); browser_im_label->pack_start(browse_image); browser_im_label->pack_start(browse_label); browse_button.add(*browser_im_label); - filename_box.pack_end (browse_button, false, false); + filename_box.pack_end(browse_button, false, false); filename_box.pack_end(export_button, false, false); file_box.add(filename_box); @@ -333,38 +325,42 @@ Export::Export() batch_box.pack_start(batch_export, false, false, 3); hide_export.set_sensitive(true); - hide_export.set_active (prefs->getBool("/dialogs/export/hideexceptselected/value", false)); + hide_export.set_active(prefs->getBool("/dialogs/export/hideexceptselected/value", false)); hide_box.pack_start(hide_export, false, false, 3); - /* Export Button row */ export_button.set_label(_("_Export")); export_button.set_use_underline(); - export_button.set_tooltip_text (_("Export the bitmap file with these settings")); + export_button.set_tooltip_text(_("Export the bitmap file with these settings")); button_box.set_border_width(3); button_box.pack_start(closeWhenDone, true, true, 0); /*Advanced*/ - Gtk::Label *label_advanced = Gtk::manage(new Gtk::Label(_("Advanced"),true)); + Gtk::Label *label_advanced = Gtk::manage(new Gtk::Label(_("Advanced"), true)); expander.set_label_widget(*label_advanced); expander.set_vexpand(false); - const char* const modes_list[]={"Gray_1", "Gray_2","Gray_4","Gray_8","Gray_16","RGB_8","RGB_16","GrayAlpha_8","GrayAlpha_16","RGBA_8","RGBA_16"}; - for(auto i : modes_list) + const char *const modes_list[] = {"Gray_1", "Gray_2", "Gray_4", "Gray_8", "Gray_16", "RGB_8", + "RGB_16", "GrayAlpha_8", "GrayAlpha_16", "RGBA_8", "RGBA_16"}; + for (auto i : modes_list) bitdepth_cb.append(i); bitdepth_cb.set_active_text("RGBA_8"); bitdepth_cb.set_hexpand(); - const char* const zlist[]={"Z_NO_COMPRESSION","Z_BEST_SPEED","2","3","4","5","Z_DEFAULT_COMPRESSION","7","8","Z_BEST_COMPRESSION"}; - for(auto i : zlist) + const char *const zlist[] = { + "Z_NO_COMPRESSION", "Z_BEST_SPEED", "2", "3", "4", "5", "Z_DEFAULT_COMPRESSION", "7", "8", + "Z_BEST_COMPRESSION"}; + for (auto i : zlist) zlib_compression.append(i); zlib_compression.set_active_text("Z_DEFAULT_COMPRESSION"); pHYs_adj = Gtk::Adjustment::create(0, 0, 100000, 0.1, 1.0, 0); pHYs_sb.set_adjustment(pHYs_adj); pHYs_sb.set_width_chars(7); - pHYs_sb.set_tooltip_text( _("Will force-set the physical dpi for the png file. Set this to 72 if you're planning to work on your png with Photoshop") ); + pHYs_sb.set_tooltip_text(_("Will force-set the physical dpi for the png file. Set this to 72 if you're planning to " + "work on your png with Photoshop")); zlib_compression.set_hexpand(); - const char* const antialising_list[] = {"CAIRO_ANTIALIAS_NONE","CAIRO_ANTIALIAS_FAST","CAIRO_ANTIALIAS_GOOD (default)","CAIRO_ANTIALIAS_BEST"}; - for(auto i : antialising_list) + const char *const antialising_list[] = {"CAIRO_ANTIALIAS_NONE", "CAIRO_ANTIALIAS_FAST", + "CAIRO_ANTIALIAS_GOOD (default)", "CAIRO_ANTIALIAS_BEST"}; + for (auto i : antialising_list) antialiasing_cb.append(i); antialiasing_cb.set_active_text(antialising_list[2]); bitdepth_label.set_halign(Gtk::ALIGN_START); @@ -374,15 +370,15 @@ Export::Export() auto table = new Gtk::Grid(); expander.add(*table); table->set_border_width(4); - table->attach(interlacing,0,0,1,1); - table->attach(bitdepth_label,0,1,1,1); - table->attach(bitdepth_cb,1,1,1,1); - table->attach(zlib_label,0,2,1,1); - table->attach(zlib_compression,1,2,1,1); - table->attach(pHYs_label,0,3,1,1); - table->attach(pHYs_sb,1,3,1,1); - table->attach(antialiasing_label,0,4,1,1); - table->attach(antialiasing_cb,1,4,1,1); + table->attach(interlacing, 0, 0, 1, 1); + table->attach(bitdepth_label, 0, 1, 1, 1); + table->attach(bitdepth_cb, 1, 1, 1, 1); + table->attach(zlib_label, 0, 2, 1, 1); + table->attach(zlib_compression, 1, 2, 1, 1); + table->attach(pHYs_label, 0, 3, 1, 1); + table->attach(pHYs_sb, 1, 3, 1, 1); + table->attach(antialiasing_label, 0, 4, 1, 1); + table->attach(antialiasing_cb, 1, 4, 1, 1); table->show(); /* Main dialog */ @@ -396,9 +392,9 @@ Export::Export() pack_end(_prog, Gtk::PACK_SHRINK); /* Signal handlers */ - filename_entry.signal_changed().connect( sigc::mem_fun(*this, &Export::onFilenameModified) ); + filename_entry.signal_changed().connect(sigc::mem_fun(*this, &Export::onFilenameModified)); // pressing enter in the filename field is the same as clicking export: - filename_entry.signal_activate().connect(sigc::mem_fun(*this, &Export::onExport) ); + filename_entry.signal_activate().connect(sigc::mem_fun(*this, &Export::onExport)); browse_button.signal_clicked().connect(sigc::mem_fun(*this, &Export::onBrowse)); batch_export.signal_clicked().connect(sigc::mem_fun(*this, &Export::onBatchClicked)); export_button.signal_clicked().connect(sigc::mem_fun(*this, &Export::onExport)); @@ -411,7 +407,7 @@ Export::Export() refreshArea(); } -Export::~Export () +Export::~Export() { selectModifiedConn.disconnect(); subselChangedConn.disconnect(); @@ -465,25 +461,25 @@ void Export::update() * this code sets the name first, it may not be the one users * really see. */ -void Export::set_default_filename () { - - if ( SP_ACTIVE_DOCUMENT && SP_ACTIVE_DOCUMENT->getDocumentFilename() ) - { - SPDocument * doc = SP_ACTIVE_DOCUMENT; +void Export::set_default_filename() +{ + if (SP_ACTIVE_DOCUMENT && SP_ACTIVE_DOCUMENT->getDocumentFilename()) { + SPDocument *doc = SP_ACTIVE_DOCUMENT; const gchar *filename = doc->getDocumentFilename(); auto &&text_extension = get_file_save_extension(Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS); - Inkscape::Extension::Output * oextension = nullptr; + Inkscape::Extension::Output *oextension = nullptr; if (!text_extension.empty()) { - oextension = dynamic_cast(Inkscape::Extension::db.get(text_extension.c_str())); + oextension = + dynamic_cast(Inkscape::Extension::db.get(text_extension.c_str())); } if (oextension != nullptr) { - gchar * old_extension = oextension->get_extension(); + gchar *old_extension = oextension->get_extension(); if (g_str_has_suffix(filename, old_extension)) { - gchar * filename_copy; - gchar * extension_point; - gchar * final_name; + gchar *filename_copy; + gchar *extension_point; + gchar *final_name; filename_copy = g_strdup(filename); extension_point = g_strrstr(filename_copy, old_extension); @@ -505,10 +501,8 @@ void Export::set_default_filename () { } doc_export_name = filename_entry.get_text(); - } - else if ( SP_ACTIVE_DOCUMENT ) - { - Glib::ustring filename = create_filepath_from_id (_("bitmap"), filename_entry.get_text()); + } else if (SP_ACTIVE_DOCUMENT) { + Glib::ustring filename = create_filepath_from_id(_("bitmap"), filename_entry.get_text()); filename_entry.set_text(filename); filename_entry.set_position(filename.length()); @@ -516,12 +510,10 @@ void Export::set_default_filename () { } } -Glib::RefPtr Export::createSpinbutton( gchar const * /*key*/, - double val, double min, double max, double step, double page, - Gtk::Grid *t, int x, int y, - const Glib::ustring& ll, const Glib::ustring& lr, - int digits, unsigned int sensitive, - void (Export::*cb)() ) +Glib::RefPtr Export::createSpinbutton(gchar const * /*key*/, double val, double min, double max, + double step, double page, Gtk::Grid *t, int x, int y, + const Glib::ustring &ll, const Glib::ustring &lr, int digits, + unsigned int sensitive, void (Export::*cb)()) { auto adj = Gtk::Adjustment::create(val, min, max, step, page, 0); @@ -529,7 +521,7 @@ Glib::RefPtr Export::createSpinbutton( gchar const * /*key*/, Gtk::Label *l = nullptr; if (!ll.empty()) { - l = new Gtk::Label(ll,true); + l = new Gtk::Label(ll, true); l->set_halign(Gtk::ALIGN_END); l->set_valign(Gtk::ALIGN_CENTER); l->set_hexpand(); @@ -543,7 +535,7 @@ Glib::RefPtr Export::createSpinbutton( gchar const * /*key*/, t->attach(*sb, x + pos, y, 1, 1); sb->set_width_chars(7); - sb->set_sensitive (sensitive); + sb->set_sensitive(sensitive); pos++; if (l) { @@ -551,28 +543,26 @@ Glib::RefPtr Export::createSpinbutton( gchar const * /*key*/, } if (!lr.empty()) { - l = new Gtk::Label(lr,true); + l = new Gtk::Label(lr, true); l->set_halign(Gtk::ALIGN_START); l->set_valign(Gtk::ALIGN_CENTER); l->set_hexpand(); t->attach(*l, x + pos, y, 1, 1); - l->set_sensitive (sensitive); + l->set_sensitive(sensitive); pos++; - l->set_mnemonic_widget (*sb); + l->set_mnemonic_widget(*sb); } if (cb) { - adj->signal_value_changed().connect( sigc::mem_fun(*this, cb) ); + adj->signal_value_changed().connect(sigc::mem_fun(*this, cb)); } return adj; } // end of createSpinbutton() - std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_entry_text) { - if (id.empty()) - { /* This should never happen */ + if (id.empty()) { /* This should never happen */ id = "bitmap"; } @@ -584,7 +574,7 @@ std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_ if (directory.empty()) { /* Grab document directory */ - const gchar* docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); + const gchar *docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); if (docFilename) { directory = Glib::path_get_dirname(docFilename); } @@ -597,7 +587,7 @@ std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_ return Glib::build_filename(directory, Glib::filename_from_utf8(id) + ".png"); } -void Export::onBatchClicked () +void Export::onBatchClicked() { if (batch_export.get_active()) { singleexport_box.set_sensitive(false); @@ -606,20 +596,21 @@ void Export::onBatchClicked () } } -void Export::updateCheckbuttons () +void Export::updateCheckbuttons() { - gint num = (gint) boost::distance(SP_ACTIVE_DESKTOP->getSelection()->items()); + gint num = (gint)boost::distance(SP_ACTIVE_DESKTOP->getSelection()->items()); if (num >= 2) { batch_export.set_sensitive(true); } else { - batch_export.set_active (false); + batch_export.set_active(false); batch_export.set_sensitive(false); } - gchar *l = g_strdup_printf(ngettext("B_atch export %d selected object","B_atch export %d selected objects",num), num); + gchar *l = + g_strdup_printf(ngettext("B_atch export %d selected object", "B_atch export %d selected objects", num), num); batch_export.set_label(l); g_free(l); - //hide_export.set_sensitive (num > 0); + // hide_export.set_sensitive (num > 0); } inline void Export::findDefaultSelection() @@ -632,7 +623,6 @@ inline void Export::findDefaultSelection() /* Try using the preferences */ if (key == SELECTION_NUMBER_OF) { - int i = SELECTION_NUMBER_OF; Glib::ustring what = prefs->getString("/dialogs/export/exportarea/value"); @@ -654,10 +644,9 @@ inline void Export::findDefaultSelection() current_key = key; selectiontype_buttons[current_key]->set_active(true); - updateCheckbuttons (); + updateCheckbuttons(); } - /** * If selection changed and "Export area" is set to "Selection" * recalculate bounds when the selection changes @@ -673,46 +662,40 @@ void Export::onSelectionChanged() updateCheckbuttons(); } -void Export::onSelectionModified ( guint /*flags*/ ) +void Export::onSelectionModified(guint /*flags*/) { - Inkscape::Selection * Sel; + Inkscape::Selection *Sel; switch (current_key) { - case SELECTION_DRAWING: - if ( SP_ACTIVE_DESKTOP ) { - SPDocument *doc; - doc = SP_ACTIVE_DESKTOP->getDocument(); - Geom::OptRect bbox = doc->getRoot()->desktopVisualBounds(); - if (bbox) { - setArea ( bbox->left(), - bbox->top(), - bbox->right(), - bbox->bottom()); + case SELECTION_DRAWING: + if (SP_ACTIVE_DESKTOP) { + SPDocument *doc; + doc = SP_ACTIVE_DESKTOP->getDocument(); + Geom::OptRect bbox = doc->getRoot()->desktopVisualBounds(); + if (bbox) { + setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); + } } - } - break; - case SELECTION_SELECTION: - Sel = SP_ACTIVE_DESKTOP->getSelection(); - if (Sel->isEmpty() == false) { - Geom::OptRect bbox = Sel->visualBounds(); - if (bbox) - { - setArea ( bbox->left(), - bbox->top(), - bbox->right(), - bbox->bottom()); + break; + case SELECTION_SELECTION: + Sel = SP_ACTIVE_DESKTOP->getSelection(); + if (Sel->isEmpty() == false) { + Geom::OptRect bbox = Sel->visualBounds(); + if (bbox) { + setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); + } } - } - break; - default: - /* Do nothing for page or for custom */ - break; + break; + default: + /* Do nothing for page or for custom */ + break; } return; } /// Called when one of the selection buttons was toggled. -void Export::onAreaTypeToggled() { +void Export::onAreaTypeToggled() +{ if (update_flag) { return; } @@ -731,114 +714,107 @@ void Export::onAreaTypeToggled() { /// Called when area needs to be refreshed /// Area type changed, unit changed, initialization -void Export::refreshArea () +void Export::refreshArea() { - if ( SP_ACTIVE_DESKTOP ) - { + if (SP_ACTIVE_DESKTOP) { SPDocument *doc; Geom::OptRect bbox; - bbox = Geom::Rect(Geom::Point(0.0, 0.0),Geom::Point(0.0, 0.0)); + bbox = Geom::Rect(Geom::Point(0.0, 0.0), Geom::Point(0.0, 0.0)); doc = SP_ACTIVE_DESKTOP->getDocument(); /* Notice how the switch is used to 'fall through' here to get various backups. If you modify this without noticing you'll probably screw something up. */ switch (current_key) { - case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) - { - bbox = SP_ACTIVE_DESKTOP->getSelection()->visualBounds(); - /* Only if there is a selection that we can set - do we break, otherwise we fall through to the - drawing */ - // std::cout << "Using selection: SELECTION" << std::endl; - current_key = SELECTION_SELECTION; - break; - } - case SELECTION_DRAWING: - if (manual_key == SELECTION_DRAWING || manual_key == SELECTION_SELECTION) { - /** \todo - * This returns wrong values if the document has a viewBox. - */ - bbox = doc->getRoot()->desktopVisualBounds(); - /* If the drawing is valid, then we'll use it and break - otherwise we drop through to the page settings */ - if (bbox) { - // std::cout << "Using selection: DRAWING" << std::endl; - current_key= SELECTION_DRAWING; + case SELECTION_SELECTION: + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { + bbox = SP_ACTIVE_DESKTOP->getSelection()->visualBounds(); + /* Only if there is a selection that we can set + do we break, otherwise we fall through to the + drawing */ + // std::cout << "Using selection: SELECTION" << std::endl; + current_key = SELECTION_SELECTION; break; } - } - case SELECTION_PAGE: - if (manual_key == SELECTION_PAGE){ - bbox = Geom::Rect(Geom::Point(0.0, 0.0), - Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); + case SELECTION_DRAWING: + if (manual_key == SELECTION_DRAWING || manual_key == SELECTION_SELECTION) { + /** \todo + * This returns wrong values if the document has a viewBox. + */ + bbox = doc->getRoot()->desktopVisualBounds(); + /* If the drawing is valid, then we'll use it and break + otherwise we drop through to the page settings */ + if (bbox) { + // std::cout << "Using selection: DRAWING" << std::endl; + current_key = SELECTION_DRAWING; + break; + } + } + case SELECTION_PAGE: + if (manual_key == SELECTION_PAGE) { + bbox = Geom::Rect(Geom::Point(0.0, 0.0), + Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); - // std::cout << "Using selection: PAGE" << std::endl; - current_key= SELECTION_PAGE; + // std::cout << "Using selection: PAGE" << std::endl; + current_key = SELECTION_PAGE; + break; + } + case SELECTION_CUSTOM: + current_key = SELECTION_CUSTOM; + default: break; - } - case SELECTION_CUSTOM: - current_key = SELECTION_CUSTOM; - default: - break; } // switch // remember area setting prefs->setString("/dialogs/export/exportarea/value", selection_names[current_key]); - if ( current_key != SELECTION_CUSTOM && bbox ) { - setArea ( bbox->min()[Geom::X], - bbox->min()[Geom::Y], - bbox->max()[Geom::X], - bbox->max()[Geom::Y]); + if (current_key != SELECTION_CUSTOM && bbox) { + setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); } } // end of if ( SP_ACTIVE_DESKTOP ) if (SP_ACTIVE_DESKTOP && !filename_modified) { - Glib::ustring filename; float xdpi = 0.0, ydpi = 0.0; switch (current_key) { - case SELECTION_PAGE: - case SELECTION_DRAWING: { - SPDocument * doc = SP_ACTIVE_DOCUMENT; - sp_document_get_export_hints (doc, filename, &xdpi, &ydpi); - - if (filename.empty()) { - if (!doc_export_name.empty()) { - filename = doc_export_name; - } - } - break; - } - case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { + case SELECTION_PAGE: + case SELECTION_DRAWING: { + SPDocument *doc = SP_ACTIVE_DOCUMENT; + sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); - SP_ACTIVE_DESKTOP->getSelection()->getExportHints(filename, &xdpi, &ydpi); - - /* If we still don't have a filename -- let's build - one that's nice */ if (filename.empty()) { - const gchar * id = "object"; - auto reprlst = SP_ACTIVE_DESKTOP->getSelection()->xmlNodes(); - for(auto i=reprlst.begin(); reprlst.end() != i; ++i) { - Inkscape::XML::Node * repr = *i; - if (repr->attribute("id")) { - id = repr->attribute("id"); - break; - } + if (!doc_export_name.empty()) { + filename = doc_export_name; } - - filename = create_filepath_from_id (id, filename_entry.get_text()); } + break; } - break; - case SELECTION_CUSTOM: - default: - break; + case SELECTION_SELECTION: + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { + SP_ACTIVE_DESKTOP->getSelection()->getExportHints(filename, &xdpi, &ydpi); + + /* If we still don't have a filename -- let's build + one that's nice */ + if (filename.empty()) { + const gchar *id = "object"; + auto reprlst = SP_ACTIVE_DESKTOP->getSelection()->xmlNodes(); + for (auto i = reprlst.begin(); reprlst.end() != i; ++i) { + Inkscape::XML::Node *repr = *i; + if (repr->attribute("id")) { + id = repr->attribute("id"); + break; + } + } + + filename = create_filepath_from_id(id, filename_entry.get_text()); + } + } + break; + case SELECTION_CUSTOM: + default: + break; } if (!filename.empty()) { @@ -863,24 +839,22 @@ void Export::refreshArea () } // end of sp_export_area_toggled() /// Called when dialog is deleted -bool Export::onProgressDelete (GdkEventAny * /*event*/) +bool Export::onProgressDelete(GdkEventAny * /*event*/) { interrupted = true; return TRUE; } // end of sp_export_progress_delete() - /// Called when progress is cancelled -void Export::onProgressCancel () +void Export::onProgressCancel() { interrupted = true; } // end of sp_export_progress_cancel() - /// Called for every progress iteration unsigned int Export::onProgressCallback(float value, void *dlg) { - auto dlg2 = reinterpret_cast(dlg); + auto dlg2 = reinterpret_cast(dlg); auto self = dlg2->get_export_panel(); if (self->interrupted) @@ -929,31 +903,30 @@ void Export::setExporting(bool exporting, Glib::ustring const &text) } } -ExportProgressDialog * -Export::create_progress_dialog(Glib::ustring progress_text) +ExportProgressDialog *Export::create_progress_dialog(Glib::ustring progress_text) { auto dlg = new ExportProgressDialog(_("Export in progress"), true); - dlg->set_transient_for( *(INKSCAPE.active_desktop()->getToplevel()) ); + dlg->set_transient_for(*(INKSCAPE.active_desktop()->getToplevel())); - Gtk::ProgressBar *prg = new Gtk::ProgressBar (); + Gtk::ProgressBar *prg = new Gtk::ProgressBar(); prg->set_text(progress_text); dlg->set_progress(prg); auto CA = dlg->get_content_area(); CA->pack_start(*prg, FALSE, FALSE, 4); - Gtk::Button* btn = dlg->add_button (_("_Cancel"),Gtk::RESPONSE_CANCEL ); + Gtk::Button *btn = dlg->add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL); - btn->signal_clicked().connect( sigc::mem_fun(*this, &Export::onProgressCancel) ); - dlg->signal_delete_event().connect( sigc::mem_fun(*this, &Export::onProgressDelete) ); + btn->signal_clicked().connect(sigc::mem_fun(*this, &Export::onProgressCancel)); + dlg->signal_delete_event().connect(sigc::mem_fun(*this, &Export::onProgressDelete)); - dlg->show_all (); + dlg->show_all(); return dlg; } static std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename) { std::string path; - //Make relative paths go from the document location, if possible: + // Make relative paths go from the document location, if possible: if (!Glib::path_is_absolute(filename) && doc->getDocumentFilename()) { auto dirname = Glib::path_get_dirname(doc->getDocumentFilename()); if (!dirname.empty()) { @@ -972,13 +945,13 @@ void Export::onUnitChanged() refreshArea(); } -void Export::onHideExceptSelected () +void Export::onHideExceptSelected() { prefs->setBool("/dialogs/export/hideexceptselected/value", hide_export.get_active()); } /// Called when export button is clicked -void Export::onExport () +void Export::onExport() { _export_raster(nullptr); } @@ -986,30 +959,32 @@ void Export::onExport () void Export::_export_raster(Inkscape::Extension::Output *extension) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) return; + if (!desktop) + return; SPNamedView *nv = desktop->getNamedView(); SPDocument *doc = desktop->getDocument(); bool exportSuccessful = false; - bool hide = hide_export.get_active (); + bool hide = hide_export.get_active(); // Advanced parameters bool do_interlace = (interlacing.get_active()); float pHYs = 0; - int zlib = zlib_compression.get_active_row_number() ; - int colortypes[] = {0,0,0,0,0,2,2,4,4,6,6}; //keep in sync with modes_list in Export constructor. values are from libpng doc. - int bitdepths[] = {1,2,4,8,16,8,16,8,16,8,16}; - int color_type = colortypes[bitdepth_cb.get_active_row_number()] ; - int bit_depth = bitdepths[bitdepth_cb.get_active_row_number()] ; + int zlib = zlib_compression.get_active_row_number(); + int colortypes[] = {0, 0, 0, 0, 0, 2, + 2, 4, 4, 6, 6}; // keep in sync with modes_list in Export constructor. values are from libpng + // doc. + int bitdepths[] = {1, 2, 4, 8, 16, 8, 16, 8, 16, 8, 16}; + int color_type = colortypes[bitdepth_cb.get_active_row_number()]; + int bit_depth = bitdepths[bitdepth_cb.get_active_row_number()]; int antialiasing = antialiasing_cb.get_active_row_number(); - - if (batch_export.get_active ()) { + if (batch_export.get_active()) { // Batch export of selected objects - gint num = (gint) boost::distance(desktop->getSelection()->items()); + gint num = (gint)boost::distance(desktop->getSelection()->items()); gint n = 0; if (num < 1) { @@ -1023,8 +998,8 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) gint export_count = 0; - auto itemlist= desktop->getSelection()->items(); - for(auto i = itemlist.begin();i!=itemlist.end() && !interrupted ;++i){ + auto itemlist = desktop->getSelection()->items(); + for (auto i = itemlist.begin(); i != itemlist.end() && !interrupted; ++i) { SPItem *item = *i; prog_dlg->set_current(n); @@ -1046,7 +1021,8 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) } // retrieve export dpi hints - const gchar *dpi_hint = item->getRepr()->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now + const gchar *dpi_hint = + item->getRepr()->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now gdouble dpi = 0.0; if (dpi_hint) { dpi = g_ascii_strtod(dpi_hint, nullptr); @@ -1058,27 +1034,29 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) Geom::OptRect area = item->documentVisualBounds(); if (area) { - gint width = (gint) (area->width() * dpi / DPI_BASE + 0.5); - gint height = (gint) (area->height() * dpi / DPI_BASE + 0.5); + gint width = (gint)(area->width() * dpi / DPI_BASE + 0.5); + gint height = (gint)(area->height() * dpi / DPI_BASE + 0.5); if (width > 1 && height > 1) { // Do export - gchar * safeFile = Inkscape::IO::sanitizeString(path.c_str()); + gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); MessageCleaner msgCleanup(desktop->messageStack()->pushF(Inkscape::IMMEDIATE_MESSAGE, - _("Exporting file %s..."), safeFile), desktop); + _("Exporting file %s..."), + safeFile), + desktop); MessageCleaner msgFlashCleanup(desktop->messageStack()->flashF(Inkscape::IMMEDIATE_MESSAGE, - _("Exporting file %s..."), safeFile), desktop); - std::vector x; - std::vector selected(desktop->getSelection()->items().begin(), desktop->getSelection()->items().end()); - if (!sp_export_png_file (doc, path.c_str(), - *area, width, height, pHYs, pHYs, - nv->pagecolor, - onProgressCallback, (void*)prog_dlg, - TRUE, // overwrite without asking - hide ? selected : x, - do_interlace, color_type, bit_depth, zlib, antialiasing - )) { - gchar * error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); + _("Exporting file %s..."), + safeFile), + desktop); + std::vector x; + std::vector selected(desktop->getSelection()->items().begin(), + desktop->getSelection()->items().end()); + if (!sp_export_png_file(doc, path.c_str(), *area, width, height, pHYs, pHYs, nv->pagecolor, + onProgressCallback, (void *)prog_dlg, + TRUE, // overwrite without asking + hide ? selected : x, do_interlace, color_type, bit_depth, zlib, + antialiasing)) { + gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); desktop->messageStack()->flashF(Inkscape::ERROR_MESSAGE, _("Could not export to filename %s."), safeFile); @@ -1096,7 +1074,8 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) } desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, - _("Successfully exported %d files from %d selected items."), export_count, num); + _("Successfully exported %d files from %d selected items."), + export_count, num); setExporting(false); delete prog_dlg; @@ -1131,12 +1110,10 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(filename)); Glib::ustring dirname = Glib::path_get_dirname(path); - if ( dirname.empty() - || !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) ) - { + if (dirname.empty() || + !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { gchar *safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); - gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), - safeDir); + gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), safeDir); desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); sp_ui_error_dialog(error); @@ -1156,7 +1133,7 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) for (auto output_ext : extension_list) { if (output_ext->deactivated() || !output_ext->is_raster()) continue; - if(Glib::str_has_suffix(path.c_str(), output_ext->get_extension())) { + if (Glib::str_has_suffix(path.c_str(), output_ext->get_extension())) { // Select the extension extension = output_ext; break; @@ -1178,7 +1155,7 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) } /* TRANSLATORS: %1 will be the filename, %2 the width, and %3 the height of the image */ - prog_dlg = create_progress_dialog (Glib::ustring::compose(_("Exporting %1 (%2 x %3)"), fn, width, height)); + prog_dlg = create_progress_dialog(Glib::ustring::compose(_("Exporting %1 (%2 x %3)"), fn, width, height)); prog_dlg->set_export_panel(this); setExporting(true, Glib::ustring::compose(_("Exporting %1 (%2 x %3)"), fn, width, height)); @@ -1186,19 +1163,16 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) prog_dlg->set_total(0); /* Do export */ - std::vector x; - std::vector selected(desktop->getSelection()->items().begin(), desktop->getSelection()->items().end()); - ExportResult status = sp_export_png_file(desktop->getDocument(), png_filename.c_str(), - area, width, height, pHYs, pHYs, //previously xdpi, ydpi. - nv->pagecolor, - onProgressCallback, (void*)prog_dlg, - overwrite, - hide ? selected : x, - do_interlace, color_type, bit_depth, zlib, antialiasing - ); + std::vector x; + std::vector selected(desktop->getSelection()->items().begin(), + desktop->getSelection()->items().end()); + ExportResult status = sp_export_png_file( + desktop->getDocument(), png_filename.c_str(), area, width, height, pHYs, pHYs, // previously xdpi, ydpi. + nv->pagecolor, onProgressCallback, (void *)prog_dlg, overwrite, hide ? selected : x, do_interlace, + color_type, bit_depth, zlib, antialiasing); if (status == EXPORT_ERROR) { - gchar * safeFile = Inkscape::IO::sanitizeString(path.c_str()); - gchar * error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); + gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); + gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); sp_ui_error_dialog(error); @@ -1206,13 +1180,12 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) g_free(safeFile); g_free(error); } else if (status == EXPORT_OK) { - exportSuccessful = true; - if(extension != nullptr) { + if (extension != nullptr) { // Remove progress dialog before showing prefs dialog. delete prog_dlg; prog_dlg = nullptr; - if(extension->prefs()) { + if (extension->prefs()) { try { extension->export_raster(doc, png_filename, path.c_str(), false); } catch (Inkscape::Extension::Output::save_failed &e) { @@ -1225,13 +1198,14 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) if (exportSuccessful) { auto recentmanager = Gtk::RecentManager::get_default(); - if(recentmanager && Glib::path_is_absolute(path)) { + if (recentmanager && Glib::path_is_absolute(path)) { Glib::ustring uri = Glib::filename_to_uri(path); recentmanager->add_item(uri); } gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); - desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, _("Drawing exported to %s."), safeFile); + desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, _("Drawing exported to %s."), + safeFile); g_free(safeFile); } } else { @@ -1248,7 +1222,7 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) filename_modified = false; setExporting(false); - if(prog_dlg) { + if (prog_dlg) { delete prog_dlg; prog_dlg = nullptr; } @@ -1256,61 +1230,20 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) /* Setup the values in the document */ switch (current_key) { - case SELECTION_PAGE: - case SELECTION_DRAWING: { - SPDocument * doc = SP_ACTIVE_DOCUMENT; - Inkscape::XML::Node * repr = doc->getReprRoot(); - bool modified = false; - - bool saved = DocumentUndo::getUndoSensitive(doc); - DocumentUndo::setUndoSensitive(doc, false); - - gchar const *temp_string = repr->attribute("inkscape:export-filename"); - if (temp_string == nullptr || (filename != temp_string)) { - repr->setAttribute("inkscape:export-filename", filename); - modified = true; - } - temp_string = repr->attribute("inkscape:export-xdpi"); - if (temp_string == nullptr || xdpi != g_ascii_strtod(temp_string, nullptr)) { - repr->setAttributeSvgDouble("inkscape:export-xdpi", xdpi); - modified = true; - } - temp_string = repr->attribute("inkscape:export-ydpi"); - if (temp_string == nullptr || ydpi != g_ascii_strtod(temp_string, nullptr)) { - repr->setAttributeSvgDouble("inkscape:export-ydpi", ydpi); - modified = true; - } - DocumentUndo::setUndoSensitive(doc, saved); + case SELECTION_PAGE: + case SELECTION_DRAWING: { + SPDocument *doc = SP_ACTIVE_DOCUMENT; + Inkscape::XML::Node *repr = doc->getReprRoot(); + bool modified = false; - if (modified) { - doc->setModifiedSinceSave(); - } - break; - } - case SELECTION_SELECTION: { - SPDocument * doc = SP_ACTIVE_DOCUMENT; - bool modified = false; - - bool saved = DocumentUndo::getUndoSensitive(doc); - DocumentUndo::setUndoSensitive(doc, false); - auto reprlst = desktop->getSelection()->xmlNodes(); - - for(auto i=reprlst.begin(); reprlst.end() != i; ++i) { - Inkscape::XML::Node * repr = *i; - const gchar * temp_string; - Glib::ustring dir = Glib::path_get_dirname(filename.c_str()); - const gchar* docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); - Glib::ustring docdir; - if (docFilename) - { - docdir = Glib::path_get_dirname(docFilename); - } - temp_string = repr->attribute("inkscape:export-filename"); + bool saved = DocumentUndo::getUndoSensitive(doc); + DocumentUndo::setUndoSensitive(doc, false); + + gchar const *temp_string = repr->attribute("inkscape:export-filename"); if (temp_string == nullptr || (filename != temp_string)) { repr->setAttribute("inkscape:export-filename", filename); modified = true; } - temp_string = repr->attribute("inkscape:export-xdpi"); if (temp_string == nullptr || xdpi != g_ascii_strtod(temp_string, nullptr)) { repr->setAttributeSvgDouble("inkscape:export-xdpi", xdpi); @@ -1321,16 +1254,56 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) repr->setAttributeSvgDouble("inkscape:export-ydpi", ydpi); modified = true; } + DocumentUndo::setUndoSensitive(doc, saved); + + if (modified) { + doc->setModifiedSinceSave(); + } + break; } - DocumentUndo::setUndoSensitive(doc, saved); + case SELECTION_SELECTION: { + SPDocument *doc = SP_ACTIVE_DOCUMENT; + bool modified = false; + + bool saved = DocumentUndo::getUndoSensitive(doc); + DocumentUndo::setUndoSensitive(doc, false); + auto reprlst = desktop->getSelection()->xmlNodes(); + + for (auto i = reprlst.begin(); reprlst.end() != i; ++i) { + Inkscape::XML::Node *repr = *i; + const gchar *temp_string; + Glib::ustring dir = Glib::path_get_dirname(filename.c_str()); + const gchar *docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); + Glib::ustring docdir; + if (docFilename) { + docdir = Glib::path_get_dirname(docFilename); + } + temp_string = repr->attribute("inkscape:export-filename"); + if (temp_string == nullptr || (filename != temp_string)) { + repr->setAttribute("inkscape:export-filename", filename); + modified = true; + } + + temp_string = repr->attribute("inkscape:export-xdpi"); + if (temp_string == nullptr || xdpi != g_ascii_strtod(temp_string, nullptr)) { + repr->setAttributeSvgDouble("inkscape:export-xdpi", xdpi); + modified = true; + } + temp_string = repr->attribute("inkscape:export-ydpi"); + if (temp_string == nullptr || ydpi != g_ascii_strtod(temp_string, nullptr)) { + repr->setAttributeSvgDouble("inkscape:export-ydpi", ydpi); + modified = true; + } + } + DocumentUndo::setUndoSensitive(doc, saved); - if (modified) { - doc->setModifiedSinceSave(); + if (modified) { + doc->setModifiedSinceSave(); + } + break; } - break; - } - default: - break; + default: + break; } } @@ -1346,7 +1319,7 @@ void Export::_export_raster(Inkscape::Extension::Output *extension) } // end of Export::onExport() /// Called when Browse button is clicked -void Export::onBrowse () +void Export::onBrowse() { // Create and show the dialog Gtk::Window *window = _app->get_active_window(); @@ -1366,26 +1339,23 @@ void Export::onBrowse () filename_entry.set_text(Glib::filename_to_utf8(file)); filename_entry.set_position(-1); auto selection_type = dialog->getSelectionType(); - //deleting dialog before exporting is important - //proper delete function should be made for dialog IMO + // deleting dialog before exporting is important + // proper delete function should be made for dialog IMO delete dialog; _export_raster(dynamic_cast(selection_type)); - }else { + } else { delete dialog; } - } // TODO: Move this to nr-rect-fns.h. bool Export::bbox_equal(Geom::Rect const &one, Geom::Rect const &two) { double const epsilon = pow(10.0, -EXPORT_COORD_PRECISION); - return ( - (fabs(one.min()[Geom::X] - two.min()[Geom::X]) < epsilon) && - (fabs(one.min()[Geom::Y] - two.min()[Geom::Y]) < epsilon) && - (fabs(one.max()[Geom::X] - two.max()[Geom::X]) < epsilon) && - (fabs(one.max()[Geom::Y] - two.max()[Geom::Y]) < epsilon) - ); + return ((fabs(one.min()[Geom::X] - two.min()[Geom::X]) < epsilon) && + (fabs(one.min()[Geom::Y] - two.min()[Geom::Y]) < epsilon) && + (fabs(one.max()[Geom::X] - two.max()[Geom::X]) < epsilon) && + (fabs(one.max()[Geom::Y] - two.max()[Geom::Y]) < epsilon)); } /** @@ -1410,15 +1380,15 @@ bool Export::bbox_equal(Geom::Rect const &one, Geom::Rect const &two) * * @todo finish writing this up. */ -void Export::detectSize() { - static const selection_type test_order[SELECTION_NUMBER_OF] = {SELECTION_SELECTION, SELECTION_DRAWING, SELECTION_PAGE, SELECTION_CUSTOM}; +void Export::detectSize() +{ + static const selection_type test_order[SELECTION_NUMBER_OF] = {SELECTION_SELECTION, SELECTION_DRAWING, + SELECTION_PAGE, SELECTION_CUSTOM}; selection_type this_test[SELECTION_NUMBER_OF + 1]; selection_type key = SELECTION_NUMBER_OF; - Geom::Point x(getValuePx(x0_adj), - getValuePx(y0_adj)); - Geom::Point y(getValuePx(x1_adj), - getValuePx(y1_adj)); + Geom::Point x(getValuePx(x0_adj), getValuePx(y0_adj)); + Geom::Point y(getValuePx(x1_adj), getValuePx(y1_adj)); Geom::Rect current_bbox(x, y); this_test[0] = current_key; @@ -1426,50 +1396,45 @@ void Export::detectSize() { this_test[i + 1] = test_order[i]; } - for (int i = 0; - i < SELECTION_NUMBER_OF + 1 && - key == SELECTION_NUMBER_OF && - SP_ACTIVE_DESKTOP != nullptr; - i++) { + for (int i = 0; i < SELECTION_NUMBER_OF + 1 && key == SELECTION_NUMBER_OF && SP_ACTIVE_DESKTOP != nullptr; i++) { switch (this_test[i]) { - case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { - Geom::OptRect bbox = (SP_ACTIVE_DESKTOP->getSelection())->bounds(SPItem::VISUAL_BBOX); + case SELECTION_SELECTION: + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { + Geom::OptRect bbox = (SP_ACTIVE_DESKTOP->getSelection())->bounds(SPItem::VISUAL_BBOX); - if ( bbox && bbox_equal(*bbox,current_bbox)) { - key = SELECTION_SELECTION; + if (bbox && bbox_equal(*bbox, current_bbox)) { + key = SELECTION_SELECTION; + } } - } - break; - case SELECTION_DRAWING: { - SPDocument *doc = SP_ACTIVE_DESKTOP->getDocument(); + break; + case SELECTION_DRAWING: { + SPDocument *doc = SP_ACTIVE_DESKTOP->getDocument(); - Geom::OptRect bbox = doc->getRoot()->desktopVisualBounds(); + Geom::OptRect bbox = doc->getRoot()->desktopVisualBounds(); - if ( bbox && bbox_equal(*bbox,current_bbox) ) { - key = SELECTION_DRAWING; + if (bbox && bbox_equal(*bbox, current_bbox)) { + key = SELECTION_DRAWING; + } + break; } - break; - } - case SELECTION_PAGE: { - SPDocument *doc; + case SELECTION_PAGE: { + SPDocument *doc; - doc = SP_ACTIVE_DESKTOP->getDocument(); + doc = SP_ACTIVE_DESKTOP->getDocument(); - Geom::Point x(0.0, 0.0); - Geom::Point y(doc->getWidth().value("px"), - doc->getHeight().value("px")); - Geom::Rect bbox(x, y); + Geom::Point x(0.0, 0.0); + Geom::Point y(doc->getWidth().value("px"), doc->getHeight().value("px")); + Geom::Rect bbox(x, y); - if (bbox_equal(bbox,current_bbox)) { - key = SELECTION_PAGE; - } + if (bbox_equal(bbox, current_bbox)) { + key = SELECTION_PAGE; + } - break; - } - default: - break; + break; + } + default: + break; } } // std::cout << std::endl; @@ -1485,7 +1450,7 @@ void Export::detectSize() { } /* sp_export_detect_size */ /// Called when area x0 value is changed -void Export::areaXChange(Glib::RefPtr& adj) +void Export::areaXChange(Glib::RefPtr &adj) { float x0, x1, xdpi, width; @@ -1499,7 +1464,7 @@ void Export::areaXChange(Glib::RefPtr& adj) x1 = getValuePx(x1_adj); xdpi = getValue(xdpi_adj); - width = floor ((x1 - x0) * xdpi / DPI_BASE + 0.5); + width = floor((x1 - x0) * xdpi / DPI_BASE + 0.5); if (width < SP_EXPORT_MIN_SIZE) { width = SP_EXPORT_MIN_SIZE; @@ -1524,7 +1489,7 @@ void Export::areaXChange(Glib::RefPtr& adj) } // end of sp_export_area_x_value_changed() /// Called when area y0 value is changed. -void Export::areaYChange(Glib::RefPtr& adj) +void Export::areaYChange(Glib::RefPtr &adj) { float y0, y1, ydpi, height; @@ -1538,12 +1503,12 @@ void Export::areaYChange(Glib::RefPtr& adj) y1 = getValuePx(y1_adj); ydpi = getValue(ydpi_adj); - height = floor ((y1 - y0) * ydpi / DPI_BASE + 0.5); + height = floor((y1 - y0) * ydpi / DPI_BASE + 0.5); if (height < SP_EXPORT_MIN_SIZE) { height = SP_EXPORT_MIN_SIZE; if (adj == y1_adj) { - //if (!strcmp (key, "y0")) { + // if (!strcmp (key, "y0")) { y1 = y0 + height * DPI_BASE / ydpi; setValuePx(y1_adj, y1); } else { @@ -1577,7 +1542,6 @@ void Export::onAreaWidthChange() float bmwidth = floor(width * xdpi / DPI_BASE + 0.5); if (bmwidth < SP_EXPORT_MIN_SIZE) { - bmwidth = SP_EXPORT_MIN_SIZE; width = bmwidth * DPI_BASE / xdpi; setValuePx(width_adj, width); @@ -1601,10 +1565,10 @@ void Export::onAreaHeightChange() update_flag = true; float y0 = getValuePx(y0_adj); - //float y1 = sp_export_value_get_px(y1_adj); + // float y1 = sp_export_value_get_px(y1_adj); float ydpi = getValue(ydpi_adj); float height = getValuePx(height_adj); - float bmheight = floor (height * ydpi / DPI_BASE + 0.5); + float bmheight = floor(height * ydpi / DPI_BASE + 0.5); if (bmheight < SP_EXPORT_MIN_SIZE) { bmheight = SP_EXPORT_MIN_SIZE; @@ -1665,7 +1629,7 @@ void Export::setImageX() } // end of setImageX() /// Called when pixel width is changed -void Export::onBitmapWidthChange () +void Export::onBitmapWidthChange() { float x0, x1, bmwidth, xdpi; @@ -1687,7 +1651,7 @@ void Export::onBitmapWidthChange () xdpi = bmwidth * DPI_BASE / (x1 - x0); setValue(xdpi_adj, xdpi); - setImageY (); + setImageY(); update_flag = false; @@ -1695,7 +1659,7 @@ void Export::onBitmapWidthChange () } // end of sp_export_bitmap_width_value_changed() /// Called when pixel height is changed -void Export::onBitmapHeightChange () +void Export::onBitmapHeightChange() { float y0, y1, bmheight, xdpi; @@ -1717,7 +1681,7 @@ void Export::onBitmapHeightChange () xdpi = bmheight * DPI_BASE / (y1 - y0); setValue(xdpi_adj, xdpi); - setImageX (); + setImageX(); update_flag = false; @@ -1781,14 +1745,13 @@ void Export::onExportXdpiChange() setValue(bmwidth_adj, bmwidth); - setImageY (); + setImageY(); update_flag = false; return; } // end of sp_export_xdpi_value_changed() - /** * A function to change the area that is used for the exported. * bitmap. @@ -1808,7 +1771,7 @@ void Export::onExportXdpiChange() * @param x1 Horizontal lower right hand corner of the picture in points. * @param y1 Vertical lower right hand corner of the picture in points. */ -void Export::setArea( double x0, double y0, double x1, double y1 ) +void Export::setArea(double x0, double y0, double x1, double y1) { update_flag = true; setValuePx(x1_adj, x1); @@ -1817,8 +1780,8 @@ void Export::setArea( double x0, double y0, double x1, double y1 ) setValuePx(y0_adj, y0); update_flag = false; - areaXChange (x1_adj); - areaYChange (y1_adj); + areaXChange(x1_adj); + areaYChange(y1_adj); return; } @@ -1829,7 +1792,7 @@ void Export::setArea( double x0, double y0, double x1, double y1 ) * @param adj The adjustment widget * @param val What value to set it to. */ -void Export::setValue(Glib::RefPtr& adj, double val ) +void Export::setValue(Glib::RefPtr &adj, double val) { if (adj) { adj->set_value(val); @@ -1847,7 +1810,7 @@ void Export::setValue(Glib::RefPtr& adj, double val ) * @param adj The adjustment widget * @param val What the value should be in points. */ -void Export::setValuePx(Glib::RefPtr& adj, double val) +void Export::setValuePx(Glib::RefPtr &adj, double val) { Unit const *unit = unit_selector.getUnit(); @@ -1866,7 +1829,7 @@ void Export::setValuePx(Glib::RefPtr& adj, double val) * * @return The value in the specified adjustment. */ -float Export::getValue(Glib::RefPtr& adj) +float Export::getValue(Glib::RefPtr &adj) { if (!adj) { g_message("sp_export_value_get : adj is NULL"); @@ -1888,9 +1851,9 @@ float Export::getValue(Glib::RefPtr& adj) * * @return The value in the adjustment in points. */ -float Export::getValuePx(Glib::RefPtr& adj) +float Export::getValuePx(Glib::RefPtr &adj) { - float value = getValue( adj); + float value = getValue(adj); Unit const *unit = unit_selector.getUnit(); return Inkscape::Util::Quantity::convert(value, unit, "px"); @@ -1917,9 +1880,9 @@ void Export::onFilenameModified() return; } // end sp_export_filename_modified -} -} -} +} // namespace Dialog +} // namespace UI +} // namespace Inkscape /* Local Variables: diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 9586e4175c..01df3289fd 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -17,26 +17,27 @@ // This has to be included prior to anything that includes setjmp.h, it croaks otherwise #include "export.h" +#include +#include +#include #include #include +#include "desktop.h" #include "document-undo.h" #include "document.h" +#include "extension/db.h" #include "file.h" +#include "helper/png-write.h" #include "inkscape-window.h" #include "inkscape.h" -#include "preferences.h" -#include "selection-chemistry.h" - -// required to set status message after export -#include "desktop.h" -#include "extension/db.h" -#include "helper/png-write.h" #include "io/resource.h" #include "io/sys.h" #include "message-stack.h" #include "object/sp-namedview.h" #include "object/sp-root.h" +#include "preferences.h" +#include "selection-chemistry.h" #include "ui/dialog-events.h" #include "ui/dialog/dialog-notebook.h" #include "ui/dialog/filedialog.h" @@ -57,8 +58,16 @@ namespace Inkscape { namespace UI { namespace Dialog { +static std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_entry_text); +static void append_ext_to_filename(Glib::ustring &filename, Glib::ustring &extension); +static Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension); +static Glib::ustring get_ext_from_filename(Glib::ustring &filename); + Export::Export() : DialogBase("/dialogs/export/", "Export") + , filename_modified(false) + , original_name() + , doc_export_name() , selectChangedConn() , subselChangedConn() , selectModifiedConn() @@ -82,16 +91,18 @@ Export::Export() // setting up units beforehand is important as we will use it to initialise other values setupUnits(); - setupSpinButtons(); setupExtensionList(); // Callback when container is dinally mapped on window. All intialisation like set active is done inside it. container->signal_map().connect(sigc::mem_fun(*this, &Export::onContainerVisible)); units->signal_changed().connect(sigc::mem_fun(*this, &Export::onUnitChanged)); + extension_cb->signal_changed().connect(sigc::mem_fun(*this, &Export::onExtensionChanged)); for (auto [key, button] : selection_buttons) { button->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &Export::onAreaTypeToggle), key)); } + filenameChangedConn = filename_entry->signal_changed().connect(sigc::mem_fun(*this, &Export::onFilenameModified)); + siExportConn = si_export->signal_clicked().connect(sigc::mem_fun(*this, &Export::onExport)); } Export::~Export() @@ -107,7 +118,6 @@ void Export::update() std::cerr << "Export::update(): _app is null" << std::endl; return; } - onSelectionChanged(); onSelectionModified(0); #if 0 @@ -123,10 +133,17 @@ void Export::onSelectionChanged() if (current_key == SELECTION_SELECTION) { selection_buttons[(selection_mode)0]->set_active(true); // This causes refresh area // return otherwise refreshArea will be called again + // even though we are at default key, selection is the one which was original key. + prefs->setString("/dialogs/export/exportarea/value", selection_names[SELECTION_SELECTION]); return; } } else { selection_buttons[SELECTION_SELECTION]->set_sensitive(true); + Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); + if (selection_names[SELECTION_SELECTION] == pref_key_name && current_key != SELECTION_SELECTION) { + selection_buttons[SELECTION_SELECTION]->set_active(); + return; + } } refreshArea(); } @@ -160,6 +177,7 @@ void Export::onSelectionModified(guint /*flags*/) break; } } + refreshExportHints(); return; } @@ -205,7 +223,7 @@ void Export::initialise_all() builder->get_widget("si_show_preview", si_show_preview); builder->get_widget("si_extention", extension_cb); - builder->get_widget("si_filename", filename); + builder->get_widget("si_filename", filename_entry); builder->get_widget("si_export", si_export); } // Single Image End @@ -252,8 +270,6 @@ void Export::setupExtensionList() extension = manual_omod->get_extension(); extension_cb->append(extension); extension_list[extension] = manual_omod; - - extension_cb->set_active(0); } void Export::setupSpinButtons() @@ -274,7 +290,8 @@ void Export::setupSpinButtons() setupSpinButton(bmheight_sb, 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, &Export::onDpiChange, SPIN_BMHEIGHT); setupSpinButton(bmwidth_sb, 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, &Export::onDpiChange, SPIN_BMWIDTH); - setupSpinButton(dpi_sb, 92.0, 0.01, 100000.0, 0.1, 1.0, 2, true, &Export::onDpiChange, SPIN_DPI); + setupSpinButton(dpi_sb, prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), 0.01, 100000.0, + 0.1, 1.0, 2, true, &Export::onDpiChange, SPIN_DPI); } template @@ -434,6 +451,7 @@ void Export::dpiChange(sb_type type) dpi = bmwidth * DPI_BASE / width; break; case SPIN_DPI: + prefs->setDouble("/dialogs/export/defaultdpi/value", dpi); break; default: break; @@ -472,13 +490,19 @@ void Export::setDefaultSelectionMode() { // Single Image Selection Mode current_key = (selection_mode)0; // default key + bool found = false; Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); for (auto [key, name] : selection_names) { if (pref_key_name == name) { current_key = key; + found = true; break; } } + if (!found) { + pref_key_name = selection_names[current_key]; + } + if (current_key == SELECTION_SELECTION && (SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { current_key = (selection_mode)0; } @@ -486,6 +510,7 @@ void Export::setDefaultSelectionMode() selection_buttons[SELECTION_SELECTION]->set_sensitive(false); } selection_buttons[current_key]->set_active(true); + prefs->setString("/dialogs/export/exportarea/value", pref_key_name); } { // Batch Export Selection Mode @@ -493,12 +518,34 @@ void Export::setDefaultSelectionMode() } } +void Export::setDefaultFilename() +{ + Glib::ustring filename; + float xdpi = 0.0, ydpi = 0.0; + SPDocument *doc = SP_ACTIVE_DOCUMENT; + sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); + if (filename.empty()) { + Glib::ustring filename_entry_text = filename_entry->get_text(); + Glib::ustring extention_entry_text = ".png"; + filename = get_default_filename(filename_entry_text, extention_entry_text); + } + doc_export_name = filename; + original_name = filename; + filename_entry->set_text(filename); + filename_entry->set_position(filename.length()); + // We only need to check xdpi + if (xdpi != 0.0) { + dpi_sb->set_value(xdpi); + } +} + void Export::refreshArea() { if (SP_ACTIVE_DESKTOP) { SPDocument *doc; Geom::OptRect bbox; doc = SP_ACTIVE_DESKTOP->getDocument(); + doc->ensureUpToDate(); switch (current_key) { case SELECTION_SELECTION: @@ -524,8 +571,61 @@ void Export::refreshArea() setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); } } +} + +void Export::refreshExportHints() +{ + if (SP_ACTIVE_DESKTOP && !filename_modified) { + SPDocument *doc = SP_ACTIVE_DOCUMENT; + Glib::ustring filename; + float xdpi = 0.0, ydpi = 0.0; + switch (current_key) { + case SELECTION_CUSTOM: + case SELECTION_PAGE: + case SELECTION_DRAWING: + sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); + if (filename.empty()) { + Glib::ustring filename_entry_text = filename_entry->get_text(); + Glib::ustring extension_entry_text = extension_cb->get_active_text(); + filename = get_default_filename(filename_entry_text, extension_entry_text); + } + doc_export_name = filename; + break; + case SELECTION_SELECTION: + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + break; + } + SP_ACTIVE_DESKTOP->getSelection()->getExportHints(filename, &xdpi, &ydpi); + + /* If we still don't have a filename -- let's build + one that's nice */ + if (filename.empty()) { + const gchar *id = "object"; + auto reprlst = SP_ACTIVE_DESKTOP->getSelection()->xmlNodes(); + for (auto i = reprlst.begin(); reprlst.end() != i; ++i) { + Inkscape::XML::Node *repr = *i; + if (repr->attribute("id")) { + id = repr->attribute("id"); + break; + } + } + filename = create_filepath_from_id(id, filename_entry->get_text()); + filename = filename + extension_cb->get_active_text(); + } + break; + default: + break; + } + if (!filename.empty()) { + original_name = filename; + filename_entry->set_text(filename); + filename_entry->set_position(filename.length()); + } - // TODO: FilenameModified + if (xdpi != 0.0) { + dpi_sb->set_value(xdpi); + } + } } void Export::setArea(double x0, double y0, double x1, double y1) @@ -548,6 +648,17 @@ void Export::setArea(double x0, double y0, double x1, double y1) blockSpinConns(false); } +Glib::ustring Export::getValidExtension(Glib::ustring &extension, Glib::ustring &original_extension) +{ + if (extension_list[extension]) { + return extension; + } + if (!original_extension.empty()) { + return original_extension; + } + return ".png"; +} + /** * SIGNALS */ @@ -556,8 +667,11 @@ void Export::setArea(double x0, double y0, double x1, double y1) void Export::onContainerVisible() { + std::cout << "Container Visible" << std::endl; setDefaultNotebookPage(); setDefaultSelectionMode(); + setDefaultFilename(); + extension_cb->set_active(0); } void Export::onAreaXChange(sb_type type) @@ -587,10 +701,10 @@ void Export::onAreaTypeToggle(selection_mode key) } // If you have reached here means the current key is active one ( not sure if multiple transitions happen but last // call will change values) - current_key = key; prefs->setString("/dialogs/export/exportarea/value", selection_names[current_key]); refreshArea(); + refreshExportHints(); } void Export::onUnitChanged() @@ -598,6 +712,133 @@ void Export::onUnitChanged() refreshArea(); } +void Export::onFilenameModified() +{ + filenameChangedConn.block(); + Glib::ustring filename = filename_entry->get_text(); + Glib::ustring filename_extension = get_ext_from_filename(filename); + Glib::ustring active_extension = extension_cb->get_active_text(); + Glib::ustring filtered_extension = getValidExtension(filename_extension, active_extension); + + if (original_name == filename) { + filename_modified = false; + } else { + filename_modified = true; + } + + extension_cb->set_active_text(filtered_extension); + + filenameChangedConn.unblock(); +} + +void Export::onExtensionChanged() +{ + filenameChangedConn.block(); + Glib::ustring filename = filename_entry->get_text(); + Glib::ustring filename_extension = get_ext_from_filename(filename); + Glib::ustring active_extension = extension_cb->get_active_text(); + if (filename_extension == active_extension) { + return; + } + if (extension_list[filename_extension]) { + auto extension_point = filename.rfind(filename_extension); + filename.erase(extension_point); + } + filename = filename + active_extension; + filename_entry->set_text(filename); + filename_entry->set_position(filename.length()); + + filenameChangedConn.unblock(); +} + +void Export::onExport() +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (!desktop) { + return; + } +} + +/** + * UTILS FUNCTIONS + */ + +std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_entry_text) +{ + if (id.empty()) { /* This should never happen */ + id = "bitmap"; + } + + std::string directory; + + if (!file_entry_text.empty()) { + directory = Glib::path_get_dirname(Glib::filename_from_utf8(file_entry_text)); + } + + if (directory.empty()) { + /* Grab document directory */ + const gchar *docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); + if (docFilename) { + directory = Glib::path_get_dirname(docFilename); + } + } + + if (directory.empty()) { + directory = Inkscape::IO::Resource::homedir_path(nullptr); + } + + return Glib::build_filename(directory, Glib::filename_from_utf8(id)); +} + +Glib::ustring get_ext_from_filename(Glib::ustring &filename) +{ + Glib::ustring extension = ""; + if (!filename.empty()) { + auto extension_point = filename.rfind('.'); + if (extension_point != Glib::ustring::npos) { + extension = filename.substr(extension_point); + } + } + return extension; +} + +void append_ext_to_filename(Glib::ustring &filename, Glib::ustring &extention) +{ + if (Glib::str_has_suffix(filename, extention)) { + return; + } + filename = filename + extention; + return; +} + +Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension) +{ + Glib::ustring filename; + if (SP_ACTIVE_DOCUMENT && SP_ACTIVE_DOCUMENT->getDocumentFilename()) { + SPDocument *doc = SP_ACTIVE_DOCUMENT; + filename = doc->getDocumentFilename(); + auto &&text_extension = get_file_save_extension(Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS); + Inkscape::Extension::Output *oextension = nullptr; + if (!text_extension.empty()) { + oextension = + dynamic_cast(Inkscape::Extension::db.get(text_extension.c_str())); + } + if (oextension != nullptr) { + Glib::ustring old_extension = oextension->get_extension(); + if (Glib::str_has_suffix(filename, old_extension)) { + auto extension_point = filename.rfind(old_extension); + filename.erase(extension_point); + } + } + filename = filename + extension; + + } else if (SP_ACTIVE_DOCUMENT) { + filename = create_filepath_from_id(_("bitmap"), filename_entry_text); + filename = filename + extension; + } + return filename; +} + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 0ede2f9e14..a64b68ad39 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -43,7 +43,7 @@ enum selection_mode SELECTION_PAGE = 0, // Default is alaways placed first SELECTION_SELECTION, SELECTION_DRAWING, - SELECTION_CUSTOM + SELECTION_CUSTOM, }; class ExportProgressDialog; @@ -91,7 +91,7 @@ private: Gtk::Box *si_preview_box = nullptr; Gtk::CheckButton *si_show_preview = nullptr; Gtk::ComboBoxText *extension_cb = nullptr; - Gtk::Entry *filename = nullptr; + Gtk::Entry *filename_entry = nullptr; Gtk::Button *si_export = nullptr; Gtk::Box *batch_export = nullptr; @@ -102,6 +102,13 @@ private: selection_mode current_key; std::map extension_list; + // Once user change filename it is set and prevent automatic changes to filename_entry + bool filename_modified; + // original name for export. Changes everytime selection changes or when exported. + Glib::ustring original_name; + // initialised only at startup and is used as fallback for original name. + Glib::ustring doc_export_name; + // Initialise all objects from builder void initialise_all(); // Add units from db @@ -117,6 +124,7 @@ private: // setup default values of widgets void setDefaultNotebookPage(); void setDefaultSelectionMode(); + void setDefaultFilename(); // Utils Functions void areaXChange(sb_type type); @@ -124,10 +132,12 @@ private: void dpiChange(sb_type type); float getValuePx(float value); void setValuePx(Glib::RefPtr &adj, double val); + Glib::ustring getValidExtension(Glib::ustring &extension, Glib::ustring &original_extension); void blockSpinConns(bool status); void refreshArea(); + void refreshExportHints(); void setArea(double x0, double y0, double x1, double y1); // signals callback @@ -137,6 +147,11 @@ private: void onDpiChange(sb_type type); void onAreaTypeToggle(selection_mode key); void onUnitChanged(); + void onExport(); + void onBatchExport(); + void onFilenameModified(); + void onExtensionChanged(); + /** * Inkscape selection change callback */ @@ -153,6 +168,8 @@ private: sigc::connection subselChangedConn; sigc::connection selectModifiedConn; std::vector spinButtonConns; + sigc::connection filenameChangedConn; + sigc::connection siExportConn; }; } // namespace Dialog } // namespace UI -- GitLab From 7e5864667c338710c8038edee86f66b83f0695e3 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Tue, 22 Jun 2021 17:00:39 +0530 Subject: [PATCH 10/40] adding export raster --- share/ui/dialog-export.glade | 129 +-- src/ui/dialog/export-old.cpp | 1896 ---------------------------------- src/ui/dialog/export-old.h | 371 ------- src/ui/dialog/export.cpp | 156 ++- src/ui/dialog/export.h | 24 +- 5 files changed, 226 insertions(+), 2350 deletions(-) delete mode 100644 src/ui/dialog/export-old.cpp delete mode 100644 src/ui/dialog/export-old.h diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 513262260c..f000b4290e 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -202,38 +202,15 @@ 10 True - + True False + 10 + 5 5 + 5 - - checkbutton - True - True - False - 20 - 10 - True - - - 0 - 0 - - - - - checkbutton - True - True - False - 20 - True - - - 0 - 1 - + @@ -318,18 +295,6 @@ 5 - - - True - True - start - True - - - 2 - 12 - - True @@ -413,68 +378,78 @@ - + True - False - Left - True - 0 + True + True - 1 + 4 2 - + True - False - Top - True - 0 + True + True - 3 - 2 + 2 + 4 + + + + + True + True + start + True + + + 2 + 12 True False - Right + DPI True 0 1 - 4 + 12 True False - Bottom + Height +(px) True 0 3 - 4 + 10 True False - Width + Width +(px) True 0 1 - 6 + 10 @@ -494,63 +469,65 @@ True False - Width -(px) + Width True 0 1 - 10 + 6 True False - Height -(px) + Bottom True 0 3 - 10 + 4 True False - DPI + Right True 0 1 - 12 + 4 - + True - True - True + False + Top + True + 0 - 4 + 3 2 - + True - True - True + False + Left + True + 0 - 2 - 4 + 1 + 2 diff --git a/src/ui/dialog/export-old.cpp b/src/ui/dialog/export-old.cpp deleted file mode 100644 index 3f70d6d620..0000000000 --- a/src/ui/dialog/export-old.cpp +++ /dev/null @@ -1,1896 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* Authors: - * Lauris Kaplinski - * bulia byak - * Johan Engelen - * Peter Bostrom - * Jon A. Cruz - * Abhishek Sharma - * Kris De Gussem - * - * Copyright (C) 1999-2007, 2012 Authors - * Copyright (C) 2001-2002 Ximian, Inc. - * - * Released under GNU GPL v2+, read the file 'COPYING' for more information. - */ - -// This has to be included prior to anything that includes setjmp.h, it croaks otherwise -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "document-undo.h" -#include "document.h" -#include "file.h" -#include "inkscape-window.h" -#include "inkscape.h" -#include "preferences.h" -#include "selection-chemistry.h" - -// required to set status message after export -#include "desktop.h" -#include "extension/db.h" -#include "helper/png-write.h" -#include "io/resource.h" -#include "io/sys.h" -#include "message-stack.h" -#include "object/sp-namedview.h" -#include "object/sp-root.h" -#include "ui/dialog-events.h" -#include "ui/dialog/dialog-notebook.h" -#include "ui/dialog/filedialog.h" -#include "ui/interface.h" -#include "ui/widget/scrollprotected.h" -#include "ui/widget/unit-menu.h" - -#ifdef _WIN32 -#include -#include -#include -#include -#endif - -#define SP_EXPORT_MIN_SIZE 1.0 - -#define DPI_BASE Inkscape::Util::Quantity::convert(1, "in", "px") - -#define EXPORT_COORD_PRECISION 3 - -#include "export.h" - -using Inkscape::Util::unit_table; - -namespace { - -class MessageCleaner -{ -public: - MessageCleaner(Inkscape::MessageId messageId, SPDesktop *desktop) - : _desktop(desktop) - , _messageId(messageId) - {} - - ~MessageCleaner() - { - if (_messageId && _desktop) { - _desktop->messageStack()->cancel(_messageId); - } - } - -private: - MessageCleaner(MessageCleaner const &other) = delete; - MessageCleaner &operator=(MessageCleaner const &other) = delete; - - SPDesktop *_desktop; - Inkscape::MessageId _messageId; -}; - -} // namespace - -namespace Inkscape { -namespace UI { -namespace Dialog { - -class ExportProgressDialog : public Gtk::Dialog -{ -private: - Gtk::ProgressBar *_progress = nullptr; - Export *_export_panel = nullptr; - int _current = 0; - int _total = 0; - -public: - ExportProgressDialog(const Glib::ustring &title, bool modal = false) - : Gtk::Dialog(title, modal) - {} - - inline void set_export_panel(const decltype(_export_panel) export_panel) { _export_panel = export_panel; } - inline decltype(_export_panel) get_export_panel() const { return _export_panel; } - - inline void set_progress(const decltype(_progress) progress) { _progress = progress; } - inline decltype(_progress) get_progress() const { return _progress; } - - inline void set_current(const int current) { _current = current; } - inline int get_current() const { return _current; } - - inline void set_total(const int total) { _total = total; } - inline int get_total() const { return _total; } -}; - -static std::string create_filepath_from_id(Glib::ustring, const Glib::ustring &); - -/** A list of strings that is used both in the preferences, and in the - data fields to describe the various values of \c selection_type. */ -static const char *selection_names[SELECTION_NUMBER_OF] = {"page", "drawing", "selection", "custom"}; - -/** The names on the buttons for the various selection types. */ -static const char *selection_labels[SELECTION_NUMBER_OF] = {N_("_Page"), N_("_Drawing"), N_("_Selection"), - N_("_Custom")}; - -Export::Export() - : DialogBase("/dialogs/export/", "Export") - , current_key(SELECTION_PAGE) - , manual_key(SELECTION_PAGE) - , original_name() - , doc_export_name() - , filename_modified(false) - , update_flag(false) - , togglebox(Gtk::ORIENTATION_HORIZONTAL, 0) - , area_box(Gtk::ORIENTATION_VERTICAL, 3) - , singleexport_box(Gtk::ORIENTATION_VERTICAL, 0) - , size_box(Gtk::ORIENTATION_VERTICAL, 3) - , file_box(Gtk::ORIENTATION_VERTICAL, 3) - , unitbox(Gtk::ORIENTATION_HORIZONTAL, 0) - , unit_selector() - , units_label(_("Units:")) - , filename_box(Gtk::ORIENTATION_HORIZONTAL, 5) - , browse_label(_("_Export As..."), true) - , browse_image() - , batch_box(Gtk::ORIENTATION_HORIZONTAL, 5) - , batch_export(_("B_atch export all selected objects")) - , interlacing(_("Use interlacing")) - , bitdepth_label(_("Bit depth")) - , bitdepth_cb() - , zlib_label(_("Compression")) - , zlib_compression() - , pHYs_label(_("pHYs dpi")) - , pHYs_sb(pHYs_adj, 1.0, 2) - , antialiasing_label(_("Antialiasing")) - , antialiasing_cb() - , hide_box(Gtk::ORIENTATION_HORIZONTAL, 3) - , hide_export(_("Hide all except selected")) - , closeWhenDone(_("Close when complete")) - , button_box(Gtk::ORIENTATION_HORIZONTAL, 3) - , _prog() - , prog_dlg(nullptr) - , interrupted(false) - , prefs(nullptr) - , selectChangedConn() - , subselChangedConn() - , selectModifiedConn() -{ - batch_export.set_use_underline(); - batch_export.set_tooltip_text(_("Export each selected object into its own PNG file, using export hints if any " - "(caution, overwrites without asking!)")); - hide_export.set_use_underline(); - hide_export.set_tooltip_text(_("In the exported image, hide all objects except those that are selected")); - interlacing.set_use_underline(); - interlacing.set_tooltip_text( - _("Enables ADAM7 interlacing for PNG output. This results in slightly larger image files, but big images can " - "already be displayed (slightly blurry) while still loading.")); - closeWhenDone.set_use_underline(); - closeWhenDone.set_tooltip_text(_("Once the export completes, close this dialog")); - prefs = Inkscape::Preferences::get(); - - singleexport_box.set_border_width(0); - - /* Export area frame */ - { - Gtk::Label *lbl = new Gtk::Label(_("Export area"), Gtk::ALIGN_START); - lbl->set_use_markup(true); - area_box.pack_start(*lbl); - - /* Units box */ - /* gets added to the vbox later, but the unit selector is needed - earlier than that */ - unit_selector.setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); - - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (desktop) { - unit_selector.setUnit(desktop->getNamedView()->display_units->abbr); - } - unitChangedConn = unit_selector.signal_changed().connect(sigc::mem_fun(*this, &Export::onUnitChanged)); - unitbox.pack_end(unit_selector, false, false, 0); - unitbox.pack_end(units_label, false, false, 3); - - for (int i = 0; i < SELECTION_NUMBER_OF; i++) { - selectiontype_buttons[i] = new Gtk::RadioButton(_(selection_labels[i]), true); - if (i > 0) { - Gtk::RadioButton::Group group = selectiontype_buttons[0]->get_group(); - selectiontype_buttons[i]->set_group(group); - } - selectiontype_buttons[i]->set_mode(false); - togglebox.pack_start(*selectiontype_buttons[i], false, true, 0); - selectiontype_buttons[i]->signal_clicked().connect(sigc::mem_fun(*this, &Export::onAreaTypeToggled)); - } - - auto t = new Gtk::Grid(); - t->set_row_spacing(4); - t->set_column_spacing(4); - - SPDocument *doc; - doc = SP_ACTIVE_DESKTOP->getDocument(); - - x0_adj = createSpinbutton("x0", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, t, 0, 0, _("_x0:"), "", - EXPORT_COORD_PRECISION, 1, &Export::onAreaX0Change); - - x1_adj = createSpinbutton("x1", doc->getWidth().value("mm"), -1000000.0, 1000000.0, 0.1, 1.0, t, 0, 1, - _("x_1:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaX1Change); - - width_adj = createSpinbutton("width", doc->getWidth().value("mm"), 0.0, PNG_UINT_31_MAX, 0.1, 1.0, t, 0, 2, - _("Wid_th:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaWidthChange); - - y0_adj = createSpinbutton("y0", 0.0, -1000000.0, 1000000.0, 0.1, 1.0, t, 2, 0, _("_y0:"), "", - EXPORT_COORD_PRECISION, 1, &Export::onAreaY0Change); - - y1_adj = createSpinbutton("y1", doc->getHeight().value("mm"), -1000000.0, 1000000.0, 0.1, 1.0, t, 2, 1, - _("y_1:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaY1Change); - - height_adj = createSpinbutton("height", doc->getHeight().value("mm"), 0.0, PNG_UINT_31_MAX, 0.1, 1.0, t, 2, 2, - _("Hei_ght:"), "", EXPORT_COORD_PRECISION, 1, &Export::onAreaHeightChange); - - area_box.pack_start(togglebox, false, false, 3); - area_box.pack_start(*t, false, false, 0); - area_box.pack_start(unitbox, false, false, 0); - - area_box.set_border_width(3); - singleexport_box.pack_start(area_box, false, false, 0); - - } // end of area box - - /* Bitmap size frame */ - { - SPDocument *doc; - doc = SP_ACTIVE_DESKTOP->getDocument(); - - size_box.set_border_width(3); - bm_label = new Gtk::Label(_("Image size"), Gtk::ALIGN_START); - bm_label->set_use_markup(true); - size_box.pack_start(*bm_label, false, false, 0); - - auto t = new Gtk::Grid(); - t->set_row_spacing(4); - t->set_column_spacing(4); - - size_box.pack_start(*t); - - bmwidth_adj = createSpinbutton("bmwidth", doc->getWidth().value("px"), 1.0, 1000000.0, 1.0, 10.0, t, 0, 0, - _("_Width:"), _("pixels at"), 0, 1, &Export::onBitmapWidthChange); - - xdpi_adj = createSpinbutton("xdpi", prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), 0.01, - 100000.0, 0.1, 1.0, t, 3, 0, "", _("dp_i"), 2, 1, &Export::onExportXdpiChange); - - bmheight_adj = createSpinbutton("bmheight", doc->getHeight().value("px"), 1.0, 1000000.0, 1.0, 10.0, t, 0, 1, - _("_Height:"), _("pixels at"), 0, 1, &Export::onBitmapHeightChange); - - /** TODO - * There's no way to set ydpi currently, so we use the defaultxdpi value here, too... - */ - ydpi_adj = createSpinbutton("ydpi", prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), 0.01, - 100000.0, 0.1, 1.0, t, 3, 1, "", _("dpi"), 2, 0, nullptr); - - singleexport_box.pack_start(size_box, Gtk::PACK_SHRINK); - } - - /* File entry */ - { - file_box.set_border_width(3); - flabel = new Gtk::Label(_("_Filename"), Gtk::ALIGN_START, Gtk::ALIGN_CENTER, true); - flabel->set_use_markup(true); - file_box.pack_start(*flabel, false, false, 0); - - set_default_filename(); - - filename_box.pack_start(filename_entry, true, true, 0); - - Gtk::Box *browser_im_label = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 3); - browse_image.set_from_icon_name("folder", Gtk::ICON_SIZE_BUTTON); - browser_im_label->pack_start(browse_image); - browser_im_label->pack_start(browse_label); - browse_button.add(*browser_im_label); - filename_box.pack_end(browse_button, false, false); - filename_box.pack_end(export_button, false, false); - - file_box.add(filename_box); - - original_name = filename_entry.get_text(); - - // focus is in the filename initially: - filename_entry.grab_focus(); - - // mnemonic in frame label moves focus to filename: - flabel->set_mnemonic_widget(filename_entry); - } - - batch_export.set_sensitive(true); - batch_box.pack_start(batch_export, false, false, 3); - - hide_export.set_sensitive(true); - hide_export.set_active(prefs->getBool("/dialogs/export/hideexceptselected/value", false)); - hide_box.pack_start(hide_export, false, false, 3); - - /* Export Button row */ - export_button.set_label(_("_Export")); - export_button.set_use_underline(); - export_button.set_tooltip_text(_("Export the bitmap file with these settings")); - - button_box.set_border_width(3); - button_box.pack_start(closeWhenDone, true, true, 0); - - /*Advanced*/ - Gtk::Label *label_advanced = Gtk::manage(new Gtk::Label(_("Advanced"), true)); - expander.set_label_widget(*label_advanced); - expander.set_vexpand(false); - const char *const modes_list[] = {"Gray_1", "Gray_2", "Gray_4", "Gray_8", "Gray_16", "RGB_8", - "RGB_16", "GrayAlpha_8", "GrayAlpha_16", "RGBA_8", "RGBA_16"}; - for (auto i : modes_list) - bitdepth_cb.append(i); - bitdepth_cb.set_active_text("RGBA_8"); - bitdepth_cb.set_hexpand(); - const char *const zlist[] = { - "Z_NO_COMPRESSION", "Z_BEST_SPEED", "2", "3", "4", "5", "Z_DEFAULT_COMPRESSION", "7", "8", - "Z_BEST_COMPRESSION"}; - for (auto i : zlist) - zlib_compression.append(i); - zlib_compression.set_active_text("Z_DEFAULT_COMPRESSION"); - pHYs_adj = Gtk::Adjustment::create(0, 0, 100000, 0.1, 1.0, 0); - pHYs_sb.set_adjustment(pHYs_adj); - pHYs_sb.set_width_chars(7); - pHYs_sb.set_tooltip_text(_("Will force-set the physical dpi for the png file. Set this to 72 if you're planning to " - "work on your png with Photoshop")); - zlib_compression.set_hexpand(); - const char *const antialising_list[] = {"CAIRO_ANTIALIAS_NONE", "CAIRO_ANTIALIAS_FAST", - "CAIRO_ANTIALIAS_GOOD (default)", "CAIRO_ANTIALIAS_BEST"}; - for (auto i : antialising_list) - antialiasing_cb.append(i); - antialiasing_cb.set_active_text(antialising_list[2]); - bitdepth_label.set_halign(Gtk::ALIGN_START); - zlib_label.set_halign(Gtk::ALIGN_START); - pHYs_label.set_halign(Gtk::ALIGN_START); - antialiasing_label.set_halign(Gtk::ALIGN_START); - auto table = new Gtk::Grid(); - expander.add(*table); - table->set_border_width(4); - table->attach(interlacing, 0, 0, 1, 1); - table->attach(bitdepth_label, 0, 1, 1, 1); - table->attach(bitdepth_cb, 1, 1, 1, 1); - table->attach(zlib_label, 0, 2, 1, 1); - table->attach(zlib_compression, 1, 2, 1, 1); - table->attach(pHYs_label, 0, 3, 1, 1); - table->attach(pHYs_sb, 1, 3, 1, 1); - table->attach(antialiasing_label, 0, 4, 1, 1); - table->attach(antialiasing_cb, 1, 4, 1, 1); - table->show(); - - /* Main dialog */ - set_spacing(0); - pack_start(singleexport_box, Gtk::PACK_SHRINK); - pack_start(file_box, Gtk::PACK_SHRINK); - pack_start(batch_box, Gtk::PACK_SHRINK); - pack_start(hide_box, Gtk::PACK_SHRINK); - pack_start(button_box, Gtk::PACK_SHRINK); - pack_start(expander, Gtk::PACK_SHRINK); - pack_end(_prog, Gtk::PACK_SHRINK); - - /* Signal handlers */ - filename_entry.signal_changed().connect(sigc::mem_fun(*this, &Export::onFilenameModified)); - // pressing enter in the filename field is the same as clicking export: - filename_entry.signal_activate().connect(sigc::mem_fun(*this, &Export::onExport)); - browse_button.signal_clicked().connect(sigc::mem_fun(*this, &Export::onBrowse)); - batch_export.signal_clicked().connect(sigc::mem_fun(*this, &Export::onBatchClicked)); - export_button.signal_clicked().connect(sigc::mem_fun(*this, &Export::onExport)); - hide_export.signal_clicked().connect(sigc::mem_fun(*this, &Export::onHideExceptSelected)); - - show_all_children(); - setExporting(false); - - findDefaultSelection(); - refreshArea(); -} - -Export::~Export() -{ - selectModifiedConn.disconnect(); - subselChangedConn.disconnect(); - selectChangedConn.disconnect(); -} - -void Export::setDesktop(SPDesktop *desktop) -{ -#if 0 - { - { - selectModifiedConn.disconnect(); - subselChangedConn.disconnect(); - selectChangedConn.disconnect(); - } - if (desktop && desktop->selection) { - - selectChangedConn = desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &Export::onSelectionChanged))); - subselChangedConn = desktop->connectToolSubselectionChanged(sigc::hide(sigc::mem_fun(*this, &Export::onSelectionChanged))); - - //// Must check flags, so can't call widget_setup() directly. - selectModifiedConn = desktop->selection->connectModified(sigc::hide<0>(sigc::mem_fun(*this, &Export::onSelectionModified))); - } - } -#endif -} - -void Export::update() -{ - if (!_app) { - std::cerr << "Export::update(): _app is null" << std::endl; - return; - } - - onSelectionChanged(); - onSelectionModified(0); -#if 0 - setDesktop(getDesktop()); -#endif -} - -/* - * set the default filename to be that of the current path + document - * with .png extension - * - * One thing to notice here is that this filename may get - * overwritten, but it won't happen here. The filename gets - * written into the text field, but then the button to select - * the area gets set. In that code the filename can be changed - * if there are some with presidence in the document. So, while - * this code sets the name first, it may not be the one users - * really see. - */ -void Export::set_default_filename() -{ - if (SP_ACTIVE_DOCUMENT && SP_ACTIVE_DOCUMENT->getDocumentFilename()) { - SPDocument *doc = SP_ACTIVE_DOCUMENT; - const gchar *filename = doc->getDocumentFilename(); - auto &&text_extension = get_file_save_extension(Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS); - Inkscape::Extension::Output *oextension = nullptr; - - if (!text_extension.empty()) { - oextension = - dynamic_cast(Inkscape::Extension::db.get(text_extension.c_str())); - } - - if (oextension != nullptr) { - gchar *old_extension = oextension->get_extension(); - if (g_str_has_suffix(filename, old_extension)) { - gchar *filename_copy; - gchar *extension_point; - gchar *final_name; - - filename_copy = g_strdup(filename); - extension_point = g_strrstr(filename_copy, old_extension); - extension_point[0] = '\0'; - - final_name = g_strconcat(filename_copy, ".png", NULL); - filename_entry.set_text(final_name); - filename_entry.set_position(strlen(final_name)); - - g_free(final_name); - g_free(filename_copy); - } - } else { - gchar *name = g_strconcat(filename, ".png", NULL); - filename_entry.set_text(name); - filename_entry.set_position(strlen(name)); - - g_free(name); - } - - doc_export_name = filename_entry.get_text(); - } else if (SP_ACTIVE_DOCUMENT) { - Glib::ustring filename = create_filepath_from_id(_("bitmap"), filename_entry.get_text()); - filename_entry.set_text(filename); - filename_entry.set_position(filename.length()); - - doc_export_name = filename_entry.get_text(); - } -} - -Glib::RefPtr Export::createSpinbutton(gchar const * /*key*/, double val, double min, double max, - double step, double page, Gtk::Grid *t, int x, int y, - const Glib::ustring &ll, const Glib::ustring &lr, int digits, - unsigned int sensitive, void (Export::*cb)()) -{ - auto adj = Gtk::Adjustment::create(val, min, max, step, page, 0); - - int pos = 0; - Gtk::Label *l = nullptr; - - if (!ll.empty()) { - l = new Gtk::Label(ll, true); - l->set_halign(Gtk::ALIGN_END); - l->set_valign(Gtk::ALIGN_CENTER); - l->set_hexpand(); - t->attach(*l, x + pos, y, 1, 1); - l->set_sensitive(sensitive); - pos++; - } - - auto sb = new Inkscape::UI::Widget::ScrollProtected(adj, 1.0, digits); - sb->set_hexpand(); - t->attach(*sb, x + pos, y, 1, 1); - - sb->set_width_chars(7); - sb->set_sensitive(sensitive); - pos++; - - if (l) { - l->set_mnemonic_widget(*sb); - } - - if (!lr.empty()) { - l = new Gtk::Label(lr, true); - l->set_halign(Gtk::ALIGN_START); - l->set_valign(Gtk::ALIGN_CENTER); - l->set_hexpand(); - t->attach(*l, x + pos, y, 1, 1); - l->set_sensitive(sensitive); - pos++; - l->set_mnemonic_widget(*sb); - } - - if (cb) { - adj->signal_value_changed().connect(sigc::mem_fun(*this, cb)); - } - - return adj; -} // end of createSpinbutton() - -std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_entry_text) -{ - if (id.empty()) { /* This should never happen */ - id = "bitmap"; - } - - std::string directory; - - if (!file_entry_text.empty()) { - directory = Glib::path_get_dirname(Glib::filename_from_utf8(file_entry_text)); - } - - if (directory.empty()) { - /* Grab document directory */ - const gchar *docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); - if (docFilename) { - directory = Glib::path_get_dirname(docFilename); - } - } - - if (directory.empty()) { - directory = Inkscape::IO::Resource::homedir_path(nullptr); - } - - return Glib::build_filename(directory, Glib::filename_from_utf8(id) + ".png"); -} - -void Export::onBatchClicked() -{ - if (batch_export.get_active()) { - singleexport_box.set_sensitive(false); - } else { - singleexport_box.set_sensitive(true); - } -} - -void Export::updateCheckbuttons() -{ - gint num = (gint)boost::distance(SP_ACTIVE_DESKTOP->getSelection()->items()); - if (num >= 2) { - batch_export.set_sensitive(true); - } else { - batch_export.set_active(false); - batch_export.set_sensitive(false); - } - gchar *l = - g_strdup_printf(ngettext("B_atch export %d selected object", "B_atch export %d selected objects", num), num); - batch_export.set_label(l); - g_free(l); - - // hide_export.set_sensitive (num > 0); -} - -inline void Export::findDefaultSelection() -{ - selection_type key = SELECTION_NUMBER_OF; - - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { - key = SELECTION_SELECTION; - } - - /* Try using the preferences */ - if (key == SELECTION_NUMBER_OF) { - int i = SELECTION_NUMBER_OF; - - Glib::ustring what = prefs->getString("/dialogs/export/exportarea/value"); - - if (!what.empty()) { - for (i = 0; i < SELECTION_NUMBER_OF; i++) { - if (what == selection_names[i]) { - break; - } - } - } - - key = (selection_type)i; - } - - if (key == SELECTION_NUMBER_OF) { - key = SELECTION_PAGE; - } - - current_key = key; - selectiontype_buttons[current_key]->set_active(true); - updateCheckbuttons(); -} - -/** - * If selection changed and "Export area" is set to "Selection" - * recalculate bounds when the selection changes - */ -void Export::onSelectionChanged() -{ - Inkscape::Selection *selection = SP_ACTIVE_DESKTOP->getSelection(); - if (manual_key != SELECTION_CUSTOM && selection) { - current_key = SELECTION_SELECTION; - refreshArea(); - } - - updateCheckbuttons(); -} - -void Export::onSelectionModified(guint /*flags*/) -{ - Inkscape::Selection *Sel; - switch (current_key) { - case SELECTION_DRAWING: - if (SP_ACTIVE_DESKTOP) { - SPDocument *doc; - doc = SP_ACTIVE_DESKTOP->getDocument(); - Geom::OptRect bbox = doc->getRoot()->desktopVisualBounds(); - if (bbox) { - setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); - } - } - break; - case SELECTION_SELECTION: - Sel = SP_ACTIVE_DESKTOP->getSelection(); - if (Sel->isEmpty() == false) { - Geom::OptRect bbox = Sel->visualBounds(); - if (bbox) { - setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); - } - } - break; - default: - /* Do nothing for page or for custom */ - break; - } - - return; -} - -/// Called when one of the selection buttons was toggled. -void Export::onAreaTypeToggled() -{ - if (update_flag) { - return; - } - - /* Find which button is active */ - selection_type key = current_key; - for (int i = 0; i < SELECTION_NUMBER_OF; i++) { - if (selectiontype_buttons[i]->get_active()) { - key = (selection_type)i; - } - } - manual_key = current_key = key; - - refreshArea(); -} - -/// Called when area needs to be refreshed -/// Area type changed, unit changed, initialization -void Export::refreshArea() -{ - if (SP_ACTIVE_DESKTOP) { - SPDocument *doc; - Geom::OptRect bbox; - bbox = Geom::Rect(Geom::Point(0.0, 0.0), Geom::Point(0.0, 0.0)); - doc = SP_ACTIVE_DESKTOP->getDocument(); - - /* Notice how the switch is used to 'fall through' here to get - various backups. If you modify this without noticing you'll - probably screw something up. */ - switch (current_key) { - case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { - bbox = SP_ACTIVE_DESKTOP->getSelection()->visualBounds(); - /* Only if there is a selection that we can set - do we break, otherwise we fall through to the - drawing */ - // std::cout << "Using selection: SELECTION" << std::endl; - current_key = SELECTION_SELECTION; - break; - } - case SELECTION_DRAWING: - if (manual_key == SELECTION_DRAWING || manual_key == SELECTION_SELECTION) { - /** \todo - * This returns wrong values if the document has a viewBox. - */ - bbox = doc->getRoot()->desktopVisualBounds(); - /* If the drawing is valid, then we'll use it and break - otherwise we drop through to the page settings */ - if (bbox) { - // std::cout << "Using selection: DRAWING" << std::endl; - current_key = SELECTION_DRAWING; - break; - } - } - case SELECTION_PAGE: - if (manual_key == SELECTION_PAGE) { - bbox = Geom::Rect(Geom::Point(0.0, 0.0), - Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); - - // std::cout << "Using selection: PAGE" << std::endl; - current_key = SELECTION_PAGE; - break; - } - case SELECTION_CUSTOM: - current_key = SELECTION_CUSTOM; - default: - break; - } // switch - - // remember area setting - prefs->setString("/dialogs/export/exportarea/value", selection_names[current_key]); - - if (current_key != SELECTION_CUSTOM && bbox) { - setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); - } - - } // end of if ( SP_ACTIVE_DESKTOP ) - - if (SP_ACTIVE_DESKTOP && !filename_modified) { - Glib::ustring filename; - float xdpi = 0.0, ydpi = 0.0; - - switch (current_key) { - case SELECTION_PAGE: - case SELECTION_DRAWING: { - SPDocument *doc = SP_ACTIVE_DOCUMENT; - sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); - - if (filename.empty()) { - if (!doc_export_name.empty()) { - filename = doc_export_name; - } - } - break; - } - case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { - SP_ACTIVE_DESKTOP->getSelection()->getExportHints(filename, &xdpi, &ydpi); - - /* If we still don't have a filename -- let's build - one that's nice */ - if (filename.empty()) { - const gchar *id = "object"; - auto reprlst = SP_ACTIVE_DESKTOP->getSelection()->xmlNodes(); - for (auto i = reprlst.begin(); reprlst.end() != i; ++i) { - Inkscape::XML::Node *repr = *i; - if (repr->attribute("id")) { - id = repr->attribute("id"); - break; - } - } - - filename = create_filepath_from_id(id, filename_entry.get_text()); - } - } - break; - case SELECTION_CUSTOM: - default: - break; - } - - if (!filename.empty()) { - original_name = filename; - filename_entry.set_text(filename); - filename_entry.set_position(filename.length()); - } - - if (xdpi != 0.0) { - setValue(xdpi_adj, xdpi); - } - - /* These can't be separate, and setting x sets y, so for - now setting this is disabled. Hopefully it won't be in - the future */ - if (FALSE && ydpi != 0.0) { - setValue(ydpi_adj, ydpi); - } - } - - return; -} // end of sp_export_area_toggled() - -/// Called when dialog is deleted -bool Export::onProgressDelete(GdkEventAny * /*event*/) -{ - interrupted = true; - return TRUE; -} // end of sp_export_progress_delete() - -/// Called when progress is cancelled -void Export::onProgressCancel() -{ - interrupted = true; -} // end of sp_export_progress_cancel() - -/// Called for every progress iteration -unsigned int Export::onProgressCallback(float value, void *dlg) -{ - auto dlg2 = reinterpret_cast(dlg); - - auto self = dlg2->get_export_panel(); - if (self->interrupted) - return FALSE; - - auto current = dlg2->get_current(); - auto total = dlg2->get_total(); - if (total > 0) { - double completed = current; - completed /= static_cast(total); - - value = completed + (value / static_cast(total)); - } - - auto prg = dlg2->get_progress(); - prg->set_fraction(value); - - if (self) { - self->_prog.set_fraction(value); - } - - int evtcount = 0; - while ((evtcount < 16) && gdk_events_pending()) { - Gtk::Main::iteration(false); - evtcount += 1; - } - - Gtk::Main::iteration(false); - return TRUE; -} // end of sp_export_progress_callback() - -void Export::setExporting(bool exporting, Glib::ustring const &text) -{ - if (exporting) { - _prog.set_text(text); - _prog.set_fraction(0.0); - _prog.set_sensitive(true); - - export_button.set_sensitive(false); - } else { - _prog.set_text(""); - _prog.set_fraction(0.0); - _prog.set_sensitive(false); - - export_button.set_sensitive(true); - } -} - -ExportProgressDialog *Export::create_progress_dialog(Glib::ustring progress_text) -{ - auto dlg = new ExportProgressDialog(_("Export in progress"), true); - dlg->set_transient_for(*(INKSCAPE.active_desktop()->getToplevel())); - - Gtk::ProgressBar *prg = new Gtk::ProgressBar(); - prg->set_text(progress_text); - dlg->set_progress(prg); - auto CA = dlg->get_content_area(); - CA->pack_start(*prg, FALSE, FALSE, 4); - - Gtk::Button *btn = dlg->add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL); - - btn->signal_clicked().connect(sigc::mem_fun(*this, &Export::onProgressCancel)); - dlg->signal_delete_event().connect(sigc::mem_fun(*this, &Export::onProgressDelete)); - - dlg->show_all(); - return dlg; -} - -static std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename) -{ - std::string path; - // Make relative paths go from the document location, if possible: - if (!Glib::path_is_absolute(filename) && doc->getDocumentFilename()) { - auto dirname = Glib::path_get_dirname(doc->getDocumentFilename()); - if (!dirname.empty()) { - path = Glib::build_filename(dirname, filename); - } - } - if (path.empty()) { - path = filename; - } - return path; -} - -// Called when unit is changed -void Export::onUnitChanged() -{ - refreshArea(); -} - -void Export::onHideExceptSelected() -{ - prefs->setBool("/dialogs/export/hideexceptselected/value", hide_export.get_active()); -} - -/// Called when export button is clicked -void Export::onExport() -{ - _export_raster(nullptr); -} - -void Export::_export_raster(Inkscape::Extension::Output *extension) -{ - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) - return; - - SPNamedView *nv = desktop->getNamedView(); - SPDocument *doc = desktop->getDocument(); - - bool exportSuccessful = false; - - bool hide = hide_export.get_active(); - - // Advanced parameters - bool do_interlace = (interlacing.get_active()); - float pHYs = 0; - int zlib = zlib_compression.get_active_row_number(); - int colortypes[] = {0, 0, 0, 0, 0, 2, - 2, 4, 4, 6, 6}; // keep in sync with modes_list in Export constructor. values are from libpng - // doc. - int bitdepths[] = {1, 2, 4, 8, 16, 8, 16, 8, 16, 8, 16}; - int color_type = colortypes[bitdepth_cb.get_active_row_number()]; - int bit_depth = bitdepths[bitdepth_cb.get_active_row_number()]; - int antialiasing = antialiasing_cb.get_active_row_number(); - - if (batch_export.get_active()) { - // Batch export of selected objects - - gint num = (gint)boost::distance(desktop->getSelection()->items()); - gint n = 0; - - if (num < 1) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No items selected.")); - return; - } - - prog_dlg = create_progress_dialog(Glib::ustring::compose(_("Exporting %1 files"), num)); - prog_dlg->set_export_panel(this); - setExporting(true, Glib::ustring::compose(_("Exporting %1 files"), num)); - - gint export_count = 0; - - auto itemlist = desktop->getSelection()->items(); - for (auto i = itemlist.begin(); i != itemlist.end() && !interrupted; ++i) { - SPItem *item = *i; - - prog_dlg->set_current(n); - prog_dlg->set_total(num); - onProgressCallback(0.0, prog_dlg); - - // retrieve export filename hint - const gchar *filename = item->getRepr()->attribute("inkscape:export-filename"); - std::string path; - if (!filename) { - auto id = item->getId(); - if (!id) { - g_warning("object has no id"); - continue; - } - path = create_filepath_from_id(id, filename_entry.get_text()); - } else { - path = absolutize_path_from_document_location(doc, filename); - } - - // retrieve export dpi hints - const gchar *dpi_hint = - item->getRepr()->attribute("inkscape:export-xdpi"); // only xdpi, ydpi is always the same now - gdouble dpi = 0.0; - if (dpi_hint) { - dpi = g_ascii_strtod(dpi_hint, nullptr); - } - if (dpi == 0.0) { - dpi = getValue(xdpi_adj); - } - pHYs = (pHYs_adj->get_value() > 0.01) ? pHYs_adj->get_value() : dpi; - - Geom::OptRect area = item->documentVisualBounds(); - if (area) { - gint width = (gint)(area->width() * dpi / DPI_BASE + 0.5); - gint height = (gint)(area->height() * dpi / DPI_BASE + 0.5); - - if (width > 1 && height > 1) { - // Do export - gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); - MessageCleaner msgCleanup(desktop->messageStack()->pushF(Inkscape::IMMEDIATE_MESSAGE, - _("Exporting file %s..."), - safeFile), - desktop); - MessageCleaner msgFlashCleanup(desktop->messageStack()->flashF(Inkscape::IMMEDIATE_MESSAGE, - _("Exporting file %s..."), - safeFile), - desktop); - std::vector x; - std::vector selected(desktop->getSelection()->items().begin(), - desktop->getSelection()->items().end()); - if (!sp_export_png_file(doc, path.c_str(), *area, width, height, pHYs, pHYs, nv->pagecolor, - onProgressCallback, (void *)prog_dlg, - TRUE, // overwrite without asking - hide ? selected : x, do_interlace, color_type, bit_depth, zlib, - antialiasing)) { - gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); - - desktop->messageStack()->flashF(Inkscape::ERROR_MESSAGE, - _("Could not export to filename %s."), safeFile); - - sp_ui_error_dialog(error); - g_free(error); - } else { - ++export_count; // one more item exported successfully - } - g_free(safeFile); - } - } - - n++; - } - - desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, - _("Successfully exported %d files from %d selected items."), - export_count, num); - - setExporting(false); - delete prog_dlg; - prog_dlg = nullptr; - interrupted = false; - exportSuccessful = (export_count > 0); - } else { - Glib::ustring filename = filename_entry.get_text(); - - if (filename.empty()) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You have to enter a filename.")); - sp_ui_error_dialog(_("You have to enter a filename")); - return; - } - - float const x0 = getValuePx(x0_adj); - float const y0 = getValuePx(y0_adj); - float const x1 = getValuePx(x1_adj); - float const y1 = getValuePx(y1_adj); - float const xdpi = getValue(xdpi_adj); - float const ydpi = getValue(ydpi_adj); - pHYs = (pHYs_adj->get_value() > 0.01) ? pHYs_adj->get_value() : xdpi; - unsigned long int const width = int(getValue(bmwidth_adj) + 0.5); - unsigned long int const height = int(getValue(bmheight_adj) + 0.5); - - if (!((x1 > x0) && (y1 > y0) && (width > 0) && (height > 0))) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("The chosen area to be exported is invalid.")); - sp_ui_error_dialog(_("The chosen area to be exported is invalid")); - return; - } - - std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(filename)); - - Glib::ustring dirname = Glib::path_get_dirname(path); - if (dirname.empty() || - !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { - gchar *safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); - gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), safeDir); - - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); - sp_ui_error_dialog(error); - - g_free(safeDir); - g_free(error); - return; - } - - auto fn = Glib::path_get_basename(path); - auto area = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * desktop->dt2doc(); - - // Select a raster output extension if not a png file (manual filename) - if (!extension && !Glib::str_has_suffix(filename, ".png")) { - Inkscape::Extension::DB::OutputList extension_list; - Inkscape::Extension::db.get_output_list(extension_list); - for (auto output_ext : extension_list) { - if (output_ext->deactivated() || !output_ext->is_raster()) - continue; - if (Glib::str_has_suffix(path.c_str(), output_ext->get_extension())) { - // Select the extension - extension = output_ext; - break; - } - } - } - - bool overwrite = false; - auto png_filename = std::string(path.c_str()); - if (extension) { - // Select the extension and set the filename to a temporary file - int tempfd_out = Glib::file_open_tmp(png_filename, "ink_ext_"); - // Do the over-write protection now, since the png is just a temp file. - if (!sp_ui_overwrite_file(filename.c_str())) { - return; - } - overwrite = true; - close(tempfd_out); - } - - /* TRANSLATORS: %1 will be the filename, %2 the width, and %3 the height of the image */ - prog_dlg = create_progress_dialog(Glib::ustring::compose(_("Exporting %1 (%2 x %3)"), fn, width, height)); - prog_dlg->set_export_panel(this); - setExporting(true, Glib::ustring::compose(_("Exporting %1 (%2 x %3)"), fn, width, height)); - - prog_dlg->set_current(0); - prog_dlg->set_total(0); - - /* Do export */ - std::vector x; - std::vector selected(desktop->getSelection()->items().begin(), - desktop->getSelection()->items().end()); - ExportResult status = sp_export_png_file( - desktop->getDocument(), png_filename.c_str(), area, width, height, pHYs, pHYs, // previously xdpi, ydpi. - nv->pagecolor, onProgressCallback, (void *)prog_dlg, overwrite, hide ? selected : x, do_interlace, - color_type, bit_depth, zlib, antialiasing); - if (status == EXPORT_ERROR) { - gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); - gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); - - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); - sp_ui_error_dialog(error); - - g_free(safeFile); - g_free(error); - } else if (status == EXPORT_OK) { - exportSuccessful = true; - if (extension != nullptr) { - // Remove progress dialog before showing prefs dialog. - delete prog_dlg; - prog_dlg = nullptr; - if (extension->prefs()) { - try { - extension->export_raster(doc, png_filename, path.c_str(), false); - } catch (Inkscape::Extension::Output::save_failed &e) { - exportSuccessful = false; - } - } else { - exportSuccessful = false; - } - } - - if (exportSuccessful) { - auto recentmanager = Gtk::RecentManager::get_default(); - if (recentmanager && Glib::path_is_absolute(path)) { - Glib::ustring uri = Glib::filename_to_uri(path); - recentmanager->add_item(uri); - } - - gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); - desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, _("Drawing exported to %s."), - safeFile); - g_free(safeFile); - } - } else { - // Extensions have their own error popup, so this only tracks failures in the png step - desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE, _("Export aborted.")); - } - if (extension != nullptr) { - unlink(png_filename.c_str()); - } - - /* Reset the filename so that it can be changed again by changing - selections and all that */ - original_name = filename; - filename_modified = false; - - setExporting(false); - if (prog_dlg) { - delete prog_dlg; - prog_dlg = nullptr; - } - interrupted = false; - - /* Setup the values in the document */ - switch (current_key) { - case SELECTION_PAGE: - case SELECTION_DRAWING: { - SPDocument *doc = SP_ACTIVE_DOCUMENT; - Inkscape::XML::Node *repr = doc->getReprRoot(); - bool modified = false; - - bool saved = DocumentUndo::getUndoSensitive(doc); - DocumentUndo::setUndoSensitive(doc, false); - - gchar const *temp_string = repr->attribute("inkscape:export-filename"); - if (temp_string == nullptr || (filename != temp_string)) { - repr->setAttribute("inkscape:export-filename", filename); - modified = true; - } - temp_string = repr->attribute("inkscape:export-xdpi"); - if (temp_string == nullptr || xdpi != g_ascii_strtod(temp_string, nullptr)) { - repr->setAttributeSvgDouble("inkscape:export-xdpi", xdpi); - modified = true; - } - temp_string = repr->attribute("inkscape:export-ydpi"); - if (temp_string == nullptr || ydpi != g_ascii_strtod(temp_string, nullptr)) { - repr->setAttributeSvgDouble("inkscape:export-ydpi", ydpi); - modified = true; - } - DocumentUndo::setUndoSensitive(doc, saved); - - if (modified) { - doc->setModifiedSinceSave(); - } - break; - } - case SELECTION_SELECTION: { - SPDocument *doc = SP_ACTIVE_DOCUMENT; - bool modified = false; - - bool saved = DocumentUndo::getUndoSensitive(doc); - DocumentUndo::setUndoSensitive(doc, false); - auto reprlst = desktop->getSelection()->xmlNodes(); - - for (auto i = reprlst.begin(); reprlst.end() != i; ++i) { - Inkscape::XML::Node *repr = *i; - const gchar *temp_string; - Glib::ustring dir = Glib::path_get_dirname(filename.c_str()); - const gchar *docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); - Glib::ustring docdir; - if (docFilename) { - docdir = Glib::path_get_dirname(docFilename); - } - temp_string = repr->attribute("inkscape:export-filename"); - if (temp_string == nullptr || (filename != temp_string)) { - repr->setAttribute("inkscape:export-filename", filename); - modified = true; - } - - temp_string = repr->attribute("inkscape:export-xdpi"); - if (temp_string == nullptr || xdpi != g_ascii_strtod(temp_string, nullptr)) { - repr->setAttributeSvgDouble("inkscape:export-xdpi", xdpi); - modified = true; - } - temp_string = repr->attribute("inkscape:export-ydpi"); - if (temp_string == nullptr || ydpi != g_ascii_strtod(temp_string, nullptr)) { - repr->setAttributeSvgDouble("inkscape:export-ydpi", ydpi); - modified = true; - } - } - DocumentUndo::setUndoSensitive(doc, saved); - - if (modified) { - doc->setModifiedSinceSave(); - } - break; - } - default: - break; - } - } - - if (exportSuccessful && closeWhenDone.get_active()) { - for (Gtk::Container *parent = get_parent(); parent; parent = parent->get_parent()) { - DialogNotebook *notebook = dynamic_cast(parent); - if (notebook) { - notebook->close_tab_callback(); - break; - } - } - } -} // end of Export::onExport() - -/// Called when Browse button is clicked -void Export::onBrowse() -{ - // Create and show the dialog - Gtk::Window *window = _app->get_active_window(); - std::string filename = Glib::filename_from_utf8(filename_entry.get_text()); - - if (filename.empty()) { - Glib::ustring tmp; - filename = create_filepath_from_id(tmp, tmp); - } - - Inkscape::UI::Dialog::FileSaveDialog *dialog = Inkscape::UI::Dialog::FileSaveDialog::create( - *window, filename, Inkscape::UI::Dialog::RASTER_TYPES, _("Select a filename for exporting"), "", "", - Inkscape::Extension::FILE_SAVE_METHOD_EXPORT); - - if (dialog->show()) { - auto file = dialog->getFilename(); - filename_entry.set_text(Glib::filename_to_utf8(file)); - filename_entry.set_position(-1); - auto selection_type = dialog->getSelectionType(); - // deleting dialog before exporting is important - // proper delete function should be made for dialog IMO - delete dialog; - _export_raster(dynamic_cast(selection_type)); - } else { - delete dialog; - } -} - -// TODO: Move this to nr-rect-fns.h. -bool Export::bbox_equal(Geom::Rect const &one, Geom::Rect const &two) -{ - double const epsilon = pow(10.0, -EXPORT_COORD_PRECISION); - return ((fabs(one.min()[Geom::X] - two.min()[Geom::X]) < epsilon) && - (fabs(one.min()[Geom::Y] - two.min()[Geom::Y]) < epsilon) && - (fabs(one.max()[Geom::X] - two.max()[Geom::X]) < epsilon) && - (fabs(one.max()[Geom::Y] - two.max()[Geom::Y]) < epsilon)); -} - -/** - *This function is used to detect the current selection setting - * based on the values in the x0, y0, x1 and y0 fields. - * - * One of the most confusing parts of this function is why the array - * is built at the beginning. What needs to happen here is that we - * should always check the current selection to see if it is the valid - * one. While this is a performance improvement it is also a usability - * one during the cases where things like selections and drawings match - * size. This way buttons change less 'randomly' (at least in the eyes - * of the user). To do this an array is built where the current selection - * type is placed first, and then the others in an order from smallest - * to largest (this can be configured by reshuffling \c test_order). - * - * All of the values in this function are rounded to two decimal places - * because that is what is shown to the user. While everything is kept - * more accurate than that, the user can't control more accurate than - * that, so for this to work for them - it needs to check on that level - * of accuracy. - * - * @todo finish writing this up. - */ -void Export::detectSize() -{ - static const selection_type test_order[SELECTION_NUMBER_OF] = {SELECTION_SELECTION, SELECTION_DRAWING, - SELECTION_PAGE, SELECTION_CUSTOM}; - selection_type this_test[SELECTION_NUMBER_OF + 1]; - selection_type key = SELECTION_NUMBER_OF; - - Geom::Point x(getValuePx(x0_adj), getValuePx(y0_adj)); - Geom::Point y(getValuePx(x1_adj), getValuePx(y1_adj)); - Geom::Rect current_bbox(x, y); - - this_test[0] = current_key; - for (int i = 0; i < SELECTION_NUMBER_OF; i++) { - this_test[i + 1] = test_order[i]; - } - - for (int i = 0; i < SELECTION_NUMBER_OF + 1 && key == SELECTION_NUMBER_OF && SP_ACTIVE_DESKTOP != nullptr; i++) { - switch (this_test[i]) { - case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { - Geom::OptRect bbox = (SP_ACTIVE_DESKTOP->getSelection())->bounds(SPItem::VISUAL_BBOX); - - if (bbox && bbox_equal(*bbox, current_bbox)) { - key = SELECTION_SELECTION; - } - } - break; - case SELECTION_DRAWING: { - SPDocument *doc = SP_ACTIVE_DESKTOP->getDocument(); - - Geom::OptRect bbox = doc->getRoot()->desktopVisualBounds(); - - if (bbox && bbox_equal(*bbox, current_bbox)) { - key = SELECTION_DRAWING; - } - break; - } - - case SELECTION_PAGE: { - SPDocument *doc; - - doc = SP_ACTIVE_DESKTOP->getDocument(); - - Geom::Point x(0.0, 0.0); - Geom::Point y(doc->getWidth().value("px"), doc->getHeight().value("px")); - Geom::Rect bbox(x, y); - - if (bbox_equal(bbox, current_bbox)) { - key = SELECTION_PAGE; - } - - break; - } - default: - break; - } - } - // std::cout << std::endl; - - if (key == SELECTION_NUMBER_OF) { - key = SELECTION_CUSTOM; - } - - current_key = key; - selectiontype_buttons[current_key]->set_active(true); - - return; -} /* sp_export_detect_size */ - -/// Called when area x0 value is changed -void Export::areaXChange(Glib::RefPtr &adj) -{ - float x0, x1, xdpi, width; - - if (update_flag) { - return; - } - - update_flag = true; - - x0 = getValuePx(x0_adj); - x1 = getValuePx(x1_adj); - xdpi = getValue(xdpi_adj); - - width = floor((x1 - x0) * xdpi / DPI_BASE + 0.5); - - if (width < SP_EXPORT_MIN_SIZE) { - width = SP_EXPORT_MIN_SIZE; - - if (adj == x1_adj) { - x1 = x0 + width * DPI_BASE / xdpi; - setValuePx(x1_adj, x1); - } else { - x0 = x1 - width * DPI_BASE / xdpi; - setValuePx(x0_adj, x0); - } - } - - setValuePx(width_adj, x1 - x0); - setValue(bmwidth_adj, width); - - detectSize(); - - update_flag = false; - - return; -} // end of sp_export_area_x_value_changed() - -/// Called when area y0 value is changed. -void Export::areaYChange(Glib::RefPtr &adj) -{ - float y0, y1, ydpi, height; - - if (update_flag) { - return; - } - - update_flag = true; - - y0 = getValuePx(y0_adj); - y1 = getValuePx(y1_adj); - ydpi = getValue(ydpi_adj); - - height = floor((y1 - y0) * ydpi / DPI_BASE + 0.5); - - if (height < SP_EXPORT_MIN_SIZE) { - height = SP_EXPORT_MIN_SIZE; - if (adj == y1_adj) { - // if (!strcmp (key, "y0")) { - y1 = y0 + height * DPI_BASE / ydpi; - setValuePx(y1_adj, y1); - } else { - y0 = y1 - height * DPI_BASE / ydpi; - setValuePx(y0_adj, y0); - } - } - - setValuePx(height_adj, y1 - y0); - setValue(bmheight_adj, height); - - detectSize(); - - update_flag = false; - - return; -} // end of sp_export_area_y_value_changed() - -/// Called when x1-x0 or area width is changed -void Export::onAreaWidthChange() -{ - if (update_flag) { - return; - } - - update_flag = true; - - float x0 = getValuePx(x0_adj); - float xdpi = getValue(xdpi_adj); - float width = getValuePx(width_adj); - float bmwidth = floor(width * xdpi / DPI_BASE + 0.5); - - if (bmwidth < SP_EXPORT_MIN_SIZE) { - bmwidth = SP_EXPORT_MIN_SIZE; - width = bmwidth * DPI_BASE / xdpi; - setValuePx(width_adj, width); - } - - setValuePx(x1_adj, x0 + width); - setValue(bmwidth_adj, bmwidth); - - update_flag = false; - - return; -} // end of sp_export_area_width_value_changed() - -/// Called when y1-y0 or area height is changed. -void Export::onAreaHeightChange() -{ - if (update_flag) { - return; - } - - update_flag = true; - - float y0 = getValuePx(y0_adj); - // float y1 = sp_export_value_get_px(y1_adj); - float ydpi = getValue(ydpi_adj); - float height = getValuePx(height_adj); - float bmheight = floor(height * ydpi / DPI_BASE + 0.5); - - if (bmheight < SP_EXPORT_MIN_SIZE) { - bmheight = SP_EXPORT_MIN_SIZE; - height = bmheight * DPI_BASE / ydpi; - setValuePx(height_adj, height); - } - - setValuePx(y1_adj, y0 + height); - setValue(bmheight_adj, bmheight); - - update_flag = false; - - return; -} // end of sp_export_area_height_value_changed() - -/** - * A function to set the ydpi. - * @param base The export dialog. - * - * This function grabs all of the y values and then figures out the - * new bitmap size based on the changing dpi value. The dpi value is - * gotten from the xdpi setting as these can not currently be independent. - */ -void Export::setImageY() -{ - float y0, y1, xdpi; - - y0 = getValuePx(y0_adj); - y1 = getValuePx(y1_adj); - xdpi = getValue(xdpi_adj); - - setValue(ydpi_adj, xdpi); - setValue(bmheight_adj, (y1 - y0) * xdpi / DPI_BASE); - - return; -} // end of setImageY() - -/** - * A function to set the xdpi. - * - * This function grabs all of the x values and then figures out the - * new bitmap size based on the changing dpi value. The dpi value is - * gotten from the xdpi setting as these can not currently be independent. - * - */ -void Export::setImageX() -{ - float x0, x1, xdpi; - - x0 = getValuePx(x0_adj); - x1 = getValuePx(x1_adj); - xdpi = getValue(xdpi_adj); - - setValue(ydpi_adj, xdpi); - setValue(bmwidth_adj, (x1 - x0) * xdpi / DPI_BASE); - - return; -} // end of setImageX() - -/// Called when pixel width is changed -void Export::onBitmapWidthChange() -{ - float x0, x1, bmwidth, xdpi; - - if (update_flag) { - return; - } - - update_flag = true; - - x0 = getValuePx(x0_adj); - x1 = getValuePx(x1_adj); - bmwidth = getValue(bmwidth_adj); - - if (bmwidth < SP_EXPORT_MIN_SIZE) { - bmwidth = SP_EXPORT_MIN_SIZE; - setValue(bmwidth_adj, bmwidth); - } - - xdpi = bmwidth * DPI_BASE / (x1 - x0); - setValue(xdpi_adj, xdpi); - - setImageY(); - - update_flag = false; - - return; -} // end of sp_export_bitmap_width_value_changed() - -/// Called when pixel height is changed -void Export::onBitmapHeightChange() -{ - float y0, y1, bmheight, xdpi; - - if (update_flag) { - return; - } - - update_flag = true; - - y0 = getValuePx(y0_adj); - y1 = getValuePx(y1_adj); - bmheight = getValue(bmheight_adj); - - if (bmheight < SP_EXPORT_MIN_SIZE) { - bmheight = SP_EXPORT_MIN_SIZE; - setValue(bmheight_adj, bmheight); - } - - xdpi = bmheight * DPI_BASE / (y1 - y0); - setValue(xdpi_adj, xdpi); - - setImageX(); - - update_flag = false; - - return; -} // end of sp_export_bitmap_width_value_changed() - -/** - * A function to adjust the bitmap width when the xdpi value changes. - * - * The first thing this function checks is to see if we are doing an - * update. If we are, this function just returns because there is another - * instance of it that will handle everything for us. If there is a - * units change, we also assume that everyone is being updated appropriately - * and there is nothing for us to do. - * - * If we're the highest level function, we set the update flag, and - * continue on our way. - * - * All of the values are grabbed using the \c sp_export_value_get functions - * (call to the _pt ones for x0 and x1 but just standard for xdpi). The - * xdpi value is saved in the preferences for the next time the dialog - * is opened. (does the selection dpi need to be set here?) - * - * A check is done to to ensure that we aren't outputting an invalid width, - * this is set by SP_EXPORT_MIN_SIZE. If that is the case the dpi is - * changed to make it valid. - * - * After all of this the bitmap width is changed. - * - * We also change the ydpi. This is a temporary hack as these can not - * currently be independent. This is likely to change in the future. - * - */ -void Export::onExportXdpiChange() -{ - float x0, x1, xdpi, bmwidth; - - if (update_flag) { - return; - } - - update_flag = true; - - x0 = getValuePx(x0_adj); - x1 = getValuePx(x1_adj); - xdpi = getValue(xdpi_adj); - - // remember xdpi setting - prefs->setDouble("/dialogs/export/defaultxdpi/value", xdpi); - - bmwidth = (x1 - x0) * xdpi / DPI_BASE; - - if (bmwidth < SP_EXPORT_MIN_SIZE) { - bmwidth = SP_EXPORT_MIN_SIZE; - if (x1 != x0) - xdpi = bmwidth * DPI_BASE / (x1 - x0); - else - xdpi = DPI_BASE; - setValue(xdpi_adj, xdpi); - } - - setValue(bmwidth_adj, bmwidth); - - setImageY(); - - update_flag = false; - - return; -} // end of sp_export_xdpi_value_changed() - -/** - * A function to change the area that is used for the exported. - * bitmap. - * - * This function just calls \c sp_export_value_set_px for each of the - * parameters that is passed in. This allows for setting them all in - * one convenient area. - * - * Update is set to suspend all of the other test running while all the - * values are being set up. This allows for a performance increase, but - * it also means that the wrong type won't be detected with only some of - * the values set. After all the values are set everyone is told that - * there has been an update. - * - * @param x0 Horizontal upper left hand corner of the picture in points. - * @param y0 Vertical upper left hand corner of the picture in points. - * @param x1 Horizontal lower right hand corner of the picture in points. - * @param y1 Vertical lower right hand corner of the picture in points. - */ -void Export::setArea(double x0, double y0, double x1, double y1) -{ - update_flag = true; - setValuePx(x1_adj, x1); - setValuePx(y1_adj, y1); - setValuePx(x0_adj, x0); - setValuePx(y0_adj, y0); - update_flag = false; - - areaXChange(x1_adj); - areaYChange(y1_adj); - - return; -} - -/** - * Sets the value of an adjustment. - * - * @param adj The adjustment widget - * @param val What value to set it to. - */ -void Export::setValue(Glib::RefPtr &adj, double val) -{ - if (adj) { - adj->set_value(val); - } -} - -/** - * A function to set a value using the units points. - * - * This function first gets the adjustment for the key that is passed - * in. It then figures out what units are currently being used in the - * dialog. After doing all of that, it then converts the incoming - *value and sets the adjustment. - * - * @param adj The adjustment widget - * @param val What the value should be in points. - */ -void Export::setValuePx(Glib::RefPtr &adj, double val) -{ - Unit const *unit = unit_selector.getUnit(); - - setValue(adj, Inkscape::Util::Quantity::convert(val, "px", unit)); - - return; -} - -/** - * Get the value of an adjustment in the export dialog. - * - * This function gets the adjustment from the data field in the export - * dialog. It then grabs the value from the adjustment. - * - * @param adj The adjustment widget - * - * @return The value in the specified adjustment. - */ -float Export::getValue(Glib::RefPtr &adj) -{ - if (!adj) { - g_message("sp_export_value_get : adj is NULL"); - return 0.0; - } - return adj->get_value(); -} - -/** - * Grabs a value in the export dialog and converts the unit - * to points. - * - * This function, at its most basic, is a call to \c sp_export_value_get - * to get the value of the adjustment. It then finds the units that - * are being used by looking at the "units" attribute of the export - * dialog. Using that it converts the returned value into points. - * - * @param adj The adjustment widget - * - * @return The value in the adjustment in points. - */ -float Export::getValuePx(Glib::RefPtr &adj) -{ - float value = getValue(adj); - Unit const *unit = unit_selector.getUnit(); - - return Inkscape::Util::Quantity::convert(value, unit, "px"); -} // end of sp_export_value_get_px() - -/** - * This function is called when the filename is changed by - * anyone. It resets the virgin bit. - * - * This function gets called when the text area is modified. It is - * looking for the case where the text area is modified from its - * original value. In that case it sets the "filename-modified" bit - * to TRUE. If the text dialog returns back to the original text, the - * bit gets reset. This should stop simple mistakes. - */ -void Export::onFilenameModified() -{ - if (original_name == filename_entry.get_text()) { - filename_modified = false; - } else { - filename_modified = true; - } - - return; -} // end sp_export_filename_modified - -} // namespace Dialog -} // namespace UI -} // namespace Inkscape - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/dialog/export-old.h b/src/ui/dialog/export-old.h deleted file mode 100644 index b499e06cfa..0000000000 --- a/src/ui/dialog/export-old.h +++ /dev/null @@ -1,371 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* Authors: - * Lauris Kaplinski - * bulia byak - * Johan Engelen - * - * Copyright (C) 1999-2007 Authors - * Copyright (C) 2001-2002 Ximian, Inc. - * - * Released under GNU GPL v2+, read the file 'COPYING' for more information. - */ - -#ifndef SP_EXPORT_H -#define SP_EXPORT_H - -#include -#include -#include -#include -#include -#include -#include - -#include "extension/output.h" -#include "ui/dialog/dialog-base.h" -#include "ui/widget/scrollprotected.h" - -namespace Inkscape { -namespace UI { -namespace Dialog { - -class ExportProgressDialog; - -/** What type of button is being pressed */ -enum selection_type { - SELECTION_PAGE = 0, /**< Export the whole page */ - SELECTION_DRAWING, /**< Export everything drawn on the page */ - SELECTION_SELECTION, /**< Export everything that is selected */ - SELECTION_CUSTOM, /**< Allows the user to set the region exported */ - SELECTION_NUMBER_OF /**< A counter for the number of these guys */ -}; - -/** - * A dialog widget to export to various image formats such as bitmap and png. - * - * Creates a dialog window for exporting an image to a bitmap if one doesn't already exist and - * shows it to the user. If the dialog has already been created, it simply shows the window. - * - */ -class Export : public DialogBase -{ -public: - Export (); - ~Export () override; - - static Export &getInstance() { - return *new Export(); - } - -private: - - /** - * A function to set the xdpi. - * - * This function grabs all of the x values and then figures out the - * new bitmap size based on the changing dpi value. The dpi value is - * gotten from the xdpi setting as these can not currently be independent. - * - */ - void setImageX(); - - /** - * A function to set the ydpi. - * - * This function grabs all of the y values and then figures out the - * new bitmap size based on the changing dpi value. The dpi value is - * gotten from the xdpi setting as these can not currently be independent. - */ - void setImageY(); - bool bbox_equal(Geom::Rect const &one, Geom::Rect const &two); - void updateCheckbuttons (); - inline void findDefaultSelection(); - void detectSize(); - void setArea ( double x0, double y0, double x1, double y1); - /* - * Getter/setter style functions for the spinbuttons - */ - void setValue(Glib::RefPtr& adj, double val); - void setValuePx(Glib::RefPtr& adj, double val); - float getValue(Glib::RefPtr& adj); - float getValuePx(Glib::RefPtr& adj); - - /** - * Helper function to create, style and pack spinbuttons for the export dialog. - * - * Creates a new spin button for the export dialog. - * @param key The name of the spin button - * @param val A default value for the spin button - * @param min Minimum value for the spin button - * @param max Maximum value for the spin button - * @param step The step size for the spin button - * @param page Size of the page increment - * @param t Table to put the spin button in - * @param x X location in the table \c t to start with - * @param y Y location in the table \c t to start with - * @param ll Text to put on the left side of the spin button (optional) - * @param lr Text to put on the right side of the spin button (optional) - * @param digits Number of digits to display after the decimal - * @param sensitive Whether the spin button is sensitive or not - * @param cb Callback for when this spin button is changed (optional) - * - * No unit_selector is stored in the created spinbutton, relies on external unit management - */ - Glib::RefPtr createSpinbutton( gchar const *key, - double val, double min, double max, double step, double page, - Gtk::Grid *t, int x, int y, - const Glib::ustring& ll, const Glib::ustring& lr, - int digits, unsigned int sensitive, - void (Export::*cb)() ); - - /** - * One of the area select radio buttons was pressed - */ - void onAreaTypeToggled(); - void refreshArea(); - - /** - * Export button callback - */ - void onExport (); - void _export_raster(Inkscape::Extension::Output *extension); - - /** - * File Browse button callback - */ - void onBrowse (); - - /** - * Area X value changed callback - */ - void onAreaX0Change() { - areaXChange(x0_adj); - } ; - void onAreaX1Change() { - areaXChange(x1_adj); - } ; - void areaXChange(Glib::RefPtr& adj); - - /** - * Area Y value changed callback - */ - void onAreaY0Change() { - areaYChange(y0_adj); - } ; - void onAreaY1Change() { - areaYChange(y1_adj); - } ; - void areaYChange(Glib::RefPtr& adj); - - /** - * Unit changed callback - */ - void onUnitChanged(); - - /** - * Hide except selected callback - */ - void onHideExceptSelected (); - - /** - * Area width value changed callback - */ - void onAreaWidthChange (); - - /** - * Area height value changed callback - */ - void onAreaHeightChange (); - - /** - * Bitmap width value changed callback - */ - void onBitmapWidthChange (); - - /** - * Bitmap height value changed callback - */ - void onBitmapHeightChange (); - - /** - * Export xdpi value changed callback - */ - void onExportXdpiChange (); - - /** - * Batch export callback - */ - void onBatchClicked (); - - /** - * Inkscape selection change callback - */ - void onSelectionChanged (); - void onSelectionModified (guint flags); - - /** - * Filename modified callback - */ - void onFilenameModified (); - - /** - * Can be invoked for setting the desktop. Currently not used. - */ - void setDesktop(SPDesktop *desktop); - - /** - * Update active window. - */ - void update() override; - - /** - * Creates progress dialog for batch exporting. - * - * @param progress_text Text to be shown in the progress bar - */ - ExportProgressDialog * create_progress_dialog(Glib::ustring progress_text); - - /** - * Callback to be used in for loop to update the progress bar. - * - * @param value number between 0 and 1 indicating the fraction of progress (0.17 = 17 % progress) - * @param dlg void pointer to the Gtk::Dialog progress dialog - */ - static unsigned int onProgressCallback(float value, void *dlg); - - /** - * Callback for pressing the cancel button. - */ - void onProgressCancel (); - - /** - * Callback invoked on closing the progress dialog. - */ - bool onProgressDelete (GdkEventAny *event); - - /** - * Handles state changes as exporting starts or stops. - */ - void setExporting(bool exporting, Glib::ustring const &text = ""); - - /* - * Utility filename and path functions - */ - void set_default_filename (); - - /* - * Currently selected export area type - * can be changed by code - */ - selection_type current_key; - /* - * Manually selected export area type(only changed by buttons) - */ - selection_type manual_key; - /* - * Original name for the export object - */ - Glib::ustring original_name; - Glib::ustring doc_export_name; - /* - * Was the Original name modified - */ - bool filename_modified; - - /* - * Flag to stop simultaneous updates - */ - bool update_flag; - - /* Area selection radio buttons */ - Gtk::Box togglebox; - Gtk::RadioButton *selectiontype_buttons[SELECTION_NUMBER_OF]; - - Gtk::Box area_box; - Gtk::Box singleexport_box; - - /* Custom size widgets */ - Glib::RefPtr x0_adj; - Glib::RefPtr x1_adj; - Glib::RefPtr y0_adj; - Glib::RefPtr y1_adj; - Glib::RefPtr width_adj; - Glib::RefPtr height_adj; - - /* Bitmap size widgets */ - Glib::RefPtr bmwidth_adj; - Glib::RefPtr bmheight_adj; - Glib::RefPtr xdpi_adj; - Glib::RefPtr ydpi_adj; - - Gtk::Box size_box; - Gtk::Label* bm_label; - - Gtk::Box file_box; - Gtk::Label *flabel; - Gtk::Entry filename_entry; - - /* Unit selector widgets */ - Gtk::Box unitbox; - Inkscape::UI::Widget::UnitMenu unit_selector; - Gtk::Label units_label; - - /* Filename widgets */ - Gtk::Box filename_box; - Gtk::Button browse_button; - Gtk::Label browse_label; - Gtk::Image browse_image; - - Gtk::Box batch_box; - Gtk::CheckButton batch_export; - - Gtk::Box hide_box; - Gtk::CheckButton hide_export; - - Gtk::CheckButton closeWhenDone; - - /* Advanced */ - Gtk::Expander expander; - Gtk::CheckButton interlacing; - Gtk::Label bitdepth_label; - Inkscape::UI::Widget::ScrollProtected bitdepth_cb; - Gtk::Label zlib_label; - Inkscape::UI::Widget::ScrollProtected zlib_compression; - Gtk::Label pHYs_label; - Glib::RefPtr pHYs_adj; - Inkscape::UI::Widget::ScrollProtected pHYs_sb; - Gtk::Label antialiasing_label; - Inkscape::UI::Widget::ScrollProtected antialiasing_cb; - - /* Export Button widgets */ - Gtk::Box button_box; - Gtk::Button export_button; - - Gtk::ProgressBar _prog; - - ExportProgressDialog *prog_dlg; - bool interrupted; // indicates whether export needs to be interrupted (read: user pressed cancel in the progress dialog) - - Inkscape::Preferences *prefs; - sigc::connection selectChangedConn; - sigc::connection subselChangedConn; - sigc::connection selectModifiedConn; - sigc::connection unitChangedConn; - -}; - -} -} -} -#endif - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 01df3289fd..785e84b1ab 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -34,6 +34,7 @@ #include "io/resource.h" #include "io/sys.h" #include "message-stack.h" +#include "object/object-set.h" #include "object/sp-namedview.h" #include "object/sp-root.h" #include "preferences.h" @@ -93,6 +94,7 @@ Export::Export() setupUnits(); setupSpinButtons(); setupExtensionList(); + setupAdvance(); // Callback when container is dinally mapped on window. All intialisation like set active is done inside it. container->signal_map().connect(sigc::mem_fun(*this, &Export::onContainerVisible)); @@ -222,6 +224,8 @@ void Export::initialise_all() builder->get_widget("si_preview_box", si_preview_box); builder->get_widget("si_show_preview", si_show_preview); + builder->get_widget("si_advance_grid", advance_grid); + builder->get_widget("si_extention", extension_cb); builder->get_widget("si_filename", filename_entry); builder->get_widget("si_export", si_export); @@ -272,6 +276,77 @@ void Export::setupExtensionList() extension_list[extension] = manual_omod; } +void Export::setupAdvance() +{ + int row = 0; + std::vector labels; + { + interlacing.set_label("Use Interlacing"); + advance_grid->attach(interlacing, 0, row, 2, 1); + row++; + } + { + labels.insert(labels.end(), {"Gray_1", "Gray_2", "Gray_4", "Gray_8", "Gray_16", "RGB_8", "RGB_16", + "GrayAlpha_8", "GrayAlpha_16", "RGBA_8", "RGBA_16"}); + bit_depth_list.insert(bit_depth_list.end(), {1, 2, 4, 8, 16, 8, 16, 8, 16, 8, 16}); + + for (auto label : labels) { + bit_depth_cb.append(label); + } + labels.clear(); + + bit_depth_cb.set_active_text("RGBA_8"); + bit_depth_cb.set_hexpand(); + Gtk::Label *bit_depth_label = Gtk::manage(new Gtk::Label(_("Bit Depth"), Gtk::ALIGN_START)); + advance_grid->attach(*bit_depth_label, 0, row, 1, 1); + advance_grid->attach(bit_depth_cb, 1, row, 1, 1); + row++; + } + { + labels.insert(labels.end(), {"Z_NO_COMPRESSION", "Z_BEST_SPEED", "2", "3", "4", "5", "Z_DEFAULT_COMPRESSION", + "7", "8", "Z_BEST_COMPRESSION"}); + + compression_list.insert(compression_list.end(), {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + for (auto label : labels) { + compression_cb.append(label); + } + labels.clear(); + + compression_cb.set_active_text("Z_DEFAULT_COMPRESSION"); + Gtk::Label *compression_label = Gtk::manage(new Gtk::Label(_("Compression"), Gtk::ALIGN_START)); + advance_grid->attach(*compression_label, 0, row, 1, 1); + advance_grid->attach(compression_cb, 1, row, 1, 1); + row++; + } + + { + auto pHYs_adj = Gtk::Adjustment::create(0, 0, 100000, 0.1, 1.0, 0); + phys_dpi_sb.set_adjustment(pHYs_adj); + phys_dpi_sb.set_width_chars(7); + phys_dpi_sb.set_digits(2); + Gtk::Label *phys_dpi_label = Gtk::manage(new Gtk::Label(_("pHYs DPI"), Gtk::ALIGN_START)); + advance_grid->attach(*phys_dpi_label, 0, row, 1, 1); + advance_grid->attach(phys_dpi_sb, 1, row, 1, 1); + row++; + } + { + labels.insert(labels.end(), {"CAIRO_ANTIALIAS_NONE", "CAIRO_ANTIALIAS_FAST", "CAIRO_ANTIALIAS_GOOD (default)", + "CAIRO_ANTIALIAS_BEST"}); + anti_aliasing_list.insert(anti_aliasing_list.end(), {0, 1, 2, 3}); + + for (auto label : labels) { + anti_aliasing_cb.append(label); + } + labels.clear(); + + anti_aliasing_cb.set_active_text("CAIRO_ANTIALIAS_GOOD (default)"); + Gtk::Label *anti_aliasing_label = Gtk::manage(new Gtk::Label(_("Anti Aliasing"), Gtk::ALIGN_START)); + advance_grid->attach(*anti_aliasing_label, 0, row, 1, 1); + advance_grid->attach(anti_aliasing_cb, 1, row, 1, 1); + row++; + } +} + void Export::setupSpinButtons() { setupSpinButton(x0_sb, 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, @@ -537,6 +612,7 @@ void Export::setDefaultFilename() if (xdpi != 0.0) { dpi_sb->set_value(xdpi); } + refreshExportHints(); } void Export::refreshArea() @@ -699,8 +775,8 @@ void Export::onAreaTypeToggle(selection_mode key) if (!selection_buttons[key]->get_active()) { return; } - // If you have reached here means the current key is active one ( not sure if multiple transitions happen but last - // call will change values) + // If you have reached here means the current key is active one ( not sure if multiple transitions happen but + // last call will change values) current_key = key; prefs->setString("/dialogs/export/exportarea/value", selection_names[current_key]); refreshArea(); @@ -725,6 +801,8 @@ void Export::onFilenameModified() } else { filename_modified = true; } + std::cout << "Original Name: " << original_name << std::endl; + std::cout << "Filename Name: " << filename << std::endl; extension_cb->set_active_text(filtered_extension); @@ -753,10 +831,73 @@ void Export::onExtensionChanged() void Export::onExport() { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) { + si_export->set_sensitive(false); + bool exportSuccessful = false; + auto extension = extension_cb->get_active_text(); + if (!extension_list[extension]) { + si_export->set_sensitive(true); return; } + auto itemlist = SP_ACTIVE_DESKTOP->getSelection()->items(); + std::vector list; + for (auto i = itemlist.begin(); i != itemlist.end(); ++i) { + SPItem *item = *i; + list.push_back(item); + } + list.push_back(item); + if (extension_list[extension]->is_raster()) { + exportSuccessful = _export_raster(extension_list[extension]); + } else { + exportSuccessful = _export_vector(extension_list[extension]); + } + si_export->set_sensitive(true); +} + +bool Export::_export_raster(Inkscape::Extension::Output *extension, std::vector *items) +{ + std::cout << "Here" << std::endl; + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (!desktop) + return false; + SPNamedView *nv = desktop->getNamedView(); + SPDocument *doc = desktop->getDocument(); + unsigned long int width, height; + Glib::ustring filename; + float xdpi = 0.0, ydpi = 0.0; + float dpi = dpi_sb->get_value(); + if (items != nullptr) { + Inkscape::ObjectSet s(doc); + for (auto it = items->begin(); it != items->end(); ++it) { + s.add(*it, true); + } + auto area = s.visualBounds(); + width = area->width() * dpi / DPI_BASE + 0.5; + height = area->height() * dpi / DPI_BASE + 0.5; + + } else { + float x0, x1, y0, y1; + x0 = getValuePx(x0_sb->get_value()); + x1 = getValuePx(x1_sb->get_value()); + y0 = getValuePx(y0_sb->get_value()); + y1 = getValuePx(y1_sb->get_value()); + width = int(bmwidth_sb->get_value() + 0.5); + height = int(bmheight_sb->get_value() + 0.5); + } + + const float dpi = dpi_sb->get_value(); + + const bool hide = hide_all->get_active(); + + // Advance Parameters + const bool use_interlacing = interlacing.get_active(); + const float pHYs = (phys_dpi_sb.get_value() > 0.01) ? phys_dpi_sb.get_value() : dpi; + return true; +} + +bool Export::_export_vector(Inkscape::Extension::Output *extension, std::vector *items) +{ + ; + return true; } /** @@ -839,6 +980,13 @@ Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ust return filename; } +bool _export_raster(Inkscape::Extension::Output *extension, ){ + SPDesktop* desktop = SP_ACTIVE_DOCUMENT; + if(!desktop){ + return; + } +} + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index a64b68ad39..12efd6b83e 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -15,11 +15,10 @@ #include +#include "extension/output.h" #include "ui/dialog/dialog-base.h" #include "ui/widget/scrollprotected.h" #include "ui/widget/unit-menu.h" -#include "extension/output.h" - namespace Inkscape { namespace UI { @@ -90,6 +89,9 @@ private: Gtk::CheckButton *hide_all = nullptr; Gtk::Box *si_preview_box = nullptr; Gtk::CheckButton *si_show_preview = nullptr; + + Gtk::Grid *advance_grid = nullptr; + Gtk::ComboBoxText *extension_cb = nullptr; Gtk::Entry *filename_entry = nullptr; Gtk::Button *si_export = nullptr; @@ -100,7 +102,18 @@ private: Inkscape::Preferences *prefs = nullptr; std::map selection_names; selection_mode current_key; - std::map extension_list; + std::map extension_list; + + // Advanced + Gtk::CheckButton interlacing; + std::vector bit_depth_list; + std::vector color_list; + Inkscape::UI::Widget::ScrollProtected bit_depth_cb; + std::vector compression_list; + Inkscape::UI::Widget::ScrollProtected compression_cb; + Inkscape::UI::Widget::ScrollProtected phys_dpi_sb; + std::vector anti_aliasing_list; + Inkscape::UI::Widget::ScrollProtected anti_aliasing_cb; // Once user change filename it is set and prevent automatic changes to filename_entry bool filename_modified; @@ -114,6 +127,7 @@ private: // Add units from db void setupUnits(); void setupExtensionList(); + void setupAdvance(); // change range and callbacks to spinbuttons void setupSpinButtons(); @@ -140,6 +154,10 @@ private: void refreshExportHints(); void setArea(double x0, double y0, double x1, double y1); + // Export Functions + bool _export_raster(Inkscape::Extension::Output *extension = nullptr, std::vector *items = nullptr); + bool _export_vector(Inkscape::Extension::Output *extension = nullptr, std::vector *items = nullptr); + // signals callback void onContainerVisible(); void onAreaXChange(sb_type type); -- GitLab From 9c75870fc7d72feffc2870951654f3e4277134ca Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Wed, 30 Jun 2021 16:52:50 +0530 Subject: [PATCH 11/40] trying to separate code --- share/share | 1 + src/ui/dialog/export-helper.h | 38 ++++ src/ui/dialog/export-single.cpp | 62 ++++++ src/ui/dialog/export-single.h | 88 ++++++++ src/ui/dialog/export.cpp | 345 ++++++++++++++++++-------------- src/ui/dialog/export.h | 69 ++++--- 6 files changed, 424 insertions(+), 179 deletions(-) create mode 120000 share/share create mode 100644 src/ui/dialog/export-helper.h create mode 100644 src/ui/dialog/export-single.cpp create mode 100644 src/ui/dialog/export-single.h diff --git a/share/share b/share/share new file mode 120000 index 0000000000..159ed8186a --- /dev/null +++ b/share/share @@ -0,0 +1 @@ +/home/anshudhar2001/Desktop/inkscape/share \ No newline at end of file diff --git a/src/ui/dialog/export-helper.h b/src/ui/dialog/export-helper.h new file mode 100644 index 0000000000..241f0b8052 --- /dev/null +++ b/src/ui/dialog/export-helper.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Authors: + * Lauris Kaplinski + * bulia byak + * Johan Engelen + * + * Copyright (C) 1999-2007 Authors + * Copyright (C) 2001-2002 Ximian, Inc. + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SP_HELPER_H +#define SP_HELPER_H + +namespace Inkscape { +namespace UI { +namespace Dialog { + +#define EXPORT_COORD_PRECISION 3 +#define SP_EXPORT_MIN_SIZE 1.0 +#define DPI_BASE Inkscape::Util::Quantity::convert(1, "in", "px") + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp new file mode 100644 index 0000000000..4165b51962 --- /dev/null +++ b/src/ui/dialog/export-single.cpp @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Authors: + * Lauris Kaplinski + * bulia byak + * Johan Engelen + * + * Copyright (C) 1999-2007 Authors + * Copyright (C) 2001-2002 Ximian, Inc. + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "export-single.h" + +#include + +#include "export-helper.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { + +enum sb_type +{ + SPIN_X0 = 0, + SPIN_X1, + SPIN_Y0, + SPIN_Y1, + SPIN_WIDTH, + SPIN_HEIGHT, + SPIN_BMWIDTH, + SPIN_BMHEIGHT, + SPIN_DPI +}; + +enum selection_mode +{ + SELECTION_PAGE = 0, // Default is alaways placed first + SELECTION_SELECTION, + SELECTION_DRAWING, + SELECTION_CUSTOM, +}; + +void SingleExport::initialise(Glib::RefPtr *builder) +{ + ; +} + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/dialog/export-single.h b/src/ui/dialog/export-single.h new file mode 100644 index 0000000000..5cc787fb61 --- /dev/null +++ b/src/ui/dialog/export-single.h @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Authors: + * Lauris Kaplinski + * bulia byak + * Johan Engelen + * + * Copyright (C) 1999-2007 Authors + * Copyright (C) 2001-2002 Ximian, Inc. + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SP_EXPORT_SINGLE_H +#define SP_EXPORT_SINGLE_H + +#include + +#include "export-helper.h" +#include "extension/output.h" +#include "ui/dialog/dialog-base.h" +#include "ui/widget/scrollprotected.h" +#include "ui/widget/unit-menu.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { + +enum sb_type +{ + SPIN_X0 = 0, + SPIN_X1, + SPIN_Y0, + SPIN_Y1, + SPIN_WIDTH, + SPIN_HEIGHT, + SPIN_BMWIDTH, + SPIN_BMHEIGHT, + SPIN_DPI +}; + +enum selection_mode +{ + SELECTION_PAGE = 0, // Default is alaways placed first + SELECTION_SELECTION, + SELECTION_DRAWING, + SELECTION_CUSTOM, +}; + +class SingleExport : public Gtk::Box +{ +public: + SingleExport(); + ~SingleExport() override; + +public: + void initialise(Glib::RefPtr *builder); + +private: + // Single Image Objects Start Here + Gtk::Box *single_image = nullptr; + + std::map spin_buttons; + Gtk::CheckButton *show_export_area = nullptr; + Inkscape::UI::Widget::UnitMenu *units = nullptr; + + Gtk::CheckButton *si_hide_all = nullptr; + Gtk::Box *si_preview_box = nullptr; + Gtk::CheckButton *si_show_preview = nullptr; + + Gtk::ComboBoxText *si_extension_cb = nullptr; + Gtk::Entry *si_filename_entry = nullptr; + Gtk::Button *si_export = nullptr; +}; +} // namespace Dialog +} // namespace UI +} // namespace Inkscape +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 785e84b1ab..8676e437b6 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -50,10 +50,6 @@ #endif -#define EXPORT_COORD_PRECISION 3 -#define SP_EXPORT_MIN_SIZE 1.0 -#define DPI_BASE Inkscape::Util::Quantity::convert(1, "in", "px") - using Inkscape::Util::unit_table; namespace Inkscape { namespace UI { @@ -63,6 +59,7 @@ static std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring static void append_ext_to_filename(Glib::ustring &filename, Glib::ustring &extension); static Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension); static Glib::ustring get_ext_from_filename(Glib::ustring &filename); +static std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename); Export::Export() : DialogBase("/dialogs/export/", "Export") @@ -99,11 +96,12 @@ Export::Export() // Callback when container is dinally mapped on window. All intialisation like set active is done inside it. container->signal_map().connect(sigc::mem_fun(*this, &Export::onContainerVisible)); units->signal_changed().connect(sigc::mem_fun(*this, &Export::onUnitChanged)); - extension_cb->signal_changed().connect(sigc::mem_fun(*this, &Export::onExtensionChanged)); + si_extension_cb->signal_changed().connect(sigc::mem_fun(*this, &Export::onExtensionChanged)); for (auto [key, button] : selection_buttons) { button->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &Export::onAreaTypeToggle), key)); } - filenameChangedConn = filename_entry->signal_changed().connect(sigc::mem_fun(*this, &Export::onFilenameModified)); + filenameChangedConn = + si_filename_entry->signal_changed().connect(sigc::mem_fun(*this, &Export::onFilenameModified)); siExportConn = si_export->signal_clicked().connect(sigc::mem_fun(*this, &Export::onExport)); } @@ -112,6 +110,8 @@ Export::~Export() selectModifiedConn.disconnect(); subselChangedConn.disconnect(); selectChangedConn.disconnect(); + + delete advance_grid; } void Export::update() @@ -189,54 +189,42 @@ void Export::initialise_all() if (builder) { // Top container builder->get_widget("Export Dialog Box", container); - - // Notebook Start - { - builder->get_widget("Export Notebook", export_notebook); - // Single Image Start - { - builder->get_widget("Single Image", single_image); - - builder->get_widget("si_s_document", selection_buttons[SELECTION_DRAWING]); - selection_names[SELECTION_DRAWING] = "drawing"; - builder->get_widget("si_s_page", selection_buttons[SELECTION_PAGE]); - selection_names[SELECTION_PAGE] = "page"; - builder->get_widget("si_s_selection", selection_buttons[SELECTION_SELECTION]); - selection_names[SELECTION_SELECTION] = "selection"; - builder->get_widget("si_s_custom", selection_buttons[SELECTION_CUSTOM]); - selection_names[SELECTION_CUSTOM] = "custom"; - - builder->get_widget_derived("si_left_sb", x0_sb); - builder->get_widget_derived("si_right_sb", x1_sb); - builder->get_widget_derived("si_top_sb", y0_sb); - builder->get_widget_derived("si_bottom_sb", y1_sb); - builder->get_widget_derived("si_height_sb", height_sb); - builder->get_widget_derived("si_width_sb", width_sb); - - builder->get_widget_derived("si_img_height_sb", bmheight_sb); - builder->get_widget_derived("si_img_width_sb", bmwidth_sb); - builder->get_widget_derived("si_dpi_sb", dpi_sb); - - builder->get_widget("si_show_export_area", show_export_area); - builder->get_widget_derived("si_units", units); - - builder->get_widget("si_hide_all", hide_all); - builder->get_widget("si_preview_box", si_preview_box); - builder->get_widget("si_show_preview", si_show_preview); - - builder->get_widget("si_advance_grid", advance_grid); - - builder->get_widget("si_extention", extension_cb); - builder->get_widget("si_filename", filename_entry); - builder->get_widget("si_export", si_export); - } // Single Image End - - // Batch Export Start - { - builder->get_widget("Batch Export", batch_export); - } // Batch Export End - - } // Notebook End + builder->get_widget("Export Notebook", export_notebook); + + builder->get_widget("Single Image", single_image); + + builder->get_widget("si_s_document", selection_buttons[SELECTION_DRAWING]); + selection_names[SELECTION_DRAWING] = "drawing"; + builder->get_widget("si_s_page", selection_buttons[SELECTION_PAGE]); + selection_names[SELECTION_PAGE] = "page"; + builder->get_widget("si_s_selection", selection_buttons[SELECTION_SELECTION]); + selection_names[SELECTION_SELECTION] = "selection"; + builder->get_widget("si_s_custom", selection_buttons[SELECTION_CUSTOM]); + selection_names[SELECTION_CUSTOM] = "custom"; + + builder->get_widget_derived("si_left_sb", spin_buttons[SPIN_X0]); + builder->get_widget_derived("si_right_sb", spin_buttons[SPIN_X1]); + builder->get_widget_derived("si_top_sb", spin_buttons[SPIN_Y0]); + builder->get_widget_derived("si_bottom_sb", spin_buttons[SPIN_Y1]); + builder->get_widget_derived("si_height_sb", spin_buttons[SPIN_HEIGHT]); + builder->get_widget_derived("si_width_sb", spin_buttons[SPIN_WIDTH]); + + builder->get_widget_derived("si_img_height_sb", spin_buttons[SPIN_BMHEIGHT]); + builder->get_widget_derived("si_img_width_sb", spin_buttons[SPIN_BMWIDTH]); + builder->get_widget_derived("si_dpi_sb", spin_buttons[SPIN_DPI]); + + builder->get_widget("si_show_export_area", show_export_area); + builder->get_widget_derived("si_units", units); + + builder->get_widget("si_hide_all", si_hide_all); + builder->get_widget("si_preview_box", si_preview_box); + builder->get_widget("si_show_preview", si_show_preview); + + builder->get_widget("si_extention", si_extension_cb); + builder->get_widget("si_filename", si_filename_entry); + builder->get_widget("si_export", si_export); + + builder->get_widget("Batch Export", batch_export); } return; } @@ -264,7 +252,7 @@ void Export::setupExtensionList() continue; extension = omod->get_extension(); - extension_cb->append(extension); + si_extension_cb->append(extension); extension_list[extension] = omod; } @@ -272,12 +260,13 @@ void Export::setupExtensionList() Inkscape::Extension::Output *manual_omod; manual_omod = dynamic_cast(Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_SVG)); extension = manual_omod->get_extension(); - extension_cb->append(extension); + si_extension_cb->append(extension); extension_list[extension] = manual_omod; } void Export::setupAdvance() { + advance_grid = new Gtk::Grid; int row = 0; std::vector labels; { @@ -288,7 +277,10 @@ void Export::setupAdvance() { labels.insert(labels.end(), {"Gray_1", "Gray_2", "Gray_4", "Gray_8", "Gray_16", "RGB_8", "RGB_16", "GrayAlpha_8", "GrayAlpha_16", "RGBA_8", "RGBA_16"}); + bit_depth_list.clear(); bit_depth_list.insert(bit_depth_list.end(), {1, 2, 4, 8, 16, 8, 16, 8, 16, 8, 16}); + color_list.clear(); + color_list.insert(color_list.end(), {0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 6}); for (auto label : labels) { bit_depth_cb.append(label); @@ -305,7 +297,7 @@ void Export::setupAdvance() { labels.insert(labels.end(), {"Z_NO_COMPRESSION", "Z_BEST_SPEED", "2", "3", "4", "5", "Z_DEFAULT_COMPRESSION", "7", "8", "Z_BEST_COMPRESSION"}); - + compression_list.clear(); compression_list.insert(compression_list.end(), {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); for (auto label : labels) { compression_cb.append(label); @@ -332,6 +324,7 @@ void Export::setupAdvance() { labels.insert(labels.end(), {"CAIRO_ANTIALIAS_NONE", "CAIRO_ANTIALIAS_FAST", "CAIRO_ANTIALIAS_GOOD (default)", "CAIRO_ANTIALIAS_BEST"}); + anti_aliasing_list.clear(); anti_aliasing_list.insert(anti_aliasing_list.end(), {0, 1, 2, 3}); for (auto label : labels) { @@ -349,24 +342,26 @@ void Export::setupAdvance() void Export::setupSpinButtons() { - setupSpinButton(x0_sb, 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + setupSpinButton(spin_buttons[SPIN_X0], 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, &Export::onAreaXChange, SPIN_X0); - setupSpinButton(x1_sb, 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + setupSpinButton(spin_buttons[SPIN_X1], 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, &Export::onAreaXChange, SPIN_X1); - setupSpinButton(y0_sb, 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + setupSpinButton(spin_buttons[SPIN_Y0], 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, &Export::onAreaYChange, SPIN_Y0); - setupSpinButton(y1_sb, 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + setupSpinButton(spin_buttons[SPIN_Y1], 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, &Export::onAreaYChange, SPIN_Y1); - setupSpinButton(height_sb, 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, EXPORT_COORD_PRECISION, true, - &Export::onAreaYChange, SPIN_HEIGHT); - setupSpinButton(width_sb, 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, EXPORT_COORD_PRECISION, true, - &Export::onAreaXChange, SPIN_WIDTH); - - setupSpinButton(bmheight_sb, 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, &Export::onDpiChange, SPIN_BMHEIGHT); - setupSpinButton(bmwidth_sb, 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, &Export::onDpiChange, SPIN_BMWIDTH); - setupSpinButton(dpi_sb, prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), 0.01, 100000.0, - 0.1, 1.0, 2, true, &Export::onDpiChange, SPIN_DPI); + setupSpinButton(spin_buttons[SPIN_HEIGHT], 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, EXPORT_COORD_PRECISION, + true, &Export::onAreaYChange, SPIN_HEIGHT); + setupSpinButton(spin_buttons[SPIN_WIDTH], 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, EXPORT_COORD_PRECISION, + true, &Export::onAreaXChange, SPIN_WIDTH); + + setupSpinButton(spin_buttons[SPIN_BMHEIGHT], 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, &Export::onDpiChange, + SPIN_BMHEIGHT); + setupSpinButton(spin_buttons[SPIN_BMWIDTH], 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, &Export::onDpiChange, + SPIN_BMWIDTH); + setupSpinButton(spin_buttons[SPIN_DPI], prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), + 0.01, 100000.0, 0.1, 1.0, 2, true, &Export::onDpiChange, SPIN_DPI); } template @@ -407,9 +402,9 @@ void Export::setValuePx(Glib::RefPtr &adj, double val) void Export::areaXChange(sb_type type) { - auto x0_adj = x0_sb->get_adjustment(); - auto x1_adj = x1_sb->get_adjustment(); - auto width_adj = width_sb->get_adjustment(); + auto x0_adj = spin_buttons[SPIN_X0]->get_adjustment(); + auto x1_adj = spin_buttons[SPIN_X1]->get_adjustment(); + auto width_adj = spin_buttons[SPIN_WIDTH]->get_adjustment(); float x0, x1, dpi, width, bmwidth; @@ -417,8 +412,8 @@ void Export::areaXChange(sb_type type) x0 = getValuePx(x0_adj->get_value()); x1 = getValuePx(x1_adj->get_value()); width = getValuePx(width_adj->get_value()); - bmwidth = bmwidth_sb->get_value(); - dpi = dpi_sb->get_value(); + bmwidth = spin_buttons[SPIN_BMWIDTH]->get_value(); + dpi = spin_buttons[SPIN_DPI]->get_value(); switch (type) { case SPIN_X0: @@ -450,14 +445,14 @@ void Export::areaXChange(sb_type type) setValuePx(x0_adj, x0); setValuePx(x1_adj, x1); setValuePx(width_adj, width); - bmwidth_sb->set_value(bmwidth); + spin_buttons[SPIN_BMWIDTH]->set_value(bmwidth); } void Export::areaYChange(sb_type type) { - auto y0_adj = y0_sb->get_adjustment(); - auto y1_adj = y1_sb->get_adjustment(); - auto height_adj = height_sb->get_adjustment(); + auto y0_adj = spin_buttons[SPIN_Y0]->get_adjustment(); + auto y1_adj = spin_buttons[SPIN_Y1]->get_adjustment(); + auto height_adj = spin_buttons[SPIN_HEIGHT]->get_adjustment(); float y0, y1, dpi, height, bmheight; @@ -465,8 +460,8 @@ void Export::areaYChange(sb_type type) y0 = getValuePx(y0_adj->get_value()); y1 = getValuePx(y1_adj->get_value()); height = getValuePx(height_adj->get_value()); - bmheight = bmheight_sb->get_value(); - dpi = dpi_sb->get_value(); + bmheight = spin_buttons[SPIN_BMHEIGHT]->get_value(); + dpi = spin_buttons[SPIN_DPI]->get_value(); switch (type) { case SPIN_Y0: @@ -498,7 +493,7 @@ void Export::areaYChange(sb_type type) setValuePx(y0_adj, y0); setValuePx(y1_adj, y1); setValuePx(height_adj, height); - bmheight_sb->set_value(bmheight); + spin_buttons[SPIN_BMHEIGHT]->set_value(bmheight); } void Export::dpiChange(sb_type type) @@ -506,11 +501,11 @@ void Export::dpiChange(sb_type type) float dpi, height, width, bmheight, bmwidth; // Get all values in px - height = getValuePx(height_sb->get_value()); - width = getValuePx(width_sb->get_value()); - bmheight = bmheight_sb->get_value(); - bmwidth = bmwidth_sb->get_value(); - dpi = dpi_sb->get_value(); + height = getValuePx(spin_buttons[SPIN_HEIGHT]->get_value()); + width = getValuePx(spin_buttons[SPIN_WIDTH]->get_value()); + bmheight = spin_buttons[SPIN_BMHEIGHT]->get_value(); + bmwidth = spin_buttons[SPIN_BMWIDTH]->get_value(); + dpi = spin_buttons[SPIN_DPI]->get_value(); switch (type) { case SPIN_BMHEIGHT: @@ -535,9 +530,9 @@ void Export::dpiChange(sb_type type) bmwidth = floor(width * dpi / DPI_BASE + 0.5); bmheight = floor(height * dpi / DPI_BASE + 0.5); - bmheight_sb->set_value(bmheight); - bmwidth_sb->set_value(bmwidth); - dpi_sb->set_value(dpi); + spin_buttons[SPIN_BMHEIGHT]->set_value(bmheight); + spin_buttons[SPIN_BMWIDTH]->set_value(bmwidth); + spin_buttons[SPIN_DPI]->set_value(dpi); } void Export::blockSpinConns(bool status = true) @@ -555,7 +550,7 @@ void Export::setDefaultNotebookPage() { // if (export_notebook && batch_export) { // auto page_num = export_notebook->page_num(*batch_export); - // export_notebook->set_current_page(page_num); + // export_notebook->set_current_page(page_num); // } } @@ -600,17 +595,17 @@ void Export::setDefaultFilename() SPDocument *doc = SP_ACTIVE_DOCUMENT; sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); if (filename.empty()) { - Glib::ustring filename_entry_text = filename_entry->get_text(); + Glib::ustring filename_entry_text = si_filename_entry->get_text(); Glib::ustring extention_entry_text = ".png"; filename = get_default_filename(filename_entry_text, extention_entry_text); } doc_export_name = filename; original_name = filename; - filename_entry->set_text(filename); - filename_entry->set_position(filename.length()); + si_filename_entry->set_text(filename); + si_filename_entry->set_position(filename.length()); // We only need to check xdpi if (xdpi != 0.0) { - dpi_sb->set_value(xdpi); + spin_buttons[SPIN_DPI]->set_value(xdpi); } refreshExportHints(); } @@ -661,8 +656,8 @@ void Export::refreshExportHints() case SELECTION_DRAWING: sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); if (filename.empty()) { - Glib::ustring filename_entry_text = filename_entry->get_text(); - Glib::ustring extension_entry_text = extension_cb->get_active_text(); + Glib::ustring filename_entry_text = si_filename_entry->get_text(); + Glib::ustring extension_entry_text = si_extension_cb->get_active_text(); filename = get_default_filename(filename_entry_text, extension_entry_text); } doc_export_name = filename; @@ -685,8 +680,8 @@ void Export::refreshExportHints() break; } } - filename = create_filepath_from_id(id, filename_entry->get_text()); - filename = filename + extension_cb->get_active_text(); + filename = create_filepath_from_id(id, si_filename_entry->get_text()); + filename = filename + si_extension_cb->get_active_text(); } break; default: @@ -694,12 +689,12 @@ void Export::refreshExportHints() } if (!filename.empty()) { original_name = filename; - filename_entry->set_text(filename); - filename_entry->set_position(filename.length()); + si_filename_entry->set_text(filename); + si_filename_entry->set_position(filename.length()); } if (xdpi != 0.0) { - dpi_sb->set_value(xdpi); + spin_buttons[SPIN_DPI]->set_value(xdpi); } } } @@ -708,10 +703,10 @@ void Export::setArea(double x0, double y0, double x1, double y1) { blockSpinConns(true); - auto x0_adj = x0_sb->get_adjustment(); - auto x1_adj = x1_sb->get_adjustment(); - auto y0_adj = y0_sb->get_adjustment(); - auto y1_adj = y1_sb->get_adjustment(); + auto x0_adj = spin_buttons[SPIN_X0]->get_adjustment(); + auto x1_adj = spin_buttons[SPIN_X1]->get_adjustment(); + auto y0_adj = spin_buttons[SPIN_Y0]->get_adjustment(); + auto y1_adj = spin_buttons[SPIN_Y1]->get_adjustment(); setValuePx(x1_adj, x1); setValuePx(y1_adj, y1); @@ -747,7 +742,7 @@ void Export::onContainerVisible() setDefaultNotebookPage(); setDefaultSelectionMode(); setDefaultFilename(); - extension_cb->set_active(0); + si_extension_cb->set_active(0); } void Export::onAreaXChange(sb_type type) @@ -791,9 +786,9 @@ void Export::onUnitChanged() void Export::onFilenameModified() { filenameChangedConn.block(); - Glib::ustring filename = filename_entry->get_text(); + Glib::ustring filename = si_filename_entry->get_text(); Glib::ustring filename_extension = get_ext_from_filename(filename); - Glib::ustring active_extension = extension_cb->get_active_text(); + Glib::ustring active_extension = si_extension_cb->get_active_text(); Glib::ustring filtered_extension = getValidExtension(filename_extension, active_extension); if (original_name == filename) { @@ -804,7 +799,7 @@ void Export::onFilenameModified() std::cout << "Original Name: " << original_name << std::endl; std::cout << "Filename Name: " << filename << std::endl; - extension_cb->set_active_text(filtered_extension); + si_extension_cb->set_active_text(filtered_extension); filenameChangedConn.unblock(); } @@ -812,9 +807,9 @@ void Export::onFilenameModified() void Export::onExtensionChanged() { filenameChangedConn.block(); - Glib::ustring filename = filename_entry->get_text(); + Glib::ustring filename = si_filename_entry->get_text(); Glib::ustring filename_extension = get_ext_from_filename(filename); - Glib::ustring active_extension = extension_cb->get_active_text(); + Glib::ustring active_extension = si_extension_cb->get_active_text(); if (filename_extension == active_extension) { return; } @@ -823,74 +818,111 @@ void Export::onExtensionChanged() filename.erase(extension_point); } filename = filename + active_extension; - filename_entry->set_text(filename); - filename_entry->set_position(filename.length()); + si_filename_entry->set_text(filename); + si_filename_entry->set_position(filename.length()); filenameChangedConn.unblock(); } +// Single Export Callback. +// Do not add batch export widgets check here void Export::onExport() { + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (!desktop) + return; si_export->set_sensitive(false); bool exportSuccessful = false; - auto extension = extension_cb->get_active_text(); + auto extension = si_extension_cb->get_active_text(); if (!extension_list[extension]) { si_export->set_sensitive(true); return; } - auto itemlist = SP_ACTIVE_DESKTOP->getSelection()->items(); - std::vector list; - for (auto i = itemlist.begin(); i != itemlist.end(); ++i) { - SPItem *item = *i; - list.push_back(item); - } - list.push_back(item); if (extension_list[extension]->is_raster()) { - exportSuccessful = _export_raster(extension_list[extension]); + double x0 = getValuePx(spin_buttons[SPIN_X0]->get_value()); + double x1 = getValuePx(spin_buttons[SPIN_X1]->get_value()); + double y0 = getValuePx(spin_buttons[SPIN_Y0]->get_value()); + double y1 = getValuePx(spin_buttons[SPIN_Y1]->get_value()); + auto area = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * desktop->dt2doc(); + + int width = int(spin_buttons[SPIN_BMWIDTH]->get_value() + 0.5); + int height = int(spin_buttons[SPIN_BMHEIGHT]->get_value() + 0.5); + + double dpi = spin_buttons[SPIN_DPI]->get_value(); + + Glib::ustring filename = si_filename_entry->get_text(); + + exportSuccessful = _export_raster(area, width, height, dpi, filename, extension_list[extension]); + } else { exportSuccessful = _export_vector(extension_list[extension]); } si_export->set_sensitive(true); } -bool Export::_export_raster(Inkscape::Extension::Output *extension, std::vector *items) +bool Export::_export_raster(Geom::Rect const &area, unsigned long int const &width, unsigned long int const &height, + float const &dpi, Glib::ustring const &filename, bool overwrite, + Inkscape::Extension::Output *extension) { - std::cout << "Here" << std::endl; SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop) return false; SPNamedView *nv = desktop->getNamedView(); SPDocument *doc = desktop->getDocument(); - unsigned long int width, height; - Glib::ustring filename; - float xdpi = 0.0, ydpi = 0.0; - float dpi = dpi_sb->get_value(); - if (items != nullptr) { - Inkscape::ObjectSet s(doc); - for (auto it = items->begin(); it != items->end(); ++it) { - s.add(*it, true); - } - auto area = s.visualBounds(); - width = area->width() * dpi / DPI_BASE + 0.5; - height = area->height() * dpi / DPI_BASE + 0.5; - } else { - float x0, x1, y0, y1; - x0 = getValuePx(x0_sb->get_value()); - x1 = getValuePx(x1_sb->get_value()); - y0 = getValuePx(y0_sb->get_value()); - y1 = getValuePx(y1_sb->get_value()); - width = int(bmwidth_sb->get_value() + 0.5); - height = int(bmheight_sb->get_value() + 0.5); + if (area.hasZeroArea() || width == 0 || height == 0) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("The chosen area to be exported is invalid.")); + sp_ui_error_dialog(_("The chosen area to be exported is invalid")); + return false; + } + if (filename.empty()) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You have to enter a filename.")); + sp_ui_error_dialog(_("You have to enter a filename")); + return false; } - const float dpi = dpi_sb->get_value(); - - const bool hide = hide_all->get_active(); + if (!extension || !extension->is_raster()) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Raster Export Error")); + sp_ui_error_dialog(_("Raster export Method is used for NON RASTER EXTENSION")); + return false; + } // Advance Parameters const bool use_interlacing = interlacing.get_active(); const float pHYs = (phys_dpi_sb.get_value() > 0.01) ? phys_dpi_sb.get_value() : dpi; + const int color_type = color_list[bit_depth_cb.get_active_row_number()]; + const int bit_depth = bit_depth_list[bit_depth_cb.get_active_row_number()]; + const int antialiasing = anti_aliasing_list[anti_aliasing_cb.get_active_row_number()]; + const int zlib = compression_list[compression_cb.get_active_row_number()]; + + std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(filename)); + Glib::ustring dirname = Glib::path_get_dirname(path); + + if (dirname.empty() || + !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { + gchar *safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); + gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), safeDir); + + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); + sp_ui_error_dialog(error); + + g_free(safeDir); + g_free(error); + return false; + } + + // Do the over-write protection now, since the png is just a temp file. + if (!overwrite && !sp_ui_overwrite_file(filename.c_str())) { + return false; + } + + auto fn = Glib::path_get_basename(path); + auto png_filename = std::string(path.c_str()); + // Select the extension and set the filename to a temporary file + int tempfd_out = Glib::file_open_tmp(png_filename, "ink_ext_"); + close(tempfd_out); + + return true; } @@ -980,11 +1012,20 @@ Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ust return filename; } -bool _export_raster(Inkscape::Extension::Output *extension, ){ - SPDesktop* desktop = SP_ACTIVE_DOCUMENT; - if(!desktop){ - return; +std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename) +{ + std::string path; + // Make relative paths go from the document location, if possible: + if (!Glib::path_is_absolute(filename) && doc->getDocumentFilename()) { + auto dirname = Glib::path_get_dirname(doc->getDocumentFilename()); + if (!dirname.empty()) { + path = Glib::build_filename(dirname, filename); + } + } + if (path.empty()) { + path = filename; } + return path; } } // namespace Dialog diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 12efd6b83e..21a8c3b795 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -24,6 +24,10 @@ namespace Inkscape { namespace UI { namespace Dialog { +#define EXPORT_COORD_PRECISION 3 +#define SP_EXPORT_MIN_SIZE 1.0 +#define DPI_BASE Inkscape::Util::Quantity::convert(1, "in", "px") + enum sb_type { SPIN_X0 = 0, @@ -45,6 +49,12 @@ enum selection_mode SELECTION_CUSTOM, }; +enum notebook_page +{ + SINGLE_IMAGE = 0, + BATCH_EXPORT +}; + class ExportProgressDialog; /** @@ -62,48 +72,42 @@ public: static Export &getInstance() { return *new Export(); } +private: + typedef Inkscape::UI::Widget::ScrollProtected SpinButton; + private: // builder and its object ( in order ) Glib::RefPtr builder; Gtk::Box *container = nullptr; Gtk::Notebook *export_notebook = nullptr; - Gtk::Box *single_image = nullptr; - + // These are toggle radio buttons. std::map selection_buttons; + // These are spin buttons in the dialog. + std::map spin_buttons; - Inkscape::UI::Widget::ScrollProtected *x0_sb = nullptr; - Inkscape::UI::Widget::ScrollProtected *x1_sb = nullptr; - Inkscape::UI::Widget::ScrollProtected *y0_sb = nullptr; - Inkscape::UI::Widget::ScrollProtected *y1_sb = nullptr; - Inkscape::UI::Widget::ScrollProtected *height_sb = nullptr; - Inkscape::UI::Widget::ScrollProtected *width_sb = nullptr; - - Inkscape::UI::Widget::ScrollProtected *bmheight_sb = nullptr; - Inkscape::UI::Widget::ScrollProtected *bmwidth_sb = nullptr; - Inkscape::UI::Widget::ScrollProtected *dpi_sb = nullptr; +private: + // Single Image Objects Start Here + Gtk::Box *single_image = nullptr; Gtk::CheckButton *show_export_area = nullptr; Inkscape::UI::Widget::UnitMenu *units = nullptr; - Gtk::CheckButton *hide_all = nullptr; + Gtk::CheckButton *si_hide_all = nullptr; Gtk::Box *si_preview_box = nullptr; Gtk::CheckButton *si_show_preview = nullptr; - Gtk::Grid *advance_grid = nullptr; - - Gtk::ComboBoxText *extension_cb = nullptr; - Gtk::Entry *filename_entry = nullptr; + Gtk::ComboBoxText *si_extension_cb = nullptr; + Gtk::Entry *si_filename_entry = nullptr; Gtk::Button *si_export = nullptr; +private: + // Batch Export Start Here Gtk::Box *batch_export = nullptr; - // Utils Variables - Inkscape::Preferences *prefs = nullptr; - std::map selection_names; - selection_mode current_key; - std::map extension_list; - +private: + // Grid to store advance options. We put this grid inside the Box of advance expander where needed. + Gtk::Grid *advance_grid = nullptr; // Advanced Gtk::CheckButton interlacing; std::vector bit_depth_list; @@ -115,12 +119,21 @@ private: std::vector anti_aliasing_list; Inkscape::UI::Widget::ScrollProtected anti_aliasing_cb; +private: // Once user change filename it is set and prevent automatic changes to filename_entry - bool filename_modified; + bool filename_modified; // Batch doesnt need this // original name for export. Changes everytime selection changes or when exported. - Glib::ustring original_name; + Glib::ustring original_name; // Batch Doesnt need this // initialised only at startup and is used as fallback for original name. - Glib::ustring doc_export_name; + Glib::ustring doc_export_name; // Batch Doesnt Need this maybe + +private: + // Utils Variables + Inkscape::Preferences *prefs = nullptr; + // Selection Names for setting prefs + std::map selection_names; + selection_mode current_key; + std::map extension_list; // Initialise all objects from builder void initialise_all(); @@ -155,7 +168,9 @@ private: void setArea(double x0, double y0, double x1, double y1); // Export Functions - bool _export_raster(Inkscape::Extension::Output *extension = nullptr, std::vector *items = nullptr); + bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsigned long int const &height, + float const &dpi, Glib::ustring const &filename, bool overwrite, + Inkscape::Extension::Output *extension); bool _export_vector(Inkscape::Extension::Output *extension = nullptr, std::vector *items = nullptr); // signals callback -- GitLab From bbddc17dbde998275c90d9ce2236a3458df14384 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Thu, 1 Jul 2021 18:00:49 +0530 Subject: [PATCH 12/40] separated pages and created helper --- share/ui/dialog-export.glade | 637 +++++++++++---------- src/ui/CMakeLists.txt | 4 + src/ui/dialog/export-helper.cpp | 323 +++++++++++ src/ui/dialog/export-helper.h | 100 +++- src/ui/dialog/export-single.cpp | 642 ++++++++++++++++++++- src/ui/dialog/export-single.h | 125 +++- src/ui/dialog/export.cpp | 980 +++----------------------------- src/ui/dialog/export.h | 135 +---- 8 files changed, 1576 insertions(+), 1370 deletions(-) create mode 100644 src/ui/dialog/export-helper.cpp diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index f000b4290e..ad3fecc784 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -1,99 +1,100 @@ - + True - False - False + False + False vertical True True - False - False - False + False + False + False True - False - False + False + False vertical 5 True - True - False + True + False True - never - always - True + never + always + True True - False - False - natural - none + False + False + natural + none + True - False - 5 - 10 + False + 5 + 10 True - True + True True - False + False - 2 - 2 + 2 + 2 True - True + True True - 4 - 4 + 4 + 4 True - True + True True - 2 - 6 + 2 + 6 True - True + True True - 4 - 6 + 4 + 6 True - False - 5 - 5 + False + 5 + 5 Image Size 0 @@ -101,40 +102,40 @@ - 1 - 8 + 1 + 8 5 True - True + True center True - 4 - 10 + 4 + 10 True - False - False - 5 + False + False + 5 True - expand + expand Document True - False - False - False + False + False + False True - False + False True @@ -146,9 +147,9 @@ Page True - False - False - False + False + False + False si_s_document @@ -161,9 +162,9 @@ Selection True - False - False - False + False + False + False si_s_document @@ -176,71 +177,35 @@ Custom True - False - False - False + False + False + False si_s_document True True - 3 + 4 - 0 - 0 + 0 + 0 7 - - - True - True - 10 - 10 - True - - - True - False - 10 - 5 - 5 - 5 - - - - - - - - True - False - 10 - Advance - True - - - - - 1 - 14 - 5 - - True - False + False Show Export True - True - False - True + True + False + True False @@ -251,14 +216,14 @@ True - False + False end True 5 True - False + False Units True 0 @@ -272,7 +237,7 @@ True - False + False 1 @@ -290,36 +255,36 @@ - 1 - 7 + 1 + 7 5 True - True + True center True - 2 - 10 + 2 + 10 True - False + False 20 - 150 - 150 + 150 + 150 True - False - 150 - face-smile + False + 150 + face-smile 6 @@ -331,16 +296,16 @@ True - False + False center vertical Preview True - True - False - True + True + False + True False @@ -352,9 +317,9 @@ Hide All True - True - False - True + True + False + True False @@ -366,168 +331,183 @@ True True - end + end 1 - 1 - 13 + 1 + 13 5 True - True + True True - 4 - 2 + 4 + 2 True - True + True True - 2 - 4 + 2 + 4 True - True + True start True - 2 - 12 + 2 + 12 True - False + False DPI True 0 - 1 - 12 + 1 + 12 True - False + False Height (px) True 0 - 3 - 10 + 3 + 10 True - False + False Width (px) True 0 - 1 - 10 + 1 + 10 True - False + False Height True 0 - 3 - 6 + 3 + 6 True - False + False Width True 0 - 1 - 6 + 1 + 6 True - False + False Bottom True 0 - 3 - 4 + 3 + 4 True - False + False Right True 0 - 1 - 4 + 1 + 4 True - False + False Top True 0 - 3 - 2 + 3 + 2 True - False + False Left True 0 - 1 - 2 + 1 + 2 + + + + + True + False + vertical + + + + + + 1 + 14 + 5 @@ -722,48 +702,67 @@ + True - False - 10 + False + 10 True - True + True True - folder-open - Filename + folder-open + Filename - 0 - 0 + 0 + 0 True - False + False center 0 - 1 - 0 + 1 + 0 Export True - False - False + False + False end - 2 - 0 + 2 + 0 + + + + + + + + + + + + + + + + + + False @@ -779,139 +778,140 @@ True - False - False + False + False Single Image right - False + False True - False - False + False + False vertical True - True + True True - never - always - False - True + never + always + False + True True - False - none + False + none + True - False + False vertical - 10 - 10 + 10 + 10 - 150 + 150 True - True + True True - never - in + never + in True - False + False True - False + False True - 10 - 10 - 10 - none + 10 + 10 + 10 + none - 50 - 50 + 50 + 50 True - True + True True - False - 50 - face-glasses + False + 50 + face-glasses - 100 - 80 + 100 + 80 True - True + True True - False - 50 - face-glasses + False + 50 + face-glasses - 100 - 80 + 100 + 80 True - True + True True - False - 50 - face-glasses + False + 50 + face-glasses - 100 - 80 + 100 + 80 True - True + True True - False - 50 - face-glasses + False + 50 + face-glasses - 100 - 80 + 100 + 80 True - True + True True - False - 50 - face-glasses + False + 50 + face-glasses @@ -922,25 +922,25 @@ - 1 - 1 + 1 + 1 5 True - False + False True - expand + expand Selection True - False - False + False + False True - False + False True @@ -952,10 +952,10 @@ Layers True - False - False + False + False True - False + False radiobutton2 @@ -966,8 +966,8 @@ - 0 - 0 + 0 + 0 7 @@ -975,106 +975,128 @@ Preview True - True - False - True + True + False + True - 1 - 2 + 1 + 2 2 True - False + False 5 Items - 5 - 2 + 5 + 2 Hide All Except Selected True - True - False - True + True + False + True - 1 - 5 + 1 + 5 5 True - True - 10 - 10 + True + 10 + 10 5 - True + True + True - False - 10 - 5 + False + 10 + 5 checkbutton True - True - False - 10 - True + True + False + 10 + True - 0 - 0 + 0 + 0 checkbutton True - True - False - True + True + False + True - 0 - 1 + 0 + 1 + + + + + + + + + + + + + + + + + + + + + True - False - 5 + False + 5 Advance True - 1 - 6 + 1 + 6 5 True - True - False - False + True + False + False @@ -1101,8 +1123,8 @@ - 1 - 3 + 1 + 3 5 2 @@ -1161,40 +1183,59 @@ + True - False - 5 - 5 - 10 + False + 5 + 5 + 10 True - True + True True - folder-open - Filename + folder-open + Filename - 0 - 0 + 0 + 0 Export True - True - True + True + True - 2 - 0 + 2 + 0 + + + + + + + + + + + + + + + + + + False @@ -1210,14 +1251,14 @@ True - False - False + False + False Batch Export right 1 - False + False diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 12ef2a3fab..aa4f2ce334 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -112,6 +112,8 @@ set(ui_SRC dialog/dialog-window.cpp dialog/document-properties.cpp dialog/export.cpp + dialog/export-single.cpp + dialog/export-helper.cpp dialog/filedialog.cpp dialog/filedialogimpl-gtkmm.cpp dialog/fill-and-stroke.cpp @@ -285,6 +287,8 @@ set(ui_SRC dialog/dialog-window.h dialog/document-properties.h dialog/export.h + dialog/export-single.h + dialog/export-helper.h dialog/filedialog.h dialog/filedialogimpl-gtkmm.h dialog/filedialogimpl-win32.h diff --git a/src/ui/dialog/export-helper.cpp b/src/ui/dialog/export-helper.cpp new file mode 100644 index 0000000000..cb85142918 --- /dev/null +++ b/src/ui/dialog/export-helper.cpp @@ -0,0 +1,323 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Authors: + * Lauris Kaplinski + * bulia byak + * Johan Engelen + * + * Copyright (C) 1999-2007 Authors + * Copyright (C) 2001-2002 Ximian, Inc. + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "export-helper.h" + +#include +#include +#include +#include +#include + +#include "desktop.h" +#include "document-undo.h" +#include "document.h" +#include "extension/db.h" +#include "file.h" +#include "helper/png-write.h" +#include "inkscape-window.h" +#include "inkscape.h" +#include "io/resource.h" +#include "io/sys.h" +#include "message-stack.h" +#include "object/object-set.h" +#include "object/sp-namedview.h" +#include "object/sp-root.h" +#include "preferences.h" +#include "selection-chemistry.h" +#include "ui/dialog-events.h" +#include "ui/dialog/dialog-notebook.h" +#include "ui/dialog/filedialog.h" +#include "ui/interface.h" +#include "ui/widget/scrollprotected.h" +#include "ui/widget/unit-menu.h" + +#ifdef _WIN32 + +#endif + +using Inkscape::Util::unit_table; + +namespace Inkscape { +namespace UI { +namespace Dialog { + +AdvanceOptions::AdvanceOptions() + : row(0) +{ + this->set_label(_("Advance")); + Gtk::Grid *grid = Gtk::manage(new Gtk::Grid()); + this->add(*grid); + std::vector labels; + { + interlacing.set_label("Use Interlacing"); + grid->attach(interlacing, 0, row, 2, 1); + row++; + } + { + labels.insert(labels.end(), {"Gray_1", "Gray_2", "Gray_4", "Gray_8", "Gray_16", "RGB_8", "RGB_16", + "GrayAlpha_8", "GrayAlpha_16", "RGBA_8", "RGBA_16"}); + bit_depth_list.clear(); + bit_depth_list.insert(bit_depth_list.end(), {1, 2, 4, 8, 16, 8, 16, 8, 16, 8, 16}); + color_list.clear(); + color_list.insert(color_list.end(), {0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 6}); + + for (auto label : labels) { + bit_depth_cb.append(label); + } + labels.clear(); + + bit_depth_cb.set_active_text("RGBA_8"); + bit_depth_cb.set_hexpand(); + Gtk::Label *bit_depth_label = Gtk::manage(new Gtk::Label(_("Bit Depth"), Gtk::ALIGN_START)); + grid->attach(*bit_depth_label, 0, row, 1, 1); + grid->attach(bit_depth_cb, 1, row, 1, 1); + row++; + } + { + labels.insert(labels.end(), {"Z_NO_COMPRESSION", "Z_BEST_SPEED", "2", "3", "4", "5", "Z_DEFAULT_COMPRESSION", + "7", "8", "Z_BEST_COMPRESSION"}); + compression_list.clear(); + compression_list.insert(compression_list.end(), {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + for (auto label : labels) { + compression_cb.append(label); + } + labels.clear(); + + compression_cb.set_active_text("Z_DEFAULT_COMPRESSION"); + Gtk::Label *compression_label = Gtk::manage(new Gtk::Label(_("Compression"), Gtk::ALIGN_START)); + grid->attach(*compression_label, 0, row, 1, 1); + grid->attach(compression_cb, 1, row, 1, 1); + row++; + } + + { + auto pHYs_adj = Gtk::Adjustment::create(0, 0, 100000, 0.1, 1.0, 0); + pHYs_sb.set_adjustment(pHYs_adj); + pHYs_sb.set_width_chars(7); + pHYs_sb.set_digits(2); + Gtk::Label *phys_dpi_label = Gtk::manage(new Gtk::Label(_("pHYs DPI"), Gtk::ALIGN_START)); + grid->attach(*phys_dpi_label, 0, row, 1, 1); + grid->attach(pHYs_sb, 1, row, 1, 1); + row++; + } + { + labels.insert(labels.end(), {"CAIRO_ANTIALIAS_NONE", "CAIRO_ANTIALIAS_FAST", "CAIRO_ANTIALIAS_GOOD (default)", + "CAIRO_ANTIALIAS_BEST"}); + anti_aliasing_list.clear(); + anti_aliasing_list.insert(anti_aliasing_list.end(), {0, 1, 2, 3}); + + for (auto label : labels) { + anti_aliasing_cb.append(label); + } + labels.clear(); + + anti_aliasing_cb.set_active_text("CAIRO_ANTIALIAS_GOOD (default)"); + Gtk::Label *anti_aliasing_label = Gtk::manage(new Gtk::Label(_("Anti Aliasing"), Gtk::ALIGN_START)); + grid->attach(*anti_aliasing_label, 0, row, 1, 1); + grid->attach(anti_aliasing_cb, 1, row, 1, 1); + row++; + } + std::cout<<"Advance Created"< ExtensionList::valid_extensions{}; +std::map ExtensionList::all_extensions{}; + +void ExtensionList::setup() +{ + this->remove_all(); + createList(); + + for (auto [key, omod] : valid_extensions) { + this->append(key); + } + this->set_active(0); +} +void ExtensionList::createList() +{ + if (list_created) { + return; + } + Inkscape::Extension::DB::OutputList extensions; + Inkscape::Extension::db.get_output_list(extensions); + Glib::ustring extension; + for (auto omod : extensions) { + all_extensions[omod->get_extension()] = omod; + + // FIXME: would be nice to grey them out instead of not listing them + if (omod->deactivated() || (omod->is_raster() != true)) + continue; + + extension = omod->get_extension(); + valid_extensions[extension] = omod; + } + + // add extentions manually + Inkscape::Extension::Output *manual_omod; + manual_omod = dynamic_cast(Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_SVG)); + extension = manual_omod->get_extension(); + valid_extensions[extension] = manual_omod; + + list_created = true; +} + +ExtensionList::~ExtensionList() +{ + ; +} +void ExtensionList::setExtensionFromFilename(Glib::ustring const &filename) +{ + Glib::ustring extension = get_ext_from_filename(filename); + if (valid_extensions[extension]) { + this->set_active_text(extension); + return; + } +} +void ExtensionList::appendExtensionToFilename(Glib::ustring &filename) +{ + Glib::ustring filename_extension = get_ext_from_filename(filename); + Glib::ustring active_extension = this->get_active_text(); + if (active_extension == filename_extension) { + return; + } + if (valid_extensions[filename_extension]) { + auto extension_point = filename.rfind(filename_extension); + filename.erase(extension_point); + } + filename = filename + active_extension; + return; +} +void ExtensionList::appendExtensionToFilename(Glib::ustring &filename, Glib::ustring &extension) +{ + createList(); + Glib::ustring filename_extension = get_ext_from_filename(filename); + Glib::ustring active_extension = extension; + if (all_extensions[filename_extension]) { + auto extension_point = filename.rfind(filename_extension); + filename.erase(extension_point); + } + if (valid_extensions[filename_extension]) { + active_extension = filename_extension; + } + if (!valid_extensions[active_extension]) { + active_extension = ".png"; + } + filename = filename + active_extension; + return; +} + +float getValuePx(float value, Unit const *unit) +{ + return Inkscape::Util::Quantity::convert(value, unit, "px"); +} + +void setValuePx(Glib::RefPtr &adj, double val, Unit const *unit) +{ + auto value = Inkscape::Util::Quantity::convert(val, "px", unit); + adj->set_value(value); + return; +} + +// We Create filename by removing already present extension in document name and replacing it with extension passed as +// parameter if exxtension is not valid. If document doesn't have a name we use bitmap as defalt name. +Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension) +{ + Glib::ustring filename; + if (SP_ACTIVE_DOCUMENT && SP_ACTIVE_DOCUMENT->getDocumentFilename()) { + SPDocument *doc = SP_ACTIVE_DOCUMENT; + filename = doc->getDocumentFilename(); + + ExtensionList::appendExtensionToFilename(filename, extension); + + } else if (SP_ACTIVE_DOCUMENT) { + filename = create_filepath_from_id(_("bitmap"), filename_entry_text); + filename = filename + extension; + } + return filename; +} + +std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_entry_text) +{ + if (id.empty()) { /* This should never happen */ + id = "bitmap"; + } + + std::string directory; + + if (!file_entry_text.empty()) { + directory = Glib::path_get_dirname(Glib::filename_from_utf8(file_entry_text)); + } + + if (directory.empty()) { + /* Grab document directory */ + const gchar *docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); + if (docFilename) { + directory = Glib::path_get_dirname(docFilename); + } + } + + if (directory.empty()) { + directory = Inkscape::IO::Resource::homedir_path(nullptr); + } + + return Glib::build_filename(directory, Glib::filename_from_utf8(id)); +} + +Glib::ustring get_ext_from_filename(Glib::ustring const &filename) +{ + Glib::ustring extension = ""; + if (!filename.empty()) { + auto extension_point = filename.rfind('.'); + if (extension_point != Glib::ustring::npos) { + extension = filename.substr(extension_point); + } + } + return extension; +} + +std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename) +{ + std::string path; + // Make relative paths go from the document location, if possible: + if (!Glib::path_is_absolute(filename) && doc->getDocumentFilename()) { + auto dirname = Glib::path_get_dirname(doc->getDocumentFilename()); + if (!dirname.empty()) { + path = Glib::build_filename(dirname, filename); + } + } + if (path.empty()) { + path = filename; + } + return path; +} + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/dialog/export-helper.h b/src/ui/dialog/export-helper.h index 241f0b8052..2705042d44 100644 --- a/src/ui/dialog/export-helper.h +++ b/src/ui/dialog/export-helper.h @@ -10,8 +10,40 @@ * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ -#ifndef SP_HELPER_H -#define SP_HELPER_H +#ifndef SP_EXPORT_HELPER_H +#define SP_EXPORT_HELPER_H + +#include +#include +#include +#include +#include + +#include "desktop.h" +#include "document-undo.h" +#include "document.h" +#include "extension/db.h" +#include "extension/output.h" +#include "file.h" +#include "helper/png-write.h" +#include "inkscape-window.h" +#include "inkscape.h" +#include "io/resource.h" +#include "io/sys.h" +#include "message-stack.h" +#include "object/object-set.h" +#include "object/sp-namedview.h" +#include "object/sp-root.h" +#include "preferences.h" +#include "selection-chemistry.h" +#include "ui/dialog-events.h" +#include "ui/dialog/dialog-notebook.h" +#include "ui/dialog/filedialog.h" +#include "ui/interface.h" +#include "ui/widget/scrollprotected.h" +#include "ui/widget/unit-menu.h" + +using Inkscape::Util::unit_table; namespace Inkscape { namespace UI { @@ -21,6 +53,70 @@ namespace Dialog { #define SP_EXPORT_MIN_SIZE 1.0 #define DPI_BASE Inkscape::Util::Quantity::convert(1, "in", "px") +// Class for storing and manipulating advance options. +class AdvanceOptions : public Gtk::Expander +{ +public: + AdvanceOptions(); + ~AdvanceOptions(); + +private: + Gtk::CheckButton interlacing; + + std::vector bit_depth_list; + std::vector color_list; + Inkscape::UI::Widget::ScrollProtected bit_depth_cb; + + std::vector compression_list; + Inkscape::UI::Widget::ScrollProtected compression_cb; + + Inkscape::UI::Widget::ScrollProtected pHYs_sb; + Gtk::SpinButton a; + + std::vector anti_aliasing_list; + Inkscape::UI::Widget::ScrollProtected anti_aliasing_cb; + +private: + int row; + +public: + int get_color() { return color_list[bit_depth_cb.get_active_row_number()]; } + int get_bit_depth() { return bit_depth_list[bit_depth_cb.get_active_row_number()]; } + int get_compression() { return compression_list[compression_cb.get_active_row_number()]; } + int get_anti_aliasing() { return anti_aliasing_list[anti_aliasing_cb.get_active_row_number()]; } + bool get_interlacing() { return interlacing.get_active(); } + double get_pHYs() { return pHYs_sb.get_value(); } +}; + +// Class for storing and manipulating extensions +class ExtensionList : public Gtk::ComboBoxText +{ +public: + ExtensionList(){}; + ExtensionList(BaseObjectType *cobject, const Glib::RefPtr &refGlade) + : Gtk::ComboBoxText(cobject){}; + ~ExtensionList(); + +public: + void setup(); + void setExtensionFromFilename(Glib::ustring const &filename); + void appendExtensionToFilename(Glib::ustring &filename); + static void createList(); + static bool list_created; + static void appendExtensionToFilename(Glib::ustring &filename, Glib::ustring &extension); + +private: + static std::map valid_extensions; + static std::map all_extensions; +}; + +float getValuePx(float value, Unit const *unit); +void setValuePx(Glib::RefPtr &adj, double val, Unit const *unit); +Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension); +std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_entry_text); +Glib::ustring get_ext_from_filename(Glib::ustring const &filename); +std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename); + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index 4165b51962..50f98aeb3f 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -12,39 +12,645 @@ #include "export-single.h" +#include +#include +#include #include +#include +#include "desktop.h" +#include "document-undo.h" +#include "document.h" #include "export-helper.h" +#include "extension/db.h" +#include "file.h" +#include "helper/png-write.h" +#include "inkscape-window.h" +#include "inkscape.h" +#include "io/resource.h" +#include "io/sys.h" +#include "message-stack.h" +#include "object/object-set.h" +#include "object/sp-namedview.h" +#include "object/sp-root.h" +#include "preferences.h" +#include "selection-chemistry.h" +#include "ui/dialog-events.h" +#include "ui/dialog/dialog-notebook.h" +#include "ui/dialog/filedialog.h" +#include "ui/interface.h" +#include "ui/widget/scrollprotected.h" +#include "ui/widget/unit-menu.h" +#ifdef _WIN32 + +#endif + +using Inkscape::Util::unit_table; namespace Inkscape { namespace UI { namespace Dialog { -enum sb_type +SingleExport::~SingleExport() { - SPIN_X0 = 0, - SPIN_X1, - SPIN_Y0, - SPIN_Y1, - SPIN_WIDTH, - SPIN_HEIGHT, - SPIN_BMWIDTH, - SPIN_BMHEIGHT, - SPIN_DPI -}; + ; +} -enum selection_mode +void SingleExport::initialise(const Glib::RefPtr &builder) { - SELECTION_PAGE = 0, // Default is alaways placed first - SELECTION_SELECTION, - SELECTION_DRAWING, - SELECTION_CUSTOM, -}; + builder->get_widget("si_s_document", selection_buttons[SELECTION_DRAWING]); + selection_names[SELECTION_DRAWING] = "drawing"; + builder->get_widget("si_s_page", selection_buttons[SELECTION_PAGE]); + selection_names[SELECTION_PAGE] = "page"; + builder->get_widget("si_s_selection", selection_buttons[SELECTION_SELECTION]); + selection_names[SELECTION_SELECTION] = "selection"; + builder->get_widget("si_s_custom", selection_buttons[SELECTION_CUSTOM]); + selection_names[SELECTION_CUSTOM] = "custom"; + + builder->get_widget_derived("si_left_sb", spin_buttons[SPIN_X0]); + builder->get_widget_derived("si_right_sb", spin_buttons[SPIN_X1]); + builder->get_widget_derived("si_top_sb", spin_buttons[SPIN_Y0]); + builder->get_widget_derived("si_bottom_sb", spin_buttons[SPIN_Y1]); + builder->get_widget_derived("si_height_sb", spin_buttons[SPIN_HEIGHT]); + builder->get_widget_derived("si_width_sb", spin_buttons[SPIN_WIDTH]); + + builder->get_widget_derived("si_img_height_sb", spin_buttons[SPIN_BMHEIGHT]); + builder->get_widget_derived("si_img_width_sb", spin_buttons[SPIN_BMWIDTH]); + builder->get_widget_derived("si_dpi_sb", spin_buttons[SPIN_DPI]); + + builder->get_widget("si_show_export_area", show_export_area); + builder->get_widget_derived("si_units", units); + + builder->get_widget("si_hide_all", si_hide_all); + builder->get_widget("si_preview_box", si_preview_box); + builder->get_widget("si_show_preview", si_show_preview); + + builder->get_widget_derived("si_extention", si_extension_cb); + builder->get_widget("si_filename", si_filename_entry); + builder->get_widget("si_export", si_export); + + builder->get_widget("si_advance_box", adv_box); +} + +void SingleExport::on_realize() +{ + std::cout << "SINGLE RE" << std::endl; + + auto desktop = SP_ACTIVE_DESKTOP; + assert(desktop); + auto *selection = desktop->getSelection(); + + selectionModifiedConn = + selection->connectModified(sigc::mem_fun(*this, &SingleExport::on_inkscape_selection_modified)); + selectionChangedConn = + selection->connectChanged(sigc::mem_fun(*this, &SingleExport::on_inkscape_selection_changed)); + + Gtk::Box::on_realize(); +} -void SingleExport::initialise(Glib::RefPtr *builder) +void SingleExport::on_unrealize() +{ + std::cout << "SINGLE UNRE" << std::endl; + selectionModifiedConn.disconnect(); + selectionChangedConn.disconnect(); + Gtk::Box::on_unrealize(); +} + +void SingleExport::on_inkscape_selection_modified(Inkscape::Selection *selection, guint flags) +{ + assert(SP_ACTIVE_DESKTOP->getSelection() == selection); + if (!(flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + return; + } + Geom::OptRect bbox; + + switch (current_key) { + case SELECTION_DRAWING: + SPDocument *doc; + doc = SP_ACTIVE_DESKTOP->getDocument(); + bbox = doc->getRoot()->desktopVisualBounds(); + if (bbox) { + setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); + } + break; + case SELECTION_SELECTION: + if (selection->isEmpty() == false) { + bbox = selection->visualBounds(); + if (bbox) { + setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); + } + } + break; + default: + /* Do nothing for page or for custom */ + break; + } + refreshExportHints(); +} + +void SingleExport::on_inkscape_selection_changed(Inkscape::Selection *selection) +{ + assert(SP_ACTIVE_DESKTOP->getSelection() == selection); + + if (selection->isEmpty()) { + selection_buttons[SELECTION_SELECTION]->set_sensitive(false); + if (current_key == SELECTION_SELECTION) { + selection_buttons[(selection_mode)0]->set_active(true); // This causes refresh area + // return otherwise refreshArea will be called again + // even though we are at default key, selection is the one which was original key. + prefs->setString("/dialogs/export/exportarea/value", selection_names[SELECTION_SELECTION]); + return; + } + } else { + selection_buttons[SELECTION_SELECTION]->set_sensitive(true); + Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); + if (selection_names[SELECTION_SELECTION] == pref_key_name && current_key != SELECTION_SELECTION) { + selection_buttons[SELECTION_SELECTION]->set_active(); + return; + } + } + refreshArea(); +} + +// Setup Single Export.Called by export on realize +void SingleExport::setup() +{ + prefs = Inkscape::Preferences::get(); + si_extension_cb->setup(); + + // Add advance options to adv box + adv_box->pack_start(advance_options, true, true, 0); + adv_box->show_all_children(); + + setupUnits(); + setupSpinButtons(); + + // set them before connecting to signals + setDefaultFilename(); + setDefaultSelectionMode(); + + // Refresh values to sync them with defaults. + refreshArea(); + refreshExportHints(); + + // Connect Signals Here + for (auto [key, button] : selection_buttons) { + button->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &SingleExport::onAreaTypeToggle), key)); + } + units->signal_changed().connect(sigc::mem_fun(*this, &SingleExport::onUnitChanged)); + filenameConn = si_filename_entry->signal_changed().connect(sigc::mem_fun(*this, &SingleExport::onFilenameModified)); + extensionConn = si_extension_cb->signal_changed().connect(sigc::mem_fun(*this, &SingleExport::onExtensionChanged)); + exportConn = si_export->signal_clicked().connect(sigc::mem_fun(*this, &SingleExport::onExport)); +} + +// Setup units combobox +void SingleExport::setupUnits() +{ + units->setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + units->setUnit(desktop->getNamedView()->display_units->abbr); + } +} + +// Create all spin buttons +void SingleExport::setupSpinButtons() +{ + setupSpinButton(spin_buttons[SPIN_X0], 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + &SingleExport::onAreaXChange, SPIN_X0); + setupSpinButton(spin_buttons[SPIN_X1], 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + &SingleExport::onAreaXChange, SPIN_X1); + setupSpinButton(spin_buttons[SPIN_Y0], 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + &SingleExport::onAreaYChange, SPIN_Y0); + setupSpinButton(spin_buttons[SPIN_Y1], 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, + &SingleExport::onAreaYChange, SPIN_Y1); + + setupSpinButton(spin_buttons[SPIN_HEIGHT], 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, EXPORT_COORD_PRECISION, + true, &SingleExport::onAreaYChange, SPIN_HEIGHT); + setupSpinButton(spin_buttons[SPIN_WIDTH], 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, EXPORT_COORD_PRECISION, + true, &SingleExport::onAreaXChange, SPIN_WIDTH); + + setupSpinButton(spin_buttons[SPIN_BMHEIGHT], 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, + &SingleExport::onDpiChange, SPIN_BMHEIGHT); + setupSpinButton(spin_buttons[SPIN_BMWIDTH], 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, + &SingleExport::onDpiChange, SPIN_BMWIDTH); + setupSpinButton(spin_buttons[SPIN_DPI], prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), + 0.01, 100000.0, 0.1, 1.0, 2, true, &SingleExport::onDpiChange, SPIN_DPI); +} + +template +void SingleExport::setupSpinButton(Gtk::SpinButton *sb, double val, double min, double max, double step, double page, + int digits, bool sensitive, void (SingleExport::*cb)(T), T param) +{ + if (sb) { + sb->set_digits(digits); + sb->set_increments(step, page); + sb->set_range(min, max); + sb->set_value(val); + sb->set_sensitive(sensitive); + sb->set_width_chars(7); + if (cb) { + auto signal = sb->signal_value_changed().connect(sigc::bind(sigc::mem_fun(*this, cb), param)); + // add signals to list to block all easily + spinButtonConns.push_back(signal); + } + } +} + +void SingleExport::refreshArea() +{ + if (SP_ACTIVE_DESKTOP) { + SPDocument *doc; + Geom::OptRect bbox; + doc = SP_ACTIVE_DESKTOP->getDocument(); + doc->ensureUpToDate(); + + switch (current_key) { + case SELECTION_SELECTION: + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { + bbox = SP_ACTIVE_DESKTOP->getSelection()->visualBounds(); + break; + } + case SELECTION_DRAWING: + bbox = doc->getRoot()->desktopVisualBounds(); + if (bbox) { + break; + } + case SELECTION_PAGE: + bbox = Geom::Rect(Geom::Point(0.0, 0.0), + Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); + break; + case SELECTION_CUSTOM: + break; + default: + break; + } + if (current_key != SELECTION_CUSTOM && bbox) { + setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); + } + } +} + +void SingleExport::refreshExportHints() +{ + if (SP_ACTIVE_DESKTOP && !filename_modified) { + SPDocument *doc = SP_ACTIVE_DOCUMENT; + Glib::ustring filename; + float xdpi = 0.0, ydpi = 0.0; + switch (current_key) { + case SELECTION_CUSTOM: + case SELECTION_PAGE: + case SELECTION_DRAWING: + sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); + if (filename.empty()) { + Glib::ustring filename_entry_text = si_filename_entry->get_text(); + Glib::ustring extension_entry_text = si_extension_cb->get_active_text(); + filename = get_default_filename(filename_entry_text, extension_entry_text); + } + doc_export_name = filename; + break; + case SELECTION_SELECTION: + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + break; + } + SP_ACTIVE_DESKTOP->getSelection()->getExportHints(filename, &xdpi, &ydpi); + + /* If we still don't have a filename -- let's build + one that's nice */ + if (filename.empty()) { + const gchar *id = "object"; + auto reprlst = SP_ACTIVE_DESKTOP->getSelection()->xmlNodes(); + for (auto i = reprlst.begin(); reprlst.end() != i; ++i) { + Inkscape::XML::Node *repr = *i; + if (repr->attribute("id")) { + id = repr->attribute("id"); + break; + } + } + filename = create_filepath_from_id(id, si_filename_entry->get_text()); + filename = filename + si_extension_cb->get_active_text(); + } + break; + default: + break; + } + if (!filename.empty()) { + original_name = filename; + si_filename_entry->set_text(filename); + si_filename_entry->set_position(filename.length()); + } + + if (xdpi != 0.0) { + spin_buttons[SPIN_DPI]->set_value(xdpi); + } + } +} + +void SingleExport::setArea(double x0, double y0, double x1, double y1) +{ + blockSpinConns(true); + + auto x0_adj = spin_buttons[SPIN_X0]->get_adjustment(); + auto x1_adj = spin_buttons[SPIN_X1]->get_adjustment(); + auto y0_adj = spin_buttons[SPIN_Y0]->get_adjustment(); + auto y1_adj = spin_buttons[SPIN_Y1]->get_adjustment(); + + Unit const *unit = units->getUnit(); + setValuePx(x1_adj, x1, unit); + setValuePx(y1_adj, y1, unit); + setValuePx(x0_adj, x0, unit); + setValuePx(y0_adj, y0, unit); + + areaXChange(SPIN_X1); + areaYChange(SPIN_Y1); + + blockSpinConns(false); +} + +// Signals CallBack + +void SingleExport::onRealize() { ; } +void SingleExport::onUnrealize() +{ + ; +} + +void SingleExport::onUnitChanged() +{ + refreshArea(); +} + +void SingleExport::onAreaTypeToggle(selection_mode key) +{ + // Prevent executing function twice + if (!selection_buttons[key]->get_active()) { + return; + } + // If you have reached here means the current key is active one ( not sure if multiple transitions happen but + // last call will change values) + current_key = key; + prefs->setString("/dialogs/export/exportarea/value", selection_names[current_key]); + refreshArea(); + refreshExportHints(); +} + +void SingleExport::onAreaXChange(sb_type type) +{ + blockSpinConns(true); + areaXChange(type); + blockSpinConns(false); +} +void SingleExport::onAreaYChange(sb_type type) +{ + blockSpinConns(true); + areaYChange(type); + blockSpinConns(false); +} +void SingleExport::onDpiChange(sb_type type) +{ + blockSpinConns(true); + dpiChange(type); + blockSpinConns(false); +} + +void SingleExport::onFilenameModified() +{ + extensionConn.block(); + Glib::ustring filename = si_filename_entry->get_text(); + + if (original_name == filename) { + filename_modified = false; + } else { + filename_modified = true; + } + + si_extension_cb->setExtensionFromFilename(filename); + + extensionConn.unblock(); +} + +void SingleExport::onExtensionChanged() +{ + filenameConn.block(); + Glib::ustring filename = si_filename_entry->get_text(); + si_extension_cb->appendExtensionToFilename(filename); + si_filename_entry->set_text(filename); + si_filename_entry->set_position(filename.length()); + filenameConn.unblock(); +} + +void SingleExport::onExport() +{ + ; +} + +// Utils Functions + +void SingleExport::blockSpinConns(bool status = true) +{ + for (auto signal : spinButtonConns) { + if (status) { + signal.block(); + } else { + signal.unblock(); + } + } +} + +void SingleExport::areaXChange(sb_type type) +{ + auto x0_adj = spin_buttons[SPIN_X0]->get_adjustment(); + auto x1_adj = spin_buttons[SPIN_X1]->get_adjustment(); + auto width_adj = spin_buttons[SPIN_WIDTH]->get_adjustment(); + + float x0, x1, dpi, width, bmwidth; + + // Get all values in px + Unit const *unit = units->getUnit(); + x0 = getValuePx(x0_adj->get_value(), unit); + x1 = getValuePx(x1_adj->get_value(), unit); + width = getValuePx(width_adj->get_value(), unit); + bmwidth = spin_buttons[SPIN_BMWIDTH]->get_value(); + dpi = spin_buttons[SPIN_DPI]->get_value(); + + switch (type) { + case SPIN_X0: + bmwidth = (x1 - x0) * dpi / DPI_BASE; + if (bmwidth < SP_EXPORT_MIN_SIZE) { + x0 = x1 - (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; + } + break; + case SPIN_X1: + bmwidth = (x1 - x0) * dpi / DPI_BASE; + if (bmwidth < SP_EXPORT_MIN_SIZE) { + x1 = x0 + (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; + } + break; + case SPIN_WIDTH: + bmwidth = width * dpi / DPI_BASE; + if (bmwidth < SP_EXPORT_MIN_SIZE) { + width = (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; + } + x1 = x0 + width; + break; + default: + break; + } + + width = x1 - x0; + bmwidth = floor(width * dpi / DPI_BASE + 0.5); + + setValuePx(x0_adj, x0, unit); + setValuePx(x1_adj, x1, unit); + setValuePx(width_adj, width, unit); + spin_buttons[SPIN_BMWIDTH]->set_value(bmwidth); +} + +void SingleExport::areaYChange(sb_type type) +{ + auto y0_adj = spin_buttons[SPIN_Y0]->get_adjustment(); + auto y1_adj = spin_buttons[SPIN_Y1]->get_adjustment(); + auto height_adj = spin_buttons[SPIN_HEIGHT]->get_adjustment(); + + float y0, y1, dpi, height, bmheight; + + // Get all values in px + Unit const *unit = units->getUnit(); + y0 = getValuePx(y0_adj->get_value(), unit); + y1 = getValuePx(y1_adj->get_value(), unit); + height = getValuePx(height_adj->get_value(), unit); + bmheight = spin_buttons[SPIN_BMHEIGHT]->get_value(); + dpi = spin_buttons[SPIN_DPI]->get_value(); + + switch (type) { + case SPIN_Y0: + bmheight = (y1 - y0) * dpi / DPI_BASE; + if (bmheight < SP_EXPORT_MIN_SIZE) { + y0 = y1 - (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; + } + break; + case SPIN_Y1: + bmheight = (y1 - y0) * dpi / DPI_BASE; + if (bmheight < SP_EXPORT_MIN_SIZE) { + y1 = y0 + (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; + } + break; + case SPIN_HEIGHT: + bmheight = height * dpi / DPI_BASE; + if (bmheight < SP_EXPORT_MIN_SIZE) { + height = (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; + } + y1 = y0 + height; + break; + default: + break; + } + + height = y1 - y0; + bmheight = floor(height * dpi / DPI_BASE + 0.5); + + setValuePx(y0_adj, y0, unit); + setValuePx(y1_adj, y1, unit); + setValuePx(height_adj, height, unit); + spin_buttons[SPIN_BMHEIGHT]->set_value(bmheight); +} + +void SingleExport::dpiChange(sb_type type) +{ + float dpi, height, width, bmheight, bmwidth; + + // Get all values in px + Unit const *unit = units->getUnit(); + height = getValuePx(spin_buttons[SPIN_HEIGHT]->get_value(), unit); + width = getValuePx(spin_buttons[SPIN_WIDTH]->get_value(), unit); + bmheight = spin_buttons[SPIN_BMHEIGHT]->get_value(); + bmwidth = spin_buttons[SPIN_BMWIDTH]->get_value(); + dpi = spin_buttons[SPIN_DPI]->get_value(); + + switch (type) { + case SPIN_BMHEIGHT: + if (bmheight < SP_EXPORT_MIN_SIZE) { + bmheight = SP_EXPORT_MIN_SIZE; + } + dpi = bmheight * DPI_BASE / height; + break; + case SPIN_BMWIDTH: + if (bmwidth < SP_EXPORT_MIN_SIZE) { + bmwidth = SP_EXPORT_MIN_SIZE; + } + dpi = bmwidth * DPI_BASE / width; + break; + case SPIN_DPI: + prefs->setDouble("/dialogs/export/defaultdpi/value", dpi); + break; + default: + break; + } + + bmwidth = floor(width * dpi / DPI_BASE + 0.5); + bmheight = floor(height * dpi / DPI_BASE + 0.5); + + spin_buttons[SPIN_BMHEIGHT]->set_value(bmheight); + spin_buttons[SPIN_BMWIDTH]->set_value(bmwidth); + spin_buttons[SPIN_DPI]->set_value(dpi); +} + +// We first check any export hints related to document. If there is none we create a default name using document name. +// doc_export_name is set here and will only be changed when exporting. +void SingleExport::setDefaultFilename() +{ + Glib::ustring filename; + float xdpi = 0.0, ydpi = 0.0; + SPDocument *doc = SP_ACTIVE_DOCUMENT; + sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); + if (filename.empty()) { + Glib::ustring filename_entry_text = si_filename_entry->get_text(); + Glib::ustring extention_entry_text = si_extension_cb->get_active_text(); + filename = get_default_filename(filename_entry_text, extention_entry_text); + } + doc_export_name = filename; + original_name = filename; + si_filename_entry->set_text(filename); + si_filename_entry->set_position(filename.length()); + + si_extension_cb->setExtensionFromFilename(filename); + + // We only need to check xdpi + if (xdpi != 0.0) { + spin_buttons[SPIN_DPI]->set_value(xdpi); + } +} + +void SingleExport::setDefaultSelectionMode() +{ + if (SP_ACTIVE_DESKTOP) { + current_key = (selection_mode)0; // default key + bool found = false; + Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); + for (auto [key, name] : selection_names) { + if (pref_key_name == name) { + current_key = key; + found = true; + break; + } + } + if (!found) { + pref_key_name = selection_names[current_key]; + } + + if (current_key == SELECTION_SELECTION && (SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + current_key = (selection_mode)0; + } + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + selection_buttons[SELECTION_SELECTION]->set_sensitive(false); + } + selection_buttons[current_key]->set_active(true); + prefs->setString("/dialogs/export/exportarea/value", pref_key_name); + } +} } // namespace Dialog } // namespace UI diff --git a/src/ui/dialog/export-single.h b/src/ui/dialog/export-single.h index 5cc787fb61..8acf0a1c81 100644 --- a/src/ui/dialog/export-single.h +++ b/src/ui/dialog/export-single.h @@ -25,41 +25,41 @@ namespace Inkscape { namespace UI { namespace Dialog { -enum sb_type -{ - SPIN_X0 = 0, - SPIN_X1, - SPIN_Y0, - SPIN_Y1, - SPIN_WIDTH, - SPIN_HEIGHT, - SPIN_BMWIDTH, - SPIN_BMHEIGHT, - SPIN_DPI -}; - -enum selection_mode -{ - SELECTION_PAGE = 0, // Default is alaways placed first - SELECTION_SELECTION, - SELECTION_DRAWING, - SELECTION_CUSTOM, -}; - class SingleExport : public Gtk::Box { public: - SingleExport(); + SingleExport(){}; + SingleExport(BaseObjectType *cobject, const Glib::RefPtr &refGlade) + : Gtk::Box(cobject){}; ~SingleExport() override; -public: - void initialise(Glib::RefPtr *builder); +private: + enum sb_type + { + SPIN_X0 = 0, + SPIN_X1, + SPIN_Y0, + SPIN_Y1, + SPIN_WIDTH, + SPIN_HEIGHT, + SPIN_BMWIDTH, + SPIN_BMHEIGHT, + SPIN_DPI + }; + + enum selection_mode + { + SELECTION_PAGE = 0, // Default is alaways placed first + SELECTION_SELECTION, + SELECTION_DRAWING, + SELECTION_CUSTOM, + }; private: - // Single Image Objects Start Here - Gtk::Box *single_image = nullptr; + typedef Inkscape::UI::Widget::ScrollProtected SpinButton; std::map spin_buttons; + std::map selection_buttons; Gtk::CheckButton *show_export_area = nullptr; Inkscape::UI::Widget::UnitMenu *units = nullptr; @@ -67,9 +67,80 @@ private: Gtk::Box *si_preview_box = nullptr; Gtk::CheckButton *si_show_preview = nullptr; - Gtk::ComboBoxText *si_extension_cb = nullptr; + ExtensionList *si_extension_cb = nullptr; Gtk::Entry *si_filename_entry = nullptr; Gtk::Button *si_export = nullptr; + Gtk::Box *adv_box = nullptr; + + AdvanceOptions advance_options; + +private: + bool filename_modified; + Glib::ustring original_name; + Glib::ustring doc_export_name; + + Inkscape::Preferences *prefs = nullptr; + std::map selection_names; + selection_mode current_key; + +public: + // initialise variables from builder + void initialise(const Glib::RefPtr &builder); + void setup(); + +private: + void setupUnits(); + void setupExtensionList(); + +private: + // change range and callbacks to spinbuttons + void setupSpinButtons(); + template + void setupSpinButton(Gtk::SpinButton *sb, double val, double min, double max, double step, double page, int digits, + bool sensitive, void (SingleExport::*cb)(T), T param); + +private: + // signals callback + void onRealize(); + void onUnrealize(); + + void onAreaXChange(sb_type type); + void onAreaYChange(sb_type type); + void onDpiChange(sb_type type); + void onAreaTypeToggle(selection_mode key); + void onUnitChanged(); + void onFilenameModified(); + void onExtensionChanged(); + void onExport(); + void on_inkscape_selection_modified(Inkscape::Selection *selection, guint flags); + void on_inkscape_selection_changed(Inkscape::Selection *selection); + +private: + void refreshArea(); + void refreshExportHints(); + void areaXChange(sb_type type); + void areaYChange(sb_type type); + void dpiChange(sb_type type); + + void setArea(double x0, double y0, double x1, double y1); + void blockSpinConns(bool status); + +private: + void setDefaultSelectionMode(); + void setDefaultFilename(); + +private: + // Signals + std::vector spinButtonConns; + sigc::connection filenameConn; + sigc::connection extensionConn; + sigc::connection exportConn; + sigc::connection selectionModifiedConn; + sigc::connection selectionChangedConn; + +private: + void on_realize() override; + void on_unrealize() override; }; } // namespace Dialog } // namespace UI diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 8676e437b6..c55c6fa8c9 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -55,17 +55,8 @@ namespace Inkscape { namespace UI { namespace Dialog { -static std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_entry_text); -static void append_ext_to_filename(Glib::ustring &filename, Glib::ustring &extension); -static Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension); -static Glib::ustring get_ext_from_filename(Glib::ustring &filename); -static std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename); - Export::Export() : DialogBase("/dialogs/export/", "Export") - , filename_modified(false) - , original_name() - , doc_export_name() , selectChangedConn() , subselChangedConn() , selectModifiedConn() @@ -78,31 +69,20 @@ Export::Export() g_error("Glade file loading failed for export screen"); return; } - // initalise all variables from gtk::builder at same place. Makes it easy to sync with glade - initialise_all(); - // add top level container and show all children. + prefs = Inkscape::Preferences::get(); + + builder->get_widget("Export Dialog Box", container); add(*container); show_all_children(); + builder->get_widget("Export Notebook", export_notebook); + builder->get_widget_derived("Single Image", single_image); - prefs = Inkscape::Preferences::get(); - - // setting up units beforehand is important as we will use it to initialise other values - setupUnits(); - setupSpinButtons(); - setupExtensionList(); - setupAdvance(); + single_image->initialise(builder); + builder->get_widget("Batch Export", batch_export); // Callback when container is dinally mapped on window. All intialisation like set active is done inside it. - container->signal_map().connect(sigc::mem_fun(*this, &Export::onContainerVisible)); - units->signal_changed().connect(sigc::mem_fun(*this, &Export::onUnitChanged)); - si_extension_cb->signal_changed().connect(sigc::mem_fun(*this, &Export::onExtensionChanged)); - for (auto [key, button] : selection_buttons) { - button->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &Export::onAreaTypeToggle), key)); - } - filenameChangedConn = - si_filename_entry->signal_changed().connect(sigc::mem_fun(*this, &Export::onFilenameModified)); - siExportConn = si_export->signal_clicked().connect(sigc::mem_fun(*this, &Export::onExport)); + container->signal_realize().connect(sigc::mem_fun(*this, &Export::onRealize)); } Export::~Export() @@ -110,441 +90,8 @@ Export::~Export() selectModifiedConn.disconnect(); subselChangedConn.disconnect(); selectChangedConn.disconnect(); - - delete advance_grid; -} - -void Export::update() -{ - if (!_app) { - std::cerr << "Export::update(): _app is null" << std::endl; - return; - } - onSelectionChanged(); - onSelectionModified(0); -#if 0 - setDesktop(getDesktop()); -#endif -} - -void Export::onSelectionChanged() -{ - Inkscape::Selection *selection = SP_ACTIVE_DESKTOP->getSelection(); - if (selection->isEmpty()) { - selection_buttons[SELECTION_SELECTION]->set_sensitive(false); - if (current_key == SELECTION_SELECTION) { - selection_buttons[(selection_mode)0]->set_active(true); // This causes refresh area - // return otherwise refreshArea will be called again - // even though we are at default key, selection is the one which was original key. - prefs->setString("/dialogs/export/exportarea/value", selection_names[SELECTION_SELECTION]); - return; - } - } else { - selection_buttons[SELECTION_SELECTION]->set_sensitive(true); - Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); - if (selection_names[SELECTION_SELECTION] == pref_key_name && current_key != SELECTION_SELECTION) { - selection_buttons[SELECTION_SELECTION]->set_active(); - return; - } - } - refreshArea(); -} - -void Export::onSelectionModified(guint /*flags*/) -{ - if (SP_ACTIVE_DESKTOP) { - Geom::OptRect bbox; - - switch (current_key) { - case SELECTION_DRAWING: - SPDocument *doc; - doc = SP_ACTIVE_DESKTOP->getDocument(); - bbox = doc->getRoot()->desktopVisualBounds(); - if (bbox) { - setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); - } - break; - case SELECTION_SELECTION: - Inkscape::Selection *Sel; - Sel = SP_ACTIVE_DESKTOP->getSelection(); - if (Sel->isEmpty() == false) { - bbox = Sel->visualBounds(); - if (bbox) { - setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); - } - } - break; - default: - /* Do nothing for page or for custom */ - break; - } - } - refreshExportHints(); - - return; -} - -void Export::initialise_all() -{ - if (builder) { - // Top container - builder->get_widget("Export Dialog Box", container); - builder->get_widget("Export Notebook", export_notebook); - - builder->get_widget("Single Image", single_image); - - builder->get_widget("si_s_document", selection_buttons[SELECTION_DRAWING]); - selection_names[SELECTION_DRAWING] = "drawing"; - builder->get_widget("si_s_page", selection_buttons[SELECTION_PAGE]); - selection_names[SELECTION_PAGE] = "page"; - builder->get_widget("si_s_selection", selection_buttons[SELECTION_SELECTION]); - selection_names[SELECTION_SELECTION] = "selection"; - builder->get_widget("si_s_custom", selection_buttons[SELECTION_CUSTOM]); - selection_names[SELECTION_CUSTOM] = "custom"; - - builder->get_widget_derived("si_left_sb", spin_buttons[SPIN_X0]); - builder->get_widget_derived("si_right_sb", spin_buttons[SPIN_X1]); - builder->get_widget_derived("si_top_sb", spin_buttons[SPIN_Y0]); - builder->get_widget_derived("si_bottom_sb", spin_buttons[SPIN_Y1]); - builder->get_widget_derived("si_height_sb", spin_buttons[SPIN_HEIGHT]); - builder->get_widget_derived("si_width_sb", spin_buttons[SPIN_WIDTH]); - - builder->get_widget_derived("si_img_height_sb", spin_buttons[SPIN_BMHEIGHT]); - builder->get_widget_derived("si_img_width_sb", spin_buttons[SPIN_BMWIDTH]); - builder->get_widget_derived("si_dpi_sb", spin_buttons[SPIN_DPI]); - - builder->get_widget("si_show_export_area", show_export_area); - builder->get_widget_derived("si_units", units); - - builder->get_widget("si_hide_all", si_hide_all); - builder->get_widget("si_preview_box", si_preview_box); - builder->get_widget("si_show_preview", si_show_preview); - - builder->get_widget("si_extention", si_extension_cb); - builder->get_widget("si_filename", si_filename_entry); - builder->get_widget("si_export", si_export); - - builder->get_widget("Batch Export", batch_export); - } - return; -} - -void Export::setupUnits() -{ - if (units) { - units->setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (desktop) { - units->setUnit(desktop->getNamedView()->display_units->abbr); - } - } -} - -void Export::setupExtensionList() -{ - Inkscape::Extension::DB::OutputList extensions; - Inkscape::Extension::db.get_output_list(extensions); - Glib::ustring extension; - - for (auto omod : extensions) { - // FIXME: would be nice to grey them out instead of not listing them - if (omod->deactivated() || (omod->is_raster() != true)) - continue; - - extension = omod->get_extension(); - si_extension_cb->append(extension); - extension_list[extension] = omod; - } - - // add extentions manually - Inkscape::Extension::Output *manual_omod; - manual_omod = dynamic_cast(Inkscape::Extension::db.get(SP_MODULE_KEY_OUTPUT_SVG)); - extension = manual_omod->get_extension(); - si_extension_cb->append(extension); - extension_list[extension] = manual_omod; } -void Export::setupAdvance() -{ - advance_grid = new Gtk::Grid; - int row = 0; - std::vector labels; - { - interlacing.set_label("Use Interlacing"); - advance_grid->attach(interlacing, 0, row, 2, 1); - row++; - } - { - labels.insert(labels.end(), {"Gray_1", "Gray_2", "Gray_4", "Gray_8", "Gray_16", "RGB_8", "RGB_16", - "GrayAlpha_8", "GrayAlpha_16", "RGBA_8", "RGBA_16"}); - bit_depth_list.clear(); - bit_depth_list.insert(bit_depth_list.end(), {1, 2, 4, 8, 16, 8, 16, 8, 16, 8, 16}); - color_list.clear(); - color_list.insert(color_list.end(), {0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 6}); - - for (auto label : labels) { - bit_depth_cb.append(label); - } - labels.clear(); - - bit_depth_cb.set_active_text("RGBA_8"); - bit_depth_cb.set_hexpand(); - Gtk::Label *bit_depth_label = Gtk::manage(new Gtk::Label(_("Bit Depth"), Gtk::ALIGN_START)); - advance_grid->attach(*bit_depth_label, 0, row, 1, 1); - advance_grid->attach(bit_depth_cb, 1, row, 1, 1); - row++; - } - { - labels.insert(labels.end(), {"Z_NO_COMPRESSION", "Z_BEST_SPEED", "2", "3", "4", "5", "Z_DEFAULT_COMPRESSION", - "7", "8", "Z_BEST_COMPRESSION"}); - compression_list.clear(); - compression_list.insert(compression_list.end(), {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); - for (auto label : labels) { - compression_cb.append(label); - } - labels.clear(); - - compression_cb.set_active_text("Z_DEFAULT_COMPRESSION"); - Gtk::Label *compression_label = Gtk::manage(new Gtk::Label(_("Compression"), Gtk::ALIGN_START)); - advance_grid->attach(*compression_label, 0, row, 1, 1); - advance_grid->attach(compression_cb, 1, row, 1, 1); - row++; - } - - { - auto pHYs_adj = Gtk::Adjustment::create(0, 0, 100000, 0.1, 1.0, 0); - phys_dpi_sb.set_adjustment(pHYs_adj); - phys_dpi_sb.set_width_chars(7); - phys_dpi_sb.set_digits(2); - Gtk::Label *phys_dpi_label = Gtk::manage(new Gtk::Label(_("pHYs DPI"), Gtk::ALIGN_START)); - advance_grid->attach(*phys_dpi_label, 0, row, 1, 1); - advance_grid->attach(phys_dpi_sb, 1, row, 1, 1); - row++; - } - { - labels.insert(labels.end(), {"CAIRO_ANTIALIAS_NONE", "CAIRO_ANTIALIAS_FAST", "CAIRO_ANTIALIAS_GOOD (default)", - "CAIRO_ANTIALIAS_BEST"}); - anti_aliasing_list.clear(); - anti_aliasing_list.insert(anti_aliasing_list.end(), {0, 1, 2, 3}); - - for (auto label : labels) { - anti_aliasing_cb.append(label); - } - labels.clear(); - - anti_aliasing_cb.set_active_text("CAIRO_ANTIALIAS_GOOD (default)"); - Gtk::Label *anti_aliasing_label = Gtk::manage(new Gtk::Label(_("Anti Aliasing"), Gtk::ALIGN_START)); - advance_grid->attach(*anti_aliasing_label, 0, row, 1, 1); - advance_grid->attach(anti_aliasing_cb, 1, row, 1, 1); - row++; - } -} - -void Export::setupSpinButtons() -{ - setupSpinButton(spin_buttons[SPIN_X0], 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, - &Export::onAreaXChange, SPIN_X0); - setupSpinButton(spin_buttons[SPIN_X1], 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, - &Export::onAreaXChange, SPIN_X1); - setupSpinButton(spin_buttons[SPIN_Y0], 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, - &Export::onAreaYChange, SPIN_Y0); - setupSpinButton(spin_buttons[SPIN_Y1], 0.0, -1000000.0, 1000000.0, 0.1, 1.0, EXPORT_COORD_PRECISION, true, - &Export::onAreaYChange, SPIN_Y1); - - setupSpinButton(spin_buttons[SPIN_HEIGHT], 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, EXPORT_COORD_PRECISION, - true, &Export::onAreaYChange, SPIN_HEIGHT); - setupSpinButton(spin_buttons[SPIN_WIDTH], 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, EXPORT_COORD_PRECISION, - true, &Export::onAreaXChange, SPIN_WIDTH); - - setupSpinButton(spin_buttons[SPIN_BMHEIGHT], 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, &Export::onDpiChange, - SPIN_BMHEIGHT); - setupSpinButton(spin_buttons[SPIN_BMWIDTH], 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, &Export::onDpiChange, - SPIN_BMWIDTH); - setupSpinButton(spin_buttons[SPIN_DPI], prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), - 0.01, 100000.0, 0.1, 1.0, 2, true, &Export::onDpiChange, SPIN_DPI); -} - -template -void Export::setupSpinButton(Gtk::SpinButton *sb, double val, double min, double max, double step, double page, - int digits, bool sensitive, void (Export::*cb)(T), T param) -{ - if (sb) { - sb->set_digits(digits); - sb->set_increments(step, page); - sb->set_range(min, max); - sb->set_value(val); - sb->set_sensitive(sensitive); - sb->set_width_chars(7); - if (cb) { - auto signal = sb->signal_value_changed().connect(sigc::bind(sigc::mem_fun(*this, cb), param)); - // add signals to list to block all easily - spinButtonConns.push_back(signal); - } - } -} - -/** - * UTILS FUNCTIONS - */ -float Export::getValuePx(float value) -{ - Unit const *unit = units->getUnit(); - return Inkscape::Util::Quantity::convert(value, unit, "px"); -} - -void Export::setValuePx(Glib::RefPtr &adj, double val) -{ - Unit const *unit = units->getUnit(); - auto value = Inkscape::Util::Quantity::convert(val, "px", unit); - adj->set_value(value); - return; -} - -void Export::areaXChange(sb_type type) -{ - auto x0_adj = spin_buttons[SPIN_X0]->get_adjustment(); - auto x1_adj = spin_buttons[SPIN_X1]->get_adjustment(); - auto width_adj = spin_buttons[SPIN_WIDTH]->get_adjustment(); - - float x0, x1, dpi, width, bmwidth; - - // Get all values in px - x0 = getValuePx(x0_adj->get_value()); - x1 = getValuePx(x1_adj->get_value()); - width = getValuePx(width_adj->get_value()); - bmwidth = spin_buttons[SPIN_BMWIDTH]->get_value(); - dpi = spin_buttons[SPIN_DPI]->get_value(); - - switch (type) { - case SPIN_X0: - bmwidth = (x1 - x0) * dpi / DPI_BASE; - if (bmwidth < SP_EXPORT_MIN_SIZE) { - x0 = x1 - (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; - } - break; - case SPIN_X1: - bmwidth = (x1 - x0) * dpi / DPI_BASE; - if (bmwidth < SP_EXPORT_MIN_SIZE) { - x1 = x0 + (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; - } - break; - case SPIN_WIDTH: - bmwidth = width * dpi / DPI_BASE; - if (bmwidth < SP_EXPORT_MIN_SIZE) { - width = (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; - } - x1 = x0 + width; - break; - default: - break; - } - - width = x1 - x0; - bmwidth = floor(width * dpi / DPI_BASE + 0.5); - - setValuePx(x0_adj, x0); - setValuePx(x1_adj, x1); - setValuePx(width_adj, width); - spin_buttons[SPIN_BMWIDTH]->set_value(bmwidth); -} - -void Export::areaYChange(sb_type type) -{ - auto y0_adj = spin_buttons[SPIN_Y0]->get_adjustment(); - auto y1_adj = spin_buttons[SPIN_Y1]->get_adjustment(); - auto height_adj = spin_buttons[SPIN_HEIGHT]->get_adjustment(); - - float y0, y1, dpi, height, bmheight; - - // Get all values in px - y0 = getValuePx(y0_adj->get_value()); - y1 = getValuePx(y1_adj->get_value()); - height = getValuePx(height_adj->get_value()); - bmheight = spin_buttons[SPIN_BMHEIGHT]->get_value(); - dpi = spin_buttons[SPIN_DPI]->get_value(); - - switch (type) { - case SPIN_Y0: - bmheight = (y1 - y0) * dpi / DPI_BASE; - if (bmheight < SP_EXPORT_MIN_SIZE) { - y0 = y1 - (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; - } - break; - case SPIN_Y1: - bmheight = (y1 - y0) * dpi / DPI_BASE; - if (bmheight < SP_EXPORT_MIN_SIZE) { - y1 = y0 + (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; - } - break; - case SPIN_HEIGHT: - bmheight = height * dpi / DPI_BASE; - if (bmheight < SP_EXPORT_MIN_SIZE) { - height = (SP_EXPORT_MIN_SIZE * DPI_BASE) / dpi; - } - y1 = y0 + height; - break; - default: - break; - } - - height = y1 - y0; - bmheight = floor(height * dpi / DPI_BASE + 0.5); - - setValuePx(y0_adj, y0); - setValuePx(y1_adj, y1); - setValuePx(height_adj, height); - spin_buttons[SPIN_BMHEIGHT]->set_value(bmheight); -} - -void Export::dpiChange(sb_type type) -{ - float dpi, height, width, bmheight, bmwidth; - - // Get all values in px - height = getValuePx(spin_buttons[SPIN_HEIGHT]->get_value()); - width = getValuePx(spin_buttons[SPIN_WIDTH]->get_value()); - bmheight = spin_buttons[SPIN_BMHEIGHT]->get_value(); - bmwidth = spin_buttons[SPIN_BMWIDTH]->get_value(); - dpi = spin_buttons[SPIN_DPI]->get_value(); - - switch (type) { - case SPIN_BMHEIGHT: - if (bmheight < SP_EXPORT_MIN_SIZE) { - bmheight = SP_EXPORT_MIN_SIZE; - } - dpi = bmheight * DPI_BASE / height; - break; - case SPIN_BMWIDTH: - if (bmwidth < SP_EXPORT_MIN_SIZE) { - bmwidth = SP_EXPORT_MIN_SIZE; - } - dpi = bmwidth * DPI_BASE / width; - break; - case SPIN_DPI: - prefs->setDouble("/dialogs/export/defaultdpi/value", dpi); - break; - default: - break; - } - - bmwidth = floor(width * dpi / DPI_BASE + 0.5); - bmheight = floor(height * dpi / DPI_BASE + 0.5); - - spin_buttons[SPIN_BMHEIGHT]->set_value(bmheight); - spin_buttons[SPIN_BMWIDTH]->set_value(bmwidth); - spin_buttons[SPIN_DPI]->set_value(dpi); -} - -void Export::blockSpinConns(bool status = true) -{ - for (auto signal : spinButtonConns) { - if (status) { - signal.block(); - } else { - signal.unblock(); - } - } -} void Export::setDefaultNotebookPage() { @@ -554,181 +101,6 @@ void Export::setDefaultNotebookPage() // } } -void Export::setDefaultSelectionMode() -{ - if (SP_ACTIVE_DESKTOP) { - { // Single Image Selection Mode - - current_key = (selection_mode)0; // default key - bool found = false; - Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); - for (auto [key, name] : selection_names) { - if (pref_key_name == name) { - current_key = key; - found = true; - break; - } - } - if (!found) { - pref_key_name = selection_names[current_key]; - } - - if (current_key == SELECTION_SELECTION && (SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { - current_key = (selection_mode)0; - } - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { - selection_buttons[SELECTION_SELECTION]->set_sensitive(false); - } - selection_buttons[current_key]->set_active(true); - prefs->setString("/dialogs/export/exportarea/value", pref_key_name); - } - - { // Batch Export Selection Mode - } - } -} - -void Export::setDefaultFilename() -{ - Glib::ustring filename; - float xdpi = 0.0, ydpi = 0.0; - SPDocument *doc = SP_ACTIVE_DOCUMENT; - sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); - if (filename.empty()) { - Glib::ustring filename_entry_text = si_filename_entry->get_text(); - Glib::ustring extention_entry_text = ".png"; - filename = get_default_filename(filename_entry_text, extention_entry_text); - } - doc_export_name = filename; - original_name = filename; - si_filename_entry->set_text(filename); - si_filename_entry->set_position(filename.length()); - // We only need to check xdpi - if (xdpi != 0.0) { - spin_buttons[SPIN_DPI]->set_value(xdpi); - } - refreshExportHints(); -} - -void Export::refreshArea() -{ - if (SP_ACTIVE_DESKTOP) { - SPDocument *doc; - Geom::OptRect bbox; - doc = SP_ACTIVE_DESKTOP->getDocument(); - doc->ensureUpToDate(); - - switch (current_key) { - case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { - bbox = SP_ACTIVE_DESKTOP->getSelection()->visualBounds(); - break; - } - case SELECTION_DRAWING: - bbox = doc->getRoot()->desktopVisualBounds(); - if (bbox) { - break; - } - case SELECTION_PAGE: - bbox = Geom::Rect(Geom::Point(0.0, 0.0), - Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); - break; - case SELECTION_CUSTOM: - break; - default: - break; - } - if (current_key != SELECTION_CUSTOM && bbox) { - setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); - } - } -} - -void Export::refreshExportHints() -{ - if (SP_ACTIVE_DESKTOP && !filename_modified) { - SPDocument *doc = SP_ACTIVE_DOCUMENT; - Glib::ustring filename; - float xdpi = 0.0, ydpi = 0.0; - switch (current_key) { - case SELECTION_CUSTOM: - case SELECTION_PAGE: - case SELECTION_DRAWING: - sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); - if (filename.empty()) { - Glib::ustring filename_entry_text = si_filename_entry->get_text(); - Glib::ustring extension_entry_text = si_extension_cb->get_active_text(); - filename = get_default_filename(filename_entry_text, extension_entry_text); - } - doc_export_name = filename; - break; - case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { - break; - } - SP_ACTIVE_DESKTOP->getSelection()->getExportHints(filename, &xdpi, &ydpi); - - /* If we still don't have a filename -- let's build - one that's nice */ - if (filename.empty()) { - const gchar *id = "object"; - auto reprlst = SP_ACTIVE_DESKTOP->getSelection()->xmlNodes(); - for (auto i = reprlst.begin(); reprlst.end() != i; ++i) { - Inkscape::XML::Node *repr = *i; - if (repr->attribute("id")) { - id = repr->attribute("id"); - break; - } - } - filename = create_filepath_from_id(id, si_filename_entry->get_text()); - filename = filename + si_extension_cb->get_active_text(); - } - break; - default: - break; - } - if (!filename.empty()) { - original_name = filename; - si_filename_entry->set_text(filename); - si_filename_entry->set_position(filename.length()); - } - - if (xdpi != 0.0) { - spin_buttons[SPIN_DPI]->set_value(xdpi); - } - } -} - -void Export::setArea(double x0, double y0, double x1, double y1) -{ - blockSpinConns(true); - - auto x0_adj = spin_buttons[SPIN_X0]->get_adjustment(); - auto x1_adj = spin_buttons[SPIN_X1]->get_adjustment(); - auto y0_adj = spin_buttons[SPIN_Y0]->get_adjustment(); - auto y1_adj = spin_buttons[SPIN_Y1]->get_adjustment(); - - setValuePx(x1_adj, x1); - setValuePx(y1_adj, y1); - setValuePx(x0_adj, x0); - setValuePx(y0_adj, y0); - - areaXChange(SPIN_X1); - areaYChange(SPIN_Y1); - - blockSpinConns(false); -} - -Glib::ustring Export::getValidExtension(Glib::ustring &extension, Glib::ustring &original_extension) -{ - if (extension_list[extension]) { - return extension; - } - if (!original_extension.empty()) { - return original_extension; - } - return ".png"; -} /** * SIGNALS @@ -736,297 +108,113 @@ Glib::ustring Export::getValidExtension(Glib::ustring &extension, Glib::ustring // Set current page based on preference/last visited page -void Export::onContainerVisible() -{ - std::cout << "Container Visible" << std::endl; - setDefaultNotebookPage(); - setDefaultSelectionMode(); - setDefaultFilename(); - si_extension_cb->set_active(0); -} - -void Export::onAreaXChange(sb_type type) -{ - blockSpinConns(true); - areaXChange(type); - blockSpinConns(false); -} -void Export::onAreaYChange(sb_type type) -{ - blockSpinConns(true); - areaYChange(type); - blockSpinConns(false); -} -void Export::onDpiChange(sb_type type) -{ - blockSpinConns(true); - dpiChange(type); - blockSpinConns(false); -} - -void Export::onAreaTypeToggle(selection_mode key) -{ - // Prevent executing function twice - if (!selection_buttons[key]->get_active()) { - return; - } - // If you have reached here means the current key is active one ( not sure if multiple transitions happen but - // last call will change values) - current_key = key; - prefs->setString("/dialogs/export/exportarea/value", selection_names[current_key]); - refreshArea(); - refreshExportHints(); -} - -void Export::onUnitChanged() +void Export::onRealize() { - refreshArea(); -} - -void Export::onFilenameModified() -{ - filenameChangedConn.block(); - Glib::ustring filename = si_filename_entry->get_text(); - Glib::ustring filename_extension = get_ext_from_filename(filename); - Glib::ustring active_extension = si_extension_cb->get_active_text(); - Glib::ustring filtered_extension = getValidExtension(filename_extension, active_extension); - - if (original_name == filename) { - filename_modified = false; - } else { - filename_modified = true; - } - std::cout << "Original Name: " << original_name << std::endl; - std::cout << "Filename Name: " << filename << std::endl; - - si_extension_cb->set_active_text(filtered_extension); - - filenameChangedConn.unblock(); -} - -void Export::onExtensionChanged() -{ - filenameChangedConn.block(); - Glib::ustring filename = si_filename_entry->get_text(); - Glib::ustring filename_extension = get_ext_from_filename(filename); - Glib::ustring active_extension = si_extension_cb->get_active_text(); - if (filename_extension == active_extension) { - return; - } - if (extension_list[filename_extension]) { - auto extension_point = filename.rfind(filename_extension); - filename.erase(extension_point); - } - filename = filename + active_extension; - si_filename_entry->set_text(filename); - si_filename_entry->set_position(filename.length()); - - filenameChangedConn.unblock(); + single_image->setup(); + // setDefaultNotebookPage(); } // Single Export Callback. // Do not add batch export widgets check here void Export::onExport() { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) - return; - si_export->set_sensitive(false); - bool exportSuccessful = false; - auto extension = si_extension_cb->get_active_text(); - if (!extension_list[extension]) { - si_export->set_sensitive(true); - return; - } - if (extension_list[extension]->is_raster()) { - double x0 = getValuePx(spin_buttons[SPIN_X0]->get_value()); - double x1 = getValuePx(spin_buttons[SPIN_X1]->get_value()); - double y0 = getValuePx(spin_buttons[SPIN_Y0]->get_value()); - double y1 = getValuePx(spin_buttons[SPIN_Y1]->get_value()); - auto area = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * desktop->dt2doc(); + // SPDesktop *desktop = SP_ACTIVE_DESKTOP; + // if (!desktop) + // return; + // si_export->set_sensitive(false); + // bool exportSuccessful = false; + // auto extension = si_extension_cb->get_active_text(); + // if (!extension_list[extension]) { + // si_export->set_sensitive(true); + // return; + // } + // if (extension_list[extension]->is_raster()) { + // double x0 = getValuePx(spin_buttons[SPIN_X0]->get_value()); + // double x1 = getValuePx(spin_buttons[SPIN_X1]->get_value()); + // double y0 = getValuePx(spin_buttons[SPIN_Y0]->get_value()); + // double y1 = getValuePx(spin_buttons[SPIN_Y1]->get_value()); + // auto area = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * desktop->dt2doc(); - int width = int(spin_buttons[SPIN_BMWIDTH]->get_value() + 0.5); - int height = int(spin_buttons[SPIN_BMHEIGHT]->get_value() + 0.5); + // int width = int(spin_buttons[SPIN_BMWIDTH]->get_value() + 0.5); + // int height = int(spin_buttons[SPIN_BMHEIGHT]->get_value() + 0.5); - double dpi = spin_buttons[SPIN_DPI]->get_value(); + // double dpi = spin_buttons[SPIN_DPI]->get_value(); - Glib::ustring filename = si_filename_entry->get_text(); + // Glib::ustring filename = si_filename_entry->get_text(); - exportSuccessful = _export_raster(area, width, height, dpi, filename, extension_list[extension]); + // exportSuccessful = _export_raster(area, width, height, dpi, filename, extension_list[extension]); - } else { - exportSuccessful = _export_vector(extension_list[extension]); - } - si_export->set_sensitive(true); + // } else { + // exportSuccessful = _export_vector(extension_list[extension]); + // } + // si_export->set_sensitive(true); } bool Export::_export_raster(Geom::Rect const &area, unsigned long int const &width, unsigned long int const &height, float const &dpi, Glib::ustring const &filename, bool overwrite, Inkscape::Extension::Output *extension) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) - return false; - SPNamedView *nv = desktop->getNamedView(); - SPDocument *doc = desktop->getDocument(); - - if (area.hasZeroArea() || width == 0 || height == 0) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("The chosen area to be exported is invalid.")); - sp_ui_error_dialog(_("The chosen area to be exported is invalid")); - return false; - } - if (filename.empty()) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You have to enter a filename.")); - sp_ui_error_dialog(_("You have to enter a filename")); - return false; - } + // SPDesktop *desktop = SP_ACTIVE_DESKTOP; + // if (!desktop) + // return false; + // SPNamedView *nv = desktop->getNamedView(); + // SPDocument *doc = desktop->getDocument(); - if (!extension || !extension->is_raster()) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Raster Export Error")); - sp_ui_error_dialog(_("Raster export Method is used for NON RASTER EXTENSION")); - return false; - } + // if (area.hasZeroArea() || width == 0 || height == 0) { + // desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("The chosen area to be exported is invalid.")); + // sp_ui_error_dialog(_("The chosen area to be exported is invalid")); + // return false; + // } + // if (filename.empty()) { + // desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You have to enter a filename.")); + // sp_ui_error_dialog(_("You have to enter a filename")); + // return false; + // } - // Advance Parameters - const bool use_interlacing = interlacing.get_active(); - const float pHYs = (phys_dpi_sb.get_value() > 0.01) ? phys_dpi_sb.get_value() : dpi; - const int color_type = color_list[bit_depth_cb.get_active_row_number()]; - const int bit_depth = bit_depth_list[bit_depth_cb.get_active_row_number()]; - const int antialiasing = anti_aliasing_list[anti_aliasing_cb.get_active_row_number()]; - const int zlib = compression_list[compression_cb.get_active_row_number()]; + // if (!extension || !extension->is_raster()) { + // desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Raster Export Error")); + // sp_ui_error_dialog(_("Raster export Method is used for NON RASTER EXTENSION")); + // return false; + // } - std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(filename)); - Glib::ustring dirname = Glib::path_get_dirname(path); + // // Advance Parameters + // const bool use_interlacing = interlacing.get_active(); + // const float pHYs = (phys_dpi_sb.get_value() > 0.01) ? phys_dpi_sb.get_value() : dpi; + // const int color_type = color_list[bit_depth_cb.get_active_row_number()]; + // const int bit_depth = bit_depth_list[bit_depth_cb.get_active_row_number()]; + // const int antialiasing = anti_aliasing_list[anti_aliasing_cb.get_active_row_number()]; + // const int zlib = compression_list[compression_cb.get_active_row_number()]; - if (dirname.empty() || - !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { - gchar *safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); - gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), safeDir); + // std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(filename)); + // Glib::ustring dirname = Glib::path_get_dirname(path); - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); - sp_ui_error_dialog(error); + // if (dirname.empty() || + // !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { + // gchar *safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); + // gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), safeDir); - g_free(safeDir); - g_free(error); - return false; - } + // desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); + // sp_ui_error_dialog(error); - // Do the over-write protection now, since the png is just a temp file. - if (!overwrite && !sp_ui_overwrite_file(filename.c_str())) { - return false; - } + // g_free(safeDir); + // g_free(error); + // return false; + // } - auto fn = Glib::path_get_basename(path); - auto png_filename = std::string(path.c_str()); - // Select the extension and set the filename to a temporary file - int tempfd_out = Glib::file_open_tmp(png_filename, "ink_ext_"); - close(tempfd_out); - + // // Do the over-write protection now, since the png is just a temp file. + // if (!overwrite && !sp_ui_overwrite_file(filename.c_str())) { + // return false; + // } - return true; -} + // auto fn = Glib::path_get_basename(path); + // auto png_filename = std::string(path.c_str()); + // // Select the extension and set the filename to a temporary file + // int tempfd_out = Glib::file_open_tmp(png_filename, "ink_ext_"); + // close(tempfd_out); -bool Export::_export_vector(Inkscape::Extension::Output *extension, std::vector *items) -{ - ; return true; } -/** - * UTILS FUNCTIONS - */ - -std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_entry_text) -{ - if (id.empty()) { /* This should never happen */ - id = "bitmap"; - } - - std::string directory; - - if (!file_entry_text.empty()) { - directory = Glib::path_get_dirname(Glib::filename_from_utf8(file_entry_text)); - } - - if (directory.empty()) { - /* Grab document directory */ - const gchar *docFilename = SP_ACTIVE_DOCUMENT->getDocumentFilename(); - if (docFilename) { - directory = Glib::path_get_dirname(docFilename); - } - } - - if (directory.empty()) { - directory = Inkscape::IO::Resource::homedir_path(nullptr); - } - - return Glib::build_filename(directory, Glib::filename_from_utf8(id)); -} - -Glib::ustring get_ext_from_filename(Glib::ustring &filename) -{ - Glib::ustring extension = ""; - if (!filename.empty()) { - auto extension_point = filename.rfind('.'); - if (extension_point != Glib::ustring::npos) { - extension = filename.substr(extension_point); - } - } - return extension; -} - -void append_ext_to_filename(Glib::ustring &filename, Glib::ustring &extention) -{ - if (Glib::str_has_suffix(filename, extention)) { - return; - } - filename = filename + extention; - return; -} - -Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension) -{ - Glib::ustring filename; - if (SP_ACTIVE_DOCUMENT && SP_ACTIVE_DOCUMENT->getDocumentFilename()) { - SPDocument *doc = SP_ACTIVE_DOCUMENT; - filename = doc->getDocumentFilename(); - auto &&text_extension = get_file_save_extension(Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS); - Inkscape::Extension::Output *oextension = nullptr; - if (!text_extension.empty()) { - oextension = - dynamic_cast(Inkscape::Extension::db.get(text_extension.c_str())); - } - if (oextension != nullptr) { - Glib::ustring old_extension = oextension->get_extension(); - if (Glib::str_has_suffix(filename, old_extension)) { - auto extension_point = filename.rfind(old_extension); - filename.erase(extension_point); - } - } - filename = filename + extension; - - } else if (SP_ACTIVE_DOCUMENT) { - filename = create_filepath_from_id(_("bitmap"), filename_entry_text); - filename = filename + extension; - } - return filename; -} - -std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename) -{ - std::string path; - // Make relative paths go from the document location, if possible: - if (!Glib::path_is_absolute(filename) && doc->getDocumentFilename()) { - auto dirname = Glib::path_get_dirname(doc->getDocumentFilename()); - if (!dirname.empty()) { - path = Glib::build_filename(dirname, filename); - } - } - if (path.empty()) { - path = filename; - } - return path; -} } // namespace Dialog } // namespace UI diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 21a8c3b795..8636a8ff72 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -15,6 +15,8 @@ #include +#include "export-helper.h" +#include "export-single.h" #include "extension/output.h" #include "ui/dialog/dialog-base.h" #include "ui/widget/scrollprotected.h" @@ -24,46 +26,12 @@ namespace Inkscape { namespace UI { namespace Dialog { -#define EXPORT_COORD_PRECISION 3 -#define SP_EXPORT_MIN_SIZE 1.0 -#define DPI_BASE Inkscape::Util::Quantity::convert(1, "in", "px") - -enum sb_type -{ - SPIN_X0 = 0, - SPIN_X1, - SPIN_Y0, - SPIN_Y1, - SPIN_WIDTH, - SPIN_HEIGHT, - SPIN_BMWIDTH, - SPIN_BMHEIGHT, - SPIN_DPI -}; - -enum selection_mode -{ - SELECTION_PAGE = 0, // Default is alaways placed first - SELECTION_SELECTION, - SELECTION_DRAWING, - SELECTION_CUSTOM, -}; - enum notebook_page { SINGLE_IMAGE = 0, BATCH_EXPORT }; -class ExportProgressDialog; - -/** - * A dialog widget to export to various image formats such as bitmap and png. - * - * Creates a dialog window for exporting an image to a bitmap if one doesn't already exist and - * shows it to the user. If the dialog has already been created, it simply shows the window. - * - */ class Export : public DialogBase { public: @@ -73,99 +41,23 @@ public: static Export &getInstance() { return *new Export(); } private: - typedef Inkscape::UI::Widget::ScrollProtected SpinButton; - -private: - // builder and its object ( in order ) Glib::RefPtr builder; + // Main Container Gtk::Box *container = nullptr; + // Notebook containing pages for diiferent export types Gtk::Notebook *export_notebook = nullptr; - // These are toggle radio buttons. - std::map selection_buttons; - // These are spin buttons in the dialog. - std::map spin_buttons; - private: - // Single Image Objects Start Here - Gtk::Box *single_image = nullptr; - - Gtk::CheckButton *show_export_area = nullptr; - Inkscape::UI::Widget::UnitMenu *units = nullptr; - - Gtk::CheckButton *si_hide_all = nullptr; - Gtk::Box *si_preview_box = nullptr; - Gtk::CheckButton *si_show_preview = nullptr; - - Gtk::ComboBoxText *si_extension_cb = nullptr; - Gtk::Entry *si_filename_entry = nullptr; - Gtk::Button *si_export = nullptr; - -private: - // Batch Export Start Here + SingleExport *single_image = nullptr; Gtk::Box *batch_export = nullptr; -private: - // Grid to store advance options. We put this grid inside the Box of advance expander where needed. - Gtk::Grid *advance_grid = nullptr; - // Advanced - Gtk::CheckButton interlacing; - std::vector bit_depth_list; - std::vector color_list; - Inkscape::UI::Widget::ScrollProtected bit_depth_cb; - std::vector compression_list; - Inkscape::UI::Widget::ScrollProtected compression_cb; - Inkscape::UI::Widget::ScrollProtected phys_dpi_sb; - std::vector anti_aliasing_list; - Inkscape::UI::Widget::ScrollProtected anti_aliasing_cb; - -private: - // Once user change filename it is set and prevent automatic changes to filename_entry - bool filename_modified; // Batch doesnt need this - // original name for export. Changes everytime selection changes or when exported. - Glib::ustring original_name; // Batch Doesnt need this - // initialised only at startup and is used as fallback for original name. - Glib::ustring doc_export_name; // Batch Doesnt Need this maybe private: // Utils Variables Inkscape::Preferences *prefs = nullptr; - // Selection Names for setting prefs - std::map selection_names; - selection_mode current_key; - std::map extension_list; - - // Initialise all objects from builder - void initialise_all(); - // Add units from db - void setupUnits(); - void setupExtensionList(); - void setupAdvance(); - - // change range and callbacks to spinbuttons - void setupSpinButtons(); - template - void setupSpinButton(Gtk::SpinButton *sb, double val, double min, double max, double step, double page, int digits, - bool sensitive, void (Export::*cb)(T), T param); // setup default values of widgets void setDefaultNotebookPage(); - void setDefaultSelectionMode(); - void setDefaultFilename(); - - // Utils Functions - void areaXChange(sb_type type); - void areaYChange(sb_type type); - void dpiChange(sb_type type); - float getValuePx(float value); - void setValuePx(Glib::RefPtr &adj, double val); - Glib::ustring getValidExtension(Glib::ustring &extension, Glib::ustring &original_extension); - - void blockSpinConns(bool status); - - void refreshArea(); - void refreshExportHints(); - void setArea(double x0, double y0, double x1, double y1); // Export Functions bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsigned long int const &height, @@ -174,16 +66,9 @@ private: bool _export_vector(Inkscape::Extension::Output *extension = nullptr, std::vector *items = nullptr); // signals callback - void onContainerVisible(); - void onAreaXChange(sb_type type); - void onAreaYChange(sb_type type); - void onDpiChange(sb_type type); - void onAreaTypeToggle(selection_mode key); - void onUnitChanged(); + void onRealize(); void onExport(); void onBatchExport(); - void onFilenameModified(); - void onExtensionChanged(); /** * Inkscape selection change callback @@ -191,18 +76,10 @@ private: void onSelectionChanged(); void onSelectionModified(guint flags); - /** - * Update active window. - */ - void update() override; - // signals sigc::connection selectChangedConn; sigc::connection subselChangedConn; sigc::connection selectModifiedConn; - std::vector spinButtonConns; - sigc::connection filenameChangedConn; - sigc::connection siExportConn; }; } // namespace Dialog } // namespace UI -- GitLab From 1654688b01ae8a0ab00ce37a549c6d11f29eaa67 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Thu, 1 Jul 2021 23:32:03 +0530 Subject: [PATCH 13/40] Export connected --- share/ui/dialog-export.glade | 28 +++--- src/ui/dialog/export-helper.cpp | 131 +++++++++++++++++++++++++++- src/ui/dialog/export-helper.h | 33 ++++++- src/ui/dialog/export-single.cpp | 148 +++++++++++++++++++++++++++++--- src/ui/dialog/export-single.h | 30 ++++++- src/ui/dialog/export.cpp | 101 ---------------------- src/ui/dialog/export.h | 5 +- 7 files changed, 335 insertions(+), 141 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index ad3fecc784..78fa6e06d9 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -702,10 +702,11 @@ - + True False + 5 10 @@ -746,22 +747,15 @@ - - - - - - - - - - - - - - - - + + True + False + + + 0 + 1 + 3 + diff --git a/src/ui/dialog/export-helper.cpp b/src/ui/dialog/export-helper.cpp index cb85142918..d1d451035e 100644 --- a/src/ui/dialog/export-helper.cpp +++ b/src/ui/dialog/export-helper.cpp @@ -127,7 +127,6 @@ AdvanceOptions::AdvanceOptions() grid->attach(anti_aliasing_cb, 1, row, 1, 1); row++; } - std::cout<<"Advance Created"< *items, AdvanceOptions *adv) +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (!desktop) + return false; + SPNamedView *nv = desktop->getNamedView(); + SPDocument *doc = desktop->getDocument(); + + if (area.hasZeroArea() || width == 0 || height == 0) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("The chosen area to be exported is invalid.")); + sp_ui_error_dialog(_("The chosen area to be exported is invalid")); + return false; + } + if (filename.empty()) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You have to enter a filename.")); + sp_ui_error_dialog(_("You have to enter a filename")); + return false; + } + + if (!extension || !extension->is_raster()) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Raster Export Error")); + sp_ui_error_dialog(_("Raster export Method is used for NON RASTER EXTENSION")); + return false; + } + + // Advance Parameters default value. We will change them later if adv dialog is provided. + bool use_interlacing = false; // Maybe use prefs here? + float pHYs = dpi; // default is dpi. + int bit_depth = 8; // corresponds to RGBA 8 + int color_type = 6; // corresponds to RGBA 8 + int zlib = 6; // Z_DEFAULT_COMPRESSION + int antialiasing = 2; // Cairo anti aliasing + + if (adv) { + use_interlacing = adv->get_interlacing(); + if (adv->get_pHYs() > 0.01) { + pHYs = adv->get_pHYs(); + } + bit_depth = adv->get_bit_depth(); + color_type = adv->get_color(); + zlib = adv->get_compression(); + antialiasing = adv->get_anti_aliasing(); + } + + std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(filename)); + Glib::ustring dirname = Glib::path_get_dirname(path); + + if (dirname.empty() || + !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { + gchar *safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); + gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), safeDir); + + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); + sp_ui_error_dialog(error); + + g_free(safeDir); + g_free(error); + return false; + } + + // Do the over-write protection now, since the png is just a temp file. + if (!overwrite && !sp_ui_overwrite_file(path.c_str())) { + return false; + } + + auto fn = Glib::path_get_basename(path); + auto png_filename = path; + { + // Select the extension and set the filename to a temporary file + int tempfd_out = Glib::file_open_tmp(png_filename, "ink_ext_"); + close(tempfd_out); + } + + // Export Start Here + std::vector selected; + if (items) { + selected = *items; + } + + ExportResult result = sp_export_png_file(desktop->getDocument(), png_filename.c_str(), area, width, height, pHYs, + pHYs, // previously xdpi, ydpi. + nv->pagecolor, callback, (void *)prog_dialog, true, selected, + use_interlacing, color_type, bit_depth, zlib, antialiasing); + + delete prog_dialog; + if (result == EXPORT_ERROR) { + gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); + gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); + + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); + sp_ui_error_dialog(error); + + g_free(safeFile); + g_free(error); + return false; + } else if (result == EXPORT_OK) { + if (extension->prefs()) { + try { + extension->export_raster(doc, png_filename, path.c_str(), false); + } catch (Inkscape::Extension::Output::save_failed &e) { + return false; + } + } else { + return false; + } + + } else { + // Extensions have their own error popup, so this only tracks failures in the png step + desktop->messageStack()->flash(Inkscape::INFORMATION_MESSAGE, _("Export aborted.")); + return false; + } + + auto recentmanager = Gtk::RecentManager::get_default(); + if (recentmanager && Glib::path_is_absolute(path)) { + Glib::ustring uri = Glib::filename_to_uri(path); + recentmanager->add_item(uri); + } + + gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); + desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, _("Drawing exported to %s."), safeFile); + g_free(safeFile); + + + unlink(png_filename.c_str()); + return true; +} + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export-helper.h b/src/ui/dialog/export-helper.h index 2705042d44..899de2b38f 100644 --- a/src/ui/dialog/export-helper.h +++ b/src/ui/dialog/export-helper.h @@ -105,11 +105,37 @@ public: static bool list_created; static void appendExtensionToFilename(Glib::ustring &filename, Glib::ustring &extension); -private: +public: static std::map valid_extensions; static std::map all_extensions; }; +class ExportProgressDialog : public Gtk::Dialog +{ +private: + Gtk::ProgressBar *_progress = nullptr; + Gtk::Widget *_export_panel = nullptr; + int _current = 0; + int _total = 0; + +public: + ExportProgressDialog(const Glib::ustring &title, bool modal = false) + : Gtk::Dialog(title, modal) + {} + + inline void set_export_panel(const decltype(_export_panel) export_panel) { _export_panel = export_panel; } + inline decltype(_export_panel) get_export_panel() const { return _export_panel; } + + inline void set_progress(const decltype(_progress) progress) { _progress = progress; } + inline decltype(_progress) get_progress() const { return _progress; } + + inline void set_current(const int current) { _current = current; } + inline int get_current() const { return _current; } + + inline void set_total(const int total) { _total = total; } + inline int get_total() const { return _total; } +}; + float getValuePx(float value, Unit const *unit); void setValuePx(Glib::RefPtr &adj, double val, Unit const *unit); Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension); @@ -117,6 +143,11 @@ std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_ Glib::ustring get_ext_from_filename(Glib::ustring const &filename); std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename); +bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsigned long int const &height, + float const &dpi, Glib::ustring const &filename, bool overwrite, unsigned (*callback)(float, void *), + ExportProgressDialog* prog_dialog, Inkscape::Extension::Output *extension, std::vector *items = nullptr, + AdvanceOptions *adv = nullptr); + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index 50f98aeb3f..63a5ecaf3d 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -89,13 +89,13 @@ void SingleExport::initialise(const Glib::RefPtr &builder) builder->get_widget("si_filename", si_filename_entry); builder->get_widget("si_export", si_export); + builder->get_widget("si_progress", _prog); + builder->get_widget("si_advance_box", adv_box); } void SingleExport::on_realize() { - std::cout << "SINGLE RE" << std::endl; - auto desktop = SP_ACTIVE_DESKTOP; assert(desktop); auto *selection = desktop->getSelection(); @@ -110,7 +110,6 @@ void SingleExport::on_realize() void SingleExport::on_unrealize() { - std::cout << "SINGLE UNRE" << std::endl; selectionModifiedConn.disconnect(); selectionChangedConn.disconnect(); Gtk::Box::on_unrealize(); @@ -369,15 +368,6 @@ void SingleExport::setArea(double x0, double y0, double x1, double y1) // Signals CallBack -void SingleExport::onRealize() -{ - ; -} -void SingleExport::onUnrealize() -{ - ; -} - void SingleExport::onUnitChanged() { refreshArea(); @@ -444,7 +434,53 @@ void SingleExport::onExtensionChanged() void SingleExport::onExport() { - ; + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (!desktop) + return; + si_export->set_sensitive(false); + bool exportSuccessful = false; + auto extension = si_extension_cb->get_active_text(); + if (!ExtensionList::valid_extensions[extension]) { + si_export->set_sensitive(true); + return; + } + + auto omod = ExtensionList::valid_extensions[extension]; + Unit const *unit = units->getUnit(); + + Glib::ustring filename = si_filename_entry->get_text(); + + if (omod->is_raster()) { + float x0 = getValuePx(spin_buttons[SPIN_X0]->get_value(), unit); + float x1 = getValuePx(spin_buttons[SPIN_X1]->get_value(), unit); + float y0 = getValuePx(spin_buttons[SPIN_Y0]->get_value(), unit); + float y1 = getValuePx(spin_buttons[SPIN_Y1]->get_value(), unit); + auto area = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * desktop->dt2doc(); + + unsigned long int width = int(spin_buttons[SPIN_BMWIDTH]->get_value() + 0.5); + unsigned long int height = int(spin_buttons[SPIN_BMHEIGHT]->get_value() + 0.5); + + float dpi = spin_buttons[SPIN_DPI]->get_value(); + + /* TRANSLATORS: %1 will be the filename, %2 the width, and %3 the height of the image */ + prog_dlg = create_progress_dialog(Glib::ustring::compose(_("Exporting %1 (%2 x %3)"), filename, width, height)); + prog_dlg->set_export_panel(this); + setExporting(true, Glib::ustring::compose(_("Exporting %1 (%2 x %3)"), filename, width, height)); + prog_dlg->set_current(0); + prog_dlg->set_total(0); + + exportSuccessful = _export_raster(area, width, height, dpi, filename, false, onProgressCallback, prog_dlg, omod, + nullptr, &advance_options); + + } else { + // exportSuccessful = _export_vector(omod); + } + setExporting(false); + si_export->set_sensitive(true); + original_name = filename; + filename_modified = false; + prog_dlg = nullptr; + interrupted = false; } // Utils Functions @@ -652,6 +688,92 @@ void SingleExport::setDefaultSelectionMode() } } +void SingleExport::setExporting(bool exporting, Glib::ustring const &text) +{ + if (exporting) { + _prog->set_text(text); + _prog->set_fraction(0.0); + _prog->set_sensitive(true); + si_export->set_sensitive(false); + } else { + _prog->set_text(""); + _prog->set_fraction(0.0); + _prog->set_sensitive(false); + + si_export->set_sensitive(true); + } +} + +ExportProgressDialog *SingleExport::create_progress_dialog(Glib::ustring progress_text) +{ + // dont forget to delete it later + auto dlg = new ExportProgressDialog(_("Export in progress"), true); + dlg->set_transient_for(*(INKSCAPE.active_desktop()->getToplevel())); + + Gtk::ProgressBar *prg = Gtk::manage(new Gtk::ProgressBar()); + prg->set_text(progress_text); + dlg->set_progress(prg); + auto CA = dlg->get_content_area(); + CA->pack_start(*prg, FALSE, FALSE, 4); + + Gtk::Button *btn = dlg->add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL); + + btn->signal_clicked().connect(sigc::mem_fun(*this, &SingleExport::onProgressCancel)); + dlg->signal_delete_event().connect(sigc::mem_fun(*this, &SingleExport::onProgressDelete)); + + dlg->show_all(); + return dlg; +} + +/// Called when dialog is deleted +bool SingleExport::onProgressDelete(GdkEventAny * /*event*/) +{ + interrupted = true; + return TRUE; +} // end of sp_export_progress_delete() + +/// Called when progress is cancelled +void SingleExport::onProgressCancel() +{ + interrupted = true; +} // end of sp_export_progress_cancel() + +/// Called for every progress iteration +unsigned int SingleExport::onProgressCallback(float value, void *dlg) +{ + auto dlg2 = reinterpret_cast(dlg); + + auto self = dynamic_cast(dlg2->get_export_panel()); + + if (!self || self->interrupted) + return FALSE; + + auto current = dlg2->get_current(); + auto total = dlg2->get_total(); + if (total > 0) { + double completed = current; + completed /= static_cast(total); + + value = completed + (value / static_cast(total)); + } + + auto prg = dlg2->get_progress(); + prg->set_fraction(value); + + if (self) { + self->_prog->set_fraction(value); + } + + int evtcount = 0; + while ((evtcount < 16) && gdk_events_pending()) { + Gtk::Main::iteration(false); + evtcount += 1; + } + + Gtk::Main::iteration(false); + return TRUE; +} // end of sp_export_progress_callback() + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export-single.h b/src/ui/dialog/export-single.h index 8acf0a1c81..6524c21834 100644 --- a/src/ui/dialog/export-single.h +++ b/src/ui/dialog/export-single.h @@ -71,6 +71,7 @@ private: Gtk::Entry *si_filename_entry = nullptr; Gtk::Button *si_export = nullptr; Gtk::Box *adv_box = nullptr; + Gtk::ProgressBar *_prog = nullptr; AdvanceOptions advance_options; @@ -100,10 +101,6 @@ private: bool sensitive, void (SingleExport::*cb)(T), T param); private: - // signals callback - void onRealize(); - void onUnrealize(); - void onAreaXChange(sb_type type); void onAreaYChange(sb_type type); void onDpiChange(sb_type type); @@ -125,6 +122,31 @@ private: void setArea(double x0, double y0, double x1, double y1); void blockSpinConns(bool status); +private: + void setExporting(bool exporting, Glib::ustring const &text = ""); + ExportProgressDialog *create_progress_dialog(Glib::ustring progress_text); + /** + * Callback to be used in for loop to update the progress bar. + * + * @param value number between 0 and 1 indicating the fraction of progress (0.17 = 17 % progress) + * @param dlg void pointer to the Gtk::Dialog progress dialog + */ + static unsigned int onProgressCallback(float value, void *dlg); + + /** + * Callback for pressing the cancel button. + */ + void onProgressCancel(); + + /** + * Callback invoked on closing the progress dialog. + */ + bool onProgressDelete(GdkEventAny *event); + +private: + ExportProgressDialog *prog_dlg; + bool interrupted; + private: void setDefaultSelectionMode(); void setDefaultFilename(); diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index c55c6fa8c9..ada8d10c27 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -114,107 +114,6 @@ void Export::onRealize() // setDefaultNotebookPage(); } -// Single Export Callback. -// Do not add batch export widgets check here -void Export::onExport() -{ - // SPDesktop *desktop = SP_ACTIVE_DESKTOP; - // if (!desktop) - // return; - // si_export->set_sensitive(false); - // bool exportSuccessful = false; - // auto extension = si_extension_cb->get_active_text(); - // if (!extension_list[extension]) { - // si_export->set_sensitive(true); - // return; - // } - // if (extension_list[extension]->is_raster()) { - // double x0 = getValuePx(spin_buttons[SPIN_X0]->get_value()); - // double x1 = getValuePx(spin_buttons[SPIN_X1]->get_value()); - // double y0 = getValuePx(spin_buttons[SPIN_Y0]->get_value()); - // double y1 = getValuePx(spin_buttons[SPIN_Y1]->get_value()); - // auto area = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * desktop->dt2doc(); - - // int width = int(spin_buttons[SPIN_BMWIDTH]->get_value() + 0.5); - // int height = int(spin_buttons[SPIN_BMHEIGHT]->get_value() + 0.5); - - // double dpi = spin_buttons[SPIN_DPI]->get_value(); - - // Glib::ustring filename = si_filename_entry->get_text(); - - // exportSuccessful = _export_raster(area, width, height, dpi, filename, extension_list[extension]); - - // } else { - // exportSuccessful = _export_vector(extension_list[extension]); - // } - // si_export->set_sensitive(true); -} - -bool Export::_export_raster(Geom::Rect const &area, unsigned long int const &width, unsigned long int const &height, - float const &dpi, Glib::ustring const &filename, bool overwrite, - Inkscape::Extension::Output *extension) -{ - // SPDesktop *desktop = SP_ACTIVE_DESKTOP; - // if (!desktop) - // return false; - // SPNamedView *nv = desktop->getNamedView(); - // SPDocument *doc = desktop->getDocument(); - - // if (area.hasZeroArea() || width == 0 || height == 0) { - // desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("The chosen area to be exported is invalid.")); - // sp_ui_error_dialog(_("The chosen area to be exported is invalid")); - // return false; - // } - // if (filename.empty()) { - // desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You have to enter a filename.")); - // sp_ui_error_dialog(_("You have to enter a filename")); - // return false; - // } - - // if (!extension || !extension->is_raster()) { - // desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Raster Export Error")); - // sp_ui_error_dialog(_("Raster export Method is used for NON RASTER EXTENSION")); - // return false; - // } - - // // Advance Parameters - // const bool use_interlacing = interlacing.get_active(); - // const float pHYs = (phys_dpi_sb.get_value() > 0.01) ? phys_dpi_sb.get_value() : dpi; - // const int color_type = color_list[bit_depth_cb.get_active_row_number()]; - // const int bit_depth = bit_depth_list[bit_depth_cb.get_active_row_number()]; - // const int antialiasing = anti_aliasing_list[anti_aliasing_cb.get_active_row_number()]; - // const int zlib = compression_list[compression_cb.get_active_row_number()]; - - // std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(filename)); - // Glib::ustring dirname = Glib::path_get_dirname(path); - - // if (dirname.empty() || - // !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { - // gchar *safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); - // gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), safeDir); - - // desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); - // sp_ui_error_dialog(error); - - // g_free(safeDir); - // g_free(error); - // return false; - // } - - // // Do the over-write protection now, since the png is just a temp file. - // if (!overwrite && !sp_ui_overwrite_file(filename.c_str())) { - // return false; - // } - - // auto fn = Glib::path_get_basename(path); - // auto png_filename = std::string(path.c_str()); - // // Select the extension and set the filename to a temporary file - // int tempfd_out = Glib::file_open_tmp(png_filename, "ink_ext_"); - // close(tempfd_out); - - return true; -} - } // namespace Dialog } // namespace UI diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 8636a8ff72..af4b5c12a9 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -60,14 +60,11 @@ private: void setDefaultNotebookPage(); // Export Functions - bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsigned long int const &height, - float const &dpi, Glib::ustring const &filename, bool overwrite, - Inkscape::Extension::Output *extension); + bool _export_vector(Inkscape::Extension::Output *extension = nullptr, std::vector *items = nullptr); // signals callback void onRealize(); - void onExport(); void onBatchExport(); /** -- GitLab From 9faeba47ce6b2f97c3e72d6a6cfd607eb9c310d4 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Fri, 2 Jul 2021 00:12:54 +0530 Subject: [PATCH 14/40] Added stop to prevent creating corrupted file at file location --- src/ui/dialog/export-helper.cpp | 3 ++- src/ui/dialog/export-helper.h | 5 +++++ src/ui/dialog/export-single.cpp | 2 ++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ui/dialog/export-helper.cpp b/src/ui/dialog/export-helper.cpp index d1d451035e..5ba3f75396 100644 --- a/src/ui/dialog/export-helper.cpp +++ b/src/ui/dialog/export-helper.cpp @@ -393,8 +393,9 @@ bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsi nv->pagecolor, callback, (void *)prog_dialog, true, selected, use_interlacing, color_type, bit_depth, zlib, antialiasing); + bool failed = result == EXPORT_ERROR || prog_dialog->get_stopped(); delete prog_dialog; - if (result == EXPORT_ERROR) { + if (failed){ gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); diff --git a/src/ui/dialog/export-helper.h b/src/ui/dialog/export-helper.h index 899de2b38f..3e17545db5 100644 --- a/src/ui/dialog/export-helper.h +++ b/src/ui/dialog/export-helper.h @@ -117,6 +117,7 @@ private: Gtk::Widget *_export_panel = nullptr; int _current = 0; int _total = 0; + bool _stopped = false; public: ExportProgressDialog(const Glib::ustring &title, bool modal = false) @@ -134,6 +135,10 @@ public: inline void set_total(const int total) { _total = total; } inline int get_total() const { return _total; } + + inline bool get_stopped() const { return _stopped; } + inline void set_stopped() { _stopped = true; } + }; float getValuePx(float value, Unit const *unit); diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index 63a5ecaf3d..18ac9f602f 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -729,6 +729,7 @@ ExportProgressDialog *SingleExport::create_progress_dialog(Glib::ustring progres bool SingleExport::onProgressDelete(GdkEventAny * /*event*/) { interrupted = true; + prog_dlg->set_stopped(); return TRUE; } // end of sp_export_progress_delete() @@ -736,6 +737,7 @@ bool SingleExport::onProgressDelete(GdkEventAny * /*event*/) void SingleExport::onProgressCancel() { interrupted = true; + prog_dlg->set_stopped(); } // end of sp_export_progress_cancel() /// Called for every progress iteration -- GitLab From 03e89bc5793ae6a81362f6caad5c600dc08b6e56 Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Fri, 2 Jul 2021 01:42:22 +0530 Subject: [PATCH 15/40] connected browse with icon click --- src/ui/dialog/export-single.cpp | 32 ++++++++++++++++++++++++++++++++ src/ui/dialog/export-single.h | 6 ++++++ src/ui/dialog/export.cpp | 5 ++--- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index 18ac9f602f..a7f8f343dc 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -200,6 +200,7 @@ void SingleExport::setup() filenameConn = si_filename_entry->signal_changed().connect(sigc::mem_fun(*this, &SingleExport::onFilenameModified)); extensionConn = si_extension_cb->signal_changed().connect(sigc::mem_fun(*this, &SingleExport::onExtensionChanged)); exportConn = si_export->signal_clicked().connect(sigc::mem_fun(*this, &SingleExport::onExport)); + si_filename_entry->signal_icon_press().connect(sigc::mem_fun(*this, &SingleExport::onBrowse)); } // Setup units combobox @@ -438,6 +439,7 @@ void SingleExport::onExport() if (!desktop) return; si_export->set_sensitive(false); + interrupted = false; bool exportSuccessful = false; auto extension = si_extension_cb->get_active_text(); if (!ExtensionList::valid_extensions[extension]) { @@ -483,6 +485,36 @@ void SingleExport::onExport() interrupted = false; } +void SingleExport::onBrowse(Gtk::EntryIconPosition pos, const GdkEventButton *ev) +{ + Gtk::Window *window = _app->get_active_window(); + Glib::ustring filename = Glib::filename_from_utf8(si_filename_entry->get_text()); + + if (filename.empty()) { + Glib::ustring tmp; + filename = create_filepath_from_id(tmp, tmp); + } + + Inkscape::UI::Dialog::FileSaveDialog *dialog = Inkscape::UI::Dialog::FileSaveDialog::create( + *window, filename, Inkscape::UI::Dialog::RASTER_TYPES, _("Select a filename for exporting"), "", "", + Inkscape::Extension::FILE_SAVE_METHOD_EXPORT); + + if (dialog->show()) { + filename = dialog->getFilename(); + Inkscape::Extension::Output* selection_type = dynamic_cast(dialog->getSelectionType()); + Glib::ustring extension = selection_type->get_extension(); + ExtensionList::appendExtensionToFilename(filename,extension); + si_filename_entry->set_text(filename); + si_filename_entry->set_position(filename.length()); + // deleting dialog before exporting is important + // proper delete function should be made for dialog IMO + delete dialog; + onExport(); + } else { + delete dialog; + } +} + // Utils Functions void SingleExport::blockSpinConns(bool status = true) diff --git a/src/ui/dialog/export-single.h b/src/ui/dialog/export-single.h index 6524c21834..912bc12281 100644 --- a/src/ui/dialog/export-single.h +++ b/src/ui/dialog/export-single.h @@ -33,6 +33,11 @@ public: : Gtk::Box(cobject){}; ~SingleExport() override; +protected: + InkscapeApplication *_app; +public: + void set_app(InkscapeApplication *app) { _app = app; }; + private: enum sb_type { @@ -109,6 +114,7 @@ private: void onFilenameModified(); void onExtensionChanged(); void onExport(); + void onBrowse(Gtk::EntryIconPosition pos, const GdkEventButton *ev); void on_inkscape_selection_modified(Inkscape::Selection *selection, guint flags); void on_inkscape_selection_changed(Inkscape::Selection *selection); diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index ada8d10c27..871a61f953 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -83,6 +83,8 @@ Export::Export() builder->get_widget("Batch Export", batch_export); // Callback when container is dinally mapped on window. All intialisation like set active is done inside it. container->signal_realize().connect(sigc::mem_fun(*this, &Export::onRealize)); + + single_image->set_app(_app); } Export::~Export() @@ -92,7 +94,6 @@ Export::~Export() selectChangedConn.disconnect(); } - void Export::setDefaultNotebookPage() { // if (export_notebook && batch_export) { @@ -101,7 +102,6 @@ void Export::setDefaultNotebookPage() // } } - /** * SIGNALS */ @@ -114,7 +114,6 @@ void Export::onRealize() // setDefaultNotebookPage(); } - } // namespace Dialog } // namespace UI } // namespace Inkscape -- GitLab From 9d89863e06833c991ab061e6b2871e7fd637904d Mon Sep 17 00:00:00 2001 From: Anshudhar Date: Fri, 2 Jul 2021 15:35:09 +0530 Subject: [PATCH 16/40] Added SVG export --- share/ui/dialog-export.glade | 18 + src/object/sp-object.cpp | 631 ++++++++++++++++++-------------- src/object/sp-object.h | 1 + src/ui/dialog/export-helper.cpp | 117 +++++- src/ui/dialog/export-helper.h | 9 +- src/ui/dialog/export-single.cpp | 50 ++- src/ui/dialog/export-single.h | 16 +- src/ui/dialog/export.cpp | 35 +- src/ui/dialog/export.h | 19 +- 9 files changed, 553 insertions(+), 343 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 78fa6e06d9..08072beb02 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -49,6 +49,8 @@ True True True + 0 + 0 False @@ -61,6 +63,8 @@ True True True + 0 + 0 4 @@ -72,6 +76,8 @@ True True True + 0 + 0 2 @@ -83,6 +89,8 @@ True True True + 0 + 0 4 @@ -113,6 +121,8 @@ True center True + 0 + 0 4 @@ -266,6 +276,8 @@ True center True + 0 + 0 2 @@ -347,6 +359,8 @@ True True True + 0 + 0 4 @@ -358,6 +372,8 @@ True True True + 0 + 0 2 @@ -370,6 +386,8 @@ True start True + 0 + 0 2 diff --git a/src/object/sp-object.cpp b/src/object/sp-object.cpp index 2c90bf1904..c88e807824 100644 --- a/src/object/sp-object.cpp +++ b/src/object/sp-object.cpp @@ -16,61 +16,57 @@ * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ +#include #include +#include #include #include -#include - -#include -#include "helper/sp-marshal.h" -#include "xml/node-event-vector.h" -#include "attributes.h" #include "attribute-rel-util.h" +#include "attributes.h" #include "color-profile.h" +#include "debug/demangle.h" +#include "debug/event-tracker.h" +#include "debug/simple-event.h" #include "document.h" -#include "preferences.h" -#include "style.h" +#include "helper/sp-marshal.h" #include "live_effects/lpeobject.h" +#include "preferences.h" #include "sp-factory.h" #include "sp-paint-server.h" #include "sp-root.h" -#include "sp-style-elem.h" #include "sp-script.h" +#include "sp-style-elem.h" #include "streq.h" #include "strneq.h" -#include "xml/node-fns.h" -#include "debug/event-tracker.h" -#include "debug/simple-event.h" -#include "debug/demangle.h" +#include "style.h" #include "util/format.h" #include "util/longest-common-suffix.h" +#include "xml/node-event-vector.h" +#include "xml/node-fns.h" #define noSP_OBJECT_DEBUG_CASCADE #define noSP_OBJECT_DEBUG #ifdef SP_OBJECT_DEBUG -# define debug(f, a...) { g_print("%s(%d) %s:", \ - __FILE__,__LINE__,__FUNCTION__); \ - g_print(f, ## a); \ - g_print("\n"); \ - } +#define debug(f, a...) \ + { \ + g_print("%s(%d) %s:", __FILE__, __LINE__, __FUNCTION__); \ + g_print(f, ##a); \ + g_print("\n"); \ + } #else -# define debug(f, a...) /* */ +#define debug(f, a...) /* */ #endif // Define to enable indented tracing of SPObject. //#define OBJECT_TRACE unsigned SPObject::indent_level = 0; -Inkscape::XML::NodeEventVector object_event_vector = { - SPObject::repr_child_added, - SPObject::repr_child_removed, - SPObject::repr_attr_changed, - SPObject::repr_content_changed, - SPObject::repr_order_changed -}; +Inkscape::XML::NodeEventVector object_event_vector = {SPObject::repr_child_added, SPObject::repr_child_removed, + SPObject::repr_attr_changed, SPObject::repr_content_changed, + SPObject::repr_order_changed}; /** * A friend class used to set internal members on SPObject so as to not expose settors in SPObject's public API @@ -78,26 +74,27 @@ Inkscape::XML::NodeEventVector object_event_vector = { class SPObjectImpl { public: - -/** - * Null's the id member of an SPObject without attempting to free prior contents. - * - * @param[inout] obj Pointer to the object which's id shall be nulled. - */ - static void setIdNull( SPObject* obj ) { + /** + * Null's the id member of an SPObject without attempting to free prior contents. + * + * @param[inout] obj Pointer to the object which's id shall be nulled. + */ + static void setIdNull(SPObject *obj) + { if (obj) { obj->id = nullptr; } } -/** - * Sets the id member of an object, freeing any prior content. - * - * @param[inout] obj Pointer to the object which's id shall be set. - * @param[in] id New id - */ - static void setId( SPObject* obj, gchar const* id ) { - if (obj && (id != obj->id) ) { + /** + * Sets the id member of an object, freeing any prior content. + * + * @param[inout] obj Pointer to the object which's id shall be set. + * @param[in] id New id + */ + static void setId(SPObject *obj, gchar const *id) + { + if (obj && (id != obj->id)) { if (obj->id) { g_free(obj->id); obj->id = nullptr; @@ -113,14 +110,26 @@ public: * Constructor, sets all attributes to default values. */ SPObject::SPObject() - : cloned(0), clone_original(nullptr), uflags(0), mflags(0), hrefcount(0), _total_hrefcount(0), - document(nullptr), parent(nullptr), id(nullptr), repr(nullptr), refCount(1), hrefList(std::list()), - _successor(nullptr), _collection_policy(SPObject::COLLECT_WITH_PARENT), - _label(nullptr), _default_label(nullptr) + : cloned(0) + , clone_original(nullptr) + , uflags(0) + , mflags(0) + , hrefcount(0) + , _total_hrefcount(0) + , document(nullptr) + , parent(nullptr) + , id(nullptr) + , repr(nullptr) + , refCount(1) + , hrefList(std::list()) + , _successor(nullptr) + , _collection_policy(SPObject::COLLECT_WITH_PARENT) + , _label(nullptr) + , _default_label(nullptr) { - debug("id=%p, typename=%s",this, g_type_name_from_instance((GTypeInstance*)this)); + debug("id=%p, typename=%s", this, g_type_name_from_instance((GTypeInstance *)this)); - //used XML Tree here. + // used XML Tree here. this->getRepr(); // TODO check why this call is made SPObjectImpl::setIdNull(this); @@ -129,14 +138,15 @@ SPObject::SPObject() // vg, g, defs, desc, title, symbol, use, image, switch, path, rect, circle, ellipse, line, polyline, // polygon, text, tspan, tref, textPath, altGlyph, glyphRef, marker, linearGradient, radialGradient, // stop, pattern, clipPath, mask, filter, feImage, a, font, glyph, missing-glyph, foreignObject - this->style = new SPStyle( nullptr, this ); // Is it necessary to call with "this"? + this->style = new SPStyle(nullptr, this); // Is it necessary to call with "this"? this->context_style = nullptr; } /** * Destructor, frees the used memory and unreferences a potential successor of the object. */ -SPObject::~SPObject() { +SPObject::~SPObject() +{ g_free(this->_label); g_free(this->_default_label); @@ -151,11 +161,11 @@ SPObject::~SPObject() { parent->children.erase(parent->children.iterator_to(*this)); } - if( style == nullptr ) { + if (style == nullptr) { // style pointer could be NULL if unreffed too many times. // Conjecture: style pointer is never NULL. std::cerr << "SPObject::~SPObject(): style pointer is NULL" << std::endl; - } else if( style->refCount() > 1 ) { + } else if (style->refCount() > 1) { // Conjecture: style pointer should be unreffed by other classes before reaching here. // Conjecture is false for SPTSpan where ref is held by InputStreamTextSource. // As an additional note: @@ -164,27 +174,30 @@ SPObject::~SPObject() { // one for the one after, along with one for each corresponding DrawingText instance. // std::cerr << "SPObject::~SPObject(): someone else still holding ref to style" << std::endl; // - sp_style_unref( this->style ); + sp_style_unref(this->style); } else { delete this->style; } } // CPPIFY: make pure virtual -void SPObject::read_content() { - //throw; +void SPObject::read_content() +{ + // throw; } -void SPObject::update(SPCtx* /*ctx*/, unsigned int /*flags*/) { - //throw; +void SPObject::update(SPCtx * /*ctx*/, unsigned int /*flags*/) +{ + // throw; } -void SPObject::modified(unsigned int /*flags*/) { +void SPObject::modified(unsigned int /*flags*/) +{ #ifdef OBJECT_TRACE - objectTrace( "SPObject::modified (default) (empty function)" ); - objectTrace( "SPObject::modified (default)", false ); + objectTrace("SPObject::modified (default) (empty function)"); + objectTrace("SPObject::modified (default)", false); #endif - //throw; + // throw; } namespace { @@ -194,10 +207,11 @@ namespace Util = Inkscape::Util; typedef Debug::SimpleEvent BaseRefCountEvent; -class RefCountEvent : public BaseRefCountEvent { +class RefCountEvent : public BaseRefCountEvent +{ public: RefCountEvent(SPObject *object, int bias, char const *name) - : BaseRefCountEvent(name) + : BaseRefCountEvent(name) { _addProperty("object", Util::format("%p", object).pointer()); _addProperty("class", Debug::demangle(typeid(*object).name())); @@ -205,45 +219,50 @@ public: } }; -class RefEvent : public RefCountEvent { +class RefEvent : public RefCountEvent +{ public: RefEvent(SPObject *object) - : RefCountEvent(object, 1, "sp-object-ref") + : RefCountEvent(object, 1, "sp-object-ref") {} }; -class UnrefEvent : public RefCountEvent { +class UnrefEvent : public RefCountEvent +{ public: UnrefEvent(SPObject *object) - : RefCountEvent(object, -1, "sp-object-unref") + : RefCountEvent(object, -1, "sp-object-unref") {} }; -} +} // namespace -gchar const* SPObject::getId() const { +gchar const *SPObject::getId() const +{ return id; } /** * Returns the id as a url param, in the form 'url(#{id})' */ -std::string SPObject::getUrl() const { +std::string SPObject::getUrl() const +{ if (id) { return std::string("url(#") + id + ")"; } return ""; } -Inkscape::XML::Node * SPObject::getRepr() { +Inkscape::XML::Node *SPObject::getRepr() +{ return repr; } -Inkscape::XML::Node const* SPObject::getRepr() const{ +Inkscape::XML::Node const *SPObject::getRepr() const +{ return repr; } - SPObject *sp_object_ref(SPObject *object, SPObject *owner) { g_return_val_if_fail(object != nullptr, NULL); @@ -274,7 +293,7 @@ SPObject *sp_object_unref(SPObject *object, SPObject *owner) return nullptr; } -void SPObject::hrefObject(SPObject* owner) +void SPObject::hrefObject(SPObject *owner) { // if (owner) std::cout << " owner: " << *owner << std::endl; @@ -284,11 +303,11 @@ void SPObject::hrefObject(SPObject* owner) _updateTotalHRefCount(1); } - if(owner) + if (owner) hrefList.push_front(owner); } -void SPObject::unhrefObject(SPObject* owner) +void SPObject::unhrefObject(SPObject *owner) { g_return_if_fail(hrefcount > 0); @@ -297,20 +316,19 @@ void SPObject::unhrefObject(SPObject* owner) _updateTotalHRefCount(-1); } - if(owner) + if (owner) hrefList.remove(owner); } -void SPObject::_updateTotalHRefCount(int increment) { +void SPObject::_updateTotalHRefCount(int increment) +{ SPObject *topmost_collectable = nullptr; - for ( SPObject *iter = this ; iter ; iter = iter->parent ) { + for (SPObject *iter = this; iter; iter = iter->parent) { iter->_total_hrefcount += increment; - if ( iter->_total_hrefcount < iter->hrefcount ) { + if (iter->_total_hrefcount < iter->hrefcount) { g_critical("HRefs overcounted"); } - if ( iter->_total_hrefcount == 0 && - iter->_collection_policy != COLLECT_WITH_PARENT ) - { + if (iter->_total_hrefcount == 0 && iter->_collection_policy != COLLECT_WITH_PARENT) { topmost_collectable = iter; } } @@ -319,11 +337,12 @@ void SPObject::_updateTotalHRefCount(int increment) { } } -bool SPObject::isAncestorOf(SPObject const *object) const { +bool SPObject::isAncestorOf(SPObject const *object) const +{ g_return_val_if_fail(object != nullptr, false); object = object->parent; while (object) { - if ( object == this ) { + if (object == this) { return true; } object = object->parent; @@ -331,16 +350,18 @@ bool SPObject::isAncestorOf(SPObject const *object) const { return false; } -SPObject const *SPObject::nearestCommonAncestor(SPObject const *object) const { +SPObject const *SPObject::nearestCommonAncestor(SPObject const *object) const +{ g_return_val_if_fail(object != nullptr, NULL); using Inkscape::Algorithms::nearest_common_ancestor; return nearest_common_ancestor(this, object, nullptr); } -static SPObject const *AncestorSon(SPObject const *obj, SPObject const *ancestor) { +static SPObject const *AncestorSon(SPObject const *obj, SPObject const *ancestor) +{ SPObject const *result = nullptr; - if ( obj && ancestor ) { + if (obj && ancestor) { if (obj->parent == ancestor) { result = obj; } else { @@ -356,7 +377,7 @@ int sp_object_compare_position(SPObject const *first, SPObject const *second) if (first != second) { SPObject const *ancestor = first->nearestCommonAncestor(second); // Need a common ancestor to be able to compare - if ( ancestor ) { + if (ancestor) { // we have an object and its ancestor (should not happen when sorting selection) if (ancestor == first) { result = 1; @@ -375,13 +396,14 @@ int sp_object_compare_position(SPObject const *first, SPObject const *second) return result; } -bool sp_object_compare_position_bool(SPObject const *first, SPObject const *second){ - return sp_object_compare_position(first,second)<0; +bool sp_object_compare_position_bool(SPObject const *first, SPObject const *second) +{ + return sp_object_compare_position(first, second) < 0; } - -SPObject *SPObject::appendChildRepr(Inkscape::XML::Node *repr) { - if ( !cloned ) { +SPObject *SPObject::appendChildRepr(Inkscape::XML::Node *repr) +{ + if (!cloned) { getRepr()->appendChild(repr); return document->getObjectByRepr(repr); } else { @@ -402,9 +424,10 @@ void SPObject::changeCSS(SPCSSAttr *css, gchar const *attr) sp_repr_css_change(this->getRepr(), css, attr); } -std::vector SPObject::childList(bool add_ref, Action) { - std::vector l; - for (auto& child: children) { +std::vector SPObject::childList(bool add_ref, Action) +{ + std::vector l; + for (auto &child : children) { if (add_ref) { sp_object_ref(&child); } @@ -429,7 +452,8 @@ gchar const *SPObject::label() const { return _label; } -gchar const *SPObject::defaultLabel() const { +gchar const *SPObject::defaultLabel() const +{ if (_label) { return _label; } else { @@ -451,8 +475,8 @@ void SPObject::setLabel(gchar const *label) getRepr()->setAttribute("inkscape:label", label); } - -void SPObject::requestOrphanCollection() { +void SPObject::requestOrphanCollection() +{ g_return_if_fail(document != nullptr); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -461,7 +485,8 @@ void SPObject::requestOrphanCollection() { // leave it } else if (dynamic_cast(this)) { // leave it - } else if ((! prefs->getBool("/options/cleanupswatches/value", false)) && SP_IS_PAINT_SERVER(this) && static_cast(this)->isSwatch() ) { + } else if ((!prefs->getBool("/options/cleanupswatches/value", false)) && SP_IS_PAINT_SERVER(this) && + static_cast(this)->isSwatch()) { // leave it } else if (IS_COLORPROFILE(this)) { // leave it @@ -484,8 +509,9 @@ void SPObject::requestOrphanCollection() { } } -void SPObject::_sendDeleteSignalRecursive() { - for (auto& child: children) { +void SPObject::_sendDeleteSignalRecursive() +{ + for (auto &child : children) { child._delete_signal.emit(&child); child._sendDeleteSignalRecursive(); } @@ -494,7 +520,7 @@ void SPObject::_sendDeleteSignalRecursive() { void SPObject::deleteObject(bool propagate, bool propagate_descendants) { sp_object_ref(this, nullptr); - if ( SP_IS_LPE_ITEM(this) && SP_LPE_ITEM(this)->hasPathEffect()) { + if (SP_IS_LPE_ITEM(this) && SP_LPE_ITEM(this)->hasPathEffect()) { SP_LPE_ITEM(this)->removeAllPathEffects(false); } if (propagate) { @@ -503,7 +529,7 @@ void SPObject::deleteObject(bool propagate, bool propagate_descendants) if (propagate_descendants) { this->_sendDeleteSignalRecursive(); } - + Inkscape::XML::Node *repr = getRepr(); if (repr && repr->parent()) { sp_repr_unparent(repr); @@ -517,18 +543,60 @@ void SPObject::deleteObject(bool propagate, bool propagate_descendants) void SPObject::cropToObject(SPObject *except) { - std::vector toDelete; - for (auto& child: children) { + std::vector toDelete; + for (auto &child : children) { if (SP_IS_ITEM(&child)) { if (child.isAncestorOf(except)) { child.cropToObject(except); - } else if(&child != except) { + } else if (&child != except) { + sp_object_ref(&child, nullptr); + toDelete.push_back(&child); + } + } + } + for (auto &i : toDelete) { + i->deleteObject(true, true); + sp_object_unref(i, nullptr); + } +} + +// Removes objects which are not related to given list of objects. +// Use Case: Group[MyRect1 , MyRect2] , MyRect3 +// List Provided: MyRect1, MyRect3 +// Output doc: Group[MyRect1], MyRect3 +// List Provided: MyRect1, Group +// Output doc: Group[MyRect1, MyRect2] (notice MyRect2 is not deleted as it is related to Group) + +void SPObject::cropToObjects(std::vector except_objects) +{ + if (except_objects.empty()) { + return; + } + std::vector toDelete; + for (auto &child : children) { + if (SP_IS_ITEM(&child)) { + std::vector except_in_child; + bool child_delete_flag = true; + for (auto except : except_objects) { + if (&child == except) { + child_delete_flag = false; + except_in_child.clear(); + break; + } + if (child.isAncestorOf(except)) { + except_in_child.push_back(except); + child_delete_flag = false; + } + } + if (child_delete_flag) { sp_object_ref(&child, nullptr); toDelete.push_back(&child); + } else { + child.cropToObjects(except_in_child); } } } - for (auto & i : toDelete) { + for (auto &i : toDelete) { i->deleteObject(true, true); sp_object_unref(i, nullptr); } @@ -536,8 +604,8 @@ void SPObject::cropToObject(SPObject *except) void SPObject::attach(SPObject *object, SPObject *prev) { - //g_return_if_fail(parent != NULL); - //g_return_if_fail(SP_IS_OBJECT(parent)); + // g_return_if_fail(parent != NULL); + // g_return_if_fail(SP_IS_OBJECT(parent)); g_return_if_fail(object != nullptr); g_return_if_fail(SP_IS_OBJECT(object)); g_return_if_fail(!prev || SP_IS_OBJECT(prev)); @@ -558,7 +626,8 @@ void SPObject::attach(SPObject *object, SPObject *prev) object->xml_space.value = this->xml_space.value; } -void SPObject::reorder(SPObject* obj, SPObject* prev) { +void SPObject::reorder(SPObject *obj, SPObject *prev) +{ g_return_if_fail(obj != nullptr); g_return_if_fail(obj->parent); g_return_if_fail(obj->parent == this); @@ -575,8 +644,8 @@ void SPObject::reorder(SPObject* obj, SPObject* prev) { void SPObject::detach(SPObject *object) { - //g_return_if_fail(parent != NULL); - //g_return_if_fail(SP_IS_OBJECT(parent)); + // g_return_if_fail(parent != NULL); + // g_return_if_fail(SP_IS_OBJECT(parent)); g_return_if_fail(object != nullptr); g_return_if_fail(SP_IS_OBJECT(object)); g_return_if_fail(object->parent == this); @@ -596,9 +665,9 @@ SPObject *SPObject::get_child_by_repr(Inkscape::XML::Node *repr) SPObject *result = nullptr; if (children.size() > 0 && children.back().getRepr() == repr) { - result = &children.back(); // optimization for common scenario + result = &children.back(); // optimization for common scenario } else { - for (auto& child: children) { + for (auto &child : children) { if (child.getRepr() == repr) { result = &child; break; @@ -634,12 +703,13 @@ static SPObject *get_closest_child_by_repr(SPObject &obj, Inkscape::XML::Node *r return nullptr; } -void SPObject::child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref) { - SPObject* object = this; +void SPObject::child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref) +{ + SPObject *object = this; const std::string type_string = NodeTraits::get_type_string(*child); - SPObject* ochild = SPFactory::createObject(type_string); + SPObject *ochild = SPFactory::createObject(type_string); if (ochild == nullptr) { // Currently, there are many node types that do not have // corresponding classes in the SPObject tree. @@ -655,19 +725,21 @@ void SPObject::child_added(Inkscape::XML::Node *child, Inkscape::XML::Node *ref) ochild->invoke_build(object->document, child, object->cloned); } -void SPObject::release() { - SPObject* object = this; - debug("id=%p, typename=%s", object, g_type_name_from_instance((GTypeInstance*)object)); - auto tmp = children | boost::adaptors::transformed([](SPObject& obj){return &obj;}); +void SPObject::release() +{ + SPObject *object = this; + debug("id=%p, typename=%s", object, g_type_name_from_instance((GTypeInstance *)object)); + auto tmp = children | boost::adaptors::transformed([](SPObject &obj) { return &obj; }); std::vector toRelease(tmp.begin(), tmp.end()); - for (auto& p: toRelease) { + for (auto &p : toRelease) { object->detach(p); } } -void SPObject::remove_child(Inkscape::XML::Node* child) { - debug("id=%p, typename=%s", this, g_type_name_from_instance((GTypeInstance*)this)); +void SPObject::remove_child(Inkscape::XML::Node *child) +{ + debug("id=%p, typename=%s", this, g_type_name_from_instance((GTypeInstance *)this)); SPObject *ochild = this->get_child_by_repr(child); @@ -677,8 +749,10 @@ void SPObject::remove_child(Inkscape::XML::Node* child) { } } -void SPObject::order_changed(Inkscape::XML::Node *child, Inkscape::XML::Node * /*old_ref*/, Inkscape::XML::Node *new_ref) { - SPObject* object = this; +void SPObject::order_changed(Inkscape::XML::Node *child, Inkscape::XML::Node * /*old_ref*/, + Inkscape::XML::Node *new_ref) +{ + SPObject *object = this; SPObject *ochild = object->get_child_by_repr(child); g_return_if_fail(ochild != nullptr); @@ -687,19 +761,19 @@ void SPObject::order_changed(Inkscape::XML::Node *child, Inkscape::XML::Node * / ochild->_position_changed_signal.emit(ochild); } -void SPObject::build(SPDocument *document, Inkscape::XML::Node *repr) { - +void SPObject::build(SPDocument *document, Inkscape::XML::Node *repr) +{ #ifdef OBJECT_TRACE - objectTrace( "SPObject::build" ); + objectTrace("SPObject::build"); #endif - SPObject* object = this; + SPObject *object = this; /* Nothing specific here */ - debug("id=%p, typename=%s", object, g_type_name_from_instance((GTypeInstance*)object)); + debug("id=%p, typename=%s", object, g_type_name_from_instance((GTypeInstance *)object)); object->readAttr(SPAttr::XML_SPACE); object->readAttr(SPAttr::LANG); - object->readAttr(SPAttr::XML_LANG); // "xml:lang" overrides "lang" per spec, read it last. + object->readAttr(SPAttr::XML_LANG); // "xml:lang" overrides "lang" per spec, read it last. object->readAttr(SPAttr::INKSCAPE_LABEL); object->readAttr(SPAttr::INKSCAPE_COLLECT); @@ -708,15 +782,15 @@ void SPObject::build(SPDocument *document, Inkscape::XML::Node *repr) { lang = object->parent->lang; } - if(object->cloned && (repr->attribute("id")) ) // The cases where this happens are when the "original" has no id. This happens - // if it is a SPString (a TextNode, e.g. in a ), or when importing - // stuff externally modified to have no id. + if (object->cloned && (repr->attribute("id"))) // The cases where this happens are when the "original" has no id. + // This happens if it is a SPString (a TextNode, e.g. in a <title>), + // or when importing stuff externally modified to have no id. object->clone_original = document->getObjectById(repr->attribute("id")); - for (Inkscape::XML::Node *rchild = repr->firstChild() ; rchild != nullptr; rchild = rchild->next()) { + for (Inkscape::XML::Node *rchild = repr->firstChild(); rchild != nullptr; rchild = rchild->next()) { const std::string typeString = NodeTraits::get_type_string(*rchild); - SPObject* child = SPFactory::createObject(typeString); + SPObject *child = SPFactory::createObject(typeString); if (child == nullptr) { // Currently, there are many node types that do not have // corresponding classes in the SPObject tree. @@ -731,19 +805,19 @@ void SPObject::build(SPDocument *document, Inkscape::XML::Node *repr) { } #ifdef OBJECT_TRACE - objectTrace( "SPObject::build", false ); + objectTrace("SPObject::build", false); #endif } void SPObject::invoke_build(SPDocument *document, Inkscape::XML::Node *repr, unsigned int cloned) { #ifdef OBJECT_TRACE - objectTrace( "SPObject::invoke_build" ); + objectTrace("SPObject::invoke_build"); #endif - debug("id=%p, typename=%s", this, g_type_name_from_instance((GTypeInstance*)this)); + debug("id=%p, typename=%s", this, g_type_name_from_instance((GTypeInstance *)this)); - //g_assert(object != NULL); - //g_assert(SP_IS_OBJECT(object)); + // g_assert(object != NULL); + // g_assert(SP_IS_OBJECT(object)); g_assert(document != nullptr); g_assert(repr != nullptr); @@ -763,7 +837,7 @@ void SPObject::invoke_build(SPDocument *document, Inkscape::XML::Node *repr, uns /* Invoke derived methods, if any */ this->build(document, repr); - if ( !cloned ) { + if (!cloned) { this->document->bindObjectToRepr(this->repr, this); if (Inkscape::XML::id_permitted(this->repr)) { @@ -796,12 +870,11 @@ void SPObject::invoke_build(SPDocument *document, Inkscape::XML::Node *repr, uns g_assert(this->getId() == nullptr); } - /* Signalling (should be connected AFTER processing derived methods */ sp_repr_add_listener(repr, &object_event_vector, this); #ifdef OBJECT_TRACE - objectTrace( "SPObject::invoke_build", false ); + objectTrace("SPObject::invoke_build", false); #endif } @@ -810,24 +883,27 @@ int SPObject::getIntAttribute(char const *key, int def) return getRepr()->getAttributeInt(key, def); } -unsigned SPObject::getPosition(){ +unsigned SPObject::getPosition() +{ g_assert(this->repr); return repr->position(); } -void SPObject::appendChild(Inkscape::XML::Node *child) { +void SPObject::appendChild(Inkscape::XML::Node *child) +{ g_assert(this->repr); repr->appendChild(child); } -SPObject* SPObject::nthChild(unsigned index) { +SPObject *SPObject::nthChild(unsigned index) +{ g_assert(this->repr); if (hasChildren()) { - std::vector<SPObject*> l; + std::vector<SPObject *> l; unsigned counter = 0; - for (auto& child: children) { + for (auto &child : children) { if (counter == index) { return &child; } @@ -837,14 +913,15 @@ SPObject* SPObject::nthChild(unsigned index) { return nullptr; } -void SPObject::addChild(Inkscape::XML::Node *child, Inkscape::XML::Node * prev) +void SPObject::addChild(Inkscape::XML::Node *child, Inkscape::XML::Node *prev) { g_assert(this->repr); - repr->addChild(child,prev); + repr->addChild(child, prev); } -void SPObject::releaseReferences() { +void SPObject::releaseReferences() +{ g_assert(this->document); g_assert(this->repr); @@ -883,7 +960,6 @@ void SPObject::releaseReferences() { this->repr = nullptr; } - SPObject *SPObject::getPrev() { SPObject *prev = nullptr; @@ -893,7 +969,7 @@ SPObject *SPObject::getPrev() return prev; } -SPObject* SPObject::getNext() +SPObject *SPObject::getNext() { SPObject *next = nullptr; if (parent && !parent->children.empty() && &parent->children.back() != this) { @@ -902,47 +978,49 @@ SPObject* SPObject::getNext() return next; } -void SPObject::repr_child_added(Inkscape::XML::Node * /*repr*/, Inkscape::XML::Node *child, Inkscape::XML::Node *ref, gpointer data) +void SPObject::repr_child_added(Inkscape::XML::Node * /*repr*/, Inkscape::XML::Node *child, Inkscape::XML::Node *ref, + gpointer data) { auto object = static_cast<SPObject *>(data); object->child_added(child, ref); } -void SPObject::repr_child_removed(Inkscape::XML::Node * /*repr*/, Inkscape::XML::Node *child, Inkscape::XML::Node * /*ref*/, gpointer data) +void SPObject::repr_child_removed(Inkscape::XML::Node * /*repr*/, Inkscape::XML::Node *child, + Inkscape::XML::Node * /*ref*/, gpointer data) { auto object = static_cast<SPObject *>(data); object->remove_child(child); } -void SPObject::repr_order_changed(Inkscape::XML::Node * /*repr*/, Inkscape::XML::Node *child, Inkscape::XML::Node *old, Inkscape::XML::Node *newer, gpointer data) +void SPObject::repr_order_changed(Inkscape::XML::Node * /*repr*/, Inkscape::XML::Node *child, Inkscape::XML::Node *old, + Inkscape::XML::Node *newer, gpointer data) { auto object = static_cast<SPObject *>(data); object->order_changed(child, old, newer); } -void SPObject::set(SPAttr key, gchar const* value) { - +void SPObject::set(SPAttr key, gchar const *value) +{ #ifdef OBJECT_TRACE std::stringstream temp; - temp << "SPObject::set: " << sp_attribute_name(key) << " " << (value?value:"null"); - objectTrace( temp.str() ); + temp << "SPObject::set: " << sp_attribute_name(key) << " " << (value ? value : "null"); + objectTrace(temp.str()); #endif g_assert(key != SPAttr::INVALID); - SPObject* object = this; + SPObject *object = this; switch (key) { - case SPAttr::ID: - //XML Tree being used here. - if ( !object->cloned && object->getRepr()->type() == Inkscape::XML::NodeType::ELEMENT_NODE ) { - SPDocument *document=object->document; - SPObject *conflict=nullptr; + // XML Tree being used here. + if (!object->cloned && object->getRepr()->type() == Inkscape::XML::NodeType::ELEMENT_NODE) { + SPDocument *document = object->document; + SPObject *conflict = nullptr; gchar const *new_id = value; @@ -950,7 +1028,7 @@ void SPObject::set(SPAttr key, gchar const* value) { conflict = document->getObjectById((char const *)new_id); } - if ( conflict && conflict != object ) { + if (conflict && conflict != object) { if (!document->isSeeking()) { sp_object_ref(conflict, nullptr); // give the conflicting object a new ID @@ -990,7 +1068,7 @@ void SPObject::set(SPAttr key, gchar const* value) { break; case SPAttr::INKSCAPE_COLLECT: - if ( value && !std::strcmp(value, "always") ) { + if (value && !std::strcmp(value, "always")) { object->setCollectionPolicy(SPObject::ALWAYS_COLLECT); } else { object->setCollectionPolicy(SPObject::COLLECT_WITH_PARENT); @@ -1027,7 +1105,7 @@ void SPObject::set(SPAttr key, gchar const* value) { break; case SPAttr::STYLE: - object->style->readFromObject( object ); + object->style->readFromObject(object); object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); break; @@ -1035,14 +1113,14 @@ void SPObject::set(SPAttr key, gchar const* value) { break; } #ifdef OBJECT_TRACE - objectTrace( "SPObject::set", false ); + objectTrace("SPObject::set", false); #endif } void SPObject::setKeyValue(SPAttr key, gchar const *value) { - //g_assert(object != NULL); - //g_assert(SP_IS_OBJECT(object)); + // g_assert(object != NULL); + // g_assert(SP_IS_OBJECT(object)); this->set(key, value); } @@ -1061,11 +1139,11 @@ void SPObject::readAttr(SPAttr keyid) void SPObject::readAttr(gchar const *key) { - //g_assert(object != NULL); - //g_assert(SP_IS_OBJECT(object)); + // g_assert(object != NULL); + // g_assert(SP_IS_OBJECT(object)); g_assert(key != nullptr); - //XML Tree being used here. + // XML Tree being used here. g_assert(this->getRepr() != nullptr); auto keyid = sp_attribute_lookup(key); @@ -1077,7 +1155,8 @@ void SPObject::readAttr(gchar const *key) } } -void SPObject::repr_attr_changed(Inkscape::XML::Node * /*repr*/, gchar const *key, gchar const * /*oldval*/, gchar const * /*newval*/, bool is_interactive, gpointer data) +void SPObject::repr_attr_changed(Inkscape::XML::Node * /*repr*/, gchar const *key, gchar const * /*oldval*/, + gchar const * /*newval*/, bool is_interactive, gpointer data) { auto object = static_cast<SPObject *>(data); @@ -1090,7 +1169,8 @@ void SPObject::repr_attr_changed(Inkscape::XML::Node * /*repr*/, gchar const *ke } } -void SPObject::repr_content_changed(Inkscape::XML::Node * /*repr*/, gchar const * /*oldcontent*/, gchar const * /*newcontent*/, gpointer data) +void SPObject::repr_content_changed(Inkscape::XML::Node * /*repr*/, gchar const * /*oldcontent*/, + gchar const * /*newcontent*/, gpointer data) { auto object = static_cast<SPObject *>(data); @@ -1112,14 +1192,15 @@ static gchar const *sp_xml_get_space_string(unsigned int space) } } -Inkscape::XML::Node* SPObject::write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) { +Inkscape::XML::Node *SPObject::write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) +{ #ifdef OBJECT_TRACE - objectTrace( "SPObject::write" ); + objectTrace("SPObject::write"); #endif if (!repr && (flags & SP_OBJECT_WRITE_BUILD)) { repr = this->getRepr()->duplicate(doc); - if (!( flags & SP_OBJECT_WRITE_EXT )) { + if (!(flags & SP_OBJECT_WRITE_EXT)) { repr->removeAttribute("inkscape:collect"); } } else if (repr) { @@ -1131,9 +1212,7 @@ Inkscape::XML::Node* SPObject::write(Inkscape::XML::Document *doc, Inkscape::XML repr->setAttribute("xml:space", xml_space); } - if ( flags & SP_OBJECT_WRITE_EXT && - this->collectionPolicy() == SPObject::ALWAYS_COLLECT ) - { + if (flags & SP_OBJECT_WRITE_EXT && this->collectionPolicy() == SPObject::ALWAYS_COLLECT) { repr->setAttribute("inkscape:collect", "always"); } else { repr->removeAttribute("inkscape:collect"); @@ -1146,14 +1225,14 @@ Inkscape::XML::Node* SPObject::write(Inkscape::XML::Document *doc, Inkscape::XML // Write style attributes (SPStyleSrc::ATTRIBUTE) back to xml object bool any_written = false; auto properties = style->properties(); - for (auto * prop : properties) { - if(prop->shall_write(SP_STYLE_FLAG_IFSET | SP_STYLE_FLAG_IFSRC, SPStyleSrc::ATTRIBUTE)) { + for (auto *prop : properties) { + if (prop->shall_write(SP_STYLE_FLAG_IFSET | SP_STYLE_FLAG_IFSRC, SPStyleSrc::ATTRIBUTE)) { // WARNING: We don't know for sure if the css names are the same as the attribute names repr->setAttributeOrRemoveIfEmpty(prop->name(), prop->get_value()); any_written = true; } } - if(any_written) { + if (any_written) { // We need to ask the object to update the style and keep things in sync // see `case SPAttr::STYLE` above for how the style attr itself does this. style->readFromObject(this); @@ -1163,8 +1242,7 @@ Inkscape::XML::Node* SPObject::write(Inkscape::XML::Document *doc, Inkscape::XML // Check for valid attributes. This may be time consuming. // It is useful, though, for debugging Inkscape code. Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - if( prefs->getBool("/options/svgoutput/check_on_editing") ) { - + if (prefs->getBool("/options/svgoutput/check_on_editing")) { unsigned int flags = sp_attribute_clean_get_prefs(); style_prop = sp_attribute_clean_style(repr, style_prop.c_str(), flags); } @@ -1187,44 +1265,44 @@ Inkscape::XML::Node* SPObject::write(Inkscape::XML::Document *doc, Inkscape::XML } #ifdef OBJECT_TRACE - objectTrace( "SPObject::write", false ); + objectTrace("SPObject::write", false); #endif return repr; } -Inkscape::XML::Node * SPObject::updateRepr(unsigned int flags) +Inkscape::XML::Node *SPObject::updateRepr(unsigned int flags) { #ifdef OBJECT_TRACE - objectTrace( "SPObject::updateRepr 1" ); + objectTrace("SPObject::updateRepr 1"); #endif - if ( !cloned ) { + if (!cloned) { Inkscape::XML::Node *repr = getRepr(); if (repr) { #ifdef OBJECT_TRACE - objectTrace( "SPObject::updateRepr 1", false ); + objectTrace("SPObject::updateRepr 1", false); #endif return updateRepr(repr->document(), repr, flags); } else { g_critical("Attempt to update non-existent repr"); #ifdef OBJECT_TRACE - objectTrace( "SPObject::updateRepr 1", false ); + objectTrace("SPObject::updateRepr 1", false); #endif return nullptr; } } else { /* cloned objects have no repr */ #ifdef OBJECT_TRACE - objectTrace( "SPObject::updateRepr 1", false ); + objectTrace("SPObject::updateRepr 1", false); #endif return nullptr; } } -Inkscape::XML::Node * SPObject::updateRepr(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, unsigned int flags) +Inkscape::XML::Node *SPObject::updateRepr(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, unsigned int flags) { #ifdef OBJECT_TRACE - objectTrace( "SPObject::updateRepr 2" ); + objectTrace("SPObject::updateRepr 2"); #endif g_assert(doc != nullptr); @@ -1232,7 +1310,7 @@ Inkscape::XML::Node * SPObject::updateRepr(Inkscape::XML::Document *doc, Inkscap if (cloned) { /* cloned objects have no repr */ #ifdef OBJECT_TRACE - objectTrace( "SPObject::updateRepr 2", false ); + objectTrace("SPObject::updateRepr 2", false); #endif return nullptr; } @@ -1243,19 +1321,18 @@ Inkscape::XML::Node * SPObject::updateRepr(Inkscape::XML::Document *doc, Inkscap #ifdef OBJECT_TRACE Inkscape::XML::Node *node = write(doc, repr, flags); - objectTrace( "SPObject::updateRepr 2", false ); + objectTrace("SPObject::updateRepr 2", false); return node; #else return this->write(doc, repr, flags); #endif - } /* Modification */ void SPObject::requestDisplayUpdate(unsigned int flags) { - g_return_if_fail( this->document != nullptr ); + g_return_if_fail(this->document != nullptr); #ifndef NDEBUG // expect no nested update calls @@ -1272,19 +1349,19 @@ void SPObject::requestDisplayUpdate(unsigned int flags) g_return_if_fail(!((flags & SP_OBJECT_MODIFIED_FLAG) && (flags & SP_OBJECT_CHILD_MODIFIED_FLAG))); #ifdef OBJECT_TRACE - objectTrace( "SPObject::requestDisplayUpdate" ); + objectTrace("SPObject::requestDisplayUpdate"); #endif bool already_propagated = (!(this->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))); - //https://stackoverflow.com/a/7841333 - if ((this->uflags & flags) != flags ) { + // https://stackoverflow.com/a/7841333 + if ((this->uflags & flags) != flags) { this->uflags |= flags; } /* If requestModified has already been called on this object or one of its children, then we * don't need to set CHILD_MODIFIED on our ancestors because it's already been done. */ if (already_propagated) { - if(this->document) { + if (this->document) { if (parent) { parent->requestDisplayUpdate(SP_OBJECT_CHILD_MODIFIED_FLAG); } else { @@ -1294,9 +1371,8 @@ void SPObject::requestDisplayUpdate(unsigned int flags) } #ifdef OBJECT_TRACE - objectTrace( "SPObject::requestDisplayUpdate", false ); + objectTrace("SPObject::requestDisplayUpdate", false); #endif - } void SPObject::updateDisplay(SPCtx *ctx, unsigned int flags) @@ -1304,13 +1380,14 @@ void SPObject::updateDisplay(SPCtx *ctx, unsigned int flags) g_return_if_fail(!(flags & ~SP_OBJECT_MODIFIED_CASCADE)); #ifdef OBJECT_TRACE - objectTrace( "SPObject::updateDisplay" ); + objectTrace("SPObject::updateDisplay"); #endif assert(++(document->update_in_progress)); #ifdef SP_OBJECT_DEBUG_CASCADE - g_print("Update %s:%s %x %x %x\n", g_type_name_from_instance((GTypeInstance *) this), getId(), flags, this->uflags, this->mflags); + g_print("Update %s:%s %x %x %x\n", g_type_name_from_instance((GTypeInstance *)this), getId(), flags, this->uflags, + this->mflags); #endif /* Get this flags */ @@ -1330,34 +1407,32 @@ void SPObject::updateDisplay(SPCtx *ctx, unsigned int flags) if ((flags & SP_OBJECT_STYLESHEET_MODIFIED_FLAG)) { style->readFromObject(this); } else if (parent && (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) && (flags & SP_OBJECT_PARENT_MODIFIED_FLAG)) { - style->cascade( this->parent->style ); + style->cascade(this->parent->style); } } - try - { + try { this->update(ctx, flags); - } - catch(...) - { + } catch (...) { /** \todo - * in case of catching an exception we need to inform the user somehow that the document is corrupted - * maybe by implementing an document flag documentOk - * or by a modal error dialog - */ - g_warning("SPObject::updateDisplay(SPCtx *ctx, unsigned int flags) : throw in ((SPObjectClass *) G_OBJECT_GET_CLASS(this))->update(this, ctx, flags);"); + * in case of catching an exception we need to inform the user somehow that the document is corrupted + * maybe by implementing an document flag documentOk + * or by a modal error dialog + */ + g_warning("SPObject::updateDisplay(SPCtx *ctx, unsigned int flags) : throw in ((SPObjectClass *) " + "G_OBJECT_GET_CLASS(this))->update(this, ctx, flags);"); } assert((document->update_in_progress)--); #ifdef OBJECT_TRACE - objectTrace( "SPObject::updateDisplay", false ); + objectTrace("SPObject::updateDisplay", false); #endif } void SPObject::requestModified(unsigned int flags) { - g_return_if_fail( this->document != nullptr ); + g_return_if_fail(this->document != nullptr); /* requestModified must be used only to set one of SP_OBJECT_MODIFIED_FLAG or * SP_OBJECT_CHILD_MODIFIED_FLAG */ @@ -1366,7 +1441,7 @@ void SPObject::requestModified(unsigned int flags) g_return_if_fail(!((flags & SP_OBJECT_MODIFIED_FLAG) && (flags & SP_OBJECT_CHILD_MODIFIED_FLAG))); #ifdef OBJECT_TRACE - objectTrace( "SPObject::requestModified" ); + objectTrace("SPObject::requestModified"); #endif bool already_propagated = (!(this->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))); @@ -1384,7 +1459,7 @@ void SPObject::requestModified(unsigned int flags) } } #ifdef OBJECT_TRACE - objectTrace( "SPObject::requestModified", false ); + objectTrace("SPObject::requestModified", false); #endif } @@ -1394,11 +1469,12 @@ void SPObject::emitModified(unsigned int flags) g_return_if_fail(!(flags & ~SP_OBJECT_MODIFIED_CASCADE)); #ifdef OBJECT_TRACE - objectTrace( "SPObject::emitModified", true, flags ); + objectTrace("SPObject::emitModified", true, flags); #endif #ifdef SP_OBJECT_DEBUG_CASCADE - g_print("Modified %s:%s %x %x %x\n", g_type_name_from_instance((GTypeInstance *) this), getId(), flags, this->uflags, this->mflags); + g_print("Modified %s:%s %x %x %x\n", g_type_name_from_instance((GTypeInstance *)this), getId(), flags, this->uflags, + this->mflags); #endif flags |= this->mflags; @@ -1415,7 +1491,7 @@ void SPObject::emitModified(unsigned int flags) sp_object_unref(this); #ifdef OBJECT_TRACE - objectTrace( "SPObject::emitModified", false ); + objectTrace("SPObject::emitModified", false); #endif } @@ -1424,7 +1500,7 @@ gchar const *SPObject::getTagName() const g_assert(repr != nullptr); /// \todo fixme: Exception if object is NULL? */ - //XML Tree being used here. + // XML Tree being used here. return getRepr()->name(); } @@ -1433,31 +1509,29 @@ gchar const *SPObject::getAttribute(gchar const *key) const g_assert(this->repr != nullptr); /// \todo fixme: Exception if object is NULL? */ - //XML Tree being used here. - return (gchar const *) getRepr()->attribute(key); + // XML Tree being used here. + return (gchar const *)getRepr()->attribute(key); } -void SPObject::setAttribute(Inkscape::Util::const_char_ptr key, - Inkscape::Util::const_char_ptr value) +void SPObject::setAttribute(Inkscape::Util::const_char_ptr key, Inkscape::Util::const_char_ptr value) { g_assert(this->repr != nullptr); /// \todo fixme: Exception if object is NULL? */ - //XML Tree being used here. + // XML Tree being used here. getRepr()->setAttribute(key, value); } - void SPObject::removeAttribute(gchar const *key) { /// \todo fixme: Exception if object is NULL? */ - //XML Tree being used here. + // XML Tree being used here. getRepr()->removeAttribute(key); } -bool SPObject::storeAsDouble( gchar const *key, double *val ) const +bool SPObject::storeAsDouble(gchar const *key, double *val) const { - g_assert(this->getRepr()!= nullptr); + g_assert(this->getRepr() != nullptr); double nan = std::numeric_limits<double>::quiet_NaN(); double temp_val = ((Inkscape::XML::Node *)(this->getRepr()))->getAttributeDouble(key, nan); if (std::isnan(temp_val)) { @@ -1468,9 +1542,7 @@ bool SPObject::storeAsDouble( gchar const *key, double *val ) const } /** Helper */ -gchar * -sp_object_get_unique_id(SPObject *object, - gchar const *id) +gchar *sp_object_get_unique_id(SPObject *object, gchar const *id) { static unsigned long count = 0; @@ -1478,7 +1550,7 @@ sp_object_get_unique_id(SPObject *object, count++; - //XML Tree being used here. + // XML Tree being used here. gchar const *name = object->getRepr()->name(); g_assert(name != nullptr); @@ -1495,23 +1567,24 @@ sp_object_get_unique_id(SPObject *object, size_t const name_len = std::strlen(name); size_t const buflen = name_len + (sizeof(count) * 10 / 4) + 1; - gchar *const buf = (gchar *) g_malloc(buflen); + gchar *const buf = (gchar *)g_malloc(buflen); std::memcpy(buf, name, name_len); gchar *const count_buf = buf + name_len; size_t const count_buflen = buflen - name_len; do { ++count; g_snprintf(count_buf, count_buflen, "%lu", count); - } while ( object->document->getObjectById(buf) != nullptr ); + } while (object->document->getObjectById(buf) != nullptr); return buf; } -void SPObject::_requireSVGVersion(Inkscape::Version version) { - for ( SPObject::ParentIterator iter=this ; iter ; ++iter ) { +void SPObject::_requireSVGVersion(Inkscape::Version version) +{ + for (SPObject::ParentIterator iter = this; iter; ++iter) { SPObject *object = iter; if (SP_IS_ROOT(object)) { SPRoot *root = SP_ROOT(object); - if ( root->version.svg < version ) { + if (root->version.svg < version) { root->version.svg = version; } } @@ -1533,7 +1606,7 @@ void SPObject::_requireSVGVersion(Inkscape::Version version) { be allowed with different localized strings. */ -gchar * SPObject::title() const +gchar *SPObject::title() const { return getTitleOrDesc("svg:title"); } @@ -1543,7 +1616,7 @@ bool SPObject::setTitle(gchar const *title, bool verbatim) return setTitleOrDesc(title, "svg:title", verbatim); } -gchar * SPObject::desc() const +gchar *SPObject::desc() const { return getTitleOrDesc("svg:desc"); } @@ -1553,14 +1626,14 @@ bool SPObject::setDesc(gchar const *desc, bool verbatim) return setTitleOrDesc(desc, "svg:desc", verbatim); } -char * SPObject::getTitleOrDesc(gchar const *svg_tagname) const +char *SPObject::getTitleOrDesc(gchar const *svg_tagname) const { char *result = nullptr; SPObject *elem = findFirstChild(svg_tagname); - if ( elem ) { - //This string copy could be avoided by changing - //the return type of SPObject::getTitleOrDesc - //to std::unique_ptr<Glib::ustring> + if (elem) { + // This string copy could be avoided by changing + // the return type of SPObject::getTitleOrDesc + // to std::unique_ptr<Glib::ustring> result = g_strdup(elem->textualContent().c_str()); } return result; @@ -1619,12 +1692,11 @@ bool SPObject::setTitleOrDesc(gchar const *value, gchar const *svg_tagname, bool repr->addChild(xml_elem, nullptr); elem = document->getObjectByRepr(xml_elem); Inkscape::GC::release(xml_elem); - } - else { + } else { // remove the current content of the 'text' or 'desc' element - auto tmp = elem->children | boost::adaptors::transformed([](SPObject& obj) { return &obj; }); - std::vector<SPObject*> vec(tmp.begin(), tmp.end()); - for (auto &child: vec) { + auto tmp = elem->children | boost::adaptors::transformed([](SPObject &obj) { return &obj; }); + std::vector<SPObject *> vec(tmp.begin(), tmp.end()); + for (auto &child : vec) { child->deleteObject(); } } @@ -1634,12 +1706,10 @@ bool SPObject::setTitleOrDesc(gchar const *value, gchar const *svg_tagname, bool return true; } -SPObject* SPObject::findFirstChild(gchar const *tagname) const +SPObject *SPObject::findFirstChild(gchar const *tagname) const { - for (auto& child: const_cast<SPObject*>(this)->children) - { - if (child.repr->type() == Inkscape::XML::NodeType::ELEMENT_NODE && - !std::strcmp(child.repr->name(), tagname)) { + for (auto &child : const_cast<SPObject *>(this)->children) { + if (child.repr->type() == Inkscape::XML::NodeType::ELEMENT_NODE && !std::strcmp(child.repr->name(), tagname)) { return &child; } } @@ -1650,14 +1720,12 @@ Glib::ustring SPObject::textualContent() const { Glib::ustring text; - for (auto& child: children) - { + for (auto &child : children) { Inkscape::XML::NodeType child_type = child.repr->type(); if (child_type == Inkscape::XML::NodeType::ELEMENT_NODE) { text += child.textualContent(); - } - else if (child_type == Inkscape::XML::NodeType::TEXT_NODE) { + } else if (child_type == Inkscape::XML::NodeType::TEXT_NODE) { text += child.repr->content(); } } @@ -1665,7 +1733,7 @@ Glib::ustring SPObject::textualContent() const } // For debugging: Print SP tree structure. -void SPObject::recursivePrintTree( unsigned level ) +void SPObject::recursivePrintTree(unsigned level) { if (level == 0) { std::cout << "SP Object Tree" << std::endl; @@ -1674,24 +1742,24 @@ void SPObject::recursivePrintTree( unsigned level ) for (unsigned i = 0; i < level; ++i) { std::cout << " "; } - std::cout << (getId()?getId():"No object id") - << " clone: " << std::boolalpha << (bool)cloned + std::cout << (getId() ? getId() : "No object id") << " clone: " << std::boolalpha << (bool)cloned << " hrefcount: " << hrefcount << std::endl; - for (auto& child: children) { + for (auto &child : children) { child.recursivePrintTree(level + 1); } } // Function to allow tracing of program flow through SPObject and derived classes. // To trace function, add at entrance ('in' = true) and exit of function ('in' = false). -void SPObject::objectTrace( std::string const &text, bool in, unsigned flags ) { - if( in ) { +void SPObject::objectTrace(std::string const &text, bool in, unsigned flags) +{ + if (in) { for (unsigned i = 0; i < indent_level; ++i) { std::cout << " "; } std::cout << text << ":" << " entrance: " - << (id?id:"null") + << (id ? id : "null") // << " uflags: " << uflags // << " mflags: " << mflags // << " flags: " << flags @@ -1704,7 +1772,7 @@ void SPObject::objectTrace( std::string const &text, bool in, unsigned flags ) { } std::cout << text << ":" << " exit: " - << (id?id:"null") + << (id ? id : "null") // << " uflags: " << uflags // << " mflags: " << mflags // << " flags: " << flags @@ -1714,11 +1782,8 @@ void SPObject::objectTrace( std::string const &text, bool in, unsigned flags ) { std::ostream &operator<<(std::ostream &out, const SPObject &o) { - out << (o.getId()?o.getId():"No ID") - << " cloned: " << std::boolalpha << (bool)o.cloned - << " ref: " << o.refCount - << " href: " << o.hrefcount - << " total href: " << o._total_hrefcount; + out << (o.getId() ? o.getId() : "No ID") << " cloned: " << std::boolalpha << (bool)o.cloned + << " ref: " << o.refCount << " href: " << o.hrefcount << " total href: " << o._total_hrefcount; return out; } /* diff --git a/src/object/sp-object.h b/src/object/sp-object.h index 968eec8d68..e3eca9b675 100644 --- a/src/object/sp-object.h +++ b/src/object/sp-object.h @@ -467,6 +467,7 @@ public: * Removes all children except for the given object, it's children and it's ancesstors. */ void cropToObject(SPObject *except); + void cropToObjects(std::vector<SPObject *> except_objects); /** * Connects a slot to be called when an object is deleted. diff --git a/src/ui/dialog/export-helper.cpp b/src/ui/dialog/export-helper.cpp index 5ba3f75396..c71e256f91 100644 --- a/src/ui/dialog/export-helper.cpp +++ b/src/ui/dialog/export-helper.cpp @@ -308,7 +308,7 @@ std::string absolutize_path_from_document_location(SPDocument *doc, const std::s bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsigned long int const &height, float const &dpi, Glib::ustring const &filename, bool overwrite, - unsigned (*callback)(float, void *), ExportProgressDialog *prog_dialog, + unsigned (*callback)(float, void *), ExportProgressDialog *&prog_dialog, Inkscape::Extension::Output *extension, std::vector<SPItem *> *items, AdvanceOptions *adv) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; @@ -395,7 +395,8 @@ bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsi bool failed = result == EXPORT_ERROR || prog_dialog->get_stopped(); delete prog_dialog; - if (failed){ + prog_dialog = nullptr; + if (failed) { gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); @@ -431,12 +432,122 @@ bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsi gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, _("Drawing exported to <b>%s</b>."), safeFile); g_free(safeFile); - unlink(png_filename.c_str()); return true; } +bool _export_vector(Inkscape::Extension::Output *extension, SPDocument *doc, Glib::ustring const &filename, + bool overwrite, std::vector<SPItem *> *items) +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (!desktop) + return false; + + if (filename.empty()) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You have to enter a filename.")); + sp_ui_error_dialog(_("You have to enter a filename")); + return false; + } + + if (!extension || extension->is_raster()) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Vector Export Error")); + sp_ui_error_dialog(_("Vector export Method is used for RASTER EXTENSION")); + return false; + } + + std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(filename)); + Glib::ustring dirname = Glib::path_get_dirname(path); + + if (dirname.empty() || + !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { + gchar *safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); + gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), safeDir); + + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); + sp_ui_error_dialog(error); + + g_free(safeDir); + g_free(error); + return false; + } + + // Do the over-write protection now + if (!overwrite && !sp_ui_overwrite_file(path.c_str())) { + return false; + } + doc->ensureUpToDate(); + SPDocument *copy_doc = (doc->copy()).get(); + copy_doc->ensureUpToDate(); + + if (items && items->size() > 0) { + std::vector<SPObject *> objects_to_export; + std::vector<SPItem *> objects = *items; + Inkscape::ObjectSet s(copy_doc); + for (auto &object : objects) { + SPObject *temp = dynamic_cast<SPObject *>(object); + + if (!temp) { + gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); + gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); + + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); + sp_ui_error_dialog(error); + + g_free(safeFile); + g_free(error); + return false; + } + SPObject *obj = copy_doc->getObjectById(temp->getId()); + if (!obj) { + gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); + gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); + + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); + sp_ui_error_dialog(error); + + g_free(safeFile); + g_free(error); + return false; + } + copy_doc->ensureUpToDate(); + + s.add(obj, true); + objects_to_export.push_back(obj); + } + copy_doc->getRoot()->cropToObjects(objects_to_export); + s.fitCanvas(true, true); + } + + copy_doc->vacuumDocument(); + try { + Inkscape::Extension::save(dynamic_cast<Inkscape::Extension::Extension *>(extension), copy_doc, path.c_str(), + false, false, false, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_COPY); + } catch (Inkscape::Extension::Output::save_failed &e) { + gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); + gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); + + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); + sp_ui_error_dialog(error); + + g_free(safeFile); + g_free(error); + return false; + } + + auto recentmanager = Gtk::RecentManager::get_default(); + if (recentmanager && Glib::path_is_absolute(path)) { + Glib::ustring uri = Glib::filename_to_uri(path); + recentmanager->add_item(uri); + } + + gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); + desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, _("Drawing exported to <b>%s</b>."), safeFile); + g_free(safeFile); + + return true; +} + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export-helper.h b/src/ui/dialog/export-helper.h index 3e17545db5..0f7bd961c5 100644 --- a/src/ui/dialog/export-helper.h +++ b/src/ui/dialog/export-helper.h @@ -138,7 +138,6 @@ public: inline bool get_stopped() const { return _stopped; } inline void set_stopped() { _stopped = true; } - }; float getValuePx(float value, Unit const *unit); @@ -149,10 +148,14 @@ Glib::ustring get_ext_from_filename(Glib::ustring const &filename); std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename); bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsigned long int const &height, - float const &dpi, Glib::ustring const &filename, bool overwrite, unsigned (*callback)(float, void *), - ExportProgressDialog* prog_dialog, Inkscape::Extension::Output *extension, std::vector<SPItem *> *items = nullptr, + float const &dpi, Glib::ustring const &filename, bool overwrite, + unsigned (*callback)(float, void *), ExportProgressDialog *&prog_dialog, + Inkscape::Extension::Output *extension, std::vector<SPItem *> *items = nullptr, AdvanceOptions *adv = nullptr); +bool _export_vector(Inkscape::Extension::Output *extension, SPDocument *doc, Glib::ustring const &filename, + bool overwrite, std::vector<SPItem *> *items = nullptr); + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index a7f8f343dc..12fe38be26 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -200,7 +200,7 @@ void SingleExport::setup() filenameConn = si_filename_entry->signal_changed().connect(sigc::mem_fun(*this, &SingleExport::onFilenameModified)); extensionConn = si_extension_cb->signal_changed().connect(sigc::mem_fun(*this, &SingleExport::onExtensionChanged)); exportConn = si_export->signal_clicked().connect(sigc::mem_fun(*this, &SingleExport::onExport)); - si_filename_entry->signal_icon_press().connect(sigc::mem_fun(*this, &SingleExport::onBrowse)); + browseConn = si_filename_entry->signal_icon_press().connect(sigc::mem_fun(*this, &SingleExport::onBrowse)); } // Setup units combobox @@ -248,7 +248,8 @@ void SingleExport::setupSpinButton(Gtk::SpinButton *sb, double val, double min, sb->set_range(min, max); sb->set_value(val); sb->set_sensitive(sensitive); - sb->set_width_chars(7); + sb->set_width_chars(0); + sb->set_max_width_chars(0); if (cb) { auto signal = sb->signal_value_changed().connect(sigc::bind(sigc::mem_fun(*this, cb), param)); // add signals to list to block all easily @@ -384,6 +385,7 @@ void SingleExport::onAreaTypeToggle(selection_mode key) // last call will change values) current_key = key; prefs->setString("/dialogs/export/exportarea/value", selection_names[current_key]); + refreshArea(); refreshExportHints(); } @@ -392,12 +394,14 @@ void SingleExport::onAreaXChange(sb_type type) { blockSpinConns(true); areaXChange(type); + selection_buttons[SELECTION_CUSTOM]->set_active(true); blockSpinConns(false); } void SingleExport::onAreaYChange(sb_type type) { blockSpinConns(true); areaYChange(type); + selection_buttons[SELECTION_CUSTOM]->set_active(true); blockSpinConns(false); } void SingleExport::onDpiChange(sb_type type) @@ -475,18 +479,36 @@ void SingleExport::onExport() nullptr, &advance_options); } else { - // exportSuccessful = _export_vector(omod); + setExporting(true, Glib::ustring::compose(_("Exporting %1"), filename)); + SPDocument *doc = desktop->getDocument(); + SPDocument *copy_doc = (doc->copy()).get(); + if (current_key == SELECTION_DRAWING) { + fit_canvas_to_drawing(copy_doc, true); + } + std::vector<SPItem *> items; + if (current_key == SELECTION_SELECTION) { + auto itemlist = desktop->getSelection()->items(); + for (auto i = itemlist.begin(); i != itemlist.end(); ++i) { + SPItem *item = *i; + items.push_back(item); + } + } + exportSuccessful = _export_vector(omod, copy_doc, filename, false, &items); + } + if (prog_dlg) { + delete prog_dlg; + prog_dlg = nullptr; } setExporting(false); si_export->set_sensitive(true); original_name = filename; filename_modified = false; - prog_dlg = nullptr; interrupted = false; } void SingleExport::onBrowse(Gtk::EntryIconPosition pos, const GdkEventButton *ev) { + browseConn.block(); Gtk::Window *window = _app->get_active_window(); Glib::ustring filename = Glib::filename_from_utf8(si_filename_entry->get_text()); @@ -501,9 +523,10 @@ void SingleExport::onBrowse(Gtk::EntryIconPosition pos, const GdkEventButton *ev if (dialog->show()) { filename = dialog->getFilename(); - Inkscape::Extension::Output* selection_type = dynamic_cast<Inkscape::Extension::Output*>(dialog->getSelectionType()); + Inkscape::Extension::Output *selection_type = + dynamic_cast<Inkscape::Extension::Output *>(dialog->getSelectionType()); Glib::ustring extension = selection_type->get_extension(); - ExtensionList::appendExtensionToFilename(filename,extension); + ExtensionList::appendExtensionToFilename(filename, extension); si_filename_entry->set_text(filename); si_filename_entry->set_position(filename.length()); // deleting dialog before exporting is important @@ -513,6 +536,7 @@ void SingleExport::onBrowse(Gtk::EntryIconPosition pos, const GdkEventButton *ev } else { delete dialog; } + browseConn.unblock(); } // Utils Functions @@ -666,8 +690,8 @@ void SingleExport::dpiChange(sb_type type) spin_buttons[SPIN_DPI]->set_value(dpi); } -// We first check any export hints related to document. If there is none we create a default name using document name. -// doc_export_name is set here and will only be changed when exporting. +// We first check any export hints related to document. If there is none we create a default name using document +// name. doc_export_name is set here and will only be changed when exporting. void SingleExport::setDefaultFilename() { Glib::ustring filename; @@ -717,6 +741,16 @@ void SingleExport::setDefaultSelectionMode() } selection_buttons[current_key]->set_active(true); prefs->setString("/dialogs/export/exportarea/value", pref_key_name); + + if (current_key == SELECTION_CUSTOM && + (spin_buttons[SPIN_HEIGHT]->get_value() == 0 || spin_buttons[SPIN_WIDTH]->get_value() == 0)) { + SPDocument *doc; + Geom::OptRect bbox; + doc = SP_ACTIVE_DESKTOP->getDocument(); + bbox = Geom::Rect(Geom::Point(0.0, 0.0), + Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); + setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); + } } } diff --git a/src/ui/dialog/export-single.h b/src/ui/dialog/export-single.h index 912bc12281..b7c0f2b44a 100644 --- a/src/ui/dialog/export-single.h +++ b/src/ui/dialog/export-single.h @@ -17,7 +17,6 @@ #include "export-helper.h" #include "extension/output.h" -#include "ui/dialog/dialog-base.h" #include "ui/widget/scrollprotected.h" #include "ui/widget/unit-menu.h" @@ -35,6 +34,7 @@ public: protected: InkscapeApplication *_app; + public: void set_app(InkscapeApplication *app) { _app = app; }; @@ -97,14 +97,18 @@ public: private: void setupUnits(); void setupExtensionList(); + void setupSpinButtons(); private: // change range and callbacks to spinbuttons - void setupSpinButtons(); template <typename T> void setupSpinButton(Gtk::SpinButton *sb, double val, double min, double max, double step, double page, int digits, bool sensitive, void (SingleExport::*cb)(T), T param); +private: + void setDefaultSelectionMode(); + void setDefaultFilename(); + private: void onAreaXChange(sb_type type); void onAreaYChange(sb_type type); @@ -124,7 +128,6 @@ private: void areaXChange(sb_type type); void areaYChange(sb_type type); void dpiChange(sb_type type); - void setArea(double x0, double y0, double x1, double y1); void blockSpinConns(bool status); @@ -150,19 +153,16 @@ private: bool onProgressDelete(GdkEventAny *event); private: - ExportProgressDialog *prog_dlg; + ExportProgressDialog *prog_dlg = nullptr; bool interrupted; -private: - void setDefaultSelectionMode(); - void setDefaultFilename(); - private: // Signals std::vector<sigc::connection> spinButtonConns; sigc::connection filenameConn; sigc::connection extensionConn; sigc::connection exportConn; + sigc::connection browseConn; sigc::connection selectionModifiedConn; sigc::connection selectionChangedConn; diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 871a61f953..ea8b8aee9f 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -57,9 +57,6 @@ namespace Dialog { Export::Export() : DialogBase("/dialogs/export/", "Export") - , selectChangedConn() - , subselChangedConn() - , selectModifiedConn() { std::string gladefile = get_filename_string(Inkscape::IO::Resource::UIS, "dialog-export.glade"); @@ -75,25 +72,33 @@ Export::Export() builder->get_widget("Export Dialog Box", container); add(*container); show_all_children(); + builder->get_widget("Export Notebook", export_notebook); - builder->get_widget_derived("Single Image", single_image); + // Initialise Single Export Here. We will setup Single Export in onRealize callback. + builder->get_widget_derived("Single Image", single_image); single_image->initialise(builder); builder->get_widget("Batch Export", batch_export); - // Callback when container is dinally mapped on window. All intialisation like set active is done inside it. + + // Callback when container is finally mapped on window. All intialisation like set active is done inside it. container->signal_realize().connect(sigc::mem_fun(*this, &Export::onRealize)); + // Provide inkscape _app instance to single Export single_image->set_app(_app); } -Export::~Export() +Export::~Export() {} + +// When conainer is visible then setup all widgets. +// It prevents gtk_is_widget assertion warning probably. +void Export::onRealize() { - selectModifiedConn.disconnect(); - subselChangedConn.disconnect(); - selectChangedConn.disconnect(); + single_image->setup(); + // setDefaultNotebookPage(); } +// Set current page based on preference/last visited page void Export::setDefaultNotebookPage() { // if (export_notebook && batch_export) { @@ -102,18 +107,6 @@ void Export::setDefaultNotebookPage() // } } -/** - * SIGNALS - */ - -// Set current page based on preference/last visited page - -void Export::onRealize() -{ - single_image->setup(); - // setDefaultNotebookPage(); -} - } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index af4b5c12a9..90c5c52dfc 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -51,32 +51,17 @@ private: SingleExport *single_image = nullptr; Gtk::Box *batch_export = nullptr; - private: - // Utils Variables Inkscape::Preferences *prefs = nullptr; // setup default values of widgets void setDefaultNotebookPage(); - // Export Functions - - bool _export_vector(Inkscape::Extension::Output *extension = nullptr, std::vector<SPItem *> *items = nullptr); - +private: // signals callback void onRealize(); void onBatchExport(); - - /** - * Inkscape selection change callback - */ - void onSelectionChanged(); - void onSelectionModified(guint flags); - - // signals - sigc::connection selectChangedConn; - sigc::connection subselChangedConn; - sigc::connection selectModifiedConn; + }; } // namespace Dialog } // namespace UI -- GitLab From 1d2a95b12bf2d135b28511b87382221690eeda19 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Fri, 2 Jul 2021 21:14:13 +0530 Subject: [PATCH 17/40] added hide selected option --- share/share | 1 - share/ui/dialog-export.glade | 46 +++++---------------------------- src/ui/dialog/export-helper.cpp | 4 ++- src/ui/dialog/export-single.cpp | 10 ++++--- src/ui/dialog/export.h | 1 - 5 files changed, 16 insertions(+), 46 deletions(-) delete mode 120000 share/share diff --git a/share/share b/share/share deleted file mode 120000 index 159ed8186a..0000000000 --- a/share/share +++ /dev/null @@ -1 +0,0 @@ -/home/anshudhar2001/Desktop/inkscape/share \ No newline at end of file diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 08072beb02..0ae19b5ee2 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -38,7 +38,7 @@ <property name="hscroll-policy">natural</property> <property name="shadow-type">none</property> <child> - <!-- n-columns=7 n-rows=15 --> + <!-- n-columns=6 n-rows=15 --> <object class="GtkGrid"> <property name="visible">True</property> <property name="can-focus">False</property> @@ -202,7 +202,7 @@ <packing> <property name="left-attach">0</property> <property name="top-attach">0</property> - <property name="width">7</property> + <property name="width">6</property> </packing> </child> <child> @@ -213,6 +213,7 @@ <object class="GtkCheckButton" id="si_show_export_area"> <property name="label" translatable="yes">Show Export</property> <property name="visible">True</property> + <property name="sensitive">False</property> <property name="can-focus">True</property> <property name="receives-default">False</property> <property name="draw-indicator">True</property> @@ -267,7 +268,7 @@ <packing> <property name="left-attach">1</property> <property name="top-attach">7</property> - <property name="width">5</property> + <property name="width">4</property> </packing> </child> <child> @@ -315,6 +316,7 @@ <object class="GtkCheckButton" id="si_show_preview"> <property name="label" translatable="yes">Preview</property> <property name="visible">True</property> + <property name="sensitive">False</property> <property name="can-focus">True</property> <property name="receives-default">False</property> <property name="draw-indicator">True</property> @@ -351,7 +353,7 @@ <packing> <property name="left-attach">1</property> <property name="top-attach">13</property> - <property name="width">5</property> + <property name="width">4</property> </packing> </child> <child> @@ -672,42 +674,6 @@ <child> <placeholder/> </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> </object> </child> </object> diff --git a/src/ui/dialog/export-helper.cpp b/src/ui/dialog/export-helper.cpp index c71e256f91..4141c73217 100644 --- a/src/ui/dialog/export-helper.cpp +++ b/src/ui/dialog/export-helper.cpp @@ -127,6 +127,8 @@ AdvanceOptions::AdvanceOptions() grid->attach(anti_aliasing_cb, 1, row, 1, 1); row++; } + grid->set_row_spacing(2); + grid->set_column_spacing(5); } AdvanceOptions::~AdvanceOptions() @@ -384,7 +386,7 @@ bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsi // Export Start Here std::vector<SPItem *> selected; - if (items) { + if (items && items->size() > 0) { selected = *items; } diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index 12fe38be26..ea226aeea0 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -439,11 +439,12 @@ void SingleExport::onExtensionChanged() void SingleExport::onExport() { + interrupted = false; + SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop) return; si_export->set_sensitive(false); - interrupted = false; bool exportSuccessful = false; auto extension = si_extension_cb->get_active_text(); if (!ExtensionList::valid_extensions[extension]) { @@ -475,8 +476,12 @@ void SingleExport::onExport() prog_dlg->set_current(0); prog_dlg->set_total(0); + std::vector<SPItem *> selected(desktop->getSelection()->items().begin(), + desktop->getSelection()->items().end()); + bool hide = si_hide_all->get_active(); + exportSuccessful = _export_raster(area, width, height, dpi, filename, false, onProgressCallback, prog_dlg, omod, - nullptr, &advance_options); + hide ? &selected : nullptr, &advance_options); } else { setExporting(true, Glib::ustring::compose(_("Exporting %1"), filename)); @@ -765,7 +770,6 @@ void SingleExport::setExporting(bool exporting, Glib::ustring const &text) _prog->set_text(""); _prog->set_fraction(0.0); _prog->set_sensitive(false); - si_export->set_sensitive(true); } } diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 90c5c52dfc..28c61e371d 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -61,7 +61,6 @@ private: // signals callback void onRealize(); void onBatchExport(); - }; } // namespace Dialog } // namespace UI -- GitLab From 38d8c7a6f7427e0957342a1a0ba4dc71b10aaaaf Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Sun, 4 Jul 2021 23:13:32 +0530 Subject: [PATCH 18/40] added batch export with multiple options --- share/ui/dialog-export.glade | 744 ++++++++++++++++++-------------- src/ui/CMakeLists.txt | 2 + src/ui/dialog/export-batch.cpp | 487 +++++++++++++++++++++ src/ui/dialog/export-batch.h | 146 +++++++ src/ui/dialog/export-helper.cpp | 137 +++++- src/ui/dialog/export-helper.h | 35 +- src/ui/dialog/export-single.cpp | 12 +- src/ui/dialog/export.cpp | 5 +- src/ui/dialog/export.h | 3 +- src/ui/widget/scrollprotected.h | 55 ++- 10 files changed, 1291 insertions(+), 335 deletions(-) create mode 100644 src/ui/dialog/export-batch.cpp create mode 100644 src/ui/dialog/export-batch.h diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 0ae19b5ee2..c594919952 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -22,14 +22,14 @@ <property name="orientation">vertical</property> <property name="spacing">5</property> <child> - <object class="GtkScrolledWindow"> + <object class="GtkScrolledWindow" id="s_scroll"> <property name="visible">True</property> <property name="can-focus">True</property> <property name="double-buffered">False</property> <property name="vexpand">True</property> <property name="hscrollbar-policy">never</property> - <property name="vscrollbar-policy">always</property> - <property name="propagate-natural-width">True</property> + <property name="vscrollbar-policy">external</property> + <property name="window-placement-set">False</property> <child> <object class="GtkViewport"> <property name="visible">True</property> @@ -42,6 +42,7 @@ <object class="GtkGrid"> <property name="visible">True</property> <property name="can-focus">False</property> + <property name="margin-top">5</property> <property name="row-spacing">5</property> <property name="column-spacing">10</property> <child> @@ -55,7 +56,7 @@ </object> <packing> <property name="left-attach">2</property> - <property name="top-attach">2</property> + <property name="top-attach">1</property> </packing> </child> <child> @@ -68,7 +69,7 @@ </object> <packing> <property name="left-attach">4</property> - <property name="top-attach">4</property> + <property name="top-attach">3</property> </packing> </child> <child> @@ -81,7 +82,7 @@ </object> <packing> <property name="left-attach">2</property> - <property name="top-attach">6</property> + <property name="top-attach">5</property> </packing> </child> <child> @@ -94,7 +95,7 @@ </object> <packing> <property name="left-attach">4</property> - <property name="top-attach">6</property> + <property name="top-attach">5</property> </packing> </child> <child> @@ -115,96 +116,6 @@ <property name="width">5</property> </packing> </child> - <child> - <object class="GtkSpinButton" id="si_img_height_sb"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="valign">center</property> - <property name="hexpand">True</property> - <property name="width-chars">0</property> - <property name="max-width-chars">0</property> - </object> - <packing> - <property name="left-attach">4</property> - <property name="top-attach">10</property> - </packing> - </child> - <child> - <object class="GtkButtonBox" id="toggle_grp2"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="double-buffered">False</property> - <property name="margin-top">5</property> - <property name="homogeneous">True</property> - <property name="layout-style">expand</property> - <child> - <object class="GtkRadioButton" id="si_s_document"> - <property name="label" translatable="yes">Document</property> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="focus-on-click">False</property> - <property name="receives-default">False</property> - <property name="active">True</property> - <property name="draw-indicator">False</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkRadioButton" id="si_s_page"> - <property name="label" translatable="yes">Page</property> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="receives-default">False</property> - <property name="draw-indicator">False</property> - <property name="group">si_s_document</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkRadioButton" id="si_s_selection"> - <property name="label" translatable="yes">Selection</property> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="receives-default">False</property> - <property name="draw-indicator">False</property> - <property name="group">si_s_document</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkRadioButton" id="si_s_custom"> - <property name="label" translatable="yes">Custom</property> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="receives-default">False</property> - <property name="draw-indicator">False</property> - <property name="group">si_s_document</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">4</property> - </packing> - </child> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">0</property> - <property name="width">6</property> - </packing> - </child> <child> <object class="GtkBox"> <property name="visible">True</property> @@ -271,20 +182,6 @@ <property name="width">4</property> </packing> </child> - <child> - <object class="GtkSpinButton" id="si_img_width_sb"> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="valign">center</property> - <property name="hexpand">True</property> - <property name="width-chars">0</property> - <property name="max-width-chars">0</property> - </object> - <packing> - <property name="left-attach">2</property> - <property name="top-attach">10</property> - </packing> - </child> <child> <object class="GtkBox" id="si_preview_box"> <property name="visible">True</property> @@ -366,7 +263,7 @@ </object> <packing> <property name="left-attach">4</property> - <property name="top-attach">2</property> + <property name="top-attach">1</property> </packing> </child> <child> @@ -379,114 +276,192 @@ </object> <packing> <property name="left-attach">2</property> - <property name="top-attach">4</property> + <property name="top-attach">3</property> </packing> </child> <child> - <object class="GtkSpinButton" id="si_dpi_sb"> + <object class="GtkLabel"> <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="valign">start</property> - <property name="hexpand">True</property> - <property name="width-chars">0</property> - <property name="max-width-chars">0</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">Height</property> + <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> - <property name="left-attach">2</property> - <property name="top-attach">12</property> + <property name="left-attach">3</property> + <property name="top-attach">5</property> </packing> </child> <child> <object class="GtkLabel"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes">DPI</property> + <property name="label" translatable="yes">Width</property> <property name="wrap">True</property> <property name="xalign">0</property> </object> <packing> <property name="left-attach">1</property> - <property name="top-attach">12</property> + <property name="top-attach">5</property> </packing> </child> <child> - <object class="GtkLabel"> + <object class="GtkBox" id="si_advance_box"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes">Height -(px)</property> - <property name="wrap">True</property> - <property name="xalign">0</property> + <property name="orientation">vertical</property> + <child> + <placeholder/> + </child> </object> <packing> - <property name="left-attach">3</property> - <property name="top-attach">10</property> + <property name="left-attach">0</property> + <property name="top-attach">14</property> + <property name="width">6</property> </packing> </child> <child> - <object class="GtkLabel"> + <!-- n-columns=4 n-rows=1 --> + <object class="GtkGrid"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes">Width -(px)</property> - <property name="wrap">True</property> - <property name="xalign">0</property> + <child> + <object class="GtkRadioButton" id="si_s_selection"> + <property name="label" translatable="yes">Selection</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="focus-on-click">False</property> + <property name="receives-default">False</property> + <property name="hexpand">True</property> + <property name="draw-indicator">False</property> + <property name="group">si_s_document</property> + </object> + <packing> + <property name="left-attach">2</property> + <property name="top-attach">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="si_s_document"> + <property name="label" translatable="yes">Document</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="focus-on-click">False</property> + <property name="receives-default">False</property> + <property name="hexpand">True</property> + <property name="active">True</property> + <property name="draw-indicator">False</property> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="si_s_page"> + <property name="label" translatable="yes">Page</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="focus-on-click">False</property> + <property name="receives-default">False</property> + <property name="hexpand">True</property> + <property name="draw-indicator">False</property> + <property name="group">si_s_document</property> + </object> + <packing> + <property name="left-attach">1</property> + <property name="top-attach">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="si_s_custom"> + <property name="label" translatable="yes">Custom</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="focus-on-click">False</property> + <property name="receives-default">False</property> + <property name="hexpand">True</property> + <property name="draw-indicator">False</property> + <property name="group">si_s_document</property> + </object> + <packing> + <property name="left-attach">3</property> + <property name="top-attach">0</property> + </packing> + </child> </object> <packing> - <property name="left-attach">1</property> - <property name="top-attach">10</property> + <property name="left-attach">0</property> + <property name="top-attach">0</property> + <property name="width">6</property> </packing> </child> <child> - <object class="GtkLabel"> + <!-- n-columns=5 n-rows=1 --> + <object class="GtkGrid"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes">Height</property> - <property name="wrap">True</property> - <property name="xalign">0</property> + <property name="row-spacing">2</property> + <property name="column-spacing">20</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> </object> <packing> - <property name="left-attach">3</property> - <property name="top-attach">6</property> + <property name="left-attach">1</property> + <property name="top-attach">9</property> + <property name="width">4</property> </packing> </child> <child> <object class="GtkLabel"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes">Width</property> + <property name="label" translatable="yes">Left</property> <property name="wrap">True</property> <property name="xalign">0</property> </object> <packing> <property name="left-attach">1</property> - <property name="top-attach">6</property> + <property name="top-attach">1</property> </packing> </child> <child> <object class="GtkLabel"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes">Bottom</property> + <property name="label" translatable="yes">Right</property> <property name="wrap">True</property> <property name="xalign">0</property> </object> <packing> - <property name="left-attach">3</property> - <property name="top-attach">4</property> + <property name="left-attach">1</property> + <property name="top-attach">3</property> </packing> </child> <child> <object class="GtkLabel"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes">Right</property> + <property name="label" translatable="yes">Bottom</property> <property name="wrap">True</property> <property name="xalign">0</property> </object> <packing> - <property name="left-attach">1</property> - <property name="top-attach">4</property> + <property name="left-attach">3</property> + <property name="top-attach">3</property> </packing> </child> <child> @@ -499,51 +474,91 @@ </object> <packing> <property name="left-attach">3</property> - <property name="top-attach">2</property> + <property name="top-attach">1</property> </packing> </child> <child> <object class="GtkLabel"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="label" translatable="yes">Left</property> + <property name="label" translatable="yes">Width +(px)</property> <property name="wrap">True</property> <property name="xalign">0</property> </object> <packing> <property name="left-attach">1</property> - <property name="top-attach">2</property> + <property name="top-attach">10</property> </packing> </child> <child> - <object class="GtkBox" id="si_advance_box"> + <object class="GtkLabel"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="orientation">vertical</property> - <child> - <placeholder/> - </child> + <property name="label" translatable="yes">Height +(px)</property> + <property name="wrap">True</property> + <property name="xalign">0</property> </object> <packing> - <property name="left-attach">1</property> - <property name="top-attach">14</property> - <property name="width">5</property> + <property name="left-attach">3</property> + <property name="top-attach">10</property> </packing> </child> <child> - <placeholder/> - </child> - <child> - <placeholder/> + <object class="GtkSpinButton" id="si_img_width_sb"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="valign">center</property> + <property name="hexpand">True</property> + <property name="width-chars">0</property> + <property name="max-width-chars">0</property> + </object> + <packing> + <property name="left-attach">2</property> + <property name="top-attach">10</property> + </packing> </child> <child> - <placeholder/> + <object class="GtkSpinButton" id="si_img_height_sb"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="valign">center</property> + <property name="hexpand">True</property> + <property name="width-chars">0</property> + <property name="max-width-chars">0</property> + </object> + <packing> + <property name="left-attach">4</property> + <property name="top-attach">10</property> + </packing> </child> <child> - <placeholder/> + <object class="GtkLabel"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="label" translatable="yes">DPI</property> + <property name="wrap">True</property> + <property name="xalign">0</property> + </object> + <packing> + <property name="left-attach">1</property> + <property name="top-attach">12</property> + </packing> </child> <child> - <placeholder/> + <object class="GtkSpinButton" id="si_dpi_sb"> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="valign">start</property> + <property name="hexpand">True</property> + <property name="width-chars">0</property> + <property name="max-width-chars">0</property> + </object> + <packing> + <property name="left-attach">2</property> + <property name="top-attach">12</property> + </packing> </child> <child> <placeholder/> @@ -772,21 +787,20 @@ <property name="double-buffered">False</property> <property name="orientation">vertical</property> <child> - <object class="GtkScrolledWindow"> + <object class="GtkScrolledWindow" id="b_scroll"> <property name="visible">True</property> <property name="can-focus">True</property> <property name="vexpand">True</property> <property name="hscrollbar-policy">never</property> - <property name="vscrollbar-policy">always</property> + <property name="vscrollbar-policy">external</property> <property name="window-placement-set">False</property> - <property name="propagate-natural-width">True</property> <child> <object class="GtkViewport"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="shadow-type">none</property> <child> - <!-- n-columns=7 n-rows=7 --> + <!-- n-columns=6 n-rows=8 --> <object class="GtkGrid"> <property name="visible">True</property> <property name="can-focus">False</property> @@ -794,19 +808,21 @@ <property name="row-spacing">10</property> <property name="column-spacing">10</property> <child> - <object class="GtkScrolledWindow"> + <object class="GtkScrolledWindow" id="b_pbox_scroll"> <property name="height-request">150</property> <property name="visible">True</property> <property name="can-focus">True</property> <property name="hexpand">True</property> <property name="hscrollbar-policy">never</property> + <property name="vscrollbar-policy">external</property> + <property name="window-placement-set">False</property> <property name="shadow-type">in</property> <child> <object class="GtkViewport"> <property name="visible">True</property> <property name="can-focus">False</property> <child> - <object class="GtkFlowBox"> + <object class="GtkFlowBox" id="b_preview_box"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="homogeneous">True</property> @@ -894,15 +910,191 @@ </child> </object> </child> + <child> + <object class="GtkFlowBoxChild"> + <property name="width-request">100</property> + <property name="height-request">80</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="pixel-size">50</property> + <property name="icon-name">face-glasses</property> + </object> + </child> + </object> + </child> + <child> + <object class="GtkFlowBoxChild"> + <property name="width-request">100</property> + <property name="height-request">80</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="pixel-size">50</property> + <property name="icon-name">face-glasses</property> + </object> + </child> + </object> + </child> + <child> + <object class="GtkFlowBoxChild"> + <property name="width-request">100</property> + <property name="height-request">80</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="pixel-size">50</property> + <property name="icon-name">face-glasses</property> + </object> + </child> + </object> + </child> + <child> + <object class="GtkFlowBoxChild"> + <property name="width-request">100</property> + <property name="height-request">80</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="pixel-size">50</property> + <property name="icon-name">face-glasses</property> + </object> + </child> + </object> + </child> + <child> + <object class="GtkFlowBoxChild"> + <property name="width-request">100</property> + <property name="height-request">80</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="pixel-size">50</property> + <property name="icon-name">face-glasses</property> + </object> + </child> + </object> + </child> + <child> + <object class="GtkFlowBoxChild"> + <property name="width-request">100</property> + <property name="height-request">80</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="pixel-size">50</property> + <property name="icon-name">face-glasses</property> + </object> + </child> + </object> + </child> + <child> + <object class="GtkFlowBoxChild"> + <property name="width-request">100</property> + <property name="height-request">80</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="pixel-size">50</property> + <property name="icon-name">face-glasses</property> + </object> + </child> + </object> + </child> + <child> + <object class="GtkFlowBoxChild"> + <property name="width-request">100</property> + <property name="height-request">80</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="pixel-size">50</property> + <property name="icon-name">face-glasses</property> + </object> + </child> + </object> + </child> + <child> + <object class="GtkFlowBoxChild"> + <property name="width-request">100</property> + <property name="height-request">80</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="pixel-size">50</property> + <property name="icon-name">face-glasses</property> + </object> + </child> + </object> + </child> + <child> + <object class="GtkFlowBoxChild"> + <property name="width-request">100</property> + <property name="height-request">80</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="pixel-size">50</property> + <property name="icon-name">face-glasses</property> + </object> + </child> + </object> + </child> + <child> + <object class="GtkFlowBoxChild"> + <property name="width-request">100</property> + <property name="height-request">80</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <child> + <object class="GtkImage"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="pixel-size">50</property> + <property name="icon-name">face-glasses</property> + </object> + </child> + </object> + </child> </object> </child> </object> </child> </object> <packing> - <property name="left-attach">1</property> + <property name="left-attach">0</property> <property name="top-attach">1</property> - <property name="width">5</property> + <property name="width">6</property> </packing> </child> <child> @@ -912,7 +1104,7 @@ <property name="hexpand">True</property> <property name="layout-style">expand</property> <child> - <object class="GtkRadioButton" id="radiobutton2"> + <object class="GtkRadioButton" id="b_s_selection"> <property name="label" translatable="yes">Selection</property> <property name="visible">True</property> <property name="can-focus">False</property> @@ -927,14 +1119,14 @@ </packing> </child> <child> - <object class="GtkRadioButton"> + <object class="GtkRadioButton" id="b_s_layers"> <property name="label" translatable="yes">Layers</property> <property name="visible">True</property> <property name="can-focus">False</property> <property name="receives-default">False</property> <property name="active">True</property> <property name="draw-indicator">False</property> - <property name="group">radiobutton2</property> + <property name="group">b_s_selection</property> </object> <packing> <property name="expand">True</property> @@ -946,25 +1138,28 @@ <packing> <property name="left-attach">0</property> <property name="top-attach">0</property> - <property name="width">7</property> + <property name="width">6</property> </packing> </child> <child> - <object class="GtkCheckButton"> + <object class="GtkCheckButton" id="b_show_preview"> <property name="label" translatable="yes">Preview</property> <property name="visible">True</property> + <property name="sensitive">False</property> <property name="can-focus">True</property> + <property name="focus-on-click">False</property> <property name="receives-default">False</property> + <property name="halign">start</property> <property name="draw-indicator">True</property> </object> <packing> - <property name="left-attach">1</property> + <property name="left-attach">0</property> <property name="top-attach">2</property> - <property name="width">2</property> + <property name="width">3</property> </packing> </child> <child> - <object class="GtkLabel"> + <object class="GtkLabel" id="b_num_elements"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="label" translatable="yes">5 Items</property> @@ -975,135 +1170,64 @@ </packing> </child> <child> - <object class="GtkCheckButton"> + <object class="GtkCheckButton" id="b_hide_all"> <property name="label" translatable="yes">Hide All Except Selected</property> <property name="visible">True</property> <property name="can-focus">True</property> + <property name="focus-on-click">False</property> <property name="receives-default">False</property> + <property name="halign">start</property> <property name="draw-indicator">True</property> </object> <packing> - <property name="left-attach">1</property> + <property name="left-attach">0</property> <property name="top-attach">5</property> - <property name="width">5</property> + <property name="width">6</property> </packing> </child> <child> - <object class="GtkExpander"> + <object class="GtkBox" id="b_advance_box"> <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="margin-top">10</property> - <property name="margin-bottom">10</property> - <property name="spacing">5</property> - <property name="label-fill">True</property> + <property name="can-focus">False</property> + <property name="orientation">vertical</property> <child> - <!-- n-columns=3 n-rows=3 --> - <object class="GtkGrid"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="margin-left">10</property> - <property name="row-spacing">5</property> - <child> - <object class="GtkCheckButton"> - <property name="label" translatable="yes">checkbutton</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="receives-default">False</property> - <property name="margin-top">10</property> - <property name="draw-indicator">True</property> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkCheckButton"> - <property name="label" translatable="yes">checkbutton</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="receives-default">False</property> - <property name="draw-indicator">True</property> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">1</property> - </packing> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - </object> - </child> - <child type="label"> - <object class="GtkLabel"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="margin-left">5</property> - <property name="label" translatable="yes">Advance</property> - <property name="wrap">True</property> - </object> + <placeholder/> </child> </object> <packing> - <property name="left-attach">1</property> + <property name="left-attach">0</property> <property name="top-attach">6</property> - <property name="width">5</property> + <property name="width">6</property> </packing> </child> <child> - <object class="GtkTreeView"> + <!-- n-columns=2 n-rows=2 --> + <object class="GtkGrid" id="b_export_list"> <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="enable-search">False</property> - <property name="show-expanders">False</property> - <child internal-child="selection"> - <object class="GtkTreeSelection"/> + <property name="can-focus">False</property> + <property name="margin-start">5</property> + <property name="margin-end">5</property> + <property name="margin-top">5</property> + <property name="margin-bottom">5</property> + <property name="row-spacing">10</property> + <property name="column-spacing">10</property> + <child> + <placeholder/> </child> <child> - <object class="GtkTreeViewColumn"> - <property name="sizing">autosize</property> - <property name="title" translatable="yes">Prefix</property> - <property name="expand">True</property> - </object> + <placeholder/> </child> <child> - <object class="GtkTreeViewColumn"> - <property name="sizing">autosize</property> - <property name="title" translatable="yes">Scale</property> - <property name="expand">True</property> - </object> + <placeholder/> </child> <child> - <object class="GtkTreeViewColumn"> - <property name="sizing">autosize</property> - <property name="title" translatable="yes">Format</property> - <property name="expand">True</property> - </object> + <placeholder/> </child> </object> <packing> - <property name="left-attach">1</property> + <property name="left-attach">0</property> <property name="top-attach">3</property> - <property name="width">5</property> + <property name="width">6</property> <property name="height">2</property> </packing> </child> @@ -1131,24 +1255,6 @@ <child> <placeholder/> </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> </object> </child> </object> @@ -1161,7 +1267,7 @@ </packing> </child> <child> - <!-- n-columns=3 n-rows=3 --> + <!-- n-columns=2 n-rows=2 --> <object class="GtkGrid"> <property name="visible">True</property> <property name="can-focus">False</property> @@ -1169,7 +1275,7 @@ <property name="row-spacing">5</property> <property name="column-spacing">10</property> <child> - <object class="GtkEntry"> + <object class="GtkEntry" id="b_filename"> <property name="visible">True</property> <property name="can-focus">True</property> <property name="hexpand">True</property> @@ -1182,37 +1288,27 @@ </packing> </child> <child> - <object class="GtkButton"> + <object class="GtkButton" id="b_export"> <property name="label" translatable="yes">Export</property> <property name="visible">True</property> <property name="can-focus">True</property> <property name="receives-default">True</property> </object> <packing> - <property name="left-attach">2</property> + <property name="left-attach">1</property> <property name="top-attach">0</property> </packing> </child> <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> + <object class="GtkProgressBar" id="b_progress_bar"> + <property name="visible">True</property> + <property name="can-focus">False</property> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">1</property> + <property name="width">2</property> + </packing> </child> </object> <packing> diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index aa4f2ce334..880785b61f 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -112,6 +112,7 @@ set(ui_SRC dialog/dialog-window.cpp dialog/document-properties.cpp dialog/export.cpp + dialog/export-batch.cpp dialog/export-single.cpp dialog/export-helper.cpp dialog/filedialog.cpp @@ -287,6 +288,7 @@ set(ui_SRC dialog/dialog-window.h dialog/document-properties.h dialog/export.h + dialog/export-batch.h dialog/export-single.h dialog/export-helper.h dialog/filedialog.h diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp new file mode 100644 index 0000000000..689a48086e --- /dev/null +++ b/src/ui/dialog/export-batch.cpp @@ -0,0 +1,487 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * bulia byak <buliabyak@users.sf.net> + * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * + * Copyright (C) 1999-2007 Authors + * Copyright (C) 2001-2002 Ximian, Inc. + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "export-batch.h" + +#include <glibmm/convert.h> +#include <glibmm/i18n.h> +#include <glibmm/miscutils.h> +#include <gtkmm.h> +#include <png.h> + +#include "desktop.h" +#include "document-undo.h" +#include "document.h" +#include "export-helper.h" +#include "extension/db.h" +#include "file.h" +#include "helper/png-write.h" +#include "inkscape-window.h" +#include "inkscape.h" +#include "io/resource.h" +#include "io/sys.h" +#include "message-stack.h" +#include "object/object-set.h" +#include "object/sp-namedview.h" +#include "object/sp-root.h" +#include "preferences.h" +#include "selection-chemistry.h" +#include "ui/dialog-events.h" +#include "ui/dialog/dialog-notebook.h" +#include "ui/dialog/filedialog.h" +#include "ui/interface.h" +#include "ui/widget/scrollprotected.h" +#include "ui/widget/unit-menu.h" +#ifdef _WIN32 + +#endif + +using Inkscape::Util::unit_table; + +namespace Inkscape { +namespace UI { +namespace Dialog { + +BatchExport::~BatchExport() +{ + ; +} + +void BatchExport::initialise(const Glib::RefPtr<Gtk::Builder> &builder) +{ + builder->get_widget("b_s_selection", selection_buttons[SELECTION_SELECTION]); + selection_names[SELECTION_SELECTION] = "selection"; + builder->get_widget("b_s_layers", selection_buttons[SELECTION_LAYER]); + selection_names[SELECTION_LAYER] = "layer"; + + builder->get_widget("b_preview_box", preview_container); + builder->get_widget("b_show_preview", show_preview); + builder->get_widget("b_num_elements", num_elements); + builder->get_widget("b_advance_box", adv_box); + builder->get_widget("b_hide_all", hide_all); + builder->get_widget("b_filename", filename_entry); + builder->get_widget("b_export", export_btn); + builder->get_widget("b_progress_bar", _prog); + builder->get_widget_derived("b_export_list", export_list); + + Inkscape::UI::Widget::ScrollTransfer<Gtk::ScrolledWindow> *temp = nullptr; + builder->get_widget_derived("b_pbox_scroll", temp); + builder->get_widget_derived("b_scroll", temp); +} + +void BatchExport::on_realize() +{ + auto desktop = SP_ACTIVE_DESKTOP; + assert(desktop); + auto *selection = desktop->getSelection(); + + selectionModifiedConn = + selection->connectModified(sigc::mem_fun(*this, &BatchExport::on_inkscape_selection_modified)); + selectionChangedConn = selection->connectChanged(sigc::mem_fun(*this, &BatchExport::on_inkscape_selection_changed)); + + Gtk::Box::on_realize(); +} + +void BatchExport::on_unrealize() +{ + selectionModifiedConn.disconnect(); + selectionChangedConn.disconnect(); + Gtk::Box::on_unrealize(); +} + +void BatchExport::on_inkscape_selection_modified(Inkscape::Selection *selection, guint flags) +{ + assert(SP_ACTIVE_DESKTOP->getSelection() == selection); + if (!(flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { + return; + } +} + +void BatchExport::on_inkscape_selection_changed(Inkscape::Selection *selection) +{ + assert(SP_ACTIVE_DESKTOP->getSelection() == selection); + if (selection->isEmpty()) { + selection_buttons[SELECTION_SELECTION]->set_sensitive(false); + if (current_key == SELECTION_SELECTION) { + selection_buttons[(selection_mode)0]->set_active(true); // This causes refresh area + // return otherwise refreshArea will be called again + // even though we are at default key, selection is the one which was original key. + prefs->setString("/dialogs/export/batchexportarea/value", selection_names[SELECTION_SELECTION]); + return; + } + } else { + selection_buttons[SELECTION_SELECTION]->set_sensitive(true); + Glib::ustring pref_key_name = prefs->getString("/dialogs/export/batchexportarea/value"); + if (selection_names[SELECTION_SELECTION] == pref_key_name && current_key != SELECTION_SELECTION) { + selection_buttons[SELECTION_SELECTION]->set_active(); + return; + } + } + refreshItems(); + refreshExportHints(); +} + +// Setup Single Export.Called by export on realize +void BatchExport::setup() +{ + prefs = Inkscape::Preferences::get(); + + // Setup Advance Options + adv_box->pack_start(advance_options, true, true, 0); + adv_box->show_all_children(); + + export_list->setup(); + + // set them before connecting to signals + setDefaultFilename(); + setDefaultSelectionMode(); + + refreshExportHints(); + + // Connect Signals + for (auto [key, button] : selection_buttons) { + button->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &BatchExport::onAreaTypeToggle), key)); + } + filenameConn = filename_entry->signal_changed().connect(sigc::mem_fun(*this, &BatchExport::onFilenameModified)); + exportConn = export_btn->signal_clicked().connect(sigc::mem_fun(*this, &BatchExport::onExport)); + browseConn = filename_entry->signal_icon_press().connect(sigc::mem_fun(*this, &BatchExport::onBrowse)); +} + +void BatchExport::refreshItems() +{ + if (!SP_ACTIVE_DESKTOP) { + return; + } + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SPDocument *doc = desktop->getDocument(); + doc->ensureUpToDate(); + gint num = 0; + switch (current_key) { + case SELECTION_SELECTION: + num = (gint)boost::distance(desktop->getSelection()->items()); + break; + case SELECTION_LAYER: + num = 0; + default: + break; + } + Glib::ustring label_text = std::to_string(num) + " Items"; + num_elements->set_text(label_text); +} + +void BatchExport::refreshExportHints() +{ + ; +} + +// Signals CallBack + +void BatchExport::onAreaTypeToggle(selection_mode key) +{ + // Prevent executing function twice + if (!selection_buttons[key]->get_active()) { + return; + } + // If you have reached here means the current key is active one ( not sure if multiple transitions happen but + // last call will change values) + current_key = key; + prefs->setString("/dialogs/export/batchexportarea/value", selection_names[current_key]); + + refreshExportHints(); +} + +void BatchExport::onFilenameModified() +{ + ; +} + +void BatchExport::onExport() +{ + interrupted = false; + + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (!desktop) + return; + export_btn->set_sensitive(false); + bool exportSuccessful = true; + + gint num = (gint)boost::distance(desktop->getSelection()->items()); + if (num < 1) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No items selected.")); + export_btn->set_sensitive(true); + return; + } + + // Find and remove any extension from filename so that we can add suffix to it. + Glib::ustring filename = filename_entry->get_text(); + Glib::ustring filename_extension = get_ext_from_filename(filename); + if (ExtensionList::all_extensions[filename_extension]) { + auto extension_point = filename.rfind(filename_extension); + filename.erase(extension_point); + } + + int n = 0; + int export_count = 0; + + // create vector of exports + int num_rows = export_list->get_rows(); + std::vector<Glib::ustring> suffixs; + std::vector<Glib::ustring> extensions; + std::vector<double> dpis; + for (int i = 0; i < num_rows; i++) { + suffixs.push_back(export_list->get_suffix(i)); + extensions.push_back(export_list->get_extension(i)); + dpis.push_back(export_list->get_dpi(i)); + } + + auto itemlist = desktop->getSelection()->items(); + for (auto i = itemlist.begin(); i != itemlist.end() && !interrupted; ++i) { + SPItem *item = *i; + if (!item) { + n++; + continue; + } + + Geom::OptRect area = item->documentVisualBounds(); + if (!area) { + n++; + continue; + } + Glib::ustring id = item->getId(); + if (id.empty()) { + n++; + continue; + } + for (int i = 0; i < num_rows; i++) { + auto omod = ExtensionList::valid_extensions[extensions[i]]; + float dpi = dpis[i]; + + Glib::ustring item_filename = filename + "_" + id; + if (!suffixs[i].empty()) { + item_filename = item_filename + "_" + suffixs[i]; + } + item_filename = item_filename + "_" + std::to_string((int)dpi); + + if (!omod) { + continue; + } + prog_dlg = create_progress_dialog(Glib::ustring::compose(_("Exporting %1 files"), num)); + prog_dlg->set_export_panel(this); + setExporting(true, Glib::ustring::compose(_("Exporting %1 files"), num)); + prog_dlg->set_current(n); + prog_dlg->set_total(num); + + onProgressCallback(0.0, prog_dlg); + bool found = getNonConflictingFilename(item_filename, extensions[i]); + if (!found) { + n++; + continue; + } + + if (omod->is_raster()) { + unsigned long int width = (int)(area->width() * dpi / DPI_BASE + 0.5); + unsigned long int height = (int)(area->height() * dpi / DPI_BASE + 0.5); + + std::vector<SPItem *> selected(desktop->getSelection()->items().begin(), + desktop->getSelection()->items().end()); + bool hide = hide_all->get_active(); + exportSuccessful = _export_raster(*area, width, height, dpi, item_filename, true, onProgressCallback, + prog_dlg, omod, hide ? &selected : nullptr, &advance_options); + } else { + // exportSuccessful = _export_vector(omod, copy_doc, filename, false, &items); + } + if (prog_dlg) { + delete prog_dlg; + prog_dlg = nullptr; + } + setExporting(false); + } + } +} + +bool BatchExport::getNonConflictingFilename(Glib::ustring &filename, Glib::ustring const extension) +{ + SPDocument *doc = SP_ACTIVE_DESKTOP->getDocument(); + Glib::ustring test_filename = filename + extension; + std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(test_filename)); + if (!Inkscape::IO::file_test(test_filename.c_str(), G_FILE_TEST_EXISTS)) { + filename = test_filename; + return true; + } + for (int i = 0; i < 100; i++) { + test_filename = filename + "_copy_" + std::to_string(i) + extension; + if (!Inkscape::IO::file_test(test_filename.c_str(), G_FILE_TEST_EXISTS)) { + filename = test_filename; + return true; + } + } + return false; +} + +void BatchExport::onBrowse(Gtk::EntryIconPosition pos, const GdkEventButton *ev) +{ + ; +} + +// Utils Functions + +// We first check any export hints related to document. If there is none we create a default name using document +// name. doc_export_name is set here and will only be changed when exporting. +void BatchExport::setDefaultFilename() +{ + Glib::ustring filename; + float xdpi = 0.0, ydpi = 0.0; + SPDocument *doc = SP_ACTIVE_DOCUMENT; + sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); + if (filename.empty()) { + Glib::ustring filename_entry_text = filename_entry->get_text(); + Glib::ustring extension = ".png"; + filename = get_default_filename(filename_entry_text, extension); + } + doc_export_name = filename; + original_name = filename; + filename_entry->set_text(filename); + filename_entry->set_position(filename.length()); +} + +void BatchExport::setDefaultSelectionMode() +{ + if (SP_ACTIVE_DESKTOP) { + current_key = (selection_mode)0; // default key + bool found = false; + Glib::ustring pref_key_name = prefs->getString("/dialogs/export/batchexportarea/value"); + for (auto [key, name] : selection_names) { + if (pref_key_name == name) { + current_key = key; + found = true; + break; + } + } + if (!found) { + pref_key_name = selection_names[current_key]; + } + + if (current_key == SELECTION_SELECTION && (SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + current_key = (selection_mode)0; + } + if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + selection_buttons[SELECTION_SELECTION]->set_sensitive(false); + } + selection_buttons[current_key]->set_active(true); + + // we need to set pref key because signals above will set set pref == current key but we sometimes change + // current key like selection key + prefs->setString("/dialogs/export/batchexportarea/value", pref_key_name); + } +} + +void BatchExport::setExporting(bool exporting, Glib::ustring const &text) +{ + if (exporting) { + _prog->set_text(text); + _prog->set_fraction(0.0); + _prog->set_sensitive(true); + export_btn->set_sensitive(false); + } else { + _prog->set_text(""); + _prog->set_fraction(0.0); + _prog->set_sensitive(false); + export_btn->set_sensitive(true); + } +} + +ExportProgressDialog *BatchExport::create_progress_dialog(Glib::ustring progress_text) +{ + // dont forget to delete it later + auto dlg = new ExportProgressDialog(_("Export in progress"), true); + dlg->set_transient_for(*(INKSCAPE.active_desktop()->getToplevel())); + + Gtk::ProgressBar *prg = Gtk::manage(new Gtk::ProgressBar()); + prg->set_text(progress_text); + dlg->set_progress(prg); + auto CA = dlg->get_content_area(); + CA->pack_start(*prg, FALSE, FALSE, 4); + + Gtk::Button *btn = dlg->add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL); + + btn->signal_clicked().connect(sigc::mem_fun(*this, &BatchExport::onProgressCancel)); + dlg->signal_delete_event().connect(sigc::mem_fun(*this, &BatchExport::onProgressDelete)); + + dlg->show_all(); + return dlg; +} + +/// Called when dialog is deleted +bool BatchExport::onProgressDelete(GdkEventAny * /*event*/) +{ + interrupted = true; + prog_dlg->set_stopped(); + return TRUE; +} // end of sp_export_progress_delete() + +/// Called when progress is cancelled +void BatchExport::onProgressCancel() +{ + interrupted = true; + prog_dlg->set_stopped(); +} // end of sp_export_progress_cancel() + +/// Called for every progress iteration +unsigned int BatchExport::onProgressCallback(float value, void *dlg) +{ + auto dlg2 = reinterpret_cast<ExportProgressDialog *>(dlg); + + auto self = dynamic_cast<BatchExport *>(dlg2->get_export_panel()); + + if (!self || self->interrupted) + return FALSE; + + auto current = dlg2->get_current(); + auto total = dlg2->get_total(); + if (total > 0) { + double completed = current; + completed /= static_cast<double>(total); + + value = completed + (value / static_cast<double>(total)); + } + + auto prg = dlg2->get_progress(); + prg->set_fraction(value); + + if (self) { + self->_prog->set_fraction(value); + } + + int evtcount = 0; + while ((evtcount < 16) && gdk_events_pending()) { + Gtk::Main::iteration(false); + evtcount += 1; + } + + Gtk::Main::iteration(false); + return TRUE; +} // end of sp_export_progress_callback() + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/dialog/export-batch.h b/src/ui/dialog/export-batch.h new file mode 100644 index 0000000000..764fc507c0 --- /dev/null +++ b/src/ui/dialog/export-batch.h @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * bulia byak <buliabyak@users.sf.net> + * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * + * Copyright (C) 1999-2007 Authors + * Copyright (C) 2001-2002 Ximian, Inc. + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SP_EXPORT_BATCH_H +#define SP_EXPORT_BATCH_H + +#include <gtkmm.h> + +#include "export-helper.h" +#include "extension/output.h" +#include "ui/widget/scroll-utils.h" +#include "ui/widget/scrollprotected.h" +#include "ui/widget/unit-menu.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { + +class BatchExport : public Gtk::Box +{ +public: + BatchExport(){}; + BatchExport(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) + : Gtk::Box(cobject){}; + ~BatchExport() override; + +protected: + InkscapeApplication *_app; + +public: + void set_app(InkscapeApplication *app) { _app = app; }; + +private: + enum selection_mode + { + SELECTION_LAYER = 0, // Default is alaways placed first + SELECTION_SELECTION, + }; + +private: + typedef Inkscape::UI::Widget::ScrollProtected<Gtk::SpinButton> SpinButton; + + std::map<selection_mode, Gtk::RadioButton *> selection_buttons; + Gtk::FlowBox *preview_container = nullptr; + Gtk::CheckButton *show_preview = nullptr; + Gtk::Label *num_elements = nullptr; + Gtk::Box *adv_box = nullptr; + Gtk::CheckButton *hide_all = nullptr; + Gtk::Entry *filename_entry = nullptr; + Gtk::Button *export_btn = nullptr; + Gtk::ProgressBar *_prog = nullptr; + ExportList *export_list = nullptr; + + AdvanceOptions advance_options; + +private: + bool filename_modified; + Glib::ustring original_name; + Glib::ustring doc_export_name; + + Inkscape::Preferences *prefs = nullptr; + std::map<selection_mode, Glib::ustring> selection_names; + selection_mode current_key; + +public: + // initialise variables from builder + void initialise(const Glib::RefPtr<Gtk::Builder> &builder); + void setup(); + bool getNonConflictingFilename(Glib::ustring& filename,Glib::ustring const extension); + +private: + void setDefaultSelectionMode(); + void setDefaultFilename(); + +private: + void onFilenameModified(); + void onAreaTypeToggle(selection_mode key); + void onExport(); + void onBrowse(Gtk::EntryIconPosition pos, const GdkEventButton *ev); + void on_inkscape_selection_modified(Inkscape::Selection *selection, guint flags); + void on_inkscape_selection_changed(Inkscape::Selection *selection); + +private: + void refreshItems(); + void refreshExportHints(); + +private: + void setExporting(bool exporting, Glib::ustring const &text = ""); + ExportProgressDialog *create_progress_dialog(Glib::ustring progress_text); + /** + * Callback to be used in for loop to update the progress bar. + * + * @param value number between 0 and 1 indicating the fraction of progress (0.17 = 17 % progress) + * @param dlg void pointer to the Gtk::Dialog progress dialog + */ + static unsigned int onProgressCallback(float value, void *dlg); + + /** + * Callback for pressing the cancel button. + */ + void onProgressCancel(); + + /** + * Callback invoked on closing the progress dialog. + */ + bool onProgressDelete(GdkEventAny *event); + +private: + ExportProgressDialog *prog_dlg = nullptr; + bool interrupted; + +private: + sigc::connection filenameConn; + sigc::connection exportConn; + sigc::connection browseConn; + sigc::connection selectionModifiedConn; + sigc::connection selectionChangedConn; + +private: + void on_realize() override; + void on_unrealize() override; +}; +} // namespace Dialog +} // namespace UI +} // namespace Inkscape +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/dialog/export-helper.cpp b/src/ui/dialog/export-helper.cpp index 4141c73217..e6d1f1aede 100644 --- a/src/ui/dialog/export-helper.cpp +++ b/src/ui/dialog/export-helper.cpp @@ -37,6 +37,7 @@ #include "ui/dialog-events.h" #include "ui/dialog/dialog-notebook.h" #include "ui/dialog/filedialog.h" +#include "ui/icon-loader.h" #include "ui/interface.h" #include "ui/widget/scrollprotected.h" #include "ui/widget/unit-menu.h" @@ -148,7 +149,7 @@ void ExtensionList::setup() for (auto [key, omod] : valid_extensions) { this->append(key); } - this->set_active(0); + this->set_active_text(".png"); } void ExtensionList::createList() { @@ -216,6 +217,7 @@ void ExtensionList::appendExtensionToFilename(Glib::ustring &filename, Glib::ust if (valid_extensions[filename_extension]) { active_extension = filename_extension; } + // We use ".png" as default extension. Change it to get extension from module. if (!valid_extensions[active_extension]) { active_extension = ".png"; } @@ -223,6 +225,139 @@ void ExtensionList::appendExtensionToFilename(Glib::ustring &filename, Glib::ust return; } +void ExportList::setup() +{ + if (_initialised) { + return; + } + _initialised = true; + prefs = Inkscape::Preferences::get(); + default_dpi = prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE); + + Gtk::Button *add_button = Gtk::manage(new Gtk::Button()); + Glib::ustring label = "Add Export"; + add_button->set_label(label); + this->attach(*add_button, 0, 0, 4, 1); + + this->insert_row(0); + + Gtk::Label *suffix_label = Gtk::manage(new Gtk::Label("Suffix")); + this->attach(*suffix_label, _suffix_col, 0, 1, 1); + suffix_label->show(); + + Gtk::Label *extension_label = Gtk::manage(new Gtk::Label("Format")); + this->attach(*extension_label, _extension_col, 0, 1, 1); + extension_label->show(); + + Gtk::Label *dpi_label = Gtk::manage(new Gtk::Label("DPI")); + this->attach(*dpi_label, _dpi_col, 0, 1, 1); + dpi_label->show(); + + append_row(); + + add_button->signal_clicked().connect(sigc::mem_fun(*this, &ExportList::append_row)); + add_button->set_hexpand(true); + add_button->show(); + + this->set_row_spacing(5); + this->set_column_spacing(2); +} + +ExportList::~ExportList() +{ + ; +} + +void ExportList::append_row() +{ + int current_row = _num_rows + 1; // because we have label row at top + this->insert_row(current_row); + + Gtk::Entry *suffix = Gtk::manage(new Gtk::Entry()); + this->attach(*suffix, _suffix_col, current_row, 1, 1); + suffix->set_width_chars(2); + suffix->set_hexpand(true); + suffix->set_placeholder_text("Suffix"); + suffix->show(); + + ExtensionList *extension = Gtk::manage(new ExtensionList()); + extension->setup(); + this->attach(*extension, _extension_col, current_row, 1, 1); + extension->show(); + + SpinButton *dpi_sb = Gtk::manage(new SpinButton()); + dpi_sb->set_digits(2); + dpi_sb->set_increments(0.1, 1.0); + dpi_sb->set_range(0.01, 100000.0); + dpi_sb->set_value(default_dpi); + dpi_sb->set_sensitive(true); + dpi_sb->set_width_chars(6); + dpi_sb->set_max_width_chars(6); + this->attach(*dpi_sb, _dpi_col, current_row, 1, 1); + dpi_sb->show(); + + Gtk::Image *pIcon = Gtk::manage(sp_get_icon_image("window-close", Gtk::ICON_SIZE_SMALL_TOOLBAR)); + Gtk::Button *delete_btn = Gtk::manage(new Gtk::Button()); + delete_btn->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + delete_btn->add(*pIcon); + this->attach(*delete_btn, _delete_col, current_row, 1, 1); + delete_btn->show(); + delete_btn->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &ExportList::delete_row), delete_btn)); + + _num_rows++; +} + +void ExportList::delete_row(Gtk::Widget *widget) +{ + if (widget == nullptr) { + return; + } + if (_num_rows <= 1) { + return; + } + int row = this->child_property_top_attach(*widget); + this->remove_row(row); + _num_rows--; +} + +Glib::ustring ExportList::get_suffix(int row) +{ + Glib::ustring suffix = ""; + Gtk::Entry *entry = dynamic_cast<Gtk::Entry *>(this->get_child_at(_suffix_col, row + 1)); + if (entry == nullptr) { + return suffix; + } + suffix = entry->get_text(); + return suffix; +} +Glib::ustring ExportList::get_extension(int row) +{ + Glib::ustring extension = ""; + ExtensionList *extension_cb = dynamic_cast<ExtensionList *>(this->get_child_at(_extension_col, row + 1)); + if (extension_cb == nullptr) { + return extension; + } + extension = extension_cb->get_active_text(); + return extension; +} +double ExportList::get_dpi(int row) +{ + double dpi = default_dpi; + SpinButton *spin_sb = dynamic_cast<SpinButton *>(this->get_child_at(_dpi_col, row + 1)); + if (spin_sb == nullptr) { + return dpi; + } + dpi = spin_sb->get_value(); + return dpi; +} + +/* + ****************************************** + * HELPER FUNCTIONS NOT SPECIF TO CLASSES * + ****************************************** + */ + float getValuePx(float value, Unit const *unit) { return Inkscape::Util::Quantity::convert(value, unit, "px"); diff --git a/src/ui/dialog/export-helper.h b/src/ui/dialog/export-helper.h index 0f7bd961c5..2f345e0b34 100644 --- a/src/ui/dialog/export-helper.h +++ b/src/ui/dialog/export-helper.h @@ -89,12 +89,12 @@ public: }; // Class for storing and manipulating extensions -class ExtensionList : public Gtk::ComboBoxText +class ExtensionList : public Inkscape::UI::Widget::ScrollProtected<Gtk::ComboBoxText> { public: ExtensionList(){}; ExtensionList(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) - : Gtk::ComboBoxText(cobject){}; + : Inkscape::UI::Widget::ScrollProtected<Gtk::ComboBoxText>(cobject, refGlade){}; ~ExtensionList(); public: @@ -140,6 +140,37 @@ public: inline void set_stopped() { _stopped = true; } }; +class ExportList : public Gtk::Grid +{ +public: + ExportList(){}; + ExportList(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) + : Gtk::Grid(cobject){}; + ~ExportList(); + +public: + void setup(); + void append_row(); + void delete_row(Gtk::Widget *widget); + Glib::ustring get_suffix(int row); + Glib::ustring get_extension(int row); + double get_dpi(int row); + int get_rows() { return _num_rows; } + +private: + typedef Inkscape::UI::Widget::ScrollProtected<Gtk::SpinButton> SpinButton; + Inkscape::Preferences *prefs = nullptr; + double default_dpi = 96.00; + +private: + bool _initialised = false; + int _num_rows = 0; + int _suffix_col = 0; + int _extension_col = 1; + int _dpi_col = 2; + int _delete_col = 3; +}; + float getValuePx(float value, Unit const *unit); void setValuePx(Glib::RefPtr<Gtk::Adjustment> &adj, double val, Unit const *unit); Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension); diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index ea226aeea0..f8376ff74a 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -92,6 +92,9 @@ void SingleExport::initialise(const Glib::RefPtr<Gtk::Builder> &builder) builder->get_widget("si_progress", _prog); builder->get_widget("si_advance_box", adv_box); + + Inkscape::UI::Widget::ScrollTransfer<Gtk::ScrolledWindow> *temp = nullptr; + builder->get_widget_derived("s_scroll", temp); } void SingleExport::on_realize() @@ -169,6 +172,7 @@ void SingleExport::on_inkscape_selection_changed(Inkscape::Selection *selection) } } refreshArea(); + refreshExportHints(); } // Setup Single Export.Called by export on realize @@ -230,9 +234,9 @@ void SingleExport::setupSpinButtons() setupSpinButton<sb_type>(spin_buttons[SPIN_WIDTH], 0.0, 0.0, PNG_UINT_31_MAX, 0.1, 1.0, EXPORT_COORD_PRECISION, true, &SingleExport::onAreaXChange, SPIN_WIDTH); - setupSpinButton<sb_type>(spin_buttons[SPIN_BMHEIGHT], 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, + setupSpinButton<sb_type>(spin_buttons[SPIN_BMHEIGHT], 1.0, 1.0, 1000000.0, 1.0, 10.0, 0, true, &SingleExport::onDpiChange, SPIN_BMHEIGHT); - setupSpinButton<sb_type>(spin_buttons[SPIN_BMWIDTH], 1.0, 1.0, 1000000.0, 1.0, 10.0, 3, true, + setupSpinButton<sb_type>(spin_buttons[SPIN_BMWIDTH], 1.0, 1.0, 1000000.0, 1.0, 10.0, 0, true, &SingleExport::onDpiChange, SPIN_BMWIDTH); setupSpinButton<sb_type>(spin_buttons[SPIN_DPI], prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), 0.01, 100000.0, 0.1, 1.0, 2, true, &SingleExport::onDpiChange, SPIN_DPI); @@ -447,12 +451,12 @@ void SingleExport::onExport() si_export->set_sensitive(false); bool exportSuccessful = false; auto extension = si_extension_cb->get_active_text(); - if (!ExtensionList::valid_extensions[extension]) { + auto omod = ExtensionList::valid_extensions[extension]; + if (!omod) { si_export->set_sensitive(true); return; } - auto omod = ExtensionList::valid_extensions[extension]; Unit const *unit = units->getUnit(); Glib::ustring filename = si_filename_entry->get_text(); diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index ea8b8aee9f..62ac847a08 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -79,13 +79,15 @@ Export::Export() builder->get_widget_derived("Single Image", single_image); single_image->initialise(builder); - builder->get_widget("Batch Export", batch_export); + builder->get_widget_derived("Batch Export", batch_export); + batch_export->initialise(builder); // Callback when container is finally mapped on window. All intialisation like set active is done inside it. container->signal_realize().connect(sigc::mem_fun(*this, &Export::onRealize)); // Provide inkscape _app instance to single Export single_image->set_app(_app); + batch_export->set_app(_app); } Export::~Export() {} @@ -95,6 +97,7 @@ Export::~Export() {} void Export::onRealize() { single_image->setup(); + batch_export->setup(); // setDefaultNotebookPage(); } diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 28c61e371d..b837eb3f76 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -17,6 +17,7 @@ #include "export-helper.h" #include "export-single.h" +#include "export-batch.h" #include "extension/output.h" #include "ui/dialog/dialog-base.h" #include "ui/widget/scrollprotected.h" @@ -49,7 +50,7 @@ private: private: SingleExport *single_image = nullptr; - Gtk::Box *batch_export = nullptr; + BatchExport *batch_export = nullptr; private: Inkscape::Preferences *prefs = nullptr; diff --git a/src/ui/widget/scrollprotected.h b/src/ui/widget/scrollprotected.h index 0be9d8c5a8..c0398fec85 100644 --- a/src/ui/widget/scrollprotected.h +++ b/src/ui/widget/scrollprotected.h @@ -11,6 +11,7 @@ */ #include <gtkmm.h> + #include "scroll-utils.h" namespace Inkscape { @@ -33,8 +34,11 @@ class ScrollProtected : public Base public: using Base::Base; using typename Base::BaseObjectType; - ScrollProtected() : Base(){} - ScrollProtected(BaseObjectType* cobject, const Glib::RefPtr<Gtk::Builder>& refGlade):Base(cobject){}; + ScrollProtected() + : Base() + {} + ScrollProtected(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) + : Base(cobject){}; virtual ~ScrollProtected(){}; protected: @@ -58,6 +62,53 @@ protected: } }; +/** + * A class decorator for scroll widgets like scrolled window to transfer scroll to + * any ancestor which is is a scrollable window when scroll reached end. + * + * For custom scroll event handlers, derived classes must implement + * on_safe_scroll_event instead of on_scroll_event. Directly connecting to + * signal_scroll_event() will bypass the scroll protection. + * + * @tparam Base A subclass of Gtk::Widget + */ +template <typename Base> +class ScrollTransfer : public Base +{ +public: + using Base::Base; + using typename Base::BaseObjectType; + ScrollTransfer() + : Base() + {} + ScrollTransfer(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) + : Base(cobject){}; + virtual ~ScrollTransfer(){}; + +protected: + /** + * Event handler for "safe" scroll events + */ + virtual bool on_safe_scroll_event(GdkEventScroll *event) + { // + return Base::on_scroll_event(event); + } + + bool on_scroll_event(GdkEventScroll *event) final + { + auto scrollable = dynamic_cast<Gtk::Widget *>(Inkscape::UI::Widget::get_scrollable_ancestor(this)); + auto adj = this->get_vadjustment(); + auto before = adj->get_value(); + bool result = on_safe_scroll_event(event); + auto after = adj->get_value(); + if (scrollable && before == after) { + return false; + } + + return result; + } +}; + } // namespace Widget } // namespace UI } // namespace Inkscape -- GitLab From 6f389dc638bdf64929e9f4f4d7e4586b4e659857 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Mon, 5 Jul 2021 00:26:20 +0530 Subject: [PATCH 19/40] Resolved copy creation in batch export --- src/ui/dialog/export-batch.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index 689a48086e..ac055c6b7f 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -311,14 +311,14 @@ void BatchExport::onExport() bool BatchExport::getNonConflictingFilename(Glib::ustring &filename, Glib::ustring const extension) { SPDocument *doc = SP_ACTIVE_DESKTOP->getDocument(); - Glib::ustring test_filename = filename + extension; - std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(test_filename)); + std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(filename)); + Glib::ustring test_filename = path + extension; if (!Inkscape::IO::file_test(test_filename.c_str(), G_FILE_TEST_EXISTS)) { filename = test_filename; return true; } - for (int i = 0; i < 100; i++) { - test_filename = filename + "_copy_" + std::to_string(i) + extension; + for (int i = 1; i <= 100; i++) { + test_filename = path + "_copy_" + std::to_string(i) + extension; if (!Inkscape::IO::file_test(test_filename.c_str(), G_FILE_TEST_EXISTS)) { filename = test_filename; return true; -- GitLab From 0083dc283416a6278341d6517d24948aefe9bf04 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Thu, 15 Jul 2021 18:13:59 +0530 Subject: [PATCH 20/40] WIP: ading list selector UI to batch export --- src/desktop.cpp | 5 ++++ src/desktop.h | 1 + src/layer-model.cpp | 11 +++++++++ src/layer-model.h | 2 ++ src/ui/dialog/export-batch.cpp | 44 ++++++++++++++++++++++++++++++---- src/ui/dialog/export-batch.h | 5 ++++ 6 files changed, 64 insertions(+), 4 deletions(-) diff --git a/src/desktop.cpp b/src/desktop.cpp index 954283fa1b..f4b0fc57f3 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -446,6 +446,11 @@ void SPDesktop::toggleLayerSolo(SPObject *object) layers->toggleLayerSolo(object); } +std::list<SPItem*> SPDesktop::getAllLayers() +{ + return layers->getAllLayers(); +} + void SPDesktop::toggleHideAllLayers(bool hide) { layers->toggleHideAllLayers(hide); diff --git a/src/desktop.h b/src/desktop.h index 40c22f77bb..54669d47f7 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -346,6 +346,7 @@ public: SPObject *currentLayer() const; void setCurrentLayer(SPObject *object); void toggleLayerSolo(SPObject *object); + std::list<SPItem *> getAllLayers(); void toggleHideAllLayers(bool hide); void toggleLockAllLayers(bool lock); void toggleLockOtherLayers(SPObject *object); diff --git a/src/layer-model.cpp b/src/layer-model.cpp index 56208af299..42a0fc8890 100644 --- a/src/layer-model.cpp +++ b/src/layer-model.cpp @@ -116,6 +116,17 @@ void LayerModel::setCurrentLayer(SPObject *object) { _layer_hierarchy->setBottom(object); } +std::list<SPItem *> LayerModel::getAllLayers() +{ + std::list<SPItem *> layers; + for (SPObject *obj = Inkscape::previous_layer(currentRoot(), currentRoot()); obj; + obj = Inkscape::previous_layer(currentRoot(), obj)) { + auto item = SP_ITEM(obj); + layers.push_back(item); + } + return layers; +} + void LayerModel::toggleHideAllLayers(bool hide) { for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), currentRoot()); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { diff --git a/src/layer-model.h b/src/layer-model.h index 8e7153875a..f0d32a86e9 100644 --- a/src/layer-model.h +++ b/src/layer-model.h @@ -28,6 +28,7 @@ class SPDocument; class SPObject; +class SPItem; namespace Inkscape { @@ -75,6 +76,7 @@ public: void reset(); void setCurrentLayer(SPObject *object); void toggleLayerSolo(SPObject *object); + std::list<SPItem *> getAllLayers(); void toggleHideAllLayers(bool hide); void toggleLockAllLayers(bool lock); void toggleLockOtherLayers(SPObject *object); diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index ac055c6b7f..bd40b5346e 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -51,6 +51,37 @@ namespace Inkscape { namespace UI { namespace Dialog { +class BatchItem : public Gtk::FlowBoxChild +{ +public: + BatchItem(SPItem *item); + ~BatchItem(){}; + +public: + Gtk::CheckButton selector; + +private: + Gtk::Grid grid; + // PreviewBox p_box; + SPItem *_item; +}; + +BatchItem::BatchItem(SPItem *item) + : grid() + , selector() +{ + if (!item) { + return; + } + _item = item; + grid.attach(selector, 0, 0, 1, 1); + Glib::ustring id = _item->getId(); + selector.set_label(id); + selector.set_active(false); + set_child(gird); + show_all_children(); +} + BatchExport::~BatchExport() { ; @@ -164,13 +195,18 @@ void BatchExport::refreshItems() SPDesktop *desktop = SP_ACTIVE_DESKTOP; SPDocument *doc = desktop->getDocument(); doc->ensureUpToDate(); - gint num = 0; + + std::set switch (current_key) { case SELECTION_SELECTION: - num = (gint)boost::distance(desktop->getSelection()->items()); + current_items.insert() + num = (int)boost::distance(desktop->getSelection()->items()); break; - case SELECTION_LAYER: - num = 0; + case SELECTION_LAYER: { + std::list<SPItem *> layers = desktop->getAllLayers(); + num = layers.size(); + break; + } default: break; } diff --git a/src/ui/dialog/export-batch.h b/src/ui/dialog/export-batch.h index 764fc507c0..b597468017 100644 --- a/src/ui/dialog/export-batch.h +++ b/src/ui/dialog/export-batch.h @@ -25,6 +25,8 @@ namespace Inkscape { namespace UI { namespace Dialog { +class BatchItem; + class BatchExport : public Gtk::Box { public: @@ -61,7 +63,10 @@ private: ExportList *export_list = nullptr; AdvanceOptions advance_options; + std::vector<BatchItem*> current_items; +private: + std::set<SPItem*> added_items; private: bool filename_modified; Glib::ustring original_name; -- GitLab From 5dde1e9fae24497e9eb58c89dcb189bf7d5d0bdf Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Tue, 3 Aug 2021 13:56:19 +0530 Subject: [PATCH 21/40] Changed related to new signal --- share/ui/dialog-export.glade | 240 +++++++++++++++++--------------- src/ui/dialog/export-batch.cpp | 85 +++++------ src/ui/dialog/export-batch.h | 31 +++-- src/ui/dialog/export-helper.cpp | 9 +- src/ui/dialog/export-helper.h | 2 +- src/ui/dialog/export-single.cpp | 101 +++++++------- src/ui/dialog/export-single.h | 23 +-- src/ui/dialog/export.cpp | 37 ++++- src/ui/dialog/export.h | 6 +- 9 files changed, 286 insertions(+), 248 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index c594919952..d38268e3d6 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -3,6 +3,7 @@ <interface> <requires lib="gtk+" version="3.20"/> <object class="GtkBox" id="Export Dialog Box"> + <property name="name">ExportDialog</property> <property name="visible">True</property> <property name="can-focus">False</property> <property name="double-buffered">False</property> @@ -320,111 +321,6 @@ <property name="width">6</property> </packing> </child> - <child> - <!-- n-columns=4 n-rows=1 --> - <object class="GtkGrid"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <child> - <object class="GtkRadioButton" id="si_s_selection"> - <property name="label" translatable="yes">Selection</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="focus-on-click">False</property> - <property name="receives-default">False</property> - <property name="hexpand">True</property> - <property name="draw-indicator">False</property> - <property name="group">si_s_document</property> - </object> - <packing> - <property name="left-attach">2</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkRadioButton" id="si_s_document"> - <property name="label" translatable="yes">Document</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="focus-on-click">False</property> - <property name="receives-default">False</property> - <property name="hexpand">True</property> - <property name="active">True</property> - <property name="draw-indicator">False</property> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkRadioButton" id="si_s_page"> - <property name="label" translatable="yes">Page</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="focus-on-click">False</property> - <property name="receives-default">False</property> - <property name="hexpand">True</property> - <property name="draw-indicator">False</property> - <property name="group">si_s_document</property> - </object> - <packing> - <property name="left-attach">1</property> - <property name="top-attach">0</property> - </packing> - </child> - <child> - <object class="GtkRadioButton" id="si_s_custom"> - <property name="label" translatable="yes">Custom</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <property name="focus-on-click">False</property> - <property name="receives-default">False</property> - <property name="hexpand">True</property> - <property name="draw-indicator">False</property> - <property name="group">si_s_document</property> - </object> - <packing> - <property name="left-attach">3</property> - <property name="top-attach">0</property> - </packing> - </child> - </object> - <packing> - <property name="left-attach">0</property> - <property name="top-attach">0</property> - <property name="width">6</property> - </packing> - </child> - <child> - <!-- n-columns=5 n-rows=1 --> - <object class="GtkGrid"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="row-spacing">2</property> - <property name="column-spacing">20</property> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="left-attach">1</property> - <property name="top-attach">9</property> - <property name="width">4</property> - </packing> - </child> <child> <object class="GtkLabel"> <property name="visible">True</property> @@ -560,6 +456,115 @@ <property name="top-attach">12</property> </packing> </child> + <child> + <!-- n-columns=5 n-rows=1 --> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <property name="row-spacing">2</property> + <property name="column-spacing">20</property> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + <child> + <placeholder/> + </child> + </object> + <packing> + <property name="left-attach">1</property> + <property name="top-attach">9</property> + <property name="width">4</property> + </packing> + </child> + <child> + <!-- n-columns=4 n-rows=1 --> + <object class="GtkGrid"> + <property name="visible">True</property> + <property name="can-focus">False</property> + <child> + <object class="GtkRadioButton" id="si_s_selection"> + <property name="label" translatable="yes">Selection</property> + <property name="name">export_selection</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="focus-on-click">False</property> + <property name="receives-default">False</property> + <property name="hexpand">True</property> + <property name="draw-indicator">False</property> + <property name="group">si_s_document</property> + </object> + <packing> + <property name="left-attach">2</property> + <property name="top-attach">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="si_s_document"> + <property name="label" translatable="yes">Document</property> + <property name="name">export_selection</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="focus-on-click">False</property> + <property name="receives-default">False</property> + <property name="hexpand">True</property> + <property name="active">True</property> + <property name="draw-indicator">False</property> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="si_s_page"> + <property name="label" translatable="yes">Page</property> + <property name="name">export_selection</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="focus-on-click">False</property> + <property name="receives-default">False</property> + <property name="hexpand">True</property> + <property name="draw-indicator">False</property> + <property name="group">si_s_document</property> + </object> + <packing> + <property name="left-attach">1</property> + <property name="top-attach">0</property> + </packing> + </child> + <child> + <object class="GtkRadioButton" id="si_s_custom"> + <property name="label" translatable="yes">Custom</property> + <property name="name">export_selection</property> + <property name="visible">True</property> + <property name="can-focus">True</property> + <property name="focus-on-click">False</property> + <property name="receives-default">False</property> + <property name="hexpand">True</property> + <property name="draw-indicator">False</property> + <property name="group">si_s_document</property> + </object> + <packing> + <property name="left-attach">3</property> + <property name="top-attach">0</property> + </packing> + </child> + </object> + <packing> + <property name="left-attach">0</property> + <property name="top-attach">0</property> + <property name="width">6</property> + </packing> + </child> <child> <placeholder/> </child> @@ -701,7 +706,7 @@ </packing> </child> <child> - <!-- n-columns=3 n-rows=2 --> + <!-- n-columns=2 n-rows=3 --> <object class="GtkGrid"> <property name="visible">True</property> <property name="can-focus">False</property> @@ -733,27 +738,27 @@ </packing> </child> <child> - <object class="GtkButton" id="si_export"> - <property name="label" translatable="yes">Export</property> + <object class="GtkProgressBar" id="si_progress"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="receives-default">False</property> - <property name="halign">end</property> </object> <packing> - <property name="left-attach">2</property> - <property name="top-attach">0</property> + <property name="left-attach">0</property> + <property name="top-attach">2</property> + <property name="width">2</property> </packing> </child> <child> - <object class="GtkProgressBar" id="si_progress"> + <object class="GtkButton" id="si_export"> + <property name="label" translatable="yes">Export</property> <property name="visible">True</property> - <property name="can-focus">False</property> + <property name="can-focus">True</property> + <property name="receives-default">False</property> </object> <packing> <property name="left-attach">0</property> <property name="top-attach">1</property> - <property name="width">3</property> + <property name="width">2</property> </packing> </child> </object> @@ -829,7 +834,8 @@ <property name="column-spacing">10</property> <property name="row-spacing">10</property> <property name="max-children-per-line">10</property> - <property name="selection-mode">none</property> + <property name="selection-mode">multiple</property> + <property name="activate-on-single-click">False</property> <child> <object class="GtkFlowBoxChild"> <property name="width-request">50</property> @@ -1106,6 +1112,7 @@ <child> <object class="GtkRadioButton" id="b_s_selection"> <property name="label" translatable="yes">Selection</property> + <property name="name">export_selection</property> <property name="visible">True</property> <property name="can-focus">False</property> <property name="receives-default">False</property> @@ -1121,6 +1128,7 @@ <child> <object class="GtkRadioButton" id="b_s_layers"> <property name="label" translatable="yes">Layers</property> + <property name="name">export_selection</property> <property name="visible">True</property> <property name="can-focus">False</property> <property name="receives-default">False</property> diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index bd40b5346e..0bee592378 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -78,7 +78,7 @@ BatchItem::BatchItem(SPItem *item) Glib::ustring id = _item->getId(); selector.set_label(id); selector.set_active(false); - set_child(gird); + // set_child(grid); show_all_children(); } @@ -109,37 +109,21 @@ void BatchExport::initialise(const Glib::RefPtr<Gtk::Builder> &builder) builder->get_widget_derived("b_scroll", temp); } -void BatchExport::on_realize() +void BatchExport::selectionModified(Inkscape::Selection *selection, guint flags) { - auto desktop = SP_ACTIVE_DESKTOP; - assert(desktop); - auto *selection = desktop->getSelection(); - - selectionModifiedConn = - selection->connectModified(sigc::mem_fun(*this, &BatchExport::on_inkscape_selection_modified)); - selectionChangedConn = selection->connectChanged(sigc::mem_fun(*this, &BatchExport::on_inkscape_selection_changed)); - - Gtk::Box::on_realize(); -} - -void BatchExport::on_unrealize() -{ - selectionModifiedConn.disconnect(); - selectionChangedConn.disconnect(); - Gtk::Box::on_unrealize(); -} - -void BatchExport::on_inkscape_selection_modified(Inkscape::Selection *selection, guint flags) -{ - assert(SP_ACTIVE_DESKTOP->getSelection() == selection); + if (!_desktop ||_desktop->getSelection() != selection) { + return; + } if (!(flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { return; } } -void BatchExport::on_inkscape_selection_changed(Inkscape::Selection *selection) +void BatchExport::selectionChanged(Inkscape::Selection *selection) { - assert(SP_ACTIVE_DESKTOP->getSelection() == selection); + if (!_desktop || _desktop->getSelection() != selection) { + return; + } if (selection->isEmpty()) { selection_buttons[SELECTION_SELECTION]->set_sensitive(false); if (current_key == SELECTION_SELECTION) { @@ -164,6 +148,10 @@ void BatchExport::on_inkscape_selection_changed(Inkscape::Selection *selection) // Setup Single Export.Called by export on realize void BatchExport::setup() { + if (setupDone) { + return; + } + setupDone = true; prefs = Inkscape::Preferences::get(); // Setup Advance Options @@ -189,21 +177,20 @@ void BatchExport::setup() void BatchExport::refreshItems() { - if (!SP_ACTIVE_DESKTOP) { + if (!_desktop) { return; } - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - SPDocument *doc = desktop->getDocument(); + SPDocument *doc = _desktop->getDocument(); doc->ensureUpToDate(); - - std::set + + // std::set + int num = 0; switch (current_key) { case SELECTION_SELECTION: - current_items.insert() - num = (int)boost::distance(desktop->getSelection()->items()); + num = (int)boost::distance(_desktop->getSelection()->items()); break; case SELECTION_LAYER: { - std::list<SPItem *> layers = desktop->getAllLayers(); + std::list<SPItem *> layers = _desktop->getAllLayers(); num = layers.size(); break; } @@ -243,16 +230,14 @@ void BatchExport::onFilenameModified() void BatchExport::onExport() { interrupted = false; - - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) + if (!_desktop) return; export_btn->set_sensitive(false); bool exportSuccessful = true; - gint num = (gint)boost::distance(desktop->getSelection()->items()); + gint num = (gint)boost::distance(_desktop->getSelection()->items()); if (num < 1) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No items selected.")); + _desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No items selected.")); export_btn->set_sensitive(true); return; } @@ -279,7 +264,7 @@ void BatchExport::onExport() dpis.push_back(export_list->get_dpi(i)); } - auto itemlist = desktop->getSelection()->items(); + auto itemlist = _desktop->getSelection()->items(); for (auto i = itemlist.begin(); i != itemlist.end() && !interrupted; ++i) { SPItem *item = *i; if (!item) { @@ -327,8 +312,8 @@ void BatchExport::onExport() unsigned long int width = (int)(area->width() * dpi / DPI_BASE + 0.5); unsigned long int height = (int)(area->height() * dpi / DPI_BASE + 0.5); - std::vector<SPItem *> selected(desktop->getSelection()->items().begin(), - desktop->getSelection()->items().end()); + std::vector<SPItem *> selected(_desktop->getSelection()->items().begin(), + _desktop->getSelection()->items().end()); bool hide = hide_all->get_active(); exportSuccessful = _export_raster(*area, width, height, dpi, item_filename, true, onProgressCallback, prog_dlg, omod, hide ? &selected : nullptr, &advance_options); @@ -346,7 +331,10 @@ void BatchExport::onExport() bool BatchExport::getNonConflictingFilename(Glib::ustring &filename, Glib::ustring const extension) { - SPDocument *doc = SP_ACTIVE_DESKTOP->getDocument(); + if(_desktop){ + return false; + } + SPDocument *doc = _desktop->getDocument(); std::string path = absolutize_path_from_document_location(doc, Glib::filename_from_utf8(filename)); Glib::ustring test_filename = path + extension; if (!Inkscape::IO::file_test(test_filename.c_str(), G_FILE_TEST_EXISTS)) { @@ -374,14 +362,17 @@ void BatchExport::onBrowse(Gtk::EntryIconPosition pos, const GdkEventButton *ev) // name. doc_export_name is set here and will only be changed when exporting. void BatchExport::setDefaultFilename() { + if (!_desktop) { + return; + } Glib::ustring filename; float xdpi = 0.0, ydpi = 0.0; - SPDocument *doc = SP_ACTIVE_DOCUMENT; + SPDocument *doc = _desktop->getDocument(); sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); if (filename.empty()) { Glib::ustring filename_entry_text = filename_entry->get_text(); Glib::ustring extension = ".png"; - filename = get_default_filename(filename_entry_text, extension); + filename = get_default_filename(filename_entry_text, extension, doc); } doc_export_name = filename; original_name = filename; @@ -391,7 +382,7 @@ void BatchExport::setDefaultFilename() void BatchExport::setDefaultSelectionMode() { - if (SP_ACTIVE_DESKTOP) { + if (_desktop) { current_key = (selection_mode)0; // default key bool found = false; Glib::ustring pref_key_name = prefs->getString("/dialogs/export/batchexportarea/value"); @@ -406,10 +397,10 @@ void BatchExport::setDefaultSelectionMode() pref_key_name = selection_names[current_key]; } - if (current_key == SELECTION_SELECTION && (SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + if (current_key == SELECTION_SELECTION && (_desktop->getSelection())->isEmpty()) { current_key = (selection_mode)0; } - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + if ((_desktop->getSelection())->isEmpty()) { selection_buttons[SELECTION_SELECTION]->set_sensitive(false); } selection_buttons[current_key]->set_active(true); diff --git a/src/ui/dialog/export-batch.h b/src/ui/dialog/export-batch.h index b597468017..b176469675 100644 --- a/src/ui/dialog/export-batch.h +++ b/src/ui/dialog/export-batch.h @@ -35,11 +35,18 @@ public: : Gtk::Box(cobject){}; ~BatchExport() override; -protected: +private: InkscapeApplication *_app; + SPDesktop *_desktop = nullptr; + +private: + bool setupDone = false; // To prevent setup() call add connections again. public: - void set_app(InkscapeApplication *app) { _app = app; }; + void setApp(InkscapeApplication *app) { _app = app; } + void setDesktop(SPDesktop *desktop) { _desktop = desktop; } + void selectionChanged(Inkscape::Selection *selection); + void selectionModified(Inkscape::Selection *selection, guint flags); private: enum selection_mode @@ -63,10 +70,11 @@ private: ExportList *export_list = nullptr; AdvanceOptions advance_options; - std::vector<BatchItem*> current_items; + std::vector<BatchItem *> current_items; private: - std::set<SPItem*> added_items; + std::set<SPItem *> added_items; + private: bool filename_modified; Glib::ustring original_name; @@ -80,7 +88,7 @@ public: // initialise variables from builder void initialise(const Glib::RefPtr<Gtk::Builder> &builder); void setup(); - bool getNonConflictingFilename(Glib::ustring& filename,Glib::ustring const extension); + bool getNonConflictingFilename(Glib::ustring &filename, Glib::ustring const extension); private: void setDefaultSelectionMode(); @@ -91,8 +99,13 @@ private: void onAreaTypeToggle(selection_mode key); void onExport(); void onBrowse(Gtk::EntryIconPosition pos, const GdkEventButton *ev); - void on_inkscape_selection_modified(Inkscape::Selection *selection, guint flags); - void on_inkscape_selection_changed(Inkscape::Selection *selection); + +public: + void refresh() + { + refreshItems(); + refreshExportHints(); + }; private: void refreshItems(); @@ -129,10 +142,6 @@ private: sigc::connection browseConn; sigc::connection selectionModifiedConn; sigc::connection selectionChangedConn; - -private: - void on_realize() override; - void on_unrealize() override; }; } // namespace Dialog } // namespace UI diff --git a/src/ui/dialog/export-helper.cpp b/src/ui/dialog/export-helper.cpp index e6d1f1aede..f97b4c7a29 100644 --- a/src/ui/dialog/export-helper.cpp +++ b/src/ui/dialog/export-helper.cpp @@ -372,16 +372,13 @@ void setValuePx(Glib::RefPtr<Gtk::Adjustment> &adj, double val, Unit const *unit // We Create filename by removing already present extension in document name and replacing it with extension passed as // parameter if exxtension is not valid. If document doesn't have a name we use bitmap as defalt name. -Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension) +Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension, SPDocument *doc) { Glib::ustring filename; - if (SP_ACTIVE_DOCUMENT && SP_ACTIVE_DOCUMENT->getDocumentFilename()) { - SPDocument *doc = SP_ACTIVE_DOCUMENT; + if (doc && doc->getDocumentFilename()) { filename = doc->getDocumentFilename(); - ExtensionList::appendExtensionToFilename(filename, extension); - - } else if (SP_ACTIVE_DOCUMENT) { + } else if (doc) { filename = create_filepath_from_id(_("bitmap"), filename_entry_text); filename = filename + extension; } diff --git a/src/ui/dialog/export-helper.h b/src/ui/dialog/export-helper.h index 2f345e0b34..d2fb97c13f 100644 --- a/src/ui/dialog/export-helper.h +++ b/src/ui/dialog/export-helper.h @@ -173,7 +173,7 @@ private: float getValuePx(float value, Unit const *unit); void setValuePx(Glib::RefPtr<Gtk::Adjustment> &adj, double val, Unit const *unit); -Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension); +Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension, SPDocument *doc); std::string create_filepath_from_id(Glib::ustring id, const Glib::ustring &file_entry_text); Glib::ustring get_ext_from_filename(Glib::ustring const &filename); std::string absolutize_path_from_document_location(SPDocument *doc, const std::string &filename); diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index f8376ff74a..660b85128f 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -97,39 +97,23 @@ void SingleExport::initialise(const Glib::RefPtr<Gtk::Builder> &builder) builder->get_widget_derived("s_scroll", temp); } -void SingleExport::on_realize() +void SingleExport::selectionModified(Inkscape::Selection *selection, guint flags) { - auto desktop = SP_ACTIVE_DESKTOP; - assert(desktop); - auto *selection = desktop->getSelection(); - - selectionModifiedConn = - selection->connectModified(sigc::mem_fun(*this, &SingleExport::on_inkscape_selection_modified)); - selectionChangedConn = - selection->connectChanged(sigc::mem_fun(*this, &SingleExport::on_inkscape_selection_changed)); - - Gtk::Box::on_realize(); -} - -void SingleExport::on_unrealize() -{ - selectionModifiedConn.disconnect(); - selectionChangedConn.disconnect(); - Gtk::Box::on_unrealize(); -} - -void SingleExport::on_inkscape_selection_modified(Inkscape::Selection *selection, guint flags) -{ - assert(SP_ACTIVE_DESKTOP->getSelection() == selection); + if (!_desktop || _desktop->getSelection() != selection) { + return; + } if (!(flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { return; } Geom::OptRect bbox; + SPDocument *doc = _desktop->getDocument(); + + if (!doc) { + return; + } switch (current_key) { case SELECTION_DRAWING: - SPDocument *doc; - doc = SP_ACTIVE_DESKTOP->getDocument(); bbox = doc->getRoot()->desktopVisualBounds(); if (bbox) { setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); @@ -150,9 +134,11 @@ void SingleExport::on_inkscape_selection_modified(Inkscape::Selection *selection refreshExportHints(); } -void SingleExport::on_inkscape_selection_changed(Inkscape::Selection *selection) +void SingleExport::selectionChanged(Inkscape::Selection *selection) { - assert(SP_ACTIVE_DESKTOP->getSelection() == selection); + if (!_desktop || _desktop->getSelection() != selection) { + return; + } if (selection->isEmpty()) { selection_buttons[SELECTION_SELECTION]->set_sensitive(false); @@ -178,6 +164,10 @@ void SingleExport::on_inkscape_selection_changed(Inkscape::Selection *selection) // Setup Single Export.Called by export on realize void SingleExport::setup() { + if (setupDone) { + return; + } + setupDone = true; prefs = Inkscape::Preferences::get(); si_extension_cb->setup(); @@ -211,9 +201,8 @@ void SingleExport::setup() void SingleExport::setupUnits() { units->setUnitType(Inkscape::Util::UNIT_TYPE_LINEAR); - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (desktop) { - units->setUnit(desktop->getNamedView()->display_units->abbr); + if (_desktop) { + units->setUnit(_desktop->getNamedView()->display_units->abbr); } } @@ -264,16 +253,16 @@ void SingleExport::setupSpinButton(Gtk::SpinButton *sb, double val, double min, void SingleExport::refreshArea() { - if (SP_ACTIVE_DESKTOP) { + if (_desktop) { SPDocument *doc; Geom::OptRect bbox; - doc = SP_ACTIVE_DESKTOP->getDocument(); + doc = _desktop->getDocument(); doc->ensureUpToDate(); switch (current_key) { case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty() == false) { - bbox = SP_ACTIVE_DESKTOP->getSelection()->visualBounds(); + if ((_desktop->getSelection())->isEmpty() == false) { + bbox = _desktop->getSelection()->visualBounds(); break; } case SELECTION_DRAWING: @@ -298,8 +287,8 @@ void SingleExport::refreshArea() void SingleExport::refreshExportHints() { - if (SP_ACTIVE_DESKTOP && !filename_modified) { - SPDocument *doc = SP_ACTIVE_DOCUMENT; + if (_desktop && !filename_modified) { + SPDocument *doc = _desktop->getDocument(); Glib::ustring filename; float xdpi = 0.0, ydpi = 0.0; switch (current_key) { @@ -310,21 +299,21 @@ void SingleExport::refreshExportHints() if (filename.empty()) { Glib::ustring filename_entry_text = si_filename_entry->get_text(); Glib::ustring extension_entry_text = si_extension_cb->get_active_text(); - filename = get_default_filename(filename_entry_text, extension_entry_text); + filename = get_default_filename(filename_entry_text, extension_entry_text, doc); } doc_export_name = filename; break; case SELECTION_SELECTION: - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + if ((_desktop->getSelection())->isEmpty()) { break; } - SP_ACTIVE_DESKTOP->getSelection()->getExportHints(filename, &xdpi, &ydpi); + _desktop->getSelection()->getExportHints(filename, &xdpi, &ydpi); /* If we still don't have a filename -- let's build one that's nice */ if (filename.empty()) { const gchar *id = "object"; - auto reprlst = SP_ACTIVE_DESKTOP->getSelection()->xmlNodes(); + auto reprlst = _desktop->getSelection()->xmlNodes(); for (auto i = reprlst.begin(); reprlst.end() != i; ++i) { Inkscape::XML::Node *repr = *i; if (repr->attribute("id")) { @@ -444,9 +433,7 @@ void SingleExport::onExtensionChanged() void SingleExport::onExport() { interrupted = false; - - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) + if (!_desktop) return; si_export->set_sensitive(false); bool exportSuccessful = false; @@ -466,7 +453,7 @@ void SingleExport::onExport() float x1 = getValuePx(spin_buttons[SPIN_X1]->get_value(), unit); float y0 = getValuePx(spin_buttons[SPIN_Y0]->get_value(), unit); float y1 = getValuePx(spin_buttons[SPIN_Y1]->get_value(), unit); - auto area = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * desktop->dt2doc(); + auto area = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * _desktop->dt2doc(); unsigned long int width = int(spin_buttons[SPIN_BMWIDTH]->get_value() + 0.5); unsigned long int height = int(spin_buttons[SPIN_BMHEIGHT]->get_value() + 0.5); @@ -480,8 +467,8 @@ void SingleExport::onExport() prog_dlg->set_current(0); prog_dlg->set_total(0); - std::vector<SPItem *> selected(desktop->getSelection()->items().begin(), - desktop->getSelection()->items().end()); + std::vector<SPItem *> selected(_desktop->getSelection()->items().begin(), + _desktop->getSelection()->items().end()); bool hide = si_hide_all->get_active(); exportSuccessful = _export_raster(area, width, height, dpi, filename, false, onProgressCallback, prog_dlg, omod, @@ -489,14 +476,14 @@ void SingleExport::onExport() } else { setExporting(true, Glib::ustring::compose(_("Exporting %1"), filename)); - SPDocument *doc = desktop->getDocument(); + SPDocument *doc = _desktop->getDocument(); SPDocument *copy_doc = (doc->copy()).get(); if (current_key == SELECTION_DRAWING) { fit_canvas_to_drawing(copy_doc, true); } std::vector<SPItem *> items; if (current_key == SELECTION_SELECTION) { - auto itemlist = desktop->getSelection()->items(); + auto itemlist = _desktop->getSelection()->items(); for (auto i = itemlist.begin(); i != itemlist.end(); ++i) { SPItem *item = *i; items.push_back(item); @@ -517,8 +504,11 @@ void SingleExport::onExport() void SingleExport::onBrowse(Gtk::EntryIconPosition pos, const GdkEventButton *ev) { - browseConn.block(); + if(!_app){ + return; + } Gtk::Window *window = _app->get_active_window(); + browseConn.block(); Glib::ustring filename = Glib::filename_from_utf8(si_filename_entry->get_text()); if (filename.empty()) { @@ -703,14 +693,17 @@ void SingleExport::dpiChange(sb_type type) // name. doc_export_name is set here and will only be changed when exporting. void SingleExport::setDefaultFilename() { + if (!_desktop) { + return; + } Glib::ustring filename; float xdpi = 0.0, ydpi = 0.0; - SPDocument *doc = SP_ACTIVE_DOCUMENT; + SPDocument *doc = _desktop->getDocument(); sp_document_get_export_hints(doc, filename, &xdpi, &ydpi); if (filename.empty()) { Glib::ustring filename_entry_text = si_filename_entry->get_text(); Glib::ustring extention_entry_text = si_extension_cb->get_active_text(); - filename = get_default_filename(filename_entry_text, extention_entry_text); + filename = get_default_filename(filename_entry_text, extention_entry_text, doc); } doc_export_name = filename; original_name = filename; @@ -727,7 +720,7 @@ void SingleExport::setDefaultFilename() void SingleExport::setDefaultSelectionMode() { - if (SP_ACTIVE_DESKTOP) { + if (_desktop) { current_key = (selection_mode)0; // default key bool found = false; Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); @@ -745,7 +738,7 @@ void SingleExport::setDefaultSelectionMode() if (current_key == SELECTION_SELECTION && (SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { current_key = (selection_mode)0; } - if ((SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + if ((_desktop->getSelection())->isEmpty()) { selection_buttons[SELECTION_SELECTION]->set_sensitive(false); } selection_buttons[current_key]->set_active(true); @@ -755,7 +748,7 @@ void SingleExport::setDefaultSelectionMode() (spin_buttons[SPIN_HEIGHT]->get_value() == 0 || spin_buttons[SPIN_WIDTH]->get_value() == 0)) { SPDocument *doc; Geom::OptRect bbox; - doc = SP_ACTIVE_DESKTOP->getDocument(); + doc = _desktop->getDocument(); bbox = Geom::Rect(Geom::Point(0.0, 0.0), Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); diff --git a/src/ui/dialog/export-single.h b/src/ui/dialog/export-single.h index b7c0f2b44a..cbee192500 100644 --- a/src/ui/dialog/export-single.h +++ b/src/ui/dialog/export-single.h @@ -32,11 +32,18 @@ public: : Gtk::Box(cobject){}; ~SingleExport() override; -protected: +private: InkscapeApplication *_app; + SPDesktop *_desktop = nullptr; + +private: + bool setupDone = false; // To prevent setup() call add connections again. public: - void set_app(InkscapeApplication *app) { _app = app; }; + void setApp(InkscapeApplication *app) { _app = app; } + void setDesktop(SPDesktop *desktop) { _desktop = desktop; } + void selectionChanged(Inkscape::Selection *selection); + void selectionModified(Inkscape::Selection *selection, guint flags); private: enum sb_type @@ -122,6 +129,12 @@ private: void on_inkscape_selection_modified(Inkscape::Selection *selection, guint flags); void on_inkscape_selection_changed(Inkscape::Selection *selection); +public: + void refresh() + { + refreshArea(); + refreshExportHints(); + }; private: void refreshArea(); void refreshExportHints(); @@ -163,12 +176,6 @@ private: sigc::connection extensionConn; sigc::connection exportConn; sigc::connection browseConn; - sigc::connection selectionModifiedConn; - sigc::connection selectionChangedConn; - -private: - void on_realize() override; - void on_unrealize() override; }; } // namespace Dialog } // namespace UI diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 62ac847a08..aaf87b32ca 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -82,12 +82,15 @@ Export::Export() builder->get_widget_derived("Batch Export", batch_export); batch_export->initialise(builder); + if (single_image) { + single_image->setDesktop(getDesktop()); + } + if (batch_export) { + batch_export->setDesktop(getDesktop()); + } + // Callback when container is finally mapped on window. All intialisation like set active is done inside it. container->signal_realize().connect(sigc::mem_fun(*this, &Export::onRealize)); - - // Provide inkscape _app instance to single Export - single_image->set_app(_app); - batch_export->set_app(_app); } Export::~Export() {} @@ -98,6 +101,9 @@ void Export::onRealize() { single_image->setup(); batch_export->setup(); + + single_image->setApp(getApp()); + batch_export->setApp(getApp()); // setDefaultNotebookPage(); } @@ -110,6 +116,29 @@ void Export::setDefaultNotebookPage() // } } +void Export::desktopReplaced() +{ + if (single_image) { + single_image->setDesktop(getDesktop()); + } + if (batch_export) { + batch_export->setDesktop(getDesktop()); + } +} + +void Export::selectionChanged(Inkscape::Selection *selection) +{ + // TODO: refresh only active page + single_image->selectionChanged(selection); + batch_export->selectionChanged(selection); +} +void Export::selectionModified(Inkscape::Selection *selection, guint flags) +{ + // TODO: refresh only active page + single_image->selectionModified(selection, flags); + batch_export->selectionModified(selection, flags); +} + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index b837eb3f76..db5d8816be 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -15,9 +15,9 @@ #include <gtkmm.h> +#include "export-batch.h" #include "export-helper.h" #include "export-single.h" -#include "export-batch.h" #include "extension/output.h" #include "ui/dialog/dialog-base.h" #include "ui/widget/scrollprotected.h" @@ -62,6 +62,10 @@ private: // signals callback void onRealize(); void onBatchExport(); + + void desktopReplaced() override; + void selectionChanged(Inkscape::Selection *selection) override; + void selectionModified(Inkscape::Selection *selection, guint flags) override; }; } // namespace Dialog } // namespace UI -- GitLab From 3843000ecd6f58224292a3c09066513e8317ff36 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Tue, 3 Aug 2021 18:41:14 +0530 Subject: [PATCH 22/40] Added selector for batch export --- share/ui/dialog-export.glade | 256 --------------------------------- src/ui/dialog/export-batch.cpp | 83 ++++++++--- src/ui/dialog/export-batch.h | 4 +- 3 files changed, 70 insertions(+), 273 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index d38268e3d6..7fd7f1f34e 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -836,262 +836,6 @@ <property name="max-children-per-line">10</property> <property name="selection-mode">multiple</property> <property name="activate-on-single-click">False</property> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">50</property> - <property name="height-request">50</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> - <child> - <object class="GtkFlowBoxChild"> - <property name="width-request">100</property> - <property name="height-request">80</property> - <property name="visible">True</property> - <property name="can-focus">True</property> - <child> - <object class="GtkImage"> - <property name="visible">True</property> - <property name="can-focus">False</property> - <property name="pixel-size">50</property> - <property name="icon-name">face-glasses</property> - </object> - </child> - </object> - </child> </object> </child> </object> diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index 0bee592378..970e61ea96 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -59,6 +59,8 @@ public: public: Gtk::CheckButton selector; + SPItem *getItem() { return _item; } + bool isActive() { return selector.get_active(); } private: Gtk::Grid grid; @@ -77,9 +79,10 @@ BatchItem::BatchItem(SPItem *item) grid.attach(selector, 0, 0, 1, 1); Glib::ustring id = _item->getId(); selector.set_label(id); - selector.set_active(false); - // set_child(grid); + selector.set_active(true); + add(grid); show_all_children(); + show(); } BatchExport::~BatchExport() @@ -111,12 +114,13 @@ void BatchExport::initialise(const Glib::RefPtr<Gtk::Builder> &builder) void BatchExport::selectionModified(Inkscape::Selection *selection, guint flags) { - if (!_desktop ||_desktop->getSelection() != selection) { + if (!_desktop || _desktop->getSelection() != selection) { return; } if (!(flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { return; } + refreshItems(); } void BatchExport::selectionChanged(Inkscape::Selection *selection) @@ -184,21 +188,59 @@ void BatchExport::refreshItems() doc->ensureUpToDate(); // std::set - int num = 0; + std::set<SPItem *> itemsList; switch (current_key) { - case SELECTION_SELECTION: - num = (int)boost::distance(_desktop->getSelection()->items()); + case SELECTION_SELECTION: { + auto items = _desktop->getSelection()->items(); + for (auto i = items.begin(); i != items.end(); ++i) { + SPItem *item = *i; + if (item) { + itemsList.insert(item); + } + } break; + } case SELECTION_LAYER: { - std::list<SPItem *> layers = _desktop->getAllLayers(); - num = layers.size(); + auto layersList = _desktop->getAllLayers(); + for (auto i = layersList.begin(); i != layersList.end(); ++i) { + SPItem *item = *i; + itemsList.insert(item); + } + break; } default: break; } + int num = itemsList.size(); Glib::ustring label_text = std::to_string(num) + " Items"; num_elements->set_text(label_text); + + std::vector<std::string> toRemove; + for (auto &[key, val] : current_items) { + SPItem *item = val->getItem(); + // if item is not present in itemList add it to remove list so that we can remove it + if (itemsList.find(item) == itemsList.end()) { + toRemove.push_back(key); + } + } + // now remove all the items + for (auto key : toRemove) { + if (current_items[key]) { + preview_container->remove(*current_items[key]); + current_items.erase(key); + } + } + + // now add which were are new + for (auto &item : itemsList) { + auto id = item->getId(); + if (current_items[id] && current_items[id]->getItem() == item) { + continue; + } + current_items[id] = Gtk::manage(new BatchItem(item)); + preview_container->insert(*current_items[id], -1); + } } void BatchExport::refreshExportHints() @@ -219,6 +261,7 @@ void BatchExport::onAreaTypeToggle(selection_mode key) current_key = key; prefs->setString("/dialogs/export/batchexportarea/value", selection_names[current_key]); + refreshItems(); refreshExportHints(); } @@ -264,9 +307,13 @@ void BatchExport::onExport() dpis.push_back(export_list->get_dpi(i)); } - auto itemlist = _desktop->getSelection()->items(); - for (auto i = itemlist.begin(); i != itemlist.end() && !interrupted; ++i) { - SPItem *item = *i; + for (auto i = current_items.begin(); i != current_items.end() && !interrupted; ++i) { + BatchItem *batchItem = i->second; + if (!batchItem->isActive()) { + n++; + continue; + } + SPItem *item = batchItem->getItem(); if (!item) { n++; continue; @@ -295,6 +342,10 @@ void BatchExport::onExport() if (!omod) { continue; } + if (prog_dlg) { + delete prog_dlg; + prog_dlg = nullptr; + } prog_dlg = create_progress_dialog(Glib::ustring::compose(_("Exporting %1 files"), num)); prog_dlg->set_export_panel(this); setExporting(true, Glib::ustring::compose(_("Exporting %1 files"), num)); @@ -320,18 +371,18 @@ void BatchExport::onExport() } else { // exportSuccessful = _export_vector(omod, copy_doc, filename, false, &items); } - if (prog_dlg) { - delete prog_dlg; - prog_dlg = nullptr; - } setExporting(false); } + if (prog_dlg) { + delete prog_dlg; + prog_dlg = nullptr; + } } } bool BatchExport::getNonConflictingFilename(Glib::ustring &filename, Glib::ustring const extension) { - if(_desktop){ + if (!_desktop) { return false; } SPDocument *doc = _desktop->getDocument(); diff --git a/src/ui/dialog/export-batch.h b/src/ui/dialog/export-batch.h index b176469675..6b564fcd9a 100644 --- a/src/ui/dialog/export-batch.h +++ b/src/ui/dialog/export-batch.h @@ -70,7 +70,9 @@ private: ExportList *export_list = nullptr; AdvanceOptions advance_options; - std::vector<BatchItem *> current_items; + +private: + std::map<std::string, BatchItem *> current_items; private: std::set<SPItem *> added_items; -- GitLab From 8066d64ca64e9e8fb710764fc7eaf4d6f2360e08 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Tue, 3 Aug 2021 19:02:38 +0530 Subject: [PATCH 23/40] Added vector export to batch --- src/ui/dialog/export-batch.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index 970e61ea96..f296736db5 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -369,7 +369,12 @@ void BatchExport::onExport() exportSuccessful = _export_raster(*area, width, height, dpi, item_filename, true, onProgressCallback, prog_dlg, omod, hide ? &selected : nullptr, &advance_options); } else { - // exportSuccessful = _export_vector(omod, copy_doc, filename, false, &items); + setExporting(true, Glib::ustring::compose(_("Exporting %1"), filename)); + SPDocument *doc = _desktop->getDocument(); + SPDocument *copy_doc = (doc->copy()).get(); + std::vector<SPItem *> items; + items.push_back(item); + exportSuccessful = _export_vector(omod, copy_doc, item_filename, true, &items); } setExporting(false); } -- GitLab From 7c53c335258e5cb2966aebde58edcec603c190ce Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Sun, 8 Aug 2021 14:14:26 +0530 Subject: [PATCH 24/40] WIP:Added preview file --- src/ui/dialog/export-preview.cpp | 65 +++++++++++++++++++++++++ src/ui/dialog/export-preview.h | 81 ++++++++++++++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 src/ui/dialog/export-preview.cpp create mode 100644 src/ui/dialog/export-preview.h diff --git a/src/ui/dialog/export-preview.cpp b/src/ui/dialog/export-preview.cpp new file mode 100644 index 0000000000..b00f7f267f --- /dev/null +++ b/src/ui/dialog/export-preview.cpp @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * bulia byak <buliabyak@users.sf.net> + * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * + * Copyright (C) 1999-2007 Authors + * Copyright (C) 2001-2002 Ximian, Inc. + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "export-preview.h" + +#include <gtkmm.h> + +namespace Inkscape { +namespace UI { +namespace Dialog { + +ExportPreview::ExportPreview() + , drawing(nullptr) + , visionkey(0) + , timer(nullptr) + , renderTimer(nullptr) + , pending(false) + , minDelay(0.1) + , targetId() + , size(128) +{ + ; +} + +void ExportPreview::setDocument(SPDocumet *document) +{ + _document = document; + if (drawing) { + if (_document) { + _document->getRoot()->invoke_hide(visionkey); + } + delete drawing; + drawing = nullptr; + } + if (_document) { + drawing = new Inkscape::Drawing(); + visionkey = SPItem::display_key_new(1); + drawing->setRoot(_document->getRoot()->invoke_show(*drawing, visionkey, SP_ITEM_SHOW_DISPLAY)); + queueRefresh(); + } +} + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file diff --git a/src/ui/dialog/export-preview.h b/src/ui/dialog/export-preview.h new file mode 100644 index 0000000000..65a4d807fd --- /dev/null +++ b/src/ui/dialog/export-preview.h @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * bulia byak <buliabyak@users.sf.net> + * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * + * Copyright (C) 1999-2007 Authors + * Copyright (C) 2001-2002 Ximian, Inc. + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef SP_EXPORT_PREVIEW_H +#define SP_EXPORT_PREVIEW_H + +#include <gtkmm.h> + +#include "desktop.h" +#include "document.h" + +class SPObject; +namespace Glib { +class Timer; +} + +namespace Inkscape { +class Drawing; +namespace UI { +namespace Dialog { + +class ExportPreview : public Gtk::Box +{ +public: + ExportPreview(Glib::ustring id); + ExportPreview(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) + : Gtk::Box(cobject){}; + ~ExportPreview() override; + +private: + Glib::ustring targetId; + + SPDocument *_document = nullptr; + SPDesktop *_desktop = nullptr; + + Drawing *drawing; + unsigned int visionkey; + Glib::Timer *timer; + Glib::Timer *renderTimer; + bool pending; + gdouble minDelay; + + int size; // size of preview image + + guchar *pixMem; // Our Itme pixels + Gtk::Image *image; // Our Item Image + +public: + void setDocument(SPDocument *document); + void setDesktop(SPDesktop *desktop); + void refreshPreview(); + +private: + void renderPreview(SPObject *obj); + void queueRefresh(); + bool refreshCB(); +}; +} // namespace Dialog +} // namespace UI +} // namespace Inkscape +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : \ No newline at end of file -- GitLab From cd02680677d35d49a2cbd9eabbe171d4eff2c364 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Mon, 9 Aug 2021 01:45:30 +0530 Subject: [PATCH 25/40] added preview in single export --- share/ui/dialog-export.glade | 13 +- src/ui/CMakeLists.txt | 4 + src/ui/dialog/export-preview.cpp | 147 ++++++++++++++++++++- src/ui/dialog/export-preview.h | 20 +-- src/ui/dialog/export-single.cpp | 29 +++- src/ui/dialog/export-single.h | 7 + src/ui/dialog/icon-preview.cpp | 193 +-------------------------- src/ui/dialog/preview-util.cpp | 220 +++++++++++++++++++++++++++++++ src/ui/dialog/preview-util.h | 24 ++++ 9 files changed, 447 insertions(+), 210 deletions(-) create mode 100644 src/ui/dialog/preview-util.cpp create mode 100644 src/ui/dialog/preview-util.h diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 7fd7f1f34e..330959896b 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -184,19 +184,18 @@ </packing> </child> <child> - <object class="GtkBox" id="si_preview_box"> + <object class="GtkBox"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="spacing">20</property> <child> - <object class="GtkImage"> - <property name="width-request">150</property> - <property name="height-request">150</property> + <object class="GtkBox" id="si_preview_box"> <property name="visible">True</property> <property name="can-focus">False</property> - <property name="pixel-size">150</property> - <property name="icon-name">face-smile</property> - <property name="icon_size">6</property> + <property name="orientation">vertical</property> + <child> + <placeholder/> + </child> </object> <packing> <property name="expand">False</property> diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 880785b61f..9599e0687a 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -115,6 +115,7 @@ set(ui_SRC dialog/export-batch.cpp dialog/export-single.cpp dialog/export-helper.cpp + dialog/export-preview.cpp dialog/filedialog.cpp dialog/filedialogimpl-gtkmm.cpp dialog/fill-and-stroke.cpp @@ -141,6 +142,7 @@ set(ui_SRC dialog/object-properties.cpp dialog/objects.cpp dialog/polar-arrange-tab.cpp + dialog/preview-util.cpp dialog/print.cpp dialog/prototype.cpp dialog/selectorsdialog.cpp @@ -291,6 +293,7 @@ set(ui_SRC dialog/export-batch.h dialog/export-single.h dialog/export-helper.h + dialog/export-preview.h dialog/filedialog.h dialog/filedialogimpl-gtkmm.h dialog/filedialogimpl-win32.h @@ -318,6 +321,7 @@ set(ui_SRC dialog/object-properties.h dialog/objects.h dialog/polar-arrange-tab.h + dialog/preview-util.h dialog/print.h dialog/prototype.h dialog/selectorsdialog.h diff --git a/src/ui/dialog/export-preview.cpp b/src/ui/dialog/export-preview.cpp index b00f7f267f..fbf9a2d186 100644 --- a/src/ui/dialog/export-preview.cpp +++ b/src/ui/dialog/export-preview.cpp @@ -12,27 +12,82 @@ #include "export-preview.h" +#include <glibmm/i18n.h> +#include <glibmm/main.h> +#include <glibmm/timer.h> #include <gtkmm.h> +#include "display/cairo-utils.h" +#include "object/sp-namedview.h" +#include "object/sp-root.h" +#include "preview-util.h" + namespace Inkscape { namespace UI { namespace Dialog { ExportPreview::ExportPreview() - , drawing(nullptr) + : drawing(nullptr) , visionkey(0) , timer(nullptr) , renderTimer(nullptr) , pending(false) , minDelay(0.1) - , targetId() , size(128) { - ; + pixMem = nullptr; + image = nullptr; + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, size); + pixMem = new guchar[size * stride]; + memset(pixMem, 0x00, size * stride); + + auto pb = Gdk::Pixbuf::create_from_data(pixMem, Gdk::COLORSPACE_RGB, true, 8, size, size, stride); + image = Gtk::make_managed<Gtk::Image>(pb); + image->show(); + // add this image to box here + this->pack_start(*image, true, true, 0); + show(); + show_all_children(); +} + +ExportPreview::~ExportPreview() +{ + if (drawing) { + if (_document) { + _document->getRoot()->invoke_hide(visionkey); + } + delete drawing; + drawing = nullptr; + } + if (timer) { + timer->stop(); + delete timer; + timer = nullptr; + } + if (renderTimer) { + renderTimer->stop(); + delete renderTimer; + renderTimer = nullptr; + } +} + +void ExportPreview::setItem(SPItem *item) +{ + _item = item; +} +void ExportPreview::setDbox(double x0, double x1, double y0, double y1) +{ + if (!_document) { + return; + } + _dbox = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * _document->dt2doc(); } -void ExportPreview::setDocument(SPDocumet *document) +void ExportPreview::setDocument(SPDocument *document) { + if (_document == document) { + return; + } _document = document; if (drawing) { if (_document) { @@ -49,6 +104,90 @@ void ExportPreview::setDocument(SPDocumet *document) } } +void ExportPreview::queueRefresh() +{ + if (!pending) { + pending = true; + if (!timer) { + timer = new Glib::Timer(); + } + Glib::signal_idle().connect(sigc::mem_fun(this, &ExportPreview::refreshCB), Glib::PRIORITY_DEFAULT_IDLE); + } +} + +bool ExportPreview::refreshCB() +{ + bool callAgain = true; + if (!timer) { + timer = new Glib::Timer(); + } + if (timer->elapsed() > minDelay) { + callAgain = false; + refreshPreview(); + pending = false; + } + return callAgain; +} + +void ExportPreview::refreshPreview() +{ + auto document = _document; + if (!timer) { + timer = new Glib::Timer(); + } + if (timer->elapsed() < minDelay) { + // Do not refresh too quickly + queueRefresh(); + } else if (document) { + renderPreview(); + timer->reset(); + } +} + +/* +This is main function which finally render preview. Call this after setting document, item and dbox. +If dbox is given it will use it. +if item is given and not dbox then item is used +If both are not given then simply we do nothing. +*/ +void ExportPreview::renderPreview() +{ + if (!renderTimer) { + renderTimer = new Glib::Timer(); + } + renderTimer->reset(); + + if (_document) { + unsigned unused; + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, size); + guchar *px = nullptr; + + if (_dbox) { + px = Inkscape::UI::PREVIEW::sp_icon_doc_icon(_document, *drawing, nullptr, size, unused, &_dbox); + } else if (_item) { + gchar const *id = _item->getId(); + px = Inkscape::UI::PREVIEW::sp_icon_doc_icon(_document, *drawing, id, size, unused); + } else { + std::cout << "Not me" << std::endl; + } + + if (px) { + memcpy(pixMem, px, size * stride); + g_free(px); + std::cout << "Image Rendered" << std::endl; + px = nullptr; + } else { + std::cout << "Image Rendered NOT" << std::endl; + memset(pixMem, 0, size * stride); + } + image->set(image->get_pixbuf()); + image->show(); + } + + renderTimer->stop(); + minDelay = std::max(0.1, renderTimer->elapsed() * 3.0); +} + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export-preview.h b/src/ui/dialog/export-preview.h index 65a4d807fd..28b41aa171 100644 --- a/src/ui/dialog/export-preview.h +++ b/src/ui/dialog/export-preview.h @@ -31,16 +31,15 @@ namespace Dialog { class ExportPreview : public Gtk::Box { public: - ExportPreview(Glib::ustring id); - ExportPreview(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) - : Gtk::Box(cobject){}; - ~ExportPreview() override; + ExportPreview(); + ~ExportPreview(); private: - Glib::ustring targetId; + SPItem *_item = nullptr; + + Geom::OptRect _dbox; SPDocument *_document = nullptr; - SPDesktop *_desktop = nullptr; Drawing *drawing; unsigned int visionkey; @@ -56,12 +55,13 @@ private: public: void setDocument(SPDocument *document); - void setDesktop(SPDesktop *desktop); - void refreshPreview(); + void setItem(SPItem *item); + void setDbox(double x0, double x1, double y0, double y1); + void queueRefresh(); private: - void renderPreview(SPObject *obj); - void queueRefresh(); + void refreshPreview(); + void renderPreview(); bool refreshCB(); }; } // namespace Dialog diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index 660b85128f..dd633ff265 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -131,6 +131,7 @@ void SingleExport::selectionModified(Inkscape::Selection *selection, guint flags /* Do nothing for page or for custom */ break; } + refreshPreview(); refreshExportHints(); } @@ -186,6 +187,9 @@ void SingleExport::setup() refreshArea(); refreshExportHints(); + // Add preview box here + refreshPreview(); + // Connect Signals Here for (auto [key, button] : selection_buttons) { button->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &SingleExport::onAreaTypeToggle), key)); @@ -282,6 +286,7 @@ void SingleExport::refreshArea() if (current_key != SELECTION_CUSTOM && bbox) { setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); } + refreshPreview(); } } @@ -504,7 +509,7 @@ void SingleExport::onExport() void SingleExport::onBrowse(Gtk::EntryIconPosition pos, const GdkEventButton *ev) { - if(!_app){ + if (!_app) { return; } Gtk::Window *window = _app->get_active_window(); @@ -843,6 +848,28 @@ unsigned int SingleExport::onProgressCallback(float value, void *dlg) return TRUE; } // end of sp_export_progress_callback() +void SingleExport::refreshPreview() +{ + if (!_desktop) { + return; + } + if (!preview) { + preview = Gtk::manage(new ExportPreview()); + si_preview_box->pack_start(*preview, true, true, 0); + si_preview_box->show_all_children(); + } + preview->setDocument(_desktop->getDocument()); + + Unit const *unit = units->getUnit(); + float x0 = getValuePx(spin_buttons[SPIN_X0]->get_value(), unit); + float x1 = getValuePx(spin_buttons[SPIN_X1]->get_value(), unit); + float y0 = getValuePx(spin_buttons[SPIN_Y0]->get_value(), unit); + float y1 = getValuePx(spin_buttons[SPIN_Y1]->get_value(), unit); + preview->setItem(nullptr); + preview->setDbox(x0,x1,y0,y1); + preview->queueRefresh(); +} + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export-single.h b/src/ui/dialog/export-single.h index cbee192500..913ef9e9f6 100644 --- a/src/ui/dialog/export-single.h +++ b/src/ui/dialog/export-single.h @@ -16,6 +16,7 @@ #include <gtkmm.h> #include "export-helper.h" +#include "export-preview.h" #include "extension/output.h" #include "ui/widget/scrollprotected.h" #include "ui/widget/unit-menu.h" @@ -76,8 +77,10 @@ private: Inkscape::UI::Widget::UnitMenu *units = nullptr; Gtk::CheckButton *si_hide_all = nullptr; + Gtk::Box *si_preview_box = nullptr; Gtk::CheckButton *si_show_preview = nullptr; + ExportPreview *preview = nullptr; ExtensionList *si_extension_cb = nullptr; Gtk::Entry *si_filename_entry = nullptr; @@ -106,6 +109,9 @@ private: void setupExtensionList(); void setupSpinButtons(); +private: + void refreshPreview(); + private: // change range and callbacks to spinbuttons template <typename T> @@ -135,6 +141,7 @@ public: refreshArea(); refreshExportHints(); }; + private: void refreshArea(); void refreshExportHints(); diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp index 070284d9f4..e5ad593f96 100644 --- a/src/ui/dialog/icon-preview.cpp +++ b/src/ui/dialog/icon-preview.cpp @@ -39,12 +39,7 @@ #include "ui/widget/frame.h" -extern "C" { -// takes doc, drawing, icon, and icon name to produce pixels -guchar * -sp_icon_doc_icon( SPDocument *doc, Inkscape::Drawing &drawing, - const gchar *name, unsigned int psize, unsigned &stride); -} +#include "preview-util.h" #define noICON_VERBOSE 1 @@ -400,188 +395,7 @@ void IconPreviewPanel::modeToggled() refreshPreview(); } -void overlayPixels(guchar *px, int width, int height, int stride, - unsigned r, unsigned g, unsigned b) -{ - int bytesPerPixel = 4; - int spacing = 4; - for ( int y = 0; y < height; y += spacing ) { - guchar *ptr = px + y * stride; - for ( int x = 0; x < width; x += spacing ) { - *(ptr++) = r; - *(ptr++) = g; - *(ptr++) = b; - *(ptr++) = 0xff; - - ptr += bytesPerPixel * (spacing - 1); - } - } - - if ( width > 1 && height > 1 ) { - // point at the last pixel - guchar *ptr = px + ((height-1) * stride) + ((width - 1) * bytesPerPixel); - - if ( width > 2 ) { - px[4] = r; - px[5] = g; - px[6] = b; - px[7] = 0xff; - ptr[-12] = r; - ptr[-11] = g; - ptr[-10] = b; - ptr[-9] = 0xff; - } - - ptr[-4] = r; - ptr[-3] = g; - ptr[-2] = b; - ptr[-1] = 0xff; - - px[0 + stride] = r; - px[1 + stride] = g; - px[2 + stride] = b; - px[3 + stride] = 0xff; - - ptr[0 - stride] = r; - ptr[1 - stride] = g; - ptr[2 - stride] = b; - ptr[3 - stride] = 0xff; - - if ( height > 2 ) { - ptr[0 - stride * 3] = r; - ptr[1 - stride * 3] = g; - ptr[2 - stride * 3] = b; - ptr[3 - stride * 3] = 0xff; - } - } -} - -// takes doc, drawing, icon, and icon name to produce pixels -extern "C" guchar * -sp_icon_doc_icon( SPDocument *doc, Inkscape::Drawing &drawing, - gchar const *name, unsigned psize, - unsigned &stride) -{ - bool const dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpSvg"); - guchar *px = nullptr; - - if (doc) { - SPObject *object = doc->getObjectById(name); - if (object && SP_IS_ITEM(object)) { - SPItem *item = SP_ITEM(object); - // Find bbox in document - Geom::OptRect dbox = item->documentVisualBounds(); - - if ( object->parent == nullptr ) - { - dbox = Geom::Rect(Geom::Point(0, 0), - Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); - } - - /* This is in document coordinates, i.e. pixels */ - if ( dbox ) { - /* Update to renderable state */ - double sf = 1.0; - drawing.root()->setTransform(Geom::Scale(sf)); - drawing.update(); - /* Item integer bbox in points */ - // NOTE: previously, each rect coordinate was rounded using floor(c + 0.5) - Geom::IntRect ibox = dbox->roundOutwards(); - - if ( dump ) { - g_message( " box --'%s' (%f,%f)-(%f,%f)", name, (double)ibox.left(), (double)ibox.top(), (double)ibox.right(), (double)ibox.bottom() ); - } - - /* Find button visible area */ - int width = ibox.width(); - int height = ibox.height(); - - if ( dump ) { - g_message( " vis --'%s' (%d,%d)", name, width, height ); - } - - { - int block = std::max(width, height); - if (block != static_cast<int>(psize) ) { - if ( dump ) { - g_message(" resizing" ); - } - sf = (double)psize / (double)block; - - drawing.root()->setTransform(Geom::Scale(sf)); - drawing.update(); - - auto scaled_box = *dbox * Geom::Scale(sf); - ibox = scaled_box.roundOutwards(); - if ( dump ) { - g_message( " box2 --'%s' (%f,%f)-(%f,%f)", name, (double)ibox.left(), (double)ibox.top(), (double)ibox.right(), (double)ibox.bottom() ); - } - - /* Find button visible area */ - width = ibox.width(); - height = ibox.height(); - if ( dump ) { - g_message( " vis2 --'%s' (%d,%d)", name, width, height ); - } - } - } - - Geom::IntPoint pdim(psize, psize); - int dx, dy; - //dx = (psize - width) / 2; - //dy = (psize - height) / 2; - dx=dy=psize; - dx=(dx-width)/2; // watch out for psize, since 'unsigned'-'signed' can cause problems if the result is negative - dy=(dy-height)/2; - Geom::IntRect area = Geom::IntRect::from_xywh(ibox.min() - Geom::IntPoint(dx,dy), pdim); - /* Actual renderable area */ - Geom::IntRect ua = *Geom::intersect(ibox, area); - - if ( dump ) { - g_message( " area --'%s' (%f,%f)-(%f,%f)", name, (double)area.left(), (double)area.top(), (double)area.right(), (double)area.bottom() ); - g_message( " ua --'%s' (%f,%f)-(%f,%f)", name, (double)ua.left(), (double)ua.top(), (double)ua.right(), (double)ua.bottom() ); - } - - stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, psize); - - /* Set up pixblock */ - px = g_new(guchar, stride * psize); - memset(px, 0x00, stride * psize); - - /* Render */ - cairo_surface_t *s = cairo_image_surface_create_for_data(px, - CAIRO_FORMAT_ARGB32, psize, psize, stride); - Inkscape::DrawingContext dc(s, ua.min()); - - SPNamedView *nv = sp_document_namedview(doc, nullptr); - float bg_r = SP_RGBA32_R_F(nv->pagecolor); - float bg_g = SP_RGBA32_G_F(nv->pagecolor); - float bg_b = SP_RGBA32_B_F(nv->pagecolor); - float bg_a = SP_RGBA32_A_F(nv->pagecolor); - - cairo_t *cr = cairo_create(s); - cairo_set_source_rgba(cr, bg_r, bg_g, bg_b, bg_a); - cairo_rectangle(cr, 0, 0, psize, psize); - cairo_fill(cr); - cairo_save(cr); - cairo_destroy(cr); - - drawing.render(dc, ua); - cairo_surface_destroy(s); - - // convert to GdkPixbuf format - convert_pixels_argb32_to_pixbuf(px, psize, psize, stride); - - if ( Inkscape::Preferences::get()->getBool("/debug/icons/overlaySvg") ) { - overlayPixels( px, psize, psize, stride, 0x00, 0x00, 0xff ); - } - } - } - } - - return px; -} // end of sp_icon_doc_icon() void IconPreviewPanel::renderPreview( SPObject* obj ) @@ -600,7 +414,7 @@ void IconPreviewPanel::renderPreview( SPObject* obj ) for ( int i = 0; i < numEntries; i++ ) { unsigned unused; int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, sizes[i]); - guchar *px = sp_icon_doc_icon(doc, *drawing, id, sizes[i], unused); + guchar *px = Inkscape::UI::PREVIEW::sp_icon_doc_icon(doc, *drawing, id, sizes[i], unused); // g_message( " size %d %s", sizes[i], (px ? "worked" : "failed") ); if ( px ) { memcpy( pixMem[i], px, sizes[i] * stride ); @@ -612,6 +426,9 @@ void IconPreviewPanel::renderPreview( SPObject* obj ) images[i]->set(images[i]->get_pixbuf()); // images[i]->queue_draw(); } + + std::cout << "Image Rendered" << std::endl; + updateMagnify(); renderTimer->stop(); diff --git a/src/ui/dialog/preview-util.cpp b/src/ui/dialog/preview-util.cpp new file mode 100644 index 0000000000..2c8ee7158b --- /dev/null +++ b/src/ui/dialog/preview-util.cpp @@ -0,0 +1,220 @@ +#include "preview-util.h" + +#include "display/cairo-utils.h" +#include "display/drawing-context.h" +#include "object/sp-namedview.h" +#include "object/sp-root.h" + +namespace Inkscape { +namespace UI { +namespace PREVIEW { + +guchar *sp_icon_doc_icon(SPDocument *doc, Inkscape::Drawing &drawing, gchar const *name, unsigned psize, + unsigned &stride, Geom::OptRect *dboxIn) +{ + // If no doc then return nullptr. Beyond this point we assume there is valid doc + if (!doc) { + return nullptr; + } + + SPObject *object = nullptr; + + if (name) { + // If name is provided and valid, object will not be nullptr beyond this + object = doc->getObjectById(name); + } + + bool const dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpSvg"); + guchar *px = nullptr; + + Geom::OptRect dbox; + if (dboxIn) { + // We have dbox from function call and hence will use it + dbox = *dboxIn; + + } else if (object && SP_ITEM(object)) { + // Else we will check if object is provided and will use its bounding box if its doesnt have parent. + // Dont know why we check for parent and then use page coordinates. Will probably change it to document after + // discussing + if (object->parent == nullptr) { + dbox = + Geom::Rect(Geom::Point(0, 0), Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); + } else { + SPItem *item = SP_ITEM(object); + dbox = item->documentVisualBounds(); + } + } else { + // If we still dont have a dbox we will use document coordinates. + dbox = doc->getRoot()->documentVisualBounds(); + } + + if (!dbox) { + // If we still dont have anything to render then return nullptr + return nullptr; + } + + /* This is in document coordinates, i.e. pixels */ + + /* Update to renderable state */ + double sf = 1.0; + drawing.root()->setTransform(Geom::Scale(sf)); + drawing.update(); + /* Item integer bbox in points */ + // NOTE: previously, each rect coordinate was rounded using floor(c + 0.5) + Geom::IntRect ibox = dbox->roundOutwards(); + + if (dump) { + g_message(" box --'%s' (%f,%f)-(%f,%f)", name, (double)ibox.left(), (double)ibox.top(), + (double)ibox.right(), (double)ibox.bottom()); + } + + /* Find button visible area */ + int width = ibox.width(); + int height = ibox.height(); + + if (dump) { + g_message(" vis --'%s' (%d,%d)", name, width, height); + } + + { + int block = std::max(width, height); + if (block != static_cast<int>(psize)) { + if (dump) { + g_message(" resizing"); + } + sf = (double)psize / (double)block; + + drawing.root()->setTransform(Geom::Scale(sf)); + drawing.update(); + + auto scaled_box = *dbox * Geom::Scale(sf); + ibox = scaled_box.roundOutwards(); + if (dump) { + g_message(" box2 --'%s' (%f,%f)-(%f,%f)", name, (double)ibox.left(), (double)ibox.top(), + (double)ibox.right(), (double)ibox.bottom()); + } + + /* Find button visible area */ + width = ibox.width(); + height = ibox.height(); + if (dump) { + g_message(" vis2 --'%s' (%d,%d)", name, width, height); + } + } + } + + Geom::IntPoint pdim(psize, psize); + int dx, dy; + // dx = (psize - width) / 2; + // dy = (psize - height) / 2; + dx = dy = psize; + // watch out for psize, since 'unsigned'-'signed' can cause problems if the result is negative + dx = (dx - width) / 2; + dy = (dy - height) / 2; + Geom::IntRect area = Geom::IntRect::from_xywh(ibox.min() - Geom::IntPoint(dx, dy), pdim); + + /* Actual renderable area */ + Geom::IntRect ua = *Geom::intersect(ibox, area); + + if (dump) { + g_message(" area --'%s' (%f,%f)-(%f,%f)", name, (double)area.left(), (double)area.top(), + (double)area.right(), (double)area.bottom()); + g_message(" ua --'%s' (%f,%f)-(%f,%f)", name, (double)ua.left(), (double)ua.top(), (double)ua.right(), + (double)ua.bottom()); + } + + stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, psize); + + /* Set up pixblock */ + px = g_new(guchar, stride * psize); + memset(px, 0x00, stride * psize); + + /* Render */ + cairo_surface_t *s = cairo_image_surface_create_for_data(px, CAIRO_FORMAT_ARGB32, psize, psize, stride); + Inkscape::DrawingContext dc(s, ua.min()); + + SPNamedView *nv = sp_document_namedview(doc, nullptr); + float bg_r = SP_RGBA32_R_F(nv->pagecolor); + float bg_g = SP_RGBA32_G_F(nv->pagecolor); + float bg_b = SP_RGBA32_B_F(nv->pagecolor); + float bg_a = SP_RGBA32_A_F(nv->pagecolor); + + cairo_t *cr = cairo_create(s); + cairo_set_source_rgba(cr, bg_r, bg_g, bg_b, bg_a); + cairo_rectangle(cr, 0, 0, psize, psize); + cairo_fill(cr); + cairo_save(cr); + cairo_destroy(cr); + + drawing.render(dc, ua); + cairo_surface_destroy(s); + + // convert to GdkPixbuf format + convert_pixels_argb32_to_pixbuf(px, psize, psize, stride); + + if (Inkscape::Preferences::get()->getBool("/debug/icons/overlaySvg")) { + overlayPixels(px, psize, psize, stride, 0x00, 0x00, 0xff); + } + + return px; +} // end of sp_icon_doc_icon() + +void overlayPixels(guchar *px, int width, int height, int stride, unsigned r, unsigned g, unsigned b) +{ + int bytesPerPixel = 4; + int spacing = 4; + for (int y = 0; y < height; y += spacing) { + guchar *ptr = px + y * stride; + for (int x = 0; x < width; x += spacing) { + *(ptr++) = r; + *(ptr++) = g; + *(ptr++) = b; + *(ptr++) = 0xff; + + ptr += bytesPerPixel * (spacing - 1); + } + } + + if (width > 1 && height > 1) { + // point at the last pixel + guchar *ptr = px + ((height - 1) * stride) + ((width - 1) * bytesPerPixel); + + if (width > 2) { + px[4] = r; + px[5] = g; + px[6] = b; + px[7] = 0xff; + + ptr[-12] = r; + ptr[-11] = g; + ptr[-10] = b; + ptr[-9] = 0xff; + } + + ptr[-4] = r; + ptr[-3] = g; + ptr[-2] = b; + ptr[-1] = 0xff; + + px[0 + stride] = r; + px[1 + stride] = g; + px[2 + stride] = b; + px[3 + stride] = 0xff; + + ptr[0 - stride] = r; + ptr[1 - stride] = g; + ptr[2 - stride] = b; + ptr[3 - stride] = 0xff; + + if (height > 2) { + ptr[0 - stride * 3] = r; + ptr[1 - stride * 3] = g; + ptr[2 - stride * 3] = b; + ptr[3 - stride * 3] = 0xff; + } + } +} + +} // namespace PREVIEW +} // namespace UI +} // namespace Inkscape \ No newline at end of file diff --git a/src/ui/dialog/preview-util.h b/src/ui/dialog/preview-util.h new file mode 100644 index 0000000000..b23df8b3b8 --- /dev/null +++ b/src/ui/dialog/preview-util.h @@ -0,0 +1,24 @@ +#ifndef SP_PREVIEW_UTIL_H +#define SP_PREVIEW_UTIL_H + +#include <glibmm/main.h> + +#include "desktop.h" +#include "display/drawing.h" +#include "document.h" + +namespace Inkscape { +namespace UI { +namespace PREVIEW { + +// takes doc, drawing, icon, and icon name to produce pixels +guchar *sp_icon_doc_icon(SPDocument *doc, Inkscape::Drawing &drawing, const gchar *name, unsigned int psize, + unsigned &stride, Geom::OptRect *dboxIn = nullptr); + +void overlayPixels(guchar *px, int width, int height, int stride, unsigned r, unsigned g, unsigned b); + +} // namespace PREVIEW +} // namespace UI +} // namespace Inkscape + +#endif \ No newline at end of file -- GitLab From 5181d6771bb5e863fd7fa30825ead71480a8097f Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Tue, 10 Aug 2021 00:55:01 +0530 Subject: [PATCH 26/40] Preview Update on Hide All and Crash resolve --- share/ui/dialog-export.glade | 42 +++++++--------- src/ui/dialog/export-preview.cpp | 84 +++++++++++++++++++++++++------- src/ui/dialog/export-preview.h | 6 +++ src/ui/dialog/export-single.cpp | 51 +++++++++++++++++-- src/ui/dialog/export-single.h | 8 ++- src/ui/dialog/export.cpp | 51 +++++++++++++------ src/ui/dialog/export.h | 10 ++-- 7 files changed, 187 insertions(+), 65 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 330959896b..831c5506b7 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -118,23 +118,11 @@ </packing> </child> <child> - <object class="GtkBox"> + <object class="GtkBox" id="si_units_row"> <property name="visible">True</property> <property name="can-focus">False</property> <child> - <object class="GtkCheckButton" id="si_show_export_area"> - <property name="label" translatable="yes">Show Export</property> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="can-focus">True</property> - <property name="receives-default">False</property> - <property name="draw-indicator">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> + <placeholder/> </child> <child> <object class="GtkBox"> @@ -192,13 +180,19 @@ <object class="GtkBox" id="si_preview_box"> <property name="visible">True</property> <property name="can-focus">False</property> + <property name="margin-start">5</property> + <property name="margin-end">5</property> + <property name="margin-top">5</property> + <property name="margin-bottom">5</property> + <property name="hexpand">True</property> + <property name="vexpand">True</property> <property name="orientation">vertical</property> <child> <placeholder/> </child> </object> <packing> - <property name="expand">False</property> + <property name="expand">True</property> <property name="fill">True</property> <property name="position">0</property> </packing> @@ -211,11 +205,11 @@ <property name="orientation">vertical</property> <child> <object class="GtkCheckButton" id="si_show_preview"> - <property name="label" translatable="yes">Preview</property> + <property name="label" translatable="yes">Show Preview</property> <property name="visible">True</property> - <property name="sensitive">False</property> <property name="can-focus">True</property> <property name="receives-default">False</property> + <property name="active">True</property> <property name="draw-indicator">True</property> </object> <packing> @@ -226,7 +220,7 @@ </child> <child> <object class="GtkCheckButton" id="si_hide_all"> - <property name="label" translatable="yes">Hide All</property> + <property name="label" translatable="yes">Show Selected only</property> <property name="visible">True</property> <property name="can-focus">True</property> <property name="receives-default">False</property> @@ -280,7 +274,7 @@ </packing> </child> <child> - <object class="GtkLabel"> + <object class="GtkLabel" id="si_label_height"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="label" translatable="yes">Height</property> @@ -293,7 +287,7 @@ </packing> </child> <child> - <object class="GtkLabel"> + <object class="GtkLabel" id="si_label_width"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="label" translatable="yes">Width</property> @@ -321,7 +315,7 @@ </packing> </child> <child> - <object class="GtkLabel"> + <object class="GtkLabel" id="si_label_left"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="label" translatable="yes">Left</property> @@ -334,7 +328,7 @@ </packing> </child> <child> - <object class="GtkLabel"> + <object class="GtkLabel" id="si_label_right"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="label" translatable="yes">Right</property> @@ -347,7 +341,7 @@ </packing> </child> <child> - <object class="GtkLabel"> + <object class="GtkLabel" id="si_label_bottom"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="label" translatable="yes">Bottom</property> @@ -360,7 +354,7 @@ </packing> </child> <child> - <object class="GtkLabel"> + <object class="GtkLabel" id="si_label_top"> <property name="visible">True</property> <property name="can-focus">False</property> <property name="label" translatable="yes">Top</property> diff --git a/src/ui/dialog/export-preview.cpp b/src/ui/dialog/export-preview.cpp index fbf9a2d186..dae8ac127a 100644 --- a/src/ui/dialog/export-preview.cpp +++ b/src/ui/dialog/export-preview.cpp @@ -18,6 +18,8 @@ #include <gtkmm.h> #include "display/cairo-utils.h" +#include "object/sp-defs.h" +#include "object/sp-item.h" #include "object/sp-namedview.h" #include "object/sp-root.h" #include "preview-util.h" @@ -46,10 +48,17 @@ ExportPreview::ExportPreview() image->show(); // add this image to box here this->pack_start(*image, true, true, 0); - show(); show_all_children(); } +void ExportPreview::resetPixels() +{ + int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, size); + memset(pixMem, 0x00, size * stride); + image->set(image->get_pixbuf()); + image->show(); +} + ExportPreview::~ExportPreview() { if (drawing) { @@ -80,27 +89,72 @@ void ExportPreview::setDbox(double x0, double x1, double y0, double y1) if (!_document) { return; } + if ((x1 - x0 == 0) || (y1 - y0) == 0) { + return; + } _dbox = Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1)) * _document->dt2doc(); } void ExportPreview::setDocument(SPDocument *document) { - if (_document == document) { - return; - } - _document = document; - if (drawing) { + if (_document != document) { + _document = document; + if (drawing) { + if (_document) { + _document->getRoot()->invoke_hide(visionkey); + } + delete drawing; + drawing = nullptr; + } if (_document) { - _document->getRoot()->invoke_hide(visionkey); + drawing = new Inkscape::Drawing(); + visionkey = SPItem::display_key_new(1); + DrawingItem *ai = _document->getRoot()->invoke_show(*drawing, visionkey, SP_ITEM_SHOW_DISPLAY); + if (ai) { + drawing->setRoot(ai); + } } - delete drawing; - drawing = nullptr; } +} + +void ExportPreview::refreshHide(const std::vector<SPItem *> *list) +{ if (_document) { - drawing = new Inkscape::Drawing(); - visionkey = SPItem::display_key_new(1); - drawing->setRoot(_document->getRoot()->invoke_show(*drawing, visionkey, SP_ITEM_SHOW_DISPLAY)); - queueRefresh(); + if (isLastHide) { + if (drawing) { + if (_document) { + _document->getRoot()->invoke_hide(visionkey); + } + delete drawing; + drawing = nullptr; + } + drawing = new Inkscape::Drawing(); + visionkey = SPItem::display_key_new(1); + DrawingItem *ai = _document->getRoot()->invoke_show(*drawing, visionkey, SP_ITEM_SHOW_DISPLAY); + if (ai) { + drawing->setRoot(ai); + } + isLastHide = false; + } + if (list && !list->empty()) { + hide_other_items_recursively(_document->getRoot(), *list); + isLastHide = true; + } + } +} + +void ExportPreview::hide_other_items_recursively(SPObject *o, const std::vector<SPItem *> &list) +{ + if (SP_IS_ITEM(o) && !SP_IS_DEFS(o) && !SP_IS_ROOT(o) && !SP_IS_GROUP(o) && + list.end() == find(list.begin(), list.end(), o)) { + SP_ITEM(o)->invoke_hide(visionkey); + } + + // recurse + if (list.end() == find(list.begin(), list.end(), o)) { + for (auto &child : o->children) { + hide_other_items_recursively(&child, list); + } } } @@ -167,17 +221,13 @@ void ExportPreview::renderPreview() } else if (_item) { gchar const *id = _item->getId(); px = Inkscape::UI::PREVIEW::sp_icon_doc_icon(_document, *drawing, id, size, unused); - } else { - std::cout << "Not me" << std::endl; } if (px) { memcpy(pixMem, px, size * stride); g_free(px); - std::cout << "Image Rendered" << std::endl; px = nullptr; } else { - std::cout << "Image Rendered NOT" << std::endl; memset(pixMem, 0, size * stride); } image->set(image->get_pixbuf()); diff --git a/src/ui/dialog/export-preview.h b/src/ui/dialog/export-preview.h index 28b41aa171..1079a56a4b 100644 --- a/src/ui/dialog/export-preview.h +++ b/src/ui/dialog/export-preview.h @@ -34,6 +34,9 @@ public: ExportPreview(); ~ExportPreview(); +private: + bool isLastHide = false; + private: SPItem *_item = nullptr; @@ -55,9 +58,12 @@ private: public: void setDocument(SPDocument *document); + void refreshHide(const std::vector<SPItem *> *list); + void hide_other_items_recursively(SPObject *o, const std::vector<SPItem *> &list); void setItem(SPItem *item); void setDbox(double x0, double x1, double y0, double y1); void queueRefresh(); + void resetPixels(); private: void refreshPreview(); diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index dd633ff265..0b259e91b9 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -74,12 +74,20 @@ void SingleExport::initialise(const Glib::RefPtr<Gtk::Builder> &builder) builder->get_widget_derived("si_height_sb", spin_buttons[SPIN_HEIGHT]); builder->get_widget_derived("si_width_sb", spin_buttons[SPIN_WIDTH]); + builder->get_widget("si_label_left", spin_labels[SPIN_X0]); + builder->get_widget("si_label_right", spin_labels[SPIN_X1]); + builder->get_widget("si_label_top", spin_labels[SPIN_Y0]); + builder->get_widget("si_label_bottom", spin_labels[SPIN_Y1]); + builder->get_widget("si_label_height", spin_labels[SPIN_HEIGHT]); + builder->get_widget("si_label_width", spin_labels[SPIN_WIDTH]); + builder->get_widget_derived("si_img_height_sb", spin_buttons[SPIN_BMHEIGHT]); builder->get_widget_derived("si_img_width_sb", spin_buttons[SPIN_BMWIDTH]); builder->get_widget_derived("si_dpi_sb", spin_buttons[SPIN_DPI]); - builder->get_widget("si_show_export_area", show_export_area); + // builder->get_widget("si_show_export_area", show_export_area); builder->get_widget_derived("si_units", units); + builder->get_widget("si_units_row", si_units_row); builder->get_widget("si_hide_all", si_hide_all); builder->get_widget("si_preview_box", si_preview_box); @@ -158,6 +166,7 @@ void SingleExport::selectionChanged(Inkscape::Selection *selection) return; } } + refreshPreview(); refreshArea(); refreshExportHints(); } @@ -166,6 +175,7 @@ void SingleExport::selectionChanged(Inkscape::Selection *selection) void SingleExport::setup() { if (setupDone) { + // We need to setup only once return; } setupDone = true; @@ -199,6 +209,8 @@ void SingleExport::setup() extensionConn = si_extension_cb->signal_changed().connect(sigc::mem_fun(*this, &SingleExport::onExtensionChanged)); exportConn = si_export->signal_clicked().connect(sigc::mem_fun(*this, &SingleExport::onExport)); browseConn = si_filename_entry->signal_icon_press().connect(sigc::mem_fun(*this, &SingleExport::onBrowse)); + si_show_preview->signal_toggled().connect(sigc::mem_fun(*this, &SingleExport::refreshPreview)); + si_hide_all->signal_toggled().connect(sigc::mem_fun(*this, &SingleExport::refreshPreview)); } // Setup units combobox @@ -286,7 +298,6 @@ void SingleExport::refreshArea() if (current_key != SELECTION_CUSTOM && bbox) { setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); } - refreshPreview(); } } @@ -386,6 +397,28 @@ void SingleExport::onAreaTypeToggle(selection_mode key) refreshArea(); refreshExportHints(); + toggleSpinButtonVisibility(); + refreshPreview(); +} + +void SingleExport::toggleSpinButtonVisibility() +{ + bool show = current_key == SELECTION_CUSTOM; + spin_buttons[SPIN_X0]->set_visible(show); + spin_buttons[SPIN_X1]->set_visible(show); + spin_buttons[SPIN_Y0]->set_visible(show); + spin_buttons[SPIN_Y1]->set_visible(show); + spin_buttons[SPIN_WIDTH]->set_visible(show); + spin_buttons[SPIN_HEIGHT]->set_visible(show); + + spin_labels[SPIN_X0]->set_visible(show); + spin_labels[SPIN_X1]->set_visible(show); + spin_labels[SPIN_Y0]->set_visible(show); + spin_labels[SPIN_Y1]->set_visible(show); + spin_labels[SPIN_WIDTH]->set_visible(show); + spin_labels[SPIN_HEIGHT]->set_visible(show); + + si_units_row->set_visible(show); } void SingleExport::onAreaXChange(sb_type type) @@ -393,6 +426,7 @@ void SingleExport::onAreaXChange(sb_type type) blockSpinConns(true); areaXChange(type); selection_buttons[SELECTION_CUSTOM]->set_active(true); + refreshPreview(); blockSpinConns(false); } void SingleExport::onAreaYChange(sb_type type) @@ -400,6 +434,7 @@ void SingleExport::onAreaYChange(sb_type type) blockSpinConns(true); areaYChange(type); selection_buttons[SELECTION_CUSTOM]->set_active(true); + refreshPreview(); blockSpinConns(false); } void SingleExport::onDpiChange(sb_type type) @@ -759,6 +794,7 @@ void SingleExport::setDefaultSelectionMode() setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); } } + toggleSpinButtonVisibility(); } void SingleExport::setExporting(bool exporting, Glib::ustring const &text) @@ -858,6 +894,14 @@ void SingleExport::refreshPreview() si_preview_box->pack_start(*preview, true, true, 0); si_preview_box->show_all_children(); } + if (!si_show_preview->get_active()) { + preview->resetPixels(); + return; + } + + std::vector<SPItem *> selected(_desktop->getSelection()->items().begin(), _desktop->getSelection()->items().end()); + bool hide = si_hide_all->get_active(); + preview->setDocument(_desktop->getDocument()); Unit const *unit = units->getUnit(); @@ -866,7 +910,8 @@ void SingleExport::refreshPreview() float y0 = getValuePx(spin_buttons[SPIN_Y0]->get_value(), unit); float y1 = getValuePx(spin_buttons[SPIN_Y1]->get_value(), unit); preview->setItem(nullptr); - preview->setDbox(x0,x1,y0,y1); + preview->setDbox(x0, x1, y0, y1); + preview->refreshHide(hide ? &selected : nullptr); preview->queueRefresh(); } diff --git a/src/ui/dialog/export-single.h b/src/ui/dialog/export-single.h index 913ef9e9f6..1f4d971f91 100644 --- a/src/ui/dialog/export-single.h +++ b/src/ui/dialog/export-single.h @@ -34,7 +34,7 @@ public: ~SingleExport() override; private: - InkscapeApplication *_app; + InkscapeApplication *_app = nullptr; SPDesktop *_desktop = nullptr; private: @@ -72,7 +72,10 @@ private: typedef Inkscape::UI::Widget::ScrollProtected<Gtk::SpinButton> SpinButton; std::map<sb_type, SpinButton *> spin_buttons; + std::map<sb_type, Gtk::Label *> spin_labels; std::map<selection_mode, Gtk::RadioButton *> selection_buttons; + + Gtk::Box *si_units_row = nullptr; Gtk::CheckButton *show_export_area = nullptr; Inkscape::UI::Widget::UnitMenu *units = nullptr; @@ -97,7 +100,7 @@ private: Inkscape::Preferences *prefs = nullptr; std::map<selection_mode, Glib::ustring> selection_names; - selection_mode current_key; + selection_mode current_key = (selection_mode)0; public: // initialise variables from builder @@ -108,6 +111,7 @@ private: void setupUnits(); void setupExtensionList(); void setupSpinButtons(); + void toggleSpinButtonVisibility(); private: void refreshPreview(); diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index aaf87b32ca..a59177dc54 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -75,22 +75,26 @@ Export::Export() builder->get_widget("Export Notebook", export_notebook); - // Initialise Single Export Here. We will setup Single Export in onRealize callback. + // Initialise Single Export and its objects builder->get_widget_derived("Single Image", single_image); single_image->initialise(builder); + // Initialise Batch Export and its objects builder->get_widget_derived("Batch Export", batch_export); batch_export->initialise(builder); if (single_image) { single_image->setDesktop(getDesktop()); + single_image->setApp(getApp()); } if (batch_export) { batch_export->setDesktop(getDesktop()); + batch_export->setApp(getApp()); } // Callback when container is finally mapped on window. All intialisation like set active is done inside it. container->signal_realize().connect(sigc::mem_fun(*this, &Export::onRealize)); + export_notebook->signal_switch_page().connect(sigc::mem_fun(*this, &Export::onPageSwitch)); } Export::~Export() {} @@ -101,19 +105,15 @@ void Export::onRealize() { single_image->setup(); batch_export->setup(); - - single_image->setApp(getApp()); - batch_export->setApp(getApp()); // setDefaultNotebookPage(); } // Set current page based on preference/last visited page void Export::setDefaultNotebookPage() { - // if (export_notebook && batch_export) { - // auto page_num = export_notebook->page_num(*batch_export); - // export_notebook->set_current_page(page_num); - // } + pages[BATCH_EXPORT] = export_notebook->page_num(*batch_export); + pages[SINGLE_IMAGE] = export_notebook->page_num(*single_image); + export_notebook->set_current_page(pages[SINGLE_IMAGE]); } void Export::desktopReplaced() @@ -128,15 +128,38 @@ void Export::desktopReplaced() void Export::selectionChanged(Inkscape::Selection *selection) { - // TODO: refresh only active page - single_image->selectionChanged(selection); - batch_export->selectionChanged(selection); + auto current_page = export_notebook->get_current_page(); + if (current_page == pages[SINGLE_IMAGE]) { + single_image->selectionChanged(selection); + } + if (current_page == pages[BATCH_EXPORT]) { + batch_export->selectionChanged(selection); + } } void Export::selectionModified(Inkscape::Selection *selection, guint flags) { - // TODO: refresh only active page - single_image->selectionModified(selection, flags); - batch_export->selectionModified(selection, flags); + auto current_page = export_notebook->get_current_page(); + if (current_page == pages[SINGLE_IMAGE]) { + single_image->selectionModified(selection, flags); + } + if (current_page == pages[BATCH_EXPORT]) { + batch_export->selectionModified(selection, flags); + } +} + +void Export::onPageSwitch(Widget *page, guint page_number) +{ + auto desktop = getDesktop(); + if (desktop) { + auto selection = desktop->getSelection(); + + if (page_number == pages[SINGLE_IMAGE]) { + single_image->selectionChanged(selection); + } + if (page_number == pages[BATCH_EXPORT]) { + batch_export->selectionChanged(selection); + } + } } } // namespace Dialog diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index db5d8816be..bf83405638 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -43,10 +43,8 @@ public: private: Glib::RefPtr<Gtk::Builder> builder; - // Main Container - Gtk::Box *container = nullptr; - // Notebook containing pages for diiferent export types - Gtk::Notebook *export_notebook = nullptr; + Gtk::Box *container = nullptr; // Main Container + Gtk::Notebook *export_notebook = nullptr; // Notebook Container for single and batch export private: SingleExport *single_image = nullptr; @@ -57,12 +55,14 @@ private: // setup default values of widgets void setDefaultNotebookPage(); + std::map<notebook_page,int> pages; private: // signals callback void onRealize(); - void onBatchExport(); + void onPageSwitch(Widget* page, guint page_number); +private: void desktopReplaced() override; void selectionChanged(Inkscape::Selection *selection) override; void selectionModified(Inkscape::Selection *selection, guint flags) override; -- GitLab From 7ceae71159bf4862c9edf1d4a9b0656fdaff1db2 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Thu, 12 Aug 2021 21:17:34 +0530 Subject: [PATCH 27/40] Export preview crash resolve and Batch Export Preview --- share/ui/dialog-export.glade | 11 ++- src/ui/dialog/export-batch.cpp | 119 +++++++++++++++++++++------- src/ui/dialog/export-batch.h | 5 +- src/ui/dialog/export-preview.cpp | 47 +++++++---- src/ui/dialog/export-preview.h | 6 ++ src/ui/dialog/export-single.cpp | 129 ++++++++++++++++++------------- src/ui/dialog/export-single.h | 1 + src/ui/dialog/export.cpp | 20 ++++- src/ui/dialog/export.h | 1 + src/ui/dialog/preview-util.cpp | 2 +- 10 files changed, 231 insertions(+), 110 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 831c5506b7..3877aef0cb 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -827,7 +827,7 @@ <property name="column-spacing">10</property> <property name="row-spacing">10</property> <property name="max-children-per-line">10</property> - <property name="selection-mode">multiple</property> + <property name="selection-mode">none</property> <property name="activate-on-single-click">False</property> </object> </child> @@ -1012,7 +1012,7 @@ </packing> </child> <child> - <!-- n-columns=2 n-rows=2 --> + <!-- n-columns=1 n-rows=3 --> <object class="GtkGrid"> <property name="visible">True</property> <property name="can-focus">False</property> @@ -1040,8 +1040,8 @@ <property name="receives-default">True</property> </object> <packing> - <property name="left-attach">1</property> - <property name="top-attach">0</property> + <property name="left-attach">0</property> + <property name="top-attach">1</property> </packing> </child> <child> @@ -1051,8 +1051,7 @@ </object> <packing> <property name="left-attach">0</property> - <property name="top-attach">1</property> - <property name="width">2</property> + <property name="top-attach">2</property> </packing> </child> </object> diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index f296736db5..1a3e4fb318 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -22,6 +22,7 @@ #include "document-undo.h" #include "document.h" #include "export-helper.h" +#include "export-preview.h" #include "extension/db.h" #include "file.h" #include "helper/png-write.h" @@ -41,6 +42,7 @@ #include "ui/interface.h" #include "ui/widget/scrollprotected.h" #include "ui/widget/unit-menu.h" + #ifdef _WIN32 #endif @@ -51,23 +53,34 @@ namespace Inkscape { namespace UI { namespace Dialog { +// START OF BATCH ITEM + class BatchItem : public Gtk::FlowBoxChild { public: BatchItem(SPItem *item); - ~BatchItem(){}; + ~BatchItem(); public: Gtk::CheckButton selector; SPItem *getItem() { return _item; } bool isActive() { return selector.get_active(); } + void refresh(); private: Gtk::Grid grid; - // PreviewBox p_box; + ExportPreview *preview = nullptr; SPItem *_item; }; +BatchItem::~BatchItem() +{ + if (preview) { + delete preview; + preview = nullptr; + } +} + BatchItem::BatchItem(SPItem *item) : grid() , selector() @@ -77,14 +90,39 @@ BatchItem::BatchItem(SPItem *item) } _item = item; grid.attach(selector, 0, 0, 1, 1); + grid.set_row_spacing(10); Glib::ustring id = _item->getId(); selector.set_label(id); selector.set_active(true); + + if (!preview) { + preview = Gtk::manage(new ExportPreview()); + grid.attach(*preview, 0, 1, 1, 1); + } + + preview->setItem(_item); + preview->setDocument(_item->document); + preview->setSize(64); + add(grid); show_all_children(); show(); + + refresh(); } +void BatchItem::refresh() +{ + if (!_item) { + return; + } + preview->queueRefresh(); +} + +// END OF BATCH ITEM + +// START OF BATCH EXPORT + BatchExport::~BatchExport() { ; @@ -170,6 +208,8 @@ void BatchExport::setup() refreshExportHints(); + refreshItems(); + // Connect Signals for (auto [key, button] : selection_buttons) { button->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &BatchExport::onAreaTypeToggle), key)); @@ -185,9 +225,12 @@ void BatchExport::refreshItems() return; } SPDocument *doc = _desktop->getDocument(); + if (!doc) { + return; + } doc->ensureUpToDate(); - // std::set + // Create New List of Items std::set<SPItem *> itemsList; switch (current_key) { case SELECTION_SELECTION: { @@ -212,21 +255,27 @@ void BatchExport::refreshItems() default: break; } + + // Number of Items int num = itemsList.size(); Glib::ustring label_text = std::to_string(num) + " Items"; num_elements->set_text(label_text); + // Create a list of items which are already present but will be removed as they are not present anymore std::vector<std::string> toRemove; for (auto &[key, val] : current_items) { SPItem *item = val->getItem(); // if item is not present in itemList add it to remove list so that we can remove it - if (itemsList.find(item) == itemsList.end()) { + auto itemItr = itemsList.find(item); + if (itemItr == itemsList.end() || (*itemItr)->getId() != key) { toRemove.push_back(key); } } + // now remove all the items for (auto key : toRemove) { if (current_items[key]) { + // Preview Boxes are GTK managed so simply removing from container will handle delete preview_container->remove(*current_items[key]); current_items.erase(key); } @@ -235,12 +284,18 @@ void BatchExport::refreshItems() // now add which were are new for (auto &item : itemsList) { auto id = item->getId(); + // If an Item with same Id is already present, Skip if (current_items[id] && current_items[id]->getItem() == item) { continue; } + // Add new item to the end of list current_items[id] = Gtk::manage(new BatchItem(item)); preview_container->insert(*current_items[id], -1); } + + for (auto &[key, val] : current_items) { + val->refresh(); + } } void BatchExport::refreshExportHints() @@ -294,7 +349,6 @@ void BatchExport::onExport() } int n = 0; - int export_count = 0; // create vector of exports int num_rows = export_list->get_rows(); @@ -307,6 +361,10 @@ void BatchExport::onExport() dpis.push_back(export_list->get_dpi(i)); } + std::vector<SPItem *> selected(_desktop->getSelection()->items().begin(), _desktop->getSelection()->items().end()); + bool hide = hide_all->get_active(); + + // Start Exporting Each Item for (auto i = current_items.begin(); i != current_items.end() && !interrupted; ++i) { BatchItem *batchItem = i->second; if (!batchItem->isActive()) { @@ -363,9 +421,6 @@ void BatchExport::onExport() unsigned long int width = (int)(area->width() * dpi / DPI_BASE + 0.5); unsigned long int height = (int)(area->height() * dpi / DPI_BASE + 0.5); - std::vector<SPItem *> selected(_desktop->getSelection()->items().begin(), - _desktop->getSelection()->items().end()); - bool hide = hide_all->get_active(); exportSuccessful = _export_raster(*area, width, height, dpi, item_filename, true, onProgressCallback, prog_dlg, omod, hide ? &selected : nullptr, &advance_options); } else { @@ -438,33 +493,32 @@ void BatchExport::setDefaultFilename() void BatchExport::setDefaultSelectionMode() { - if (_desktop) { - current_key = (selection_mode)0; // default key - bool found = false; - Glib::ustring pref_key_name = prefs->getString("/dialogs/export/batchexportarea/value"); - for (auto [key, name] : selection_names) { - if (pref_key_name == name) { - current_key = key; - found = true; - break; - } - } - if (!found) { - pref_key_name = selection_names[current_key]; + current_key = (selection_mode)0; // default key + bool found = false; + Glib::ustring pref_key_name = prefs->getString("/dialogs/export/batchexportarea/value"); + for (auto [key, name] : selection_names) { + if (pref_key_name == name) { + current_key = key; + found = true; + break; } - + } + if (!found) { + pref_key_name = selection_names[current_key]; + } + if (_desktop) { if (current_key == SELECTION_SELECTION && (_desktop->getSelection())->isEmpty()) { current_key = (selection_mode)0; } if ((_desktop->getSelection())->isEmpty()) { selection_buttons[SELECTION_SELECTION]->set_sensitive(false); } - selection_buttons[current_key]->set_active(true); - - // we need to set pref key because signals above will set set pref == current key but we sometimes change - // current key like selection key - prefs->setString("/dialogs/export/batchexportarea/value", pref_key_name); } + selection_buttons[current_key]->set_active(true); + + // we need to set pref key because signals above will set set pref == current key but we sometimes change + // current key like selection key + prefs->setString("/dialogs/export/batchexportarea/value", pref_key_name); } void BatchExport::setExporting(bool exporting, Glib::ustring const &text) @@ -509,14 +563,14 @@ bool BatchExport::onProgressDelete(GdkEventAny * /*event*/) interrupted = true; prog_dlg->set_stopped(); return TRUE; -} // end of sp_export_progress_delete() +} /// Called when progress is cancelled void BatchExport::onProgressCancel() { interrupted = true; prog_dlg->set_stopped(); -} // end of sp_export_progress_cancel() +} /// Called for every progress iteration unsigned int BatchExport::onProgressCallback(float value, void *dlg) @@ -552,7 +606,12 @@ unsigned int BatchExport::onProgressCallback(float value, void *dlg) Gtk::Main::iteration(false); return TRUE; -} // end of sp_export_progress_callback() +} + +void BatchExport::setDocument(SPDocument *document) +{ + ; +} } // namespace Dialog } // namespace UI diff --git a/src/ui/dialog/export-batch.h b/src/ui/dialog/export-batch.h index 6b564fcd9a..8221f8d540 100644 --- a/src/ui/dialog/export-batch.h +++ b/src/ui/dialog/export-batch.h @@ -44,6 +44,7 @@ private: public: void setApp(InkscapeApplication *app) { _app = app; } + void setDocument(SPDocument* document); void setDesktop(SPDesktop *desktop) { _desktop = desktop; } void selectionChanged(Inkscape::Selection *selection); void selectionModified(Inkscape::Selection *selection, guint flags); @@ -72,11 +73,9 @@ private: AdvanceOptions advance_options; private: + // Store all items to be displayed in flowbox std::map<std::string, BatchItem *> current_items; -private: - std::set<SPItem *> added_items; - private: bool filename_modified; Glib::ustring original_name; diff --git a/src/ui/dialog/export-preview.cpp b/src/ui/dialog/export-preview.cpp index dae8ac127a..05621ef05a 100644 --- a/src/ui/dialog/export-preview.cpp +++ b/src/ui/dialog/export-preview.cpp @@ -18,6 +18,7 @@ #include <gtkmm.h> #include "display/cairo-utils.h" +#include "inkscape.h" #include "object/sp-defs.h" #include "object/sp-item.h" #include "object/sp-namedview.h" @@ -44,7 +45,7 @@ ExportPreview::ExportPreview() memset(pixMem, 0x00, size * stride); auto pb = Gdk::Pixbuf::create_from_data(pixMem, Gdk::COLORSPACE_RGB, true, 8, size, size, stride); - image = Gtk::make_managed<Gtk::Image>(pb); + image = Gtk::manage(new Gtk::Image(pb)); image->show(); // add this image to box here this->pack_start(*image, true, true, 0); @@ -53,9 +54,15 @@ ExportPreview::ExportPreview() void ExportPreview::resetPixels() { + if (pixMem) { + delete pixMem; + pixMem = nullptr; + } int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, size); + pixMem = new guchar[size * stride]; + auto pb = Gdk::Pixbuf::create_from_data(pixMem, Gdk::COLORSPACE_RGB, true, 8, size, size, stride); memset(pixMem, 0x00, size * stride); - image->set(image->get_pixbuf()); + image->set(pb); image->show(); } @@ -78,6 +85,8 @@ ExportPreview::~ExportPreview() delete renderTimer; renderTimer = nullptr; } + _item = nullptr; + _document = nullptr; } void ExportPreview::setItem(SPItem *item) @@ -97,22 +106,20 @@ void ExportPreview::setDbox(double x0, double x1, double y0, double y1) void ExportPreview::setDocument(SPDocument *document) { - if (_document != document) { - _document = document; - if (drawing) { - if (_document) { - _document->getRoot()->invoke_hide(visionkey); - } - delete drawing; - drawing = nullptr; - } + if (drawing) { if (_document) { - drawing = new Inkscape::Drawing(); - visionkey = SPItem::display_key_new(1); - DrawingItem *ai = _document->getRoot()->invoke_show(*drawing, visionkey, SP_ITEM_SHOW_DISPLAY); - if (ai) { - drawing->setRoot(ai); - } + _document->getRoot()->invoke_hide(visionkey); + } + delete drawing; + drawing = nullptr; + } + _document = document; + if (_document) { + drawing = new Inkscape::Drawing(); + visionkey = SPItem::display_key_new(1); + DrawingItem *ai = _document->getRoot()->invoke_show(*drawing, visionkey, SP_ITEM_SHOW_DISPLAY); + if (ai) { + drawing->setRoot(ai); } } } @@ -160,6 +167,9 @@ void ExportPreview::hide_other_items_recursively(SPObject *o, const std::vector< void ExportPreview::queueRefresh() { + if (drawing == nullptr) { + return; + } if (!pending) { pending = true; if (!timer) { @@ -210,6 +220,9 @@ void ExportPreview::renderPreview() renderTimer = new Glib::Timer(); } renderTimer->reset(); + if (drawing == nullptr) { + return; + } if (_document) { unsigned unused; diff --git a/src/ui/dialog/export-preview.h b/src/ui/dialog/export-preview.h index 1079a56a4b..7e66034c25 100644 --- a/src/ui/dialog/export-preview.h +++ b/src/ui/dialog/export-preview.h @@ -65,6 +65,12 @@ public: void queueRefresh(); void resetPixels(); + void setSize(int newSize) + { + size = newSize; + resetPixels(); + } + private: void refreshPreview(); void renderPreview(); diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index 0b259e91b9..8eb51ecb12 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -56,6 +56,9 @@ SingleExport::~SingleExport() ; } +/** + * Initialise Builder Objects. Called in Export constructor. + */ void SingleExport::initialise(const Glib::RefPtr<Gtk::Builder> &builder) { builder->get_widget("si_s_document", selection_buttons[SELECTION_DRAWING]); @@ -105,6 +108,7 @@ void SingleExport::initialise(const Glib::RefPtr<Gtk::Builder> &builder) builder->get_widget_derived("s_scroll", temp); } +// Inkscape Selection Modified CallBack void SingleExport::selectionModified(Inkscape::Selection *selection, guint flags) { if (!_desktop || _desktop->getSelection() != selection) { @@ -120,26 +124,29 @@ void SingleExport::selectionModified(Inkscape::Selection *selection, guint flags return; } - switch (current_key) { - case SELECTION_DRAWING: - bbox = doc->getRoot()->desktopVisualBounds(); - if (bbox) { - setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); - } - break; - case SELECTION_SELECTION: - if (selection->isEmpty() == false) { - bbox = selection->visualBounds(); - if (bbox) { - setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); - } - } - break; - default: - /* Do nothing for page or for custom */ - break; - } - refreshPreview(); + // Will Remove this code after testing + + // switch (current_key) { + // case SELECTION_DRAWING: + // bbox = doc->getRoot()->desktopVisualBounds(); + // if (bbox) { + // setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); + // } + // break; + // case SELECTION_SELECTION: + // if (selection->isEmpty() == false) { + // bbox = selection->visualBounds(); + // if (bbox) { + // setArea(bbox->left(), bbox->top(), bbox->right(), bbox->bottom()); + // } + // } + // break; + // default: + // /* Do nothing for page or for custom */ + // break; + // } + + refreshArea(); refreshExportHints(); } @@ -148,25 +155,31 @@ void SingleExport::selectionChanged(Inkscape::Selection *selection) if (!_desktop || _desktop->getSelection() != selection) { return; } - + Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); + for (auto [key, name] : selection_names) { + if (name == pref_key_name && current_key != key && key != SELECTION_SELECTION) { + selection_buttons[key]->set_active(true); + current_key = key; + break; + } + } if (selection->isEmpty()) { selection_buttons[SELECTION_SELECTION]->set_sensitive(false); if (current_key == SELECTION_SELECTION) { selection_buttons[(selection_mode)0]->set_active(true); // This causes refresh area - // return otherwise refreshArea will be called again // even though we are at default key, selection is the one which was original key. prefs->setString("/dialogs/export/exportarea/value", selection_names[SELECTION_SELECTION]); + // return otherwise refreshArea will be called again return; } } else { selection_buttons[SELECTION_SELECTION]->set_sensitive(true); - Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); if (selection_names[SELECTION_SELECTION] == pref_key_name && current_key != SELECTION_SELECTION) { selection_buttons[SELECTION_SELECTION]->set_active(); return; } } - refreshPreview(); + refreshArea(); refreshExportHints(); } @@ -197,9 +210,6 @@ void SingleExport::setup() refreshArea(); refreshExportHints(); - // Add preview box here - refreshPreview(); - // Connect Signals Here for (auto [key, button] : selection_buttons) { button->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &SingleExport::onAreaTypeToggle), key)); @@ -299,6 +309,7 @@ void SingleExport::refreshArea() setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); } } + refreshPreview(); } void SingleExport::refreshExportHints() @@ -348,6 +359,12 @@ void SingleExport::refreshExportHints() original_name = filename; si_filename_entry->set_text(filename); si_filename_entry->set_position(filename.length()); + } else { + Glib::ustring newName = !doc_export_name.empty() ? doc_export_name : original_name; + if (!newName.empty()) { + si_filename_entry->set_text(filename); + si_filename_entry->set_position(filename.length()); + } } if (xdpi != 0.0) { @@ -398,7 +415,6 @@ void SingleExport::onAreaTypeToggle(selection_mode key) refreshArea(); refreshExportHints(); toggleSpinButtonVisibility(); - refreshPreview(); } void SingleExport::toggleSpinButtonVisibility() @@ -760,30 +776,27 @@ void SingleExport::setDefaultFilename() void SingleExport::setDefaultSelectionMode() { - if (_desktop) { - current_key = (selection_mode)0; // default key - bool found = false; - Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); - for (auto [key, name] : selection_names) { - if (pref_key_name == name) { - current_key = key; - found = true; - break; - } - } - if (!found) { - pref_key_name = selection_names[current_key]; + current_key = (selection_mode)0; // default key + bool found = false; + Glib::ustring pref_key_name = prefs->getString("/dialogs/export/exportarea/value"); + for (auto [key, name] : selection_names) { + if (pref_key_name == name) { + current_key = key; + found = true; + break; } + } + if (!found) { + pref_key_name = selection_names[current_key]; + } - if (current_key == SELECTION_SELECTION && (SP_ACTIVE_DESKTOP->getSelection())->isEmpty()) { + if (_desktop) { + if (current_key == SELECTION_SELECTION && (_desktop->getSelection())->isEmpty()) { current_key = (selection_mode)0; } if ((_desktop->getSelection())->isEmpty()) { selection_buttons[SELECTION_SELECTION]->set_sensitive(false); } - selection_buttons[current_key]->set_active(true); - prefs->setString("/dialogs/export/exportarea/value", pref_key_name); - if (current_key == SELECTION_CUSTOM && (spin_buttons[SPIN_HEIGHT]->get_value() == 0 || spin_buttons[SPIN_WIDTH]->get_value() == 0)) { SPDocument *doc; @@ -793,7 +806,12 @@ void SingleExport::setDefaultSelectionMode() Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px"))); setArea(bbox->min()[Geom::X], bbox->min()[Geom::Y], bbox->max()[Geom::X], bbox->max()[Geom::Y]); } + } else { + current_key = (selection_mode)0; } + selection_buttons[current_key]->set_active(true); + prefs->setString("/dialogs/export/exportarea/value", pref_key_name); + toggleSpinButtonVisibility(); } @@ -839,16 +857,15 @@ bool SingleExport::onProgressDelete(GdkEventAny * /*event*/) interrupted = true; prog_dlg->set_stopped(); return TRUE; -} // end of sp_export_progress_delete() - +} /// Called when progress is cancelled void SingleExport::onProgressCancel() { interrupted = true; prog_dlg->set_stopped(); -} // end of sp_export_progress_cancel() +} -/// Called for every progress iteration +// Called for every progress iteration unsigned int SingleExport::onProgressCallback(float value, void *dlg) { auto dlg2 = reinterpret_cast<ExportProgressDialog *>(dlg); @@ -882,7 +899,7 @@ unsigned int SingleExport::onProgressCallback(float value, void *dlg) Gtk::Main::iteration(false); return TRUE; -} // end of sp_export_progress_callback() +} void SingleExport::refreshPreview() { @@ -902,8 +919,6 @@ void SingleExport::refreshPreview() std::vector<SPItem *> selected(_desktop->getSelection()->items().begin(), _desktop->getSelection()->items().end()); bool hide = si_hide_all->get_active(); - preview->setDocument(_desktop->getDocument()); - Unit const *unit = units->getUnit(); float x0 = getValuePx(spin_buttons[SPIN_X0]->get_value(), unit); float x1 = getValuePx(spin_buttons[SPIN_X1]->get_value(), unit); @@ -915,6 +930,16 @@ void SingleExport::refreshPreview() preview->queueRefresh(); } +void SingleExport::setDocument(SPDocument *document) +{ + if (!preview) { + preview = Gtk::manage(new ExportPreview()); + si_preview_box->pack_start(*preview, true, true, 0); + si_preview_box->show_all_children(); + } + preview->setDocument(document); +} + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/export-single.h b/src/ui/dialog/export-single.h index 1f4d971f91..5eef46593d 100644 --- a/src/ui/dialog/export-single.h +++ b/src/ui/dialog/export-single.h @@ -42,6 +42,7 @@ private: public: void setApp(InkscapeApplication *app) { _app = app; } + void setDocument(SPDocument* document); void setDesktop(SPDesktop *desktop) { _desktop = desktop; } void selectionChanged(Inkscape::Selection *selection); void selectionModified(Inkscape::Selection *selection, guint flags); diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index a59177dc54..9afa15b770 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -103,9 +103,17 @@ Export::~Export() {} // It prevents gtk_is_widget assertion warning probably. void Export::onRealize() { + if (single_image) { + single_image->setDesktop(getDesktop()); + single_image->setApp(getApp()); + } + if (batch_export) { + batch_export->setDesktop(getDesktop()); + batch_export->setApp(getApp()); + } single_image->setup(); batch_export->setup(); - // setDefaultNotebookPage(); + setDefaultNotebookPage(); } // Set current page based on preference/last visited page @@ -116,6 +124,16 @@ void Export::setDefaultNotebookPage() export_notebook->set_current_page(pages[SINGLE_IMAGE]); } +void Export::documentReplaced() +{ + if (single_image) { + single_image->setDocument(getDocument()); + } + if (batch_export) { + batch_export->setDocument(getDocument()); + } +} + void Export::desktopReplaced() { if (single_image) { diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index bf83405638..41b78b0dd7 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -63,6 +63,7 @@ private: void onPageSwitch(Widget* page, guint page_number); private: + void documentReplaced() override; void desktopReplaced() override; void selectionChanged(Inkscape::Selection *selection) override; void selectionModified(Inkscape::Selection *selection, guint flags) override; diff --git a/src/ui/dialog/preview-util.cpp b/src/ui/dialog/preview-util.cpp index 2c8ee7158b..29970570f8 100644 --- a/src/ui/dialog/preview-util.cpp +++ b/src/ui/dialog/preview-util.cpp @@ -43,7 +43,7 @@ guchar *sp_icon_doc_icon(SPDocument *doc, Inkscape::Drawing &drawing, gchar cons SPItem *item = SP_ITEM(object); dbox = item->documentVisualBounds(); } - } else { + } else if (doc->getRoot()) { // If we still dont have a dbox we will use document coordinates. dbox = doc->getRoot()->documentVisualBounds(); } -- GitLab From 7202da8f50355f1c793ca422c794b346dcf79940 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Tue, 17 Aug 2021 19:30:50 +0530 Subject: [PATCH 28/40] Ui cleanup and review changes --- share/ui/dialog-export.glade | 23 +++-- share/ui/style.css | 11 +++ src/object/sp-object.cpp | 12 ++- src/ui/dialog/export-batch.cpp | 59 +++++++++++-- src/ui/dialog/export-batch.h | 3 +- src/ui/dialog/export-helper.cpp | 140 +++++++++++++++---------------- src/ui/dialog/export-helper.h | 15 ++-- src/ui/dialog/export-preview.cpp | 3 + 8 files changed, 162 insertions(+), 104 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 3877aef0cb..4924b02e13 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -184,8 +184,6 @@ <property name="margin-end">5</property> <property name="margin-top">5</property> <property name="margin-bottom">5</property> - <property name="hexpand">True</property> - <property name="vexpand">True</property> <property name="orientation">vertical</property> <child> <placeholder/> @@ -207,7 +205,7 @@ <object class="GtkCheckButton" id="si_show_preview"> <property name="label" translatable="yes">Show Preview</property> <property name="visible">True</property> - <property name="can-focus">True</property> + <property name="can-focus">False</property> <property name="receives-default">False</property> <property name="active">True</property> <property name="draw-indicator">True</property> @@ -222,7 +220,7 @@ <object class="GtkCheckButton" id="si_hide_all"> <property name="label" translatable="yes">Show Selected only</property> <property name="visible">True</property> - <property name="can-focus">True</property> + <property name="can-focus">False</property> <property name="receives-default">False</property> <property name="draw-indicator">True</property> </object> @@ -488,7 +486,7 @@ <property name="label" translatable="yes">Selection</property> <property name="name">export_selection</property> <property name="visible">True</property> - <property name="can-focus">True</property> + <property name="can-focus">False</property> <property name="focus-on-click">False</property> <property name="receives-default">False</property> <property name="hexpand">True</property> @@ -505,7 +503,7 @@ <property name="label" translatable="yes">Document</property> <property name="name">export_selection</property> <property name="visible">True</property> - <property name="can-focus">True</property> + <property name="can-focus">False</property> <property name="focus-on-click">False</property> <property name="receives-default">False</property> <property name="hexpand">True</property> @@ -522,7 +520,7 @@ <property name="label" translatable="yes">Page</property> <property name="name">export_selection</property> <property name="visible">True</property> - <property name="can-focus">True</property> + <property name="can-focus">False</property> <property name="focus-on-click">False</property> <property name="receives-default">False</property> <property name="hexpand">True</property> @@ -539,7 +537,7 @@ <property name="label" translatable="yes">Custom</property> <property name="name">export_selection</property> <property name="visible">True</property> - <property name="can-focus">True</property> + <property name="can-focus">False</property> <property name="focus-on-click">False</property> <property name="receives-default">False</property> <property name="hexpand">True</property> @@ -745,7 +743,7 @@ <object class="GtkButton" id="si_export"> <property name="label" translatable="yes">Export</property> <property name="visible">True</property> - <property name="can-focus">True</property> + <property name="can-focus">False</property> <property name="receives-default">False</property> </object> <packing> @@ -890,8 +888,7 @@ <object class="GtkCheckButton" id="b_show_preview"> <property name="label" translatable="yes">Preview</property> <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="can-focus">True</property> + <property name="can-focus">False</property> <property name="focus-on-click">False</property> <property name="receives-default">False</property> <property name="halign">start</property> @@ -918,7 +915,7 @@ <object class="GtkCheckButton" id="b_hide_all"> <property name="label" translatable="yes">Hide All Except Selected</property> <property name="visible">True</property> - <property name="can-focus">True</property> + <property name="can-focus">False</property> <property name="focus-on-click">False</property> <property name="receives-default">False</property> <property name="halign">start</property> @@ -1036,7 +1033,7 @@ <object class="GtkButton" id="b_export"> <property name="label" translatable="yes">Export</property> <property name="visible">True</property> - <property name="can-focus">True</property> + <property name="can-focus">False</property> <property name="receives-default">True</property> </object> <packing> diff --git a/share/ui/style.css b/share/ui/style.css index e9b1631602..7746078257 100644 --- a/share/ui/style.css +++ b/share/ui/style.css @@ -550,3 +550,14 @@ stackswitcher button { .color-palette-main-box scrolledwindow undershoot.left { background-image: none; } +/* + * Inkscape Export Dialog + */ + +#ExportDialog #export_selection{ + border-radius:0px; +} +#ExportDialog #export_preview_box{ + border:1px solid; +} + diff --git a/src/object/sp-object.cpp b/src/object/sp-object.cpp index c88e807824..e0364168cc 100644 --- a/src/object/sp-object.cpp +++ b/src/object/sp-object.cpp @@ -64,9 +64,15 @@ //#define OBJECT_TRACE unsigned SPObject::indent_level = 0; -Inkscape::XML::NodeEventVector object_event_vector = {SPObject::repr_child_added, SPObject::repr_child_removed, - SPObject::repr_attr_changed, SPObject::repr_content_changed, - SPObject::repr_order_changed}; +//clang-format off +Inkscape::XML::NodeEventVector object_event_vector = { + SPObject::repr_child_added, + SPObject::repr_child_removed, + SPObject::repr_attr_changed, + SPObject::repr_content_changed, + SPObject::repr_order_changed +}; +//clang-format on /** * A friend class used to set internal members on SPObject so as to not expose settors in SPObject's public API diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index 1a3e4fb318..8b693a5dfd 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -65,7 +65,7 @@ public: Gtk::CheckButton selector; SPItem *getItem() { return _item; } bool isActive() { return selector.get_active(); } - void refresh(); + void refresh(bool hide = false); private: Gtk::Grid grid; @@ -94,6 +94,7 @@ BatchItem::BatchItem(SPItem *item) Glib::ustring id = _item->getId(); selector.set_label(id); selector.set_active(true); + selector.set_can_focus(false); if (!preview) { preview = Gtk::manage(new ExportPreview()); @@ -107,16 +108,19 @@ BatchItem::BatchItem(SPItem *item) add(grid); show_all_children(); show(); - - refresh(); + this->set_can_focus(false); } -void BatchItem::refresh() +void BatchItem::refresh(bool hide) { if (!_item) { return; } - preview->queueRefresh(); + if (hide) { + preview->resetPixels(); + } else { + preview->queueRefresh(); + } } // END OF BATCH ITEM @@ -214,6 +218,7 @@ void BatchExport::setup() for (auto [key, button] : selection_buttons) { button->signal_toggled().connect(sigc::bind(sigc::mem_fun(*this, &BatchExport::onAreaTypeToggle), key)); } + show_preview->signal_toggled().connect(sigc::mem_fun(*this, &BatchExport::refreshPreview)); filenameConn = filename_entry->signal_changed().connect(sigc::mem_fun(*this, &BatchExport::onFilenameModified)); exportConn = export_btn->signal_clicked().connect(sigc::mem_fun(*this, &BatchExport::onExport)); browseConn = filename_entry->signal_icon_press().connect(sigc::mem_fun(*this, &BatchExport::onBrowse)); @@ -293,8 +298,17 @@ void BatchExport::refreshItems() preview_container->insert(*current_items[id], -1); } + refreshPreview(); +} + +void BatchExport::refreshPreview() +{ for (auto &[key, val] : current_items) { - val->refresh(); + if (show_preview->get_active()) { + val->refresh(); + } else { + val->refresh(true); + } } } @@ -464,7 +478,38 @@ bool BatchExport::getNonConflictingFilename(Glib::ustring &filename, Glib::ustri void BatchExport::onBrowse(Gtk::EntryIconPosition pos, const GdkEventButton *ev) { - ; + if (!_app) { + return; + } + Gtk::Window *window = _app->get_active_window(); + browseConn.block(); + Glib::ustring filename = Glib::filename_from_utf8(filename_entry->get_text()); + + if (filename.empty()) { + Glib::ustring tmp; + filename = create_filepath_from_id(tmp, tmp); + } + + Inkscape::UI::Dialog::FileSaveDialog *dialog = Inkscape::UI::Dialog::FileSaveDialog::create( + *window, filename, Inkscape::UI::Dialog::RASTER_TYPES, _("Select a filename for exporting"), "", "", + Inkscape::Extension::FILE_SAVE_METHOD_EXPORT); + + if (dialog->show()) { + filename = dialog->getFilename(); + Inkscape::Extension::Output *selection_type = + dynamic_cast<Inkscape::Extension::Output *>(dialog->getSelectionType()); + Glib::ustring extension = selection_type->get_extension(); + ExtensionList::appendExtensionToFilename(filename, extension); + filename_entry->set_text(filename); + filename_entry->set_position(filename.length()); + // deleting dialog before exporting is important + // proper delete function should be made for dialog IMO + delete dialog; + onExport(); + } else { + delete dialog; + } + browseConn.unblock(); } // Utils Functions diff --git a/src/ui/dialog/export-batch.h b/src/ui/dialog/export-batch.h index 8221f8d540..459f7a41ec 100644 --- a/src/ui/dialog/export-batch.h +++ b/src/ui/dialog/export-batch.h @@ -44,7 +44,7 @@ private: public: void setApp(InkscapeApplication *app) { _app = app; } - void setDocument(SPDocument* document); + void setDocument(SPDocument *document); void setDesktop(SPDesktop *desktop) { _desktop = desktop; } void selectionChanged(Inkscape::Selection *selection); void selectionModified(Inkscape::Selection *selection, guint flags); @@ -109,6 +109,7 @@ public: }; private: + void refreshPreview(); void refreshItems(); void refreshExportHints(); diff --git a/src/ui/dialog/export-helper.cpp b/src/ui/dialog/export-helper.cpp index f97b4c7a29..de53597a5c 100644 --- a/src/ui/dialog/export-helper.cpp +++ b/src/ui/dialog/export-helper.cpp @@ -58,26 +58,30 @@ AdvanceOptions::AdvanceOptions() this->set_label(_("Advance")); Gtk::Grid *grid = Gtk::manage(new Gtk::Grid()); this->add(*grid); - std::vector<Glib::ustring> labels; { - interlacing.set_label("Use Interlacing"); + interlacing.set_label(_("Use Interlacing")); grid->attach(interlacing, 0, row, 2, 1); row++; } { - labels.insert(labels.end(), {"Gray_1", "Gray_2", "Gray_4", "Gray_8", "Gray_16", "RGB_8", "RGB_16", - "GrayAlpha_8", "GrayAlpha_16", "RGBA_8", "RGBA_16"}); bit_depth_list.clear(); - bit_depth_list.insert(bit_depth_list.end(), {1, 2, 4, 8, 16, 8, 16, 8, 16, 8, 16}); - color_list.clear(); - color_list.insert(color_list.end(), {0, 0, 0, 0, 0, 2, 2, 4, 4, 6, 6}); - - for (auto label : labels) { + bit_depth_list.insert(bit_depth_list.end(), {{_("Gray 1"), {1, 0}}, + {_("Gray 2"), {2, 0}}, + {_("Gray 4"), {4, 0}}, + {_("Gray 8"), {8, 0}}, + {_("Gray 16"), {16, 0}}, + {_("RGB 8"), {8, 2}}, + {_("RGB 16"), {16, 2}}, + {_("GrayAlpha 8"), {8, 4}}, + {_("GrayAlpha 16"), {16, 4}}, + {_("RGBA 8"), {8, 6}}, + {_("RGBA 16"), {16, 6}}}); + + for (auto [label, depth] : bit_depth_list) { bit_depth_cb.append(label); } - labels.clear(); - bit_depth_cb.set_active_text("RGBA_8"); + bit_depth_cb.set_active_text(_("RGBA 8")); bit_depth_cb.set_hexpand(); Gtk::Label *bit_depth_label = Gtk::manage(new Gtk::Label(_("Bit Depth"), Gtk::ALIGN_START)); grid->attach(*bit_depth_label, 0, row, 1, 1); @@ -85,16 +89,22 @@ AdvanceOptions::AdvanceOptions() row++; } { - labels.insert(labels.end(), {"Z_NO_COMPRESSION", "Z_BEST_SPEED", "2", "3", "4", "5", "Z_DEFAULT_COMPRESSION", - "7", "8", "Z_BEST_COMPRESSION"}); compression_list.clear(); - compression_list.insert(compression_list.end(), {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); - for (auto label : labels) { + compression_list.insert(compression_list.end(), {{_("Z No Compression"), 0}, + {_("Z Best Speed"), 1}, + {_("2"), 2}, + {_("3"), 3}, + {_("4"), 4}, + {_("5"), 5}, + {_("Z Default Compression"), 6}, + {_("7"), 7}, + {_("8"), 8}, + {_("Z Best Compression"), 9}}); + for (auto [label, compress] : compression_list) { compression_cb.append(label); } - labels.clear(); - compression_cb.set_active_text("Z_DEFAULT_COMPRESSION"); + compression_cb.set_active_text(_("Z Default Compression")); Gtk::Label *compression_label = Gtk::manage(new Gtk::Label(_("Compression"), Gtk::ALIGN_START)); grid->attach(*compression_label, 0, row, 1, 1); grid->attach(compression_cb, 1, row, 1, 1); @@ -112,23 +122,23 @@ AdvanceOptions::AdvanceOptions() row++; } { - labels.insert(labels.end(), {"CAIRO_ANTIALIAS_NONE", "CAIRO_ANTIALIAS_FAST", "CAIRO_ANTIALIAS_GOOD (default)", - "CAIRO_ANTIALIAS_BEST"}); anti_aliasing_list.clear(); - anti_aliasing_list.insert(anti_aliasing_list.end(), {0, 1, 2, 3}); + anti_aliasing_list.insert(anti_aliasing_list.end(), {{_("Cairo Antialias None"), 0}, + {_("Cairo Antialias Fast"), 1}, + {_("Cairo Antialias Good (Default)"), 2}, + {_("Cairo Antialias Best"), 3}}); - for (auto label : labels) { + for (auto [label, anti_alias] : anti_aliasing_list) { anti_aliasing_cb.append(label); } - labels.clear(); - anti_aliasing_cb.set_active_text("CAIRO_ANTIALIAS_GOOD (default)"); + anti_aliasing_cb.set_active_text(_("Cairo Antialias Good (Default)")); Gtk::Label *anti_aliasing_label = Gtk::manage(new Gtk::Label(_("Anti Aliasing"), Gtk::ALIGN_START)); grid->attach(*anti_aliasing_label, 0, row, 1, 1); grid->attach(anti_aliasing_cb, 1, row, 1, 1); row++; } - grid->set_row_spacing(2); + grid->set_row_spacing(4); grid->set_column_spacing(5); } @@ -370,8 +380,8 @@ void setValuePx(Glib::RefPtr<Gtk::Adjustment> &adj, double val, Unit const *unit return; } -// We Create filename by removing already present extension in document name and replacing it with extension passed as -// parameter if exxtension is not valid. If document doesn't have a name we use bitmap as defalt name. +// We Create filename by removing already present extension in document name and replacing it with extension passed +// as parameter if exxtension is not valid. If document doesn't have a name we use bitmap as defalt name. Glib::ustring get_default_filename(Glib::ustring &filename_entry_text, Glib::ustring &extension, SPDocument *doc) { Glib::ustring filename; @@ -492,14 +502,12 @@ bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsi if (dirname.empty() || !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { - gchar *safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); - gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), safeDir); - - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); - sp_ui_error_dialog(error); + Glib::ustring safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); + Glib::ustring error = + g_strdup_printf(_("Directory <b>%s</b> does not exist or is not a directory.\n"), safeDir.c_str()); - g_free(safeDir); - g_free(error); + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error.c_str()); + sp_ui_error_dialog(error.c_str()); return false; } @@ -531,14 +539,11 @@ bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsi delete prog_dialog; prog_dialog = nullptr; if (failed) { - gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); - gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); - - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); - sp_ui_error_dialog(error); + Glib::ustring safeFile = Inkscape::IO::sanitizeString(path.c_str()); + Glib::ustring error = g_strdup_printf(_("Could not export to filename <b>%s</b>.\n"), safeFile.c_str()); - g_free(safeFile); - g_free(error); + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error.c_str()); + sp_ui_error_dialog(error.c_str()); return false; } else if (result == EXPORT_OK) { if (extension->prefs()) { @@ -563,9 +568,9 @@ bool _export_raster(Geom::Rect const &area, unsigned long int const &width, unsi recentmanager->add_item(uri); } - gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); - desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, _("Drawing exported to <b>%s</b>."), safeFile); - g_free(safeFile); + Glib::ustring safeFile = Inkscape::IO::sanitizeString(path.c_str()); + desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, _("Drawing exported to <b>%s</b>."), + safeFile.c_str()); unlink(png_filename.c_str()); return true; @@ -595,14 +600,13 @@ bool _export_vector(Inkscape::Extension::Output *extension, SPDocument *doc, Gli if (dirname.empty() || !Inkscape::IO::file_test(dirname.c_str(), (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) { - gchar *safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); - gchar *error = g_strdup_printf(_("Directory %s does not exist or is not a directory.\n"), safeDir); + Glib::ustring safeDir = Inkscape::IO::sanitizeString(dirname.c_str()); + Glib::ustring error = + g_strdup_printf(_("Directory <b>%s</b> does not exist or is not a directory.\n"), safeDir.c_str()); - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); - sp_ui_error_dialog(error); + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error.c_str()); + sp_ui_error_dialog(error.c_str()); - g_free(safeDir); - g_free(error); return false; } @@ -622,26 +626,21 @@ bool _export_vector(Inkscape::Extension::Output *extension, SPDocument *doc, Gli SPObject *temp = dynamic_cast<SPObject *>(object); if (!temp) { - gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); - gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); + Glib::ustring safeFile = Inkscape::IO::sanitizeString(path.c_str()); + Glib::ustring error = g_strdup_printf(_("Could not export to filename <b>%s</b>.\n"), safeFile.c_str()); - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); - sp_ui_error_dialog(error); - - g_free(safeFile); - g_free(error); + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error.c_str()); + sp_ui_error_dialog(error.c_str()); return false; } SPObject *obj = copy_doc->getObjectById(temp->getId()); if (!obj) { - gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); - gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); + Glib::ustring safeFile = Inkscape::IO::sanitizeString(path.c_str()); + Glib::ustring error = g_strdup_printf(_("Could not export to filename <b>%s</b>.\n"), safeFile.c_str()); - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); - sp_ui_error_dialog(error); + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error.c_str()); + sp_ui_error_dialog(error.c_str()); - g_free(safeFile); - g_free(error); return false; } copy_doc->ensureUpToDate(); @@ -658,14 +657,12 @@ bool _export_vector(Inkscape::Extension::Output *extension, SPDocument *doc, Gli Inkscape::Extension::save(dynamic_cast<Inkscape::Extension::Extension *>(extension), copy_doc, path.c_str(), false, false, false, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_COPY); } catch (Inkscape::Extension::Output::save_failed &e) { - gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); - gchar *error = g_strdup_printf(_("Could not export to filename %s.\n"), safeFile); + Glib::ustring safeFile = Inkscape::IO::sanitizeString(path.c_str()); + Glib::ustring error = g_strdup_printf(_("Could not export to filename <b>%s</b>.\n"), safeFile.c_str()); - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error); - sp_ui_error_dialog(error); + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, error.c_str()); + sp_ui_error_dialog(error.c_str()); - g_free(safeFile); - g_free(error); return false; } @@ -675,10 +672,9 @@ bool _export_vector(Inkscape::Extension::Output *extension, SPDocument *doc, Gli recentmanager->add_item(uri); } - gchar *safeFile = Inkscape::IO::sanitizeString(path.c_str()); - desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, _("Drawing exported to <b>%s</b>."), safeFile); - g_free(safeFile); - + Glib::ustring safeFile = Inkscape::IO::sanitizeString(path.c_str()); + desktop->messageStack()->flashF(Inkscape::INFORMATION_MESSAGE, _("Drawing exported to <b>%s</b>."), + safeFile.c_str()); return true; } diff --git a/src/ui/dialog/export-helper.h b/src/ui/dialog/export-helper.h index d2fb97c13f..40eaf1700c 100644 --- a/src/ui/dialog/export-helper.h +++ b/src/ui/dialog/export-helper.h @@ -63,27 +63,26 @@ public: private: Gtk::CheckButton interlacing; - std::vector<int> bit_depth_list; - std::vector<int> color_list; + std::vector<std::pair<Glib::ustring, std::pair<int,int>>> bit_depth_list; Inkscape::UI::Widget::ScrollProtected<Gtk::ComboBoxText> bit_depth_cb; - std::vector<int> compression_list; + std::vector<std::pair<Glib::ustring, int>> compression_list; Inkscape::UI::Widget::ScrollProtected<Gtk::ComboBoxText> compression_cb; Inkscape::UI::Widget::ScrollProtected<Gtk::SpinButton> pHYs_sb; Gtk::SpinButton a; - std::vector<int> anti_aliasing_list; + std::vector<std::pair<Glib::ustring, int>> anti_aliasing_list; Inkscape::UI::Widget::ScrollProtected<Gtk::ComboBoxText> anti_aliasing_cb; private: int row; public: - int get_color() { return color_list[bit_depth_cb.get_active_row_number()]; } - int get_bit_depth() { return bit_depth_list[bit_depth_cb.get_active_row_number()]; } - int get_compression() { return compression_list[compression_cb.get_active_row_number()]; } - int get_anti_aliasing() { return anti_aliasing_list[anti_aliasing_cb.get_active_row_number()]; } + int get_color() { return bit_depth_list[bit_depth_cb.get_active_row_number()].second.second; } + int get_bit_depth() { return bit_depth_list[bit_depth_cb.get_active_row_number()].second.first; } + int get_compression() { return compression_list[compression_cb.get_active_row_number()].second; } + int get_anti_aliasing() { return anti_aliasing_list[anti_aliasing_cb.get_active_row_number()].second; } bool get_interlacing() { return interlacing.get_active(); } double get_pHYs() { return pHYs_sb.get_value(); } }; diff --git a/src/ui/dialog/export-preview.cpp b/src/ui/dialog/export-preview.cpp index 05621ef05a..9eb2d9019d 100644 --- a/src/ui/dialog/export-preview.cpp +++ b/src/ui/dialog/export-preview.cpp @@ -50,6 +50,9 @@ ExportPreview::ExportPreview() // add this image to box here this->pack_start(*image, true, true, 0); show_all_children(); + this->set_name("export_preview_box"); + this->set_can_focus(false); + image->set_can_focus(false); } void ExportPreview::resetPixels() -- GitLab From 3fae401a49e06fac1d68b20049ed4d3eb92264ba Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Tue, 17 Aug 2021 19:41:49 +0530 Subject: [PATCH 29/40] scrollbar visibility inside batch preview --- share/ui/dialog-export.glade | 1 - 1 file changed, 1 deletion(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 4924b02e13..3991da30d7 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -810,7 +810,6 @@ <property name="can-focus">True</property> <property name="hexpand">True</property> <property name="hscrollbar-policy">never</property> - <property name="vscrollbar-policy">external</property> <property name="window-placement-set">False</property> <property name="shadow-type">in</property> <child> -- GitLab From b910fbae2af7f12b8c41d7cca8eb28470d1842ad Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Tue, 17 Aug 2021 19:56:57 +0530 Subject: [PATCH 30/40] Clang Tidy fixes --- src/ui/dialog/export-batch.cpp | 5 ++--- src/ui/dialog/export-helper.h | 6 +++--- src/ui/dialog/export-preview.h | 2 +- src/ui/widget/scrollprotected.h | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index 8b693a5dfd..825420ba64 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -59,7 +59,7 @@ class BatchItem : public Gtk::FlowBoxChild { public: BatchItem(SPItem *item); - ~BatchItem(); + ~BatchItem() override; public: Gtk::CheckButton selector; @@ -250,8 +250,7 @@ void BatchExport::refreshItems() } case SELECTION_LAYER: { auto layersList = _desktop->getAllLayers(); - for (auto i = layersList.begin(); i != layersList.end(); ++i) { - SPItem *item = *i; + for (auto item : layersList) { itemsList.insert(item); } diff --git a/src/ui/dialog/export-helper.h b/src/ui/dialog/export-helper.h index 40eaf1700c..c865d61540 100644 --- a/src/ui/dialog/export-helper.h +++ b/src/ui/dialog/export-helper.h @@ -58,12 +58,12 @@ class AdvanceOptions : public Gtk::Expander { public: AdvanceOptions(); - ~AdvanceOptions(); + ~AdvanceOptions() override; private: Gtk::CheckButton interlacing; - std::vector<std::pair<Glib::ustring, std::pair<int,int>>> bit_depth_list; + std::vector<std::pair<Glib::ustring, std::pair<int, int>>> bit_depth_list; Inkscape::UI::Widget::ScrollProtected<Gtk::ComboBoxText> bit_depth_cb; std::vector<std::pair<Glib::ustring, int>> compression_list; @@ -94,7 +94,7 @@ public: ExtensionList(){}; ExtensionList(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) : Inkscape::UI::Widget::ScrollProtected<Gtk::ComboBoxText>(cobject, refGlade){}; - ~ExtensionList(); + ~ExtensionList() override; public: void setup(); diff --git a/src/ui/dialog/export-preview.h b/src/ui/dialog/export-preview.h index 7e66034c25..300ac1ff86 100644 --- a/src/ui/dialog/export-preview.h +++ b/src/ui/dialog/export-preview.h @@ -32,7 +32,7 @@ class ExportPreview : public Gtk::Box { public: ExportPreview(); - ~ExportPreview(); + ~ExportPreview() override; private: bool isLastHide = false; diff --git a/src/ui/widget/scrollprotected.h b/src/ui/widget/scrollprotected.h index c0398fec85..dbf2ff39ec 100644 --- a/src/ui/widget/scrollprotected.h +++ b/src/ui/widget/scrollprotected.h @@ -39,7 +39,7 @@ public: {} ScrollProtected(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) : Base(cobject){}; - virtual ~ScrollProtected(){}; + ~ScrollProtected() override{}; protected: /** @@ -83,7 +83,7 @@ public: {} ScrollTransfer(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) : Base(cobject){}; - virtual ~ScrollTransfer(){}; + ~ScrollTransfer() override{}; protected: /** -- GitLab From 4e78d0939f371a537c112ccd4ef3ecac11020e55 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Wed, 18 Aug 2021 16:46:43 +0530 Subject: [PATCH 31/40] Dpi 0 decimal, Batch Preview Style, Single Preview always on --- share/ui/dialog-export.glade | 4 +++- src/object/sp-object.cpp | 17 +++++++---------- src/ui/dialog/export-batch.cpp | 24 +++++++++++++++++++----- src/ui/dialog/export-helper.cpp | 21 +++++++++++++++++---- src/ui/dialog/export-helper.h | 2 +- src/ui/dialog/export-preview.cpp | 1 + src/ui/dialog/export-single.cpp | 2 +- 7 files changed, 49 insertions(+), 22 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 3991da30d7..c67e20b68e 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -204,9 +204,9 @@ <child> <object class="GtkCheckButton" id="si_show_preview"> <property name="label" translatable="yes">Show Preview</property> - <property name="visible">True</property> <property name="can-focus">False</property> <property name="receives-default">False</property> + <property name="no-show-all">True</property> <property name="active">True</property> <property name="draw-indicator">True</property> </object> @@ -809,6 +809,7 @@ <property name="visible">True</property> <property name="can-focus">True</property> <property name="hexpand">True</property> + <property name="vexpand">True</property> <property name="hscrollbar-policy">never</property> <property name="window-placement-set">False</property> <property name="shadow-type">in</property> @@ -891,6 +892,7 @@ <property name="focus-on-click">False</property> <property name="receives-default">False</property> <property name="halign">start</property> + <property name="active">True</property> <property name="draw-indicator">True</property> </object> <packing> diff --git a/src/object/sp-object.cpp b/src/object/sp-object.cpp index e0364168cc..0635a14c3a 100644 --- a/src/object/sp-object.cpp +++ b/src/object/sp-object.cpp @@ -65,13 +65,9 @@ unsigned SPObject::indent_level = 0; //clang-format off -Inkscape::XML::NodeEventVector object_event_vector = { - SPObject::repr_child_added, - SPObject::repr_child_removed, - SPObject::repr_attr_changed, - SPObject::repr_content_changed, - SPObject::repr_order_changed -}; +Inkscape::XML::NodeEventVector object_event_vector = {SPObject::repr_child_added, SPObject::repr_child_removed, + SPObject::repr_attr_changed, SPObject::repr_content_changed, + SPObject::repr_order_changed}; //clang-format on /** @@ -442,10 +438,10 @@ std::vector<SPObject *> SPObject::childList(bool add_ref, Action) return l; } -std::vector<SPObject*> SPObject::ancestorList(bool root_to_tip) +std::vector<SPObject *> SPObject::ancestorList(bool root_to_tip) { std::vector<SPObject *> ancestors; - for (SPObject::ParentIterator iter=parent ; iter ; ++iter) { + for (SPObject::ParentIterator iter = parent; iter; ++iter) { ancestors.push_back(iter); } if (root_to_tip) { @@ -454,7 +450,8 @@ std::vector<SPObject*> SPObject::ancestorList(bool root_to_tip) return ancestors; } -gchar const *SPObject::label() const { +gchar const *SPObject::label() const +{ return _label; } diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index 825420ba64..d51325cf6b 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -69,6 +69,7 @@ public: private: Gtk::Grid grid; + Gtk::Label label; ExportPreview *preview = nullptr; SPItem *_item; }; @@ -89,26 +90,39 @@ BatchItem::BatchItem(SPItem *item) return; } _item = item; - grid.attach(selector, 0, 0, 1, 1); - grid.set_row_spacing(10); + grid.attach(selector, 0, 1, 1, 1); + grid.set_row_spacing(5); + grid.set_column_spacing(5); + Glib::ustring id = _item->getId(); - selector.set_label(id); + Glib::ustring compactId = id.substr(0,7); + if(id.length()>7){ + compactId = compactId + "..."; + } + selector.set_active(true); selector.set_can_focus(false); + selector.set_valign(Gtk::Align::ALIGN_END); + selector.set_margin_start(2); + selector.set_margin_bottom(2); if (!preview) { preview = Gtk::manage(new ExportPreview()); - grid.attach(*preview, 0, 1, 1, 1); + grid.attach(*preview, 0, 0, 2, 2); } - preview->setItem(_item); preview->setDocument(_item->document); preview->setSize(64); + label.set_text(compactId); + label.set_halign(Gtk::Align::ALIGN_CENTER); + grid.attach(label, 0, 2, 2, 1); + add(grid); show_all_children(); show(); this->set_can_focus(false); + this->set_tooltip_text(id); } void BatchItem::refresh(bool hide) diff --git a/src/ui/dialog/export-helper.cpp b/src/ui/dialog/export-helper.cpp index de53597a5c..067708e550 100644 --- a/src/ui/dialog/export-helper.cpp +++ b/src/ui/dialog/export-helper.cpp @@ -296,9 +296,9 @@ void ExportList::append_row() extension->show(); SpinButton *dpi_sb = Gtk::manage(new SpinButton()); - dpi_sb->set_digits(2); - dpi_sb->set_increments(0.1, 1.0); - dpi_sb->set_range(0.01, 100000.0); + dpi_sb->set_digits(0); + dpi_sb->set_increments(1.0, 1.0); + dpi_sb->set_range(1.0, 100000.0); dpi_sb->set_value(default_dpi); dpi_sb->set_sensitive(true); dpi_sb->set_width_chars(6); @@ -309,10 +309,17 @@ void ExportList::append_row() Gtk::Image *pIcon = Gtk::manage(sp_get_icon_image("window-close", Gtk::ICON_SIZE_SMALL_TOOLBAR)); Gtk::Button *delete_btn = Gtk::manage(new Gtk::Button()); delete_btn->set_relief(Gtk::RELIEF_NONE); + delete_btn->set_no_show_all(true); + if (_num_rows != 0) { + Gtk::Widget *d_button_0 = dynamic_cast<Gtk::Widget *>(this->get_child_at(_delete_col, 1)); + if (d_button_0) { + d_button_0->show(); + } + delete_btn->show(); + } pIcon->show(); delete_btn->add(*pIcon); this->attach(*delete_btn, _delete_col, current_row, 1, 1); - delete_btn->show(); delete_btn->signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &ExportList::delete_row), delete_btn)); _num_rows++; @@ -329,6 +336,12 @@ void ExportList::delete_row(Gtk::Widget *widget) int row = this->child_property_top_attach(*widget); this->remove_row(row); _num_rows--; + if (_num_rows <= 1) { + Gtk::Widget *d_button_0 = dynamic_cast<Gtk::Widget *>(this->get_child_at(_delete_col, 1)); + if (d_button_0) { + d_button_0->hide(); + } + } } Glib::ustring ExportList::get_suffix(int row) diff --git a/src/ui/dialog/export-helper.h b/src/ui/dialog/export-helper.h index c865d61540..f3d8111984 100644 --- a/src/ui/dialog/export-helper.h +++ b/src/ui/dialog/export-helper.h @@ -145,7 +145,7 @@ public: ExportList(){}; ExportList(BaseObjectType *cobject, const Glib::RefPtr<Gtk::Builder> &refGlade) : Gtk::Grid(cobject){}; - ~ExportList(); + ~ExportList() override; public: void setup(); diff --git a/src/ui/dialog/export-preview.cpp b/src/ui/dialog/export-preview.cpp index 9eb2d9019d..395df133ae 100644 --- a/src/ui/dialog/export-preview.cpp +++ b/src/ui/dialog/export-preview.cpp @@ -47,6 +47,7 @@ ExportPreview::ExportPreview() auto pb = Gdk::Pixbuf::create_from_data(pixMem, Gdk::COLORSPACE_RGB, true, 8, size, size, stride); image = Gtk::manage(new Gtk::Image(pb)); image->show(); + image->set_name("export_preview_image"); // add this image to box here this->pack_start(*image, true, true, 0); show_all_children(); diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index 8eb51ecb12..bab45a45a8 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -254,7 +254,7 @@ void SingleExport::setupSpinButtons() setupSpinButton<sb_type>(spin_buttons[SPIN_BMWIDTH], 1.0, 1.0, 1000000.0, 1.0, 10.0, 0, true, &SingleExport::onDpiChange, SPIN_BMWIDTH); setupSpinButton<sb_type>(spin_buttons[SPIN_DPI], prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), - 0.01, 100000.0, 0.1, 1.0, 2, true, &SingleExport::onDpiChange, SPIN_DPI); + 1.0, 100000.0, 1.0, 1.0, 0, true, &SingleExport::onDpiChange, SPIN_DPI); } template <typename T> -- GitLab From a579e96f36a79439103115f1b4658c7a35d03aa0 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Wed, 18 Aug 2021 17:01:32 +0530 Subject: [PATCH 32/40] Show selected refresh in Batch Export --- share/ui/dialog-export.glade | 2 +- src/ui/dialog/export-batch.cpp | 22 +++++++++++++++------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index c67e20b68e..2a068b3887 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -914,7 +914,7 @@ </child> <child> <object class="GtkCheckButton" id="b_hide_all"> - <property name="label" translatable="yes">Hide All Except Selected</property> + <property name="label" translatable="yes">Show Selected Only</property> <property name="visible">True</property> <property name="can-focus">False</property> <property name="focus-on-click">False</property> diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index d51325cf6b..40d4733594 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -66,6 +66,7 @@ public: SPItem *getItem() { return _item; } bool isActive() { return selector.get_active(); } void refresh(bool hide = false); + void refreshHide(const std::vector<SPItem *> *list) { preview->refreshHide(list); } private: Gtk::Grid grid; @@ -95,8 +96,8 @@ BatchItem::BatchItem(SPItem *item) grid.set_column_spacing(5); Glib::ustring id = _item->getId(); - Glib::ustring compactId = id.substr(0,7); - if(id.length()>7){ + Glib::ustring compactId = id.substr(0, 7); + if (id.length() > 7) { compactId = compactId + "..."; } @@ -236,6 +237,7 @@ void BatchExport::setup() filenameConn = filename_entry->signal_changed().connect(sigc::mem_fun(*this, &BatchExport::onFilenameModified)); exportConn = export_btn->signal_clicked().connect(sigc::mem_fun(*this, &BatchExport::onExport)); browseConn = filename_entry->signal_icon_press().connect(sigc::mem_fun(*this, &BatchExport::onBrowse)); + hide_all->signal_toggled().connect(sigc::mem_fun(*this, &BatchExport::refreshPreview)); } void BatchExport::refreshItems() @@ -316,11 +318,17 @@ void BatchExport::refreshItems() void BatchExport::refreshPreview() { - for (auto &[key, val] : current_items) { - if (show_preview->get_active()) { - val->refresh(); - } else { - val->refresh(true); + if (_desktop) { + std::vector<SPItem *> selected(_desktop->getSelection()->items().begin(), + _desktop->getSelection()->items().end()); + bool hide = hide_all->get_active(); + for (auto &[key, val] : current_items) { + if (show_preview->get_active()) { + val->refreshHide(hide ? &selected : nullptr); + val->refresh(); + } else { + val->refresh(true); + } } } } -- GitLab From 98257cdc71bf3739e68d90cb062bc563dbcdf7e2 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Tue, 24 Aug 2021 00:56:22 +0530 Subject: [PATCH 33/40] small changes for review --- share/ui/dialog-export.glade | 15 +++++++++++++-- src/ui/dialog/export-batch.cpp | 5 +++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 2a068b3887..903682dad9 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -218,7 +218,7 @@ </child> <child> <object class="GtkCheckButton" id="si_hide_all"> - <property name="label" translatable="yes">Show Selected only</property> + <property name="label" translatable="yes">Export Selected only</property> <property name="visible">True</property> <property name="can-focus">False</property> <property name="receives-default">False</property> @@ -400,6 +400,7 @@ <property name="hexpand">True</property> <property name="width-chars">0</property> <property name="max-width-chars">0</property> + <property name="input-purpose">number</property> </object> <packing> <property name="left-attach">2</property> @@ -489,6 +490,7 @@ <property name="can-focus">False</property> <property name="focus-on-click">False</property> <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Export selected Objects</property> <property name="hexpand">True</property> <property name="draw-indicator">False</property> <property name="group">si_s_document</property> @@ -506,6 +508,7 @@ <property name="can-focus">False</property> <property name="focus-on-click">False</property> <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Export everything inside Document</property> <property name="hexpand">True</property> <property name="active">True</property> <property name="draw-indicator">False</property> @@ -523,6 +526,7 @@ <property name="can-focus">False</property> <property name="focus-on-click">False</property> <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Export cropped content inside the page</property> <property name="hexpand">True</property> <property name="draw-indicator">False</property> <property name="group">si_s_document</property> @@ -540,6 +544,7 @@ <property name="can-focus">False</property> <property name="focus-on-click">False</property> <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Export Custom Area by specifying coordinates</property> <property name="hexpand">True</property> <property name="draw-indicator">False</property> <property name="group">si_s_document</property> @@ -709,6 +714,7 @@ <property name="can-focus">True</property> <property name="hexpand">True</property> <property name="secondary-icon-name">folder-open</property> + <property name="secondary-icon-tooltip-text" translatable="yes">Browse Export Directory</property> <property name="placeholder-text" translatable="yes">Filename</property> </object> <packing> @@ -720,6 +726,7 @@ <object class="GtkComboBoxText" id="si_extention"> <property name="visible">True</property> <property name="can-focus">False</property> + <property name="tooltip-text" translatable="yes">Select export format</property> <property name="valign">center</property> <property name="active">0</property> </object> @@ -768,6 +775,7 @@ <object class="GtkLabel"> <property name="visible">True</property> <property name="can-focus">False</property> + <property name="tooltip-text" translatable="yes">Export a part of document</property> <property name="double-buffered">False</property> <property name="label" translatable="yes">Single Image</property> <property name="justify">right</property> @@ -851,6 +859,7 @@ <property name="visible">True</property> <property name="can-focus">False</property> <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Export selected Objects/Groups to separate file</property> <property name="active">True</property> <property name="draw-indicator">False</property> </object> @@ -867,6 +876,7 @@ <property name="visible">True</property> <property name="can-focus">False</property> <property name="receives-default">False</property> + <property name="tooltip-text" translatable="yes">Export Layers as separate file</property> <property name="active">True</property> <property name="draw-indicator">False</property> <property name="group">b_s_selection</property> @@ -914,7 +924,7 @@ </child> <child> <object class="GtkCheckButton" id="b_hide_all"> - <property name="label" translatable="yes">Show Selected Only</property> + <property name="label" translatable="yes">Export Selected Only</property> <property name="visible">True</property> <property name="can-focus">False</property> <property name="focus-on-click">False</property> @@ -1068,6 +1078,7 @@ <object class="GtkLabel"> <property name="visible">True</property> <property name="can-focus">False</property> + <property name="tooltip-text" translatable="yes">Batch Export Objects and Layers</property> <property name="double-buffered">False</property> <property name="label" translatable="yes">Batch Export</property> <property name="justify">right</property> diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index 40d4733594..ac5fa0d5de 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -368,8 +368,9 @@ void BatchExport::onExport() export_btn->set_sensitive(false); bool exportSuccessful = true; - gint num = (gint)boost::distance(_desktop->getSelection()->items()); - if (num < 1) { + + // If there are no selected button, simply flash message in status bar + if (current_items.size() == 0) { _desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No items selected.")); export_btn->set_sensitive(true); return; -- GitLab From c058cea70684f447e1b9571eb3dbbcf9fc751938 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Tue, 24 Aug 2021 01:54:03 +0530 Subject: [PATCH 34/40] changed batch preview to standalone --- src/ui/dialog/export-batch.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index ac5fa0d5de..c7166413f4 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -319,11 +319,13 @@ void BatchExport::refreshItems() void BatchExport::refreshPreview() { if (_desktop) { - std::vector<SPItem *> selected(_desktop->getSelection()->items().begin(), - _desktop->getSelection()->items().end()); + // For Batch Export we are now hiding all object except current object + // std::vector<SPItem *> selected(_desktop->getSelection()->items().begin(), + // _desktop->getSelection()->items().end()); bool hide = hide_all->get_active(); for (auto &[key, val] : current_items) { if (show_preview->get_active()) { + std::vector<SPItem *> selected = {val->getItem()}; val->refreshHide(hide ? &selected : nullptr); val->refresh(); } else { @@ -368,8 +370,8 @@ void BatchExport::onExport() export_btn->set_sensitive(false); bool exportSuccessful = true; - // If there are no selected button, simply flash message in status bar + int num = current_items.size(); if (current_items.size() == 0) { _desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No items selected.")); export_btn->set_sensitive(true); -- GitLab From 754e2636ae0f4b16dc8912ea0ad28508f7ffab22 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Sun, 29 Aug 2021 18:25:39 +0530 Subject: [PATCH 35/40] Added standalone export in batch export --- src/ui/dialog/export-batch.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index c7166413f4..1bcb6c4836 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -399,7 +399,9 @@ void BatchExport::onExport() dpis.push_back(export_list->get_dpi(i)); } - std::vector<SPItem *> selected(_desktop->getSelection()->items().begin(), _desktop->getSelection()->items().end()); + // We are exporting standalone items only for now + // std::vector<SPItem *> selected(_desktop->getSelection()->items().begin(), + // _desktop->getSelection()->items().end()); bool hide = hide_all->get_active(); // Start Exporting Each Item @@ -459,8 +461,9 @@ void BatchExport::onExport() unsigned long int width = (int)(area->width() * dpi / DPI_BASE + 0.5); unsigned long int height = (int)(area->height() * dpi / DPI_BASE + 0.5); + std::vector<SPItem *> show_only = {item}; exportSuccessful = _export_raster(*area, width, height, dpi, item_filename, true, onProgressCallback, - prog_dlg, omod, hide ? &selected : nullptr, &advance_options); + prog_dlg, omod, hide ? &show_only : nullptr, &advance_options); } else { setExporting(true, Glib::ustring::compose(_("Exporting %1"), filename)); SPDocument *doc = _desktop->getDocument(); -- GitLab From 9c8fa47955cd1bcc82ea06658d31867bc3e809a6 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Sun, 29 Aug 2021 21:31:37 +0530 Subject: [PATCH 36/40] using label istead of id in batch_export --- src/ui/dialog/export-batch.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index 1bcb6c4836..6db39714a8 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -95,7 +95,10 @@ BatchItem::BatchItem(SPItem *item) grid.set_row_spacing(5); grid.set_column_spacing(5); - Glib::ustring id = _item->getId(); + Glib::ustring id = _item->defaultLabel(); + if (id.empty()) { + id = _item->getId(); + } Glib::ustring compactId = id.substr(0, 7); if (id.length() > 7) { compactId = compactId + "..."; @@ -422,7 +425,10 @@ void BatchExport::onExport() n++; continue; } - Glib::ustring id = item->getId(); + Glib::ustring id = item->defaultLabel(); + if (id.empty()) { + id = item->getId(); + } if (id.empty()) { n++; continue; -- GitLab From 3cdd9f575286d68f649dc35c52ea772ef205eccd Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Sun, 29 Aug 2021 22:08:32 +0530 Subject: [PATCH 37/40] Added license where neccessary --- src/ui/dialog/export-batch.cpp | 3 ++- src/ui/dialog/export-batch.h | 3 ++- src/ui/dialog/export-helper.cpp | 7 ++----- src/ui/dialog/export-helper.h | 7 ++----- src/ui/dialog/export-preview.cpp | 7 ++----- src/ui/dialog/export-preview.h | 7 ++----- src/ui/dialog/export-single.cpp | 3 ++- src/ui/dialog/export-single.h | 3 ++- src/ui/dialog/export.cpp | 3 ++- src/ui/dialog/export.h | 3 ++- src/ui/dialog/preview-util.cpp | 19 +++++++++++++++++++ src/ui/dialog/preview-util.h | 21 ++++++++++++++++++++- src/ui/widget/scrollprotected.h | 3 ++- 13 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/ui/dialog/export-batch.cpp b/src/ui/dialog/export-batch.cpp index 6db39714a8..d90abd9713 100644 --- a/src/ui/dialog/export-batch.cpp +++ b/src/ui/dialog/export-batch.cpp @@ -3,8 +3,9 @@ * Lauris Kaplinski <lauris@kaplinski.com> * bulia byak <buliabyak@users.sf.net> * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> * - * Copyright (C) 1999-2007 Authors + * Copyright (C) 1999-2007, 2021 Authors * Copyright (C) 2001-2002 Ximian, Inc. * * Released under GNU GPL v2+, read the file 'COPYING' for more information. diff --git a/src/ui/dialog/export-batch.h b/src/ui/dialog/export-batch.h index 459f7a41ec..ab8b89d44c 100644 --- a/src/ui/dialog/export-batch.h +++ b/src/ui/dialog/export-batch.h @@ -3,8 +3,9 @@ * Lauris Kaplinski <lauris@kaplinski.com> * bulia byak <buliabyak@users.sf.net> * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> * - * Copyright (C) 1999-2007 Authors + * Copyright (C) 1999-2007, 2021 Authors * Copyright (C) 2001-2002 Ximian, Inc. * * Released under GNU GPL v2+, read the file 'COPYING' for more information. diff --git a/src/ui/dialog/export-helper.cpp b/src/ui/dialog/export-helper.cpp index 067708e550..1359d19f51 100644 --- a/src/ui/dialog/export-helper.cpp +++ b/src/ui/dialog/export-helper.cpp @@ -1,11 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* Authors: - * Lauris Kaplinski <lauris@kaplinski.com> - * bulia byak <buliabyak@users.sf.net> - * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> * - * Copyright (C) 1999-2007 Authors - * Copyright (C) 2001-2002 Ximian, Inc. + * Copyright (C) 2021 Authors * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ diff --git a/src/ui/dialog/export-helper.h b/src/ui/dialog/export-helper.h index f3d8111984..6e03c7dd8f 100644 --- a/src/ui/dialog/export-helper.h +++ b/src/ui/dialog/export-helper.h @@ -1,11 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* Authors: - * Lauris Kaplinski <lauris@kaplinski.com> - * bulia byak <buliabyak@users.sf.net> - * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> * - * Copyright (C) 1999-2007 Authors - * Copyright (C) 2001-2002 Ximian, Inc. + * Copyright (C) 2021 Authors * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ diff --git a/src/ui/dialog/export-preview.cpp b/src/ui/dialog/export-preview.cpp index 395df133ae..4256236498 100644 --- a/src/ui/dialog/export-preview.cpp +++ b/src/ui/dialog/export-preview.cpp @@ -1,11 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* Authors: - * Lauris Kaplinski <lauris@kaplinski.com> - * bulia byak <buliabyak@users.sf.net> - * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> * - * Copyright (C) 1999-2007 Authors - * Copyright (C) 2001-2002 Ximian, Inc. + * Copyright (C) 2021 Authors * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ diff --git a/src/ui/dialog/export-preview.h b/src/ui/dialog/export-preview.h index 300ac1ff86..e97c74d567 100644 --- a/src/ui/dialog/export-preview.h +++ b/src/ui/dialog/export-preview.h @@ -1,11 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* Authors: - * Lauris Kaplinski <lauris@kaplinski.com> - * bulia byak <buliabyak@users.sf.net> - * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> * - * Copyright (C) 1999-2007 Authors - * Copyright (C) 2001-2002 Ximian, Inc. + * Copyright (C) 2021 Authors * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index bab45a45a8..7ce4690c3b 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -3,8 +3,9 @@ * Lauris Kaplinski <lauris@kaplinski.com> * bulia byak <buliabyak@users.sf.net> * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> * - * Copyright (C) 1999-2007 Authors + * Copyright (C) 1999-2007, 2021 Authors * Copyright (C) 2001-2002 Ximian, Inc. * * Released under GNU GPL v2+, read the file 'COPYING' for more information. diff --git a/src/ui/dialog/export-single.h b/src/ui/dialog/export-single.h index 5eef46593d..e6a0d4dcb1 100644 --- a/src/ui/dialog/export-single.h +++ b/src/ui/dialog/export-single.h @@ -3,8 +3,9 @@ * Lauris Kaplinski <lauris@kaplinski.com> * bulia byak <buliabyak@users.sf.net> * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> * - * Copyright (C) 1999-2007 Authors + * Copyright (C) 1999-2007, 2021 Authors * Copyright (C) 2001-2002 Ximian, Inc. * * Released under GNU GPL v2+, read the file 'COPYING' for more information. diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 9afa15b770..6ccf67fcc1 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -7,8 +7,9 @@ * Jon A. Cruz <jon@joncruz.org> * Abhishek Sharma * Kris De Gussem <Kris.DeGussem@gmail.com> + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> * - * Copyright (C) 1999-2007, 2012 Authors + * Copyright (C) 1999-2007, 2012, 2021 Authors * Copyright (C) 2001-2002 Ximian, Inc. * * Released under GNU GPL v2+, read the file 'COPYING' for more information. diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 41b78b0dd7..f434f558e4 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -3,8 +3,9 @@ * Lauris Kaplinski <lauris@kaplinski.com> * bulia byak <buliabyak@users.sf.net> * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> * - * Copyright (C) 1999-2007 Authors + * Copyright (C) 1999-2007, 2021 Authors * Copyright (C) 2001-2002 Ximian, Inc. * * Released under GNU GPL v2+, read the file 'COPYING' for more information. diff --git a/src/ui/dialog/preview-util.cpp b/src/ui/dialog/preview-util.cpp index 29970570f8..42ec5de0a1 100644 --- a/src/ui/dialog/preview-util.cpp +++ b/src/ui/dialog/preview-util.cpp @@ -1,3 +1,22 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** + * @file + * Utility functions for previewing icon representation. + */ +/* Authors: + * Jon A. Cruz + * Bob Jamison + * Other dudes from The Inkscape Organization + * Abhishek Sharma + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> + * + * Copyright (C) 2004 Bob Jamison + * Copyright (C) 2005,2010 Jon A. Cruz + * Copyright (C) 2021 Anshudhar Kumar Singh + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + #include "preview-util.h" #include "display/cairo-utils.h" diff --git a/src/ui/dialog/preview-util.h b/src/ui/dialog/preview-util.h index b23df8b3b8..e2d6504437 100644 --- a/src/ui/dialog/preview-util.h +++ b/src/ui/dialog/preview-util.h @@ -1,7 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** + * @file + * Utility functions for previewing icon representation. + */ +/* Authors: + * Jon A. Cruz + * Bob Jamison + * Other dudes from The Inkscape Organization + * Abhishek Sharma + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> + * + * Copyright (C) 2004 Bob Jamison + * Copyright (C) 2005,2010 Jon A. Cruz + * Copyright (C) 2021 Anshudhar Kumar Singh + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + #ifndef SP_PREVIEW_UTIL_H #define SP_PREVIEW_UTIL_H -#include <glibmm/main.h> +#include <glibmm/main.h>u #include "desktop.h" #include "display/drawing.h" diff --git a/src/ui/widget/scrollprotected.h b/src/ui/widget/scrollprotected.h index dbf2ff39ec..7e4a123aac 100644 --- a/src/ui/widget/scrollprotected.h +++ b/src/ui/widget/scrollprotected.h @@ -4,8 +4,9 @@ /* Authors: * Thomas Holder + * Anshudhar Kumar Singh <anshudhar2001@gmail.com> * - * Copyright (C) 2020 authors + * Copyright (C) 2020-2021 Authors * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ -- GitLab From f40f4feff5c8876b07210f9a6b9a47eaa616d847 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Sun, 29 Aug 2021 22:14:41 +0530 Subject: [PATCH 38/40] code style --- src/desktop.cpp | 2 +- src/object/sp-object.h | 11 +-- src/ui/dialog/export-single.h | 2 +- src/ui/dialog/export.h | 4 +- src/ui/dialog/icon-preview.cpp | 163 +++++++++++++++------------------ 5 files changed, 83 insertions(+), 99 deletions(-) diff --git a/src/desktop.cpp b/src/desktop.cpp index f4b0fc57f3..74284be784 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -446,7 +446,7 @@ void SPDesktop::toggleLayerSolo(SPObject *object) layers->toggleLayerSolo(object); } -std::list<SPItem*> SPDesktop::getAllLayers() +std::list<SPItem *> SPDesktop::getAllLayers() { return layers->getAllLayers(); } diff --git a/src/object/sp-object.h b/src/object/sp-object.h index e3eca9b675..51c0e5cfa1 100644 --- a/src/object/sp-object.h +++ b/src/object/sp-object.h @@ -466,8 +466,8 @@ public: /** * Removes all children except for the given object, it's children and it's ancesstors. */ - void cropToObject(SPObject *except); - void cropToObjects(std::vector<SPObject *> except_objects); + void cropToObject(SPObject *except); + void cropToObjects(std::vector<SPObject *> except_objects); /** * Connects a slot to be called when an object is deleted. @@ -481,11 +481,10 @@ public: * * @see SPObject::deleteObject */ - sigc::connection connectDelete(sigc::slot<void, SPObject *> slot) { - return _delete_signal.connect(slot); - } + sigc::connection connectDelete(sigc::slot<void, SPObject *> slot) { return _delete_signal.connect(slot); } - sigc::connection connectPositionChanged(sigc::slot<void, SPObject *> slot) { + sigc::connection connectPositionChanged(sigc::slot<void, SPObject *> slot) + { return _position_changed_signal.connect(slot); } diff --git a/src/ui/dialog/export-single.h b/src/ui/dialog/export-single.h index e6a0d4dcb1..b19966e60b 100644 --- a/src/ui/dialog/export-single.h +++ b/src/ui/dialog/export-single.h @@ -43,7 +43,7 @@ private: public: void setApp(InkscapeApplication *app) { _app = app; } - void setDocument(SPDocument* document); + void setDocument(SPDocument *document); void setDesktop(SPDesktop *desktop) { _desktop = desktop; } void selectionChanged(Inkscape::Selection *selection); void selectionModified(Inkscape::Selection *selection, guint flags); diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index f434f558e4..cc8c0e4d2a 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -56,12 +56,12 @@ private: // setup default values of widgets void setDefaultNotebookPage(); - std::map<notebook_page,int> pages; + std::map<notebook_page, int> pages; private: // signals callback void onRealize(); - void onPageSwitch(Widget* page, guint page_number); + void onPageSwitch(Widget *page, guint page_number); private: void documentReplaced() override; diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp index e5ad593f96..2b2208945c 100644 --- a/src/ui/dialog/icon-preview.cpp +++ b/src/ui/dialog/icon-preview.cpp @@ -15,31 +15,26 @@ * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ +#include "icon-preview.h" + #include <glibmm/i18n.h> -#include <glibmm/timer.h> #include <glibmm/main.h> - +#include <glibmm/timer.h> #include <gtkmm/buttonbox.h> #include <gtkmm/checkbutton.h> #include <gtkmm/frame.h> #include "desktop.h" -#include "document.h" -#include "inkscape.h" -#include "verbs.h" - #include "display/cairo-utils.h" -#include "display/drawing.h" #include "display/drawing-context.h" - +#include "display/drawing.h" +#include "document.h" +#include "inkscape.h" #include "object/sp-namedview.h" #include "object/sp-root.h" - -#include "icon-preview.h" - -#include "ui/widget/frame.h" - #include "preview-util.h" +#include "ui/widget/frame.h" +#include "verbs.h" #define noICON_VERBOSE 1 @@ -47,7 +42,6 @@ namespace Inkscape { namespace UI { namespace Dialog { - IconPreviewPanel &IconPreviewPanel::getInstance() { IconPreviewPanel *instance = new IconPreviewPanel(); @@ -63,8 +57,8 @@ IconPreviewPanel &IconPreviewPanel::getInstance() void IconPreviewPanel::on_button_clicked(int which) { - if ( hot != which ) { - buttons[hot]->set_active( false ); + if (hot != which) { + buttons[hot]->set_active(false); hot = which; updateMagnify(); @@ -72,9 +66,6 @@ void IconPreviewPanel::on_button_clicked(int which) } } - - - //######################################################################### //## C O N S T R U C T O R / D E S T R U C T O R //######################################################################### @@ -103,7 +94,7 @@ IconPreviewPanel::IconPreviewPanel() std::vector<Glib::ustring> pref_sizes = prefs->getAllDirs("/iconpreview/sizes/default"); std::vector<int> rawSizes; - for (auto & pref_size : pref_sizes) { + for (auto &pref_size : pref_sizes) { if (prefs->getBool(pref_size + "/show", true)) { int sizeVal = prefs->getInt(pref_size + "/value", -1); if (sizeVal > 0) { @@ -112,17 +103,16 @@ IconPreviewPanel::IconPreviewPanel() } } - if ( !rawSizes.empty() ) { + if (!rawSizes.empty()) { numEntries = rawSizes.size(); sizes = new int[numEntries]; int i = 0; - for ( std::vector<int>::iterator it = rawSizes.begin(); it != rawSizes.end(); ++it, ++i ) { + for (std::vector<int>::iterator it = rawSizes.begin(); it != rawSizes.end(); ++it, ++i) { sizes[i] = *it; } } - if ( numEntries < 1 ) - { + if (numEntries < 1) { numEntries = 5; sizes = new int[numEntries]; sizes[0] = 16; @@ -132,13 +122,12 @@ IconPreviewPanel::IconPreviewPanel() sizes[4] = 128; } - pixMem = new guchar*[numEntries]; - images = new Gtk::Image*[numEntries]; - labels = new Glib::ustring*[numEntries]; - buttons = new Gtk::ToggleToolButton*[numEntries]; - + pixMem = new guchar *[numEntries]; + images = new Gtk::Image *[numEntries]; + labels = new Glib::ustring *[numEntries]; + buttons = new Gtk::ToggleToolButton *[numEntries]; - for ( int i = 0; i < numEntries; i++ ) { + for (int i = 0; i < numEntries; i++) { char *label = g_strdup_printf(_("%d x %d"), sizes[i], sizes[i]); labels[i] = new Glib::ustring(label); g_free(label); @@ -146,33 +135,31 @@ IconPreviewPanel::IconPreviewPanel() images[i] = nullptr; } + magLabel.set_label(*labels[hot]); - magLabel.set_label( *labels[hot] ); - - Gtk::Box* magBox = new Gtk::Box(Gtk::ORIENTATION_VERTICAL); + Gtk::Box *magBox = new Gtk::Box(Gtk::ORIENTATION_VERTICAL); UI::Widget::Frame *magFrame = Gtk::manage(new UI::Widget::Frame(_("Magnified:"))); - magFrame->add( magnified ); - - magBox->pack_start( *magFrame, Gtk::PACK_EXPAND_WIDGET ); - magBox->pack_start( magLabel, Gtk::PACK_SHRINK ); + magFrame->add(magnified); + magBox->pack_start(*magFrame, Gtk::PACK_EXPAND_WIDGET); + magBox->pack_start(magLabel, Gtk::PACK_SHRINK); Gtk::Box *verts = new Gtk::Box(Gtk::ORIENTATION_VERTICAL); Gtk::Box *horiz = nullptr; int previous = 0; int avail = 0; - for ( int i = numEntries - 1; i >= 0; --i ) { + for (int i = numEntries - 1; i >= 0; --i) { int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, sizes[i]); pixMem[i] = new guchar[sizes[i] * stride]; - memset( pixMem[i], 0x00, sizes[i] * stride ); + memset(pixMem[i], 0x00, sizes[i] * stride); auto pb = Gdk::Pixbuf::create_from_data(pixMem[i], Gdk::COLORSPACE_RGB, true, 8, sizes[i], sizes[i], stride); images[i] = Gtk::make_managed<Gtk::Image>(pb); Glib::ustring label(*labels[i]); buttons[i] = new Gtk::ToggleToolButton(label); - buttons[i]->set_active( i == hot ); - if ( prefs->getBool("/iconpreview/showFrames", true) ) { + buttons[i]->set_active(i == hot); + if (prefs->getBool("/iconpreview/showFrames", true)) { Gtk::Frame *frame = new Gtk::Frame(); frame->set_shadow_type(Gtk::SHADOW_ETCHED_IN); frame->add(*images[i]); @@ -183,12 +170,13 @@ IconPreviewPanel::IconPreviewPanel() buttons[i]->set_tooltip_text(label); - buttons[i]->signal_clicked().connect( sigc::bind<int>( sigc::mem_fun(*this, &IconPreviewPanel::on_button_clicked), i) ); + buttons[i]->signal_clicked().connect( + sigc::bind<int>(sigc::mem_fun(*this, &IconPreviewPanel::on_button_clicked), i)); buttons[i]->set_halign(Gtk::ALIGN_CENTER); buttons[i]->set_valign(Gtk::ALIGN_CENTER); - if ( !pack || ( (avail == 0) && (previous == 0) ) ) { + if (!pack || ((avail == 0) && (previous == 0))) { verts->pack_end(*(buttons[i]), Gtk::PACK_SHRINK); previous = sizes[i]; avail = sizes[i]; @@ -217,20 +205,22 @@ IconPreviewPanel::IconPreviewPanel() } iconBox.pack_start(splitter); - splitter.pack1( *magBox, true, false ); - UI::Widget::Frame *actuals = Gtk::manage(new UI::Widget::Frame (_("Actual Size:"))); + splitter.pack1(*magBox, true, false); + UI::Widget::Frame *actuals = Gtk::manage(new UI::Widget::Frame(_("Actual Size:"))); actuals->set_border_width(4); actuals->add(*verts); - splitter.pack2( *actuals, false, false ); + splitter.pack2(*actuals, false, false); - - selectionButton = new Gtk::CheckButton(C_("Icon preview window", "Sele_ction"), true);//selectionButton = (Gtk::ToggleButton*) gtk_check_button_new_with_mnemonic(_("_Selection")); // , GTK_RESPONSE_APPLY - magBox->pack_start( *selectionButton, Gtk::PACK_SHRINK ); + selectionButton = + new Gtk::CheckButton(C_("Icon preview window", "Sele_ction"), + true); // selectionButton = (Gtk::ToggleButton*) + // gtk_check_button_new_with_mnemonic(_("_Selection")); // , GTK_RESPONSE_APPLY + magBox->pack_start(*selectionButton, Gtk::PACK_SHRINK); selectionButton->set_tooltip_text(_("Selection only or whole document")); - selectionButton->signal_clicked().connect( sigc::mem_fun(*this, &IconPreviewPanel::modeToggled) ); + selectionButton->signal_clicked().connect(sigc::mem_fun(*this, &IconPreviewPanel::modeToggled)); gint val = prefs->getBool("/iconpreview/selectionOnly"); - selectionButton->set_active( val != 0 ); + selectionButton->set_active(val != 0); pack_start(iconBox, Gtk::PACK_SHRINK); @@ -251,7 +241,7 @@ IconPreviewPanel::~IconPreviewPanel() delete timer; timer = nullptr; } - if ( renderTimer ) { + if (renderTimer) { renderTimer->stop(); delete renderTimer; renderTimer = nullptr; @@ -264,7 +254,6 @@ IconPreviewPanel::~IconPreviewPanel() //## M E T H O D S //######################################################################### - #if ICON_VERBOSE static Glib::ustring getTimestr() { @@ -312,20 +301,19 @@ void IconPreviewPanel::refreshPreview() } if (timer->elapsed() < minDelay) { #if ICON_VERBOSE - g_message( "%s Deferring refresh as too soon. calling queueRefresh()", getTimestr().c_str() ); -#endif //ICON_VERBOSE - // Do not refresh too quickly + g_message("%s Deferring refresh as too soon. calling queueRefresh()", getTimestr().c_str()); +#endif // ICON_VERBOSE + // Do not refresh too quickly queueRefresh(); } else if (document) { #if ICON_VERBOSE - g_message( "%s Refreshing preview.", getTimestr().c_str() ); + g_message("%s Refreshing preview.", getTimestr().c_str()); #endif // ICON_VERBOSE bool hold = Inkscape::Preferences::get()->getBool("/iconpreview/selectionHold", true); SPObject *target = nullptr; - if ( selectionButton && selectionButton->get_active() ) - { - target = (hold && !targetId.empty()) ? document->getObjectById( targetId.c_str() ) : nullptr; - if ( !target ) { + if (selectionButton && selectionButton->get_active()) { + target = (hold && !targetId.empty()) ? document->getObjectById(targetId.c_str()) : nullptr; + if (!target) { targetId.clear(); if (auto selection = getSelection()) { for (auto item : selection->items()) { @@ -343,7 +331,7 @@ void IconPreviewPanel::refreshPreview() renderPreview(target); } #if ICON_VERBOSE - g_message( "%s resetting timer", getTimestr().c_str() ); + g_message("%s resetting timer", getTimestr().c_str()); #endif // ICON_VERBOSE timer->reset(); } @@ -355,14 +343,14 @@ bool IconPreviewPanel::refreshCB() if (!timer) { timer = new Glib::Timer(); } - if ( timer->elapsed() > minDelay ) { + if (timer->elapsed() > minDelay) { #if ICON_VERBOSE - g_message( "%s refreshCB() timer has progressed", getTimestr().c_str() ); + g_message("%s refreshCB() timer has progressed", getTimestr().c_str()); #endif // ICON_VERBOSE callAgain = false; refreshPreview(); #if ICON_VERBOSE - g_message( "%s refreshCB() setting pending false", getTimestr().c_str() ); + g_message("%s refreshCB() setting pending false", getTimestr().c_str()); #endif // ICON_VERBOSE pending = false; } @@ -374,12 +362,12 @@ void IconPreviewPanel::queueRefresh() if (!pending) { pending = true; #if ICON_VERBOSE - g_message( "%s queueRefresh() Setting pending true", getTimestr().c_str() ); + g_message("%s queueRefresh() Setting pending true", getTimestr().c_str()); #endif // ICON_VERBOSE if (!timer) { timer = new Glib::Timer(); } - Glib::signal_idle().connect( sigc::mem_fun(this, &IconPreviewPanel::refreshCB), Glib::PRIORITY_DEFAULT_IDLE ); + Glib::signal_idle().connect(sigc::mem_fun(this, &IconPreviewPanel::refreshCB), Glib::PRIORITY_DEFAULT_IDLE); } } @@ -388,40 +376,37 @@ void IconPreviewPanel::modeToggled() Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool selectionOnly = (selectionButton && selectionButton->get_active()); prefs->setBool("/iconpreview/selectionOnly", selectionOnly); - if ( !selectionOnly ) { + if (!selectionOnly) { targetId.clear(); } refreshPreview(); } - - - -void IconPreviewPanel::renderPreview( SPObject* obj ) +void IconPreviewPanel::renderPreview(SPObject *obj) { - SPDocument * doc = obj->document; - gchar const * id = obj->getId(); - if ( !renderTimer ) { + SPDocument *doc = obj->document; + gchar const *id = obj->getId(); + if (!renderTimer) { renderTimer = new Glib::Timer(); } renderTimer->reset(); #if ICON_VERBOSE - g_message("%s setting up to render '%s' as the icon", getTimestr().c_str(), id ); + g_message("%s setting up to render '%s' as the icon", getTimestr().c_str(), id); #endif // ICON_VERBOSE - for ( int i = 0; i < numEntries; i++ ) { + for (int i = 0; i < numEntries; i++) { unsigned unused; int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, sizes[i]); guchar *px = Inkscape::UI::PREVIEW::sp_icon_doc_icon(doc, *drawing, id, sizes[i], unused); -// g_message( " size %d %s", sizes[i], (px ? "worked" : "failed") ); - if ( px ) { - memcpy( pixMem[i], px, sizes[i] * stride ); - g_free( px ); + // g_message( " size %d %s", sizes[i], (px ? "worked" : "failed") ); + if (px) { + memcpy(pixMem[i], px, sizes[i] * stride); + g_free(px); px = nullptr; } else { - memset( pixMem[i], 0, sizes[i] * stride ); + memset(pixMem[i], 0, sizes[i] * stride); } images[i]->set(images[i]->get_pixbuf()); // images[i]->queue_draw(); @@ -432,7 +417,7 @@ void IconPreviewPanel::renderPreview( SPObject* obj ) updateMagnify(); renderTimer->stop(); - minDelay = std::max( 0.1, renderTimer->elapsed() * 3.0 ); + minDelay = std::max(0.1, renderTimer->elapsed() * 3.0); #if ICON_VERBOSE g_message(" render took %f seconds.", renderTimer->elapsed()); #endif // ICON_VERBOSE @@ -440,16 +425,16 @@ void IconPreviewPanel::renderPreview( SPObject* obj ) void IconPreviewPanel::updateMagnify() { - Glib::RefPtr<Gdk::Pixbuf> buf = images[hot]->get_pixbuf()->scale_simple( 128, 128, Gdk::INTERP_NEAREST ); - magLabel.set_label( *labels[hot] ); - magnified.set( buf ); + Glib::RefPtr<Gdk::Pixbuf> buf = images[hot]->get_pixbuf()->scale_simple(128, 128, Gdk::INTERP_NEAREST); + magLabel.set_label(*labels[hot]); + magnified.set(buf); // magnified.queue_draw(); // magnified.get_parent()->queue_draw(); } -} //namespace Dialogs -} //namespace UI -} //namespace Inkscape +} // namespace Dialog +} // namespace UI +} // namespace Inkscape /* Local Variables: -- GitLab From 2da1eca36c46a39d6bd8c53a66bbb46bd92f5630 Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Sun, 29 Aug 2021 22:43:25 +0530 Subject: [PATCH 39/40] fixed typo in header --- src/ui/dialog/preview-util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ui/dialog/preview-util.h b/src/ui/dialog/preview-util.h index e2d6504437..2bcd755fa4 100644 --- a/src/ui/dialog/preview-util.h +++ b/src/ui/dialog/preview-util.h @@ -20,7 +20,7 @@ #ifndef SP_PREVIEW_UTIL_H #define SP_PREVIEW_UTIL_H -#include <glibmm/main.h>u +#include <glibmm/main.h> #include "desktop.h" #include "display/drawing.h" -- GitLab From a1cb627875e791871aa4394c9c31778e257dd52b Mon Sep 17 00:00:00 2001 From: Anshudhar <anshudhar2001@gmail.com> Date: Mon, 30 Aug 2021 17:42:48 +0530 Subject: [PATCH 40/40] Changed dpi to 2 decimal places --- share/ui/dialog-export.glade | 1 + src/ui/dialog/export-helper.cpp | 4 ++-- src/ui/dialog/export-single.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/share/ui/dialog-export.glade b/share/ui/dialog-export.glade index 903682dad9..ff23a4709e 100644 --- a/share/ui/dialog-export.glade +++ b/share/ui/dialog-export.glade @@ -301,6 +301,7 @@ <object class="GtkBox" id="si_advance_box"> <property name="visible">True</property> <property name="can-focus">False</property> + <property name="no-show-all">True</property> <property name="orientation">vertical</property> <child> <placeholder/> diff --git a/src/ui/dialog/export-helper.cpp b/src/ui/dialog/export-helper.cpp index 1359d19f51..34ca75b9a0 100644 --- a/src/ui/dialog/export-helper.cpp +++ b/src/ui/dialog/export-helper.cpp @@ -293,8 +293,8 @@ void ExportList::append_row() extension->show(); SpinButton *dpi_sb = Gtk::manage(new SpinButton()); - dpi_sb->set_digits(0); - dpi_sb->set_increments(1.0, 1.0); + dpi_sb->set_digits(2); + dpi_sb->set_increments(0.1, 1.0); dpi_sb->set_range(1.0, 100000.0); dpi_sb->set_value(default_dpi); dpi_sb->set_sensitive(true); diff --git a/src/ui/dialog/export-single.cpp b/src/ui/dialog/export-single.cpp index 7ce4690c3b..757560e71d 100644 --- a/src/ui/dialog/export-single.cpp +++ b/src/ui/dialog/export-single.cpp @@ -255,7 +255,7 @@ void SingleExport::setupSpinButtons() setupSpinButton<sb_type>(spin_buttons[SPIN_BMWIDTH], 1.0, 1.0, 1000000.0, 1.0, 10.0, 0, true, &SingleExport::onDpiChange, SPIN_BMWIDTH); setupSpinButton<sb_type>(spin_buttons[SPIN_DPI], prefs->getDouble("/dialogs/export/defaultxdpi/value", DPI_BASE), - 1.0, 100000.0, 1.0, 1.0, 0, true, &SingleExport::onDpiChange, SPIN_DPI); + 1.0, 100000.0, 0.1, 1.0, 2, true, &SingleExport::onDpiChange, SPIN_DPI); } template <typename T> -- GitLab