index 07052559d38fa5a281149d648d739f55545b3088..2a5ededbb475bf88fd9f0f35b722587cb484a9fd 100644 (file)
-/*
+/**
* Implementation of the file dialog interfaces defined in filedialog.h
*
* Authors:
* Bob Jamison
* Other dudes from The Inkscape Organization
*
* Implementation of the file dialog interfaces defined in filedialog.h
*
* Authors:
* Bob Jamison
* Other dudes from The Inkscape Organization
*
- * Copyright (C) 2004 The Inkscape Organization
+ * Copyright (C) 2004-2007 Bob Jamison
+ * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>
+ * Copyright (C) 2004-2007 The Inkscape Organization
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
+//General includes
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <set>
-
+//Gtk includes
+#include <gtkmm.h>
+#include <glibmm/i18n.h>
+#include <glib/gstdio.h>
//Temporary ugly hack
//Temporary ugly hack
-//Remove these after the get_filter() calls in
+//Remove this after the get_filter() calls in
//show() on both classes are fixed
#include <gtk/gtkfilechooser.h>
//show() on both classes are fixed
#include <gtk/gtkfilechooser.h>
-
//Another hack
#include <gtk/gtkentry.h>
#include <gtk/gtkexpander.h>
//Another hack
#include <gtk/gtkentry.h>
#include <gtk/gtkexpander.h>
+#ifdef WITH_GNOME_VFS
+# include <libgnomevfs/gnome-vfs-init.h> // gnome_vfs_initialized
+#endif
-#include <unistd.h>
-#include <sys/stat.h>
-#include <glibmm/i18n.h>
-#include <gtkmm/box.h>
-#include <gtkmm/filechooserdialog.h>
-#include <gtkmm/menubar.h>
-#include <gtkmm/menu.h>
-#include <gtkmm/entry.h>
-#include <gtkmm/expander.h>
-#include <gtkmm/comboboxtext.h>
-#include <gtkmm/stock.h>
-#include <gdkmm/pixbuf.h>
+
+//Inkscape includes
#include "prefs-utils.h"
#include <dialogs/dialog-events.h>
#include <extension/input.h>
#include "prefs-utils.h"
#include <dialogs/dialog-events.h>
#include <extension/input.h>
#include "filedialog.h"
#include "gc-core.h"
#include "filedialog.h"
#include "gc-core.h"
+//For export dialog
+#include "ui/widget/scalar-unit.h"
+
+
+//Routines from file.cpp
#undef INK_DUMP_FILENAME_CONV
#ifdef INK_DUMP_FILENAME_CONV
#undef INK_DUMP_FILENAME_CONV
#ifdef INK_DUMP_FILENAME_CONV
void dump_ustr( const Glib::ustring& ustr );
#endif
void dump_ustr( const Glib::ustring& ustr );
#endif
-namespace Inkscape {
-namespace UI {
-namespace Dialog {
-void FileDialogExtensionToPattern (Glib::ustring &pattern, gchar * in_file_extension);
+
+namespace Inkscape
+{
+namespace UI
+{
+namespace Dialog
+{
+
+
+
+
+
+//########################################################################
+//### U T I L I T Y
+//########################################################################
+
+/**
+ \brief A quick function to turn a standard extension into a searchable
+ pattern for the file dialogs
+ \param pattern The patter that the extension should be written to
+ \param in_file_extension The C string that represents the extension
+
+ This function just goes through the string, and takes all characters
+ and puts a [<upper><lower>] so that both are searched and shown in
+ the file dialog. This function edits the pattern string to make
+ this happen.
+*/
+static void
+fileDialogExtensionToPattern(Glib::ustring &pattern,
+ Glib::ustring &extension)
+{
+ for (unsigned int i = 0; i < extension.length(); i++ )
+ {
+ Glib::ustring::value_type ch = extension[i];
+ if ( Glib::Unicode::isalpha(ch) )
+ {
+ pattern += '[';
+ pattern += Glib::Unicode::toupper(ch);
+ pattern += Glib::Unicode::tolower(ch);
+ pattern += ']';
+ }
+ else
+ {
+ pattern += ch;
+ }
+ }
+}
+
+
+/**
+ * Hack: Find all entry widgets in a container
+ */
+static void
+findEntryWidgets(Gtk::Container *parent,
+ std::vector<Gtk::Entry *> &result)
+{
+ if (!parent)
+ return;
+ std::vector<Gtk::Widget *> children = parent->get_children();
+ for (unsigned int i=0; i<children.size() ; i++)
+ {
+ Gtk::Widget *child = children[i];
+ GtkWidget *wid = child->gobj();
+ if (GTK_IS_ENTRY(wid))
+ result.push_back((Gtk::Entry *)child);
+ else if (GTK_IS_CONTAINER(wid))
+ findEntryWidgets((Gtk::Container *)child, result);
+ }
+
+}
+
+
+
+
+/**
+ * Hack: Find all expander widgets in a container
+ */
+static void
+findExpanderWidgets(Gtk::Container *parent,
+ std::vector<Gtk::Expander *> &result)
+{
+ if (!parent)
+ return;
+ std::vector<Gtk::Widget *> children = parent->get_children();
+ for (unsigned int i=0; i<children.size() ; i++)
+ {
+ Gtk::Widget *child = children[i];
+ GtkWidget *wid = child->gobj();
+ if (GTK_IS_EXPANDER(wid))
+ result.push_back((Gtk::Expander *)child);
+ else if (GTK_IS_CONTAINER(wid))
+ findExpanderWidgets((Gtk::Container *)child, result);
+ }
+
+}
+
/*#########################################################################
### SVG Preview Widget
#########################################################################*/
/*#########################################################################
### SVG Preview Widget
#########################################################################*/
+
/**
* Simple class for displaying an SVG file in the "preview widget."
* Currently, this is just a wrapper of the sp_svg_view Gtk widget.
/**
* Simple class for displaying an SVG file in the "preview widget."
* Currently, this is just a wrapper of the sp_svg_view Gtk widget.
class SVGPreview : public Gtk::VBox
{
public:
class SVGPreview : public Gtk::VBox
{
public:
+
SVGPreview();
SVGPreview();
+
~SVGPreview();
bool setDocument(SPDocument *doc);
~SVGPreview();
bool setDocument(SPDocument *doc);
document = doc;
//This should remove it from the box, and free resources
document = doc;
//This should remove it from the box, and free resources
- if (viewerGtk) {
+ if (viewerGtk)
gtk_widget_destroy(viewerGtk);
gtk_widget_destroy(viewerGtk);
- }
viewerGtk = sp_svg_view_widget_new(doc);
GtkWidget *vbox = (GtkWidget *)gobj();
viewerGtk = sp_svg_view_widget_new(doc);
GtkWidget *vbox = (GtkWidget *)gobj();
return true;
}
return true;
}
+
bool SVGPreview::setFileName(Glib::ustring &theFileName)
{
Glib::ustring fileName = theFileName;
fileName = Glib::filename_to_utf8(fileName);
bool SVGPreview::setFileName(Glib::ustring &theFileName)
{
Glib::ustring fileName = theFileName;
fileName = Glib::filename_to_utf8(fileName);
- SPDocument *doc = sp_document_new (fileName.c_str(), 0);
+ /**
+ * I don't know why passing false to keepalive is bad. But it
+ * prevents the display of an svg with a non-ascii filename
+ */
+ SPDocument *doc = sp_document_new (fileName.c_str(), true);
if (!doc) {
g_warning("SVGView: error loading document '%s'\n", fileName.c_str());
return false;
if (!doc) {
g_warning("SVGView: error loading document '%s'\n", fileName.c_str());
return false;
"<svg\n"
"xmlns=\"http://www.w3.org/2000/svg\"\n"
"xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
"<svg\n"
"xmlns=\"http://www.w3.org/2000/svg\"\n"
"xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
- "width=\"%d\" height=\"%d\">\n"
+ "width=\"%d\" height=\"%d\">\n" //# VALUES HERE
"<rect\n"
" style=\"fill:#eeeeee;stroke:none\"\n"
" x=\"-100\" y=\"-100\" width=\"4000\" height=\"4000\"/>\n"
"<rect\n"
" style=\"fill:#eeeeee;stroke:none\"\n"
" x=\"-100\" y=\"-100\" width=\"4000\" height=\"4000\"/>\n"
" style=\"font-size:24.000000;font-style:normal;font-weight:normal;"
" fill:#000000;fill-opacity:1.0000000;stroke:none;"
" font-family:Bitstream Vera Sans\"\n"
" style=\"font-size:24.000000;font-style:normal;font-weight:normal;"
" fill:#000000;fill-opacity:1.0000000;stroke:none;"
" font-family:Bitstream Vera Sans\"\n"
- " x=\"10\" y=\"26\">%d x %d</text>\n"
+ " x=\"10\" y=\"26\">%d x %d</text>\n" //# VALUES HERE
"</svg>\n\n";
//if (!Glib::get_charset()) //If we are not utf8
"</svg>\n\n";
//if (!Glib::get_charset()) //If we are not utf8
"<svg\n"
"xmlns=\"http://www.w3.org/2000/svg\"\n"
"xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
"<svg\n"
"xmlns=\"http://www.w3.org/2000/svg\"\n"
"xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
- "width=\"%d\" height=\"%d\">\n"
+ "width=\"%d\" height=\"%d\">\n" //# VALUES HERE
"<g transform=\"translate(-190,24.27184)\" style=\"opacity:0.12\">\n"
"<path\n"
"style=\"font-size:12;fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:0.936193pt\"\n"
"<g transform=\"translate(-190,24.27184)\" style=\"opacity:0.12\">\n"
"<path\n"
"style=\"font-size:12;fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:0.936193pt\"\n"
"font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;"
"stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
"font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr\"\n"
"font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;"
"stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
"font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr\"\n"
- "x=\"190\" y=\"240\">%s</text></g>\n"
+ "x=\"190\" y=\"240\">%s</text></g>\n" //# VALUE HERE
"</svg>\n\n";
//Fill in the template
"</svg>\n\n";
//Fill in the template
}
}
+
+/**
+ * Inform the user that the svg file is too large to be displayed.
+ * This does not check for sizes of embedded images (yet)
+ */
void SVGPreview::showTooLarge(long fileLength)
{
void SVGPreview::showTooLarge(long fileLength)
{
"<svg\n"
"xmlns=\"http://www.w3.org/2000/svg\"\n"
"xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
"<svg\n"
"xmlns=\"http://www.w3.org/2000/svg\"\n"
"xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
- "width=\"%d\" height=\"%d\">\n"
+ "width=\"%d\" height=\"%d\">\n" //# VALUES HERE
"<g transform=\"translate(-170,24.27184)\" style=\"opacity:0.12\">\n"
"<path\n"
"style=\"font-size:12;fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:0.936193pt\"\n"
"<g transform=\"translate(-170,24.27184)\" style=\"opacity:0.12\">\n"
"<path\n"
"style=\"font-size:12;fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:0.936193pt\"\n"
"font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;"
"stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
"font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr\"\n"
"font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;"
"stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
"font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr\"\n"
- "x=\"170\" y=\"215\">%5.1f MB</text>\n"
+ "x=\"170\" y=\"215\">%5.1f MB</text>\n" //# VALUE HERE
"<text xml:space=\"preserve\"\n"
"style=\"font-size:24.000000;font-style:normal;font-variant:normal;font-weight:bold;"
"font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;"
"stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
"font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr\"\n"
"<text xml:space=\"preserve\"\n"
"style=\"font-size:24.000000;font-style:normal;font-variant:normal;font-weight:bold;"
"font-stretch:normal;fill:#000000;fill-opacity:1.0000000;stroke:none;stroke-width:1.0000000pt;"
"stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1.0000000;"
"font-family:Bitstream Vera Sans;text-anchor:middle;writing-mode:lr\"\n"
- "x=\"180\" y=\"245\">%s</text>\n"
+ "x=\"180\" y=\"245\">%s</text>\n" //# VALUE HERE
"</svg>\n\n";
//Fill in the template
"</svg>\n\n";
//Fill in the template
}
}
+
+/**
+ * Return true if the string ends with the given suffix
+ */
static bool
hasSuffix(Glib::ustring &str, Glib::ustring &ext)
{
int strLen = str.length();
int extLen = ext.length();
if (extLen > strLen)
static bool
hasSuffix(Glib::ustring &str, Glib::ustring &ext)
{
int strLen = str.length();
int extLen = ext.length();
if (extLen > strLen)
- {
return false;
return false;
- }
int strpos = strLen-1;
for (int extpos = extLen-1 ; extpos>=0 ; extpos--, strpos--)
int strpos = strLen-1;
for (int extpos = extLen-1 ; extpos>=0 ; extpos--, strpos--)
- {
+ {
Glib::ustring::value_type ch = str[strpos];
if (ch != ext[extpos])
Glib::ustring::value_type ch = str[strpos];
if (ch != ext[extpos])
- {
+ {
if ( ((ch & 0xff80) != 0) ||
static_cast<Glib::ustring::value_type>( g_ascii_tolower( static_cast<gchar>(0x07f & ch) ) ) != ext[extpos] )
if ( ((ch & 0xff80) != 0) ||
static_cast<Glib::ustring::value_type>( g_ascii_tolower( static_cast<gchar>(0x07f & ch) ) ) != ext[extpos] )
- {
+ {
return false;
return false;
+ }
}
}
}
}
- }
return true;
}
return true;
}
{
Glib::ustring ext = extensions[j];
if (hasSuffix(fileName, ext))
{
Glib::ustring ext = extensions[j];
if (hasSuffix(fileName, ext))
- {
return true;
return true;
- }
}
}
return false;
}
}
return false;
if (!Glib::file_test(fileName, Glib::FILE_TEST_EXISTS))
return false;
if (!Glib::file_test(fileName, Glib::FILE_TEST_EXISTS))
return false;
- gchar *fName = (gchar *)fileName.c_str();
- //g_message("fname:%s\n", fName);
+ //g_message("fname:%s", fileName.c_str());
+ if (Glib::file_test(fileName, Glib::FILE_TEST_IS_DIR)) {
+ showNoPreview();
+ return false;
+ }
if (Glib::file_test(fileName, Glib::FILE_TEST_IS_REGULAR))
{
if (Glib::file_test(fileName, Glib::FILE_TEST_IS_REGULAR))
{
+ Glib::ustring fileNameUtf8 = Glib::filename_to_utf8(fileName);
+ gchar *fName = (gchar *)fileNameUtf8.c_str();
struct stat info;
struct stat info;
- if (stat(fName, &info))
+ if (g_stat(fName, &info))
{
{
+ g_warning("SVGPreview::set() : %s : %s",
+ fName, strerror(errno));
return FALSE;
}
long fileLen = info.st_size;
return FALSE;
}
long fileLen = info.st_size;
return FALSE;
}
}
return FALSE;
}
}
-
+
Glib::ustring svg = ".svg";
Glib::ustring svgz = ".svgz";
if ((dialogType == SVG_TYPES || dialogType == IMPORT_TYPES) &&
(hasSuffix(fileName, svg) || hasSuffix(fileName, svgz) )
Glib::ustring svg = ".svg";
Glib::ustring svgz = ".svgz";
if ((dialogType == SVG_TYPES || dialogType == IMPORT_TYPES) &&
(hasSuffix(fileName, svg) || hasSuffix(fileName, svgz) )
- )
- {
+ ) {
bool retval = setFileName(fileName);
showingNoPreview = false;
return retval;
bool retval = setFileName(fileName);
showingNoPreview = false;
return retval;
- }
- else if (isValidImageFile(fileName))
- {
+ } else if (isValidImageFile(fileName)) {
showImage(fileName);
showingNoPreview = false;
return true;
showImage(fileName);
showingNoPreview = false;
return true;
- }
- else
- {
+ } else {
showNoPreview();
return false;
showNoPreview();
return false;
- }
+ }
}
}
/*#########################################################################
/*#########################################################################
-### F I L E O P E N
+### F I L E D I A L O G B A S E C L A S S
#########################################################################*/
/**
#########################################################################*/
/**
- * Our implementation class for the FileOpenDialog interface..
+ * This class is the base implementation for the others. This
+ * reduces redundancies and bugs.
*/
*/
-class FileOpenDialogImpl : public FileOpenDialog, public Gtk::FileChooserDialog
+class FileDialogBase : public Gtk::FileChooserDialog
{
public:
{
public:
- FileOpenDialogImpl(char const *dir,
- FileDialogType fileTypes,
- char const *title);
- virtual ~FileOpenDialogImpl();
-
- bool show();
+ /**
+ *
+ */
+ FileDialogBase(const Glib::ustring &title, FileDialogType type, gchar const* preferenceBase) :
+ Gtk::FileChooserDialog(title),
+ preferenceBase(preferenceBase ? preferenceBase : "unknown"),
+ dialogType(type)
+ {
+ internalSetup();
+ }
- Inkscape::Extension::Extension *getSelectionType();
+ /**
+ *
+ */
+ FileDialogBase(const Glib::ustring &title,
+ Gtk::FileChooserAction dialogType, FileDialogType type, gchar const* preferenceBase) :
+ Gtk::FileChooserDialog(title, dialogType),
+ preferenceBase(preferenceBase ? preferenceBase : "unknown"),
+ dialogType(type)
+ {
+ internalSetup();
+ }
- gchar *getFilename();
+ /**
+ *
+ */
+ virtual ~FileDialogBase()
+ {}
- Glib::SListHandle<Glib::ustring> getFilenames ();
protected:
protected:
+ void cleanup( bool showConfirmed );
-
-
-private:
-
-
+ Glib::ustring preferenceBase;
/**
* What type of 'open' are we? (open, import, place, etc)
*/
/**
* What type of 'open' are we? (open, import, place, etc)
*/
*/
SVGPreview svgPreview;
*/
SVGPreview svgPreview;
- /**
- * Callback for seeing if the preview needs to be drawn
- */
- void updatePreviewCallback();
+ //# Child widgets
+ Gtk::CheckButton previewCheckbox;
- /**
- * Fix to allow the user to type the file name
- */
- Gtk::Entry fileNameEntry;
+private:
+ void internalSetup();
/**
/**
- * Create a filter menu for this type of dialog
+ * Callback for user changing preview checkbox
*/
*/
- void createFilterMenu();
+ void _previewEnabledCB();
/**
/**
- * Callback for user input into fileNameEntry
+ * Callback for seeing if the preview needs to be drawn
*/
*/
- void fileNameEntryChangedCallback();
+ void _updatePreviewCallback();
+};
- /**
- * Callback for user changing which item is selected on the list
- */
- void fileSelectedCallback();
+void FileDialogBase::internalSetup()
+{
+ bool enablePreview =
+ (bool)prefs_get_int_attribute( preferenceBase.c_str(),
+ "enable_preview", 1 );
- /**
- * Filter name->extension lookup
- */
- std::map<Glib::ustring, Inkscape::Extension::Extension *> extensionMap;
+ previewCheckbox.set_label( Glib::ustring(_("Enable Preview")) );
+ previewCheckbox.set_active( enablePreview );
- /**
- * The extension to use to write this file
- */
- Inkscape::Extension::Extension *extension;
+ previewCheckbox.signal_toggled().connect(
+ sigc::mem_fun(*this, &FileDialogBase::_previewEnabledCB) );
- /**
- * Filename that was given
- */
- Glib::ustring myFilename;
+ //Catch selection-changed events, so we can adjust the text widget
+ signal_update_preview().connect(
+ sigc::mem_fun(*this, &FileDialogBase::_updatePreviewCallback) );
-};
+ //###### Add a preview widget
+ set_preview_widget(svgPreview);
+ set_preview_widget_active( enablePreview );
+ set_use_preview_label (false);
+
+}
+void FileDialogBase::cleanup( bool showConfirmed )
+{
+ if ( showConfirmed )
+ prefs_set_int_attribute( preferenceBase.c_str(),
+ "enable_preview", previewCheckbox.get_active() );
+}
+
+
+void FileDialogBase::_previewEnabledCB()
+{
+ bool enabled = previewCheckbox.get_active();
+ set_preview_widget_active(enabled);
+ if ( enabled ) {
+ _updatePreviewCallback();
+ }
+}
/**
* Callback for checking if the preview needs to be redrawn
*/
/**
* Callback for checking if the preview needs to be redrawn
*/
-void FileOpenDialogImpl::updatePreviewCallback()
+void FileDialogBase::_updatePreviewCallback()
{
Glib::ustring fileName = get_preview_filename();
{
Glib::ustring fileName = get_preview_filename();
- if (fileName.length() < 1)
+
+#ifdef WITH_GNOME_VFS
+ if ( fileName.empty() && gnome_vfs_initialized() ) {
+ fileName = get_preview_uri();
+ }
+#endif
+
+ if (fileName.empty()) {
return;
return;
+ }
+
svgPreview.set(fileName, dialogType);
}
svgPreview.set(fileName, dialogType);
}
-
-
+/*#########################################################################
+### F I L E O P E N
+#########################################################################*/
/**
/**
- * Callback for fileNameEntry widget
+ * Our implementation class for the FileOpenDialog interface..
*/
*/
-void FileOpenDialogImpl::fileNameEntryChangedCallback()
+class FileOpenDialogImpl : public FileOpenDialog, public FileDialogBase
{
{
- Glib::ustring fileName = fileNameEntry.get_text();
+public:
- // TODO remove this leak
- fileName = Glib::filename_from_utf8(fileName);
+ FileOpenDialogImpl(const Glib::ustring &dir,
+ FileDialogType fileTypes,
+ const Glib::ustring &title);
- //g_message("User hit return. Text is '%s'\n", fName.c_str());
+ virtual ~FileOpenDialogImpl();
- if (!Glib::path_is_absolute(fileName)) {
- //try appending to the current path
- // not this way: fileName = get_current_folder() + "/" + fName;
- std::vector<Glib::ustring> pathSegments;
- pathSegments.push_back( get_current_folder() );
- pathSegments.push_back( fileName );
- fileName = Glib::build_filename(pathSegments);
- }
+ bool show();
- //g_message("path:'%s'\n", fName.c_str());
+ Inkscape::Extension::Extension *getSelectionType();
- if (Glib::file_test(fileName, Glib::FILE_TEST_IS_DIR)) {
- set_current_folder(fileName);
- } else if (Glib::file_test(fileName, Glib::FILE_TEST_IS_REGULAR)) {
- //dialog with either (1) select a regular file or (2) cd to dir
- //simulate an 'OK'
- set_filename(fileName);
- response(Gtk::RESPONSE_OK);
- }
-}
+ Glib::ustring getFilename();
+ std::vector<Glib::ustring> getFilenames ();
+private:
+ /**
+ * Create a filter menu for this type of dialog
+ */
+ void createFilterMenu();
+
+ /**
+ * Filter name->extension lookup
+ */
+ std::map<Glib::ustring, Inkscape::Extension::Extension *> extensionMap;
+
+ /**
+ * The extension to use to write this file
+ */
+ Inkscape::Extension::Extension *extension;
+
+ /**
+ * Filename that was given
+ */
+ Glib::ustring myFilename;
+
+};
-/**
- * Callback for fileNameEntry widget
- */
-void FileOpenDialogImpl::fileSelectedCallback()
-{
- Glib::ustring fileName = get_filename();
- if (!Glib::get_charset()) //If we are not utf8
- fileName = Glib::filename_to_utf8(fileName);
- //g_message("User selected '%s'\n",
- // filename().c_str());
-#ifdef INK_DUMP_FILENAME_CONV
- ::dump_ustr( get_filename() );
-#endif
- fileNameEntry.set_text(fileName);
-}
if (imod->deactivated()) continue;
Glib::ustring upattern("*");
if (imod->deactivated()) continue;
Glib::ustring upattern("*");
- FileDialogExtensionToPattern (upattern, imod->get_extension());
+ Glib::ustring extension = imod->get_extension();
+ fileDialogExtensionToPattern(upattern, extension);
Gtk::FileFilter filter;
Glib::ustring uname(_(imod->get_filetypename()));
Gtk::FileFilter filter;
Glib::ustring uname(_(imod->get_filetypename()));
/**
* Constructor. Not called directly. Use the factory.
*/
/**
* Constructor. Not called directly. Use the factory.
*/
-FileOpenDialogImpl::FileOpenDialogImpl(char const *dir,
+FileOpenDialogImpl::FileOpenDialogImpl(const Glib::ustring &dir,
FileDialogType fileTypes,
FileDialogType fileTypes,
- char const *title) :
- Gtk::FileChooserDialog(Glib::ustring(title))
+ const Glib::ustring &title) :
+ FileDialogBase(title, fileTypes, "dialogs.open")
{
{
/* And also Multiple Files */
set_select_multiple(true);
/* And also Multiple Files */
set_select_multiple(true);
- /* Initalize to Autodetect */
+#ifdef WITH_GNOME_VFS
+ if (gnome_vfs_initialized()) {
+ set_local_only(false);
+ }
+#endif
+
+ /* Initalize to Autodetect */
extension = NULL;
/* No filename to start out with */
myFilename = "";
extension = NULL;
/* No filename to start out with */
myFilename = "";
/* Set the pwd and/or the filename */
/* Set the pwd and/or the filename */
- if (dir != NULL)
- {
+ if (dir.size() > 0)
+ {
Glib::ustring udir(dir);
Glib::ustring::size_type len = udir.length();
// leaving a trailing backslash on the directory name leads to the infamous
// double-directory bug on win32
if (len != 0 && udir[len - 1] == '\\') udir.erase(len - 1);
set_current_folder(udir.c_str());
Glib::ustring udir(dir);
Glib::ustring::size_type len = udir.length();
// leaving a trailing backslash on the directory name leads to the infamous
// double-directory bug on win32
if (len != 0 && udir[len - 1] == '\\') udir.erase(len - 1);
set_current_folder(udir.c_str());
- }
-
- //###### Add the file types menu
- createFilterMenu();
-
- //###### Add a preview widget
- set_preview_widget(svgPreview);
- set_preview_widget_active(true);
- set_use_preview_label (false);
+ }
- //Catch selection-changed events, so we can adjust the text widget
- signal_update_preview().connect(
- sigc::mem_fun(*this, &FileOpenDialogImpl::updatePreviewCallback) );
+ set_extra_widget( previewCheckbox );
- //###### Add a text entry bar, and tie it to file chooser events
- fileNameEntry.set_text(get_current_folder());
- set_extra_widget(fileNameEntry);
- fileNameEntry.grab_focus();
- //Catch when user hits [return] on the text field
- fileNameEntry.signal_activate().connect(
- sigc::mem_fun(*this, &FileOpenDialogImpl::fileNameEntryChangedCallback) );
+ //###### Add the file types menu
+ createFilterMenu();
- //Catch selection-changed events, so we can adjust the text widget
- signal_selection_changed().connect(
- sigc::mem_fun(*this, &FileOpenDialogImpl::fileSelectedCallback) );
add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
- add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK);
-
+ set_default(*add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK));
}
}
/**
* Public factory. Called by file.cpp, among others.
*/
/**
* Public factory. Called by file.cpp, among others.
*/
-FileOpenDialog *FileOpenDialog::create(char const *path,
+FileOpenDialog *FileOpenDialog::create(const Glib::ustring &path,
FileDialogType fileTypes,
FileDialogType fileTypes,
- char const *title)
+ const Glib::ustring &title)
{
FileOpenDialog *dialog = new FileOpenDialogImpl(path, fileTypes, title);
return dialog;
{
FileOpenDialog *dialog = new FileOpenDialogImpl(path, fileTypes, title);
return dialog;
extension = extensionMap[gtk_file_filter_get_name(filter)];
}
myFilename = get_filename();
extension = extensionMap[gtk_file_filter_get_name(filter)];
}
myFilename = get_filename();
+#ifdef WITH_GNOME_VFS
+ if (myFilename.empty() && gnome_vfs_initialized())
+ myFilename = get_uri();
+#endif
+ cleanup( true );
return TRUE;
}
else
{
return TRUE;
}
else
{
+ cleanup( false );
return FALSE;
}
}
return FALSE;
}
}
/**
* Get the file name chosen by the user. Valid after an [OK]
*/
/**
* Get the file name chosen by the user. Valid after an [OK]
*/
-gchar *
+Glib::ustring
FileOpenDialogImpl::getFilename (void)
{
return g_strdup(myFilename.c_str());
FileOpenDialogImpl::getFilename (void)
{
return g_strdup(myFilename.c_str());
/**
* To Get Multiple filenames selected at-once.
*/
/**
* To Get Multiple filenames selected at-once.
*/
-Glib::SListHandle<Glib::ustring>FileOpenDialogImpl::getFilenames()
+std::vector<Glib::ustring>FileOpenDialogImpl::getFilenames()
{
{
- return get_filenames();
+ std::vector<Glib::ustring> result = get_filenames();
+#ifdef WITH_GNOME_VFS
+ if (result.empty() && gnome_vfs_initialized())
+ result = get_uris();
+#endif
+ return result;
}
}
-/*#########################################################################
-# F I L E S A V E
-#########################################################################*/
+//########################################################################
+//# F I L E S A V E
+//########################################################################
class FileType
{
class FileType
{
/**
* Our implementation of the FileSaveDialog interface.
*/
/**
* Our implementation of the FileSaveDialog interface.
*/
-class FileSaveDialogImpl : public FileSaveDialog, public Gtk::FileChooserDialog
+class FileSaveDialogImpl : public FileSaveDialog, public FileDialogBase
{
public:
{
public:
- FileSaveDialogImpl(char const *dir,
+ FileSaveDialogImpl(const Glib::ustring &dir,
FileDialogType fileTypes,
FileDialogType fileTypes,
- char const *title,
- char const *default_key);
+ const Glib::ustring &title,
+ const Glib::ustring &default_key);
virtual ~FileSaveDialogImpl();
bool show();
Inkscape::Extension::Extension *getSelectionType();
virtual ~FileSaveDialogImpl();
bool show();
Inkscape::Extension::Extension *getSelectionType();
+ virtual void setSelectionType( Inkscape::Extension::Extension * key );
- gchar *getFilename();
+ Glib::ustring getFilename();
+ void change_title(const Glib::ustring& title);
+ void change_path(const Glib::ustring& path);
+ void updateNameAndExtension();
private:
private:
- /**
- * What type of 'open' are we? (save, export, etc)
- */
- FileDialogType dialogType;
-
- /**
- * Our svg preview widget
- */
- SVGPreview svgPreview;
-
/**
* Fix to allow the user to type the file name
*/
Gtk::Entry *fileNameEntry;
/**
* Fix to allow the user to type the file name
*/
Gtk::Entry *fileNameEntry;
- /**
- * Callback for seeing if the preview needs to be drawn
- */
- void updatePreviewCallback();
-
-
-
- /**
- * Allow the specification of the output file type
- */
- Gtk::HBox fileTypeBox;
/**
* Allow the specification of the output file type
/**
* Allow the specification of the output file type
std::vector<FileType> fileTypes;
//# Child widgets
std::vector<FileType> fileTypes;
//# Child widgets
- Gtk::CheckButton fileTypeCheckbox;
+ Gtk::HBox childBox;
+ Gtk::VBox checksBox;
+ Gtk::CheckButton fileTypeCheckbox;
/**
* Callback for user input into fileNameEntry
/**
* Callback for user input into fileNameEntry
void createFileTypeMenu();
void createFileTypeMenu();
- bool append_extension;
-
/**
* The extension to use to write this file
*/
/**
* The extension to use to write this file
*/
* Filename that was given
*/
Glib::ustring myFilename;
* Filename that was given
*/
Glib::ustring myFilename;
-};
-
-
-
-
+ /**
+ * List of known file extensions.
+ */
+ std::set<Glib::ustring> knownExtensions;
+};
-/**
- * Callback for checking if the preview needs to be redrawn
- */
-void FileSaveDialogImpl::updatePreviewCallback()
-{
- Glib::ustring fileName = get_preview_filename();
- if (!fileName.c_str())
- return;
- bool retval = svgPreview.set(fileName, dialogType);
- set_preview_widget_active(retval);
-}
return;
FileType type = fileTypes[sel];
//g_message("selected: %s\n", type.name.c_str());
return;
FileType type = fileTypes[sel];
//g_message("selected: %s\n", type.name.c_str());
+
+ extension = type.extension;
Gtk::FileFilter filter;
filter.add_pattern(type.pattern);
set_filter(filter);
Gtk::FileFilter filter;
filter.add_pattern(type.pattern);
set_filter(filter);
+
+ updateNameAndExtension();
}
}
{
Inkscape::Extension::DB::OutputList extension_list;
Inkscape::Extension::db.get_output_list(extension_list);
{
Inkscape::Extension::DB::OutputList extension_list;
Inkscape::Extension::db.get_output_list(extension_list);
+ knownExtensions.clear();
for (Inkscape::Extension::DB::OutputList::iterator current_item = extension_list.begin();
current_item != extension_list.end(); current_item++)
for (Inkscape::Extension::DB::OutputList::iterator current_item = extension_list.begin();
current_item != extension_list.end(); current_item++)
FileType type;
type.name = (_(omod->get_filetypename()));
type.pattern = "*";
FileType type;
type.name = (_(omod->get_filetypename()));
type.pattern = "*";
- FileDialogExtensionToPattern (type.pattern, omod->get_extension());
+ Glib::ustring extension = omod->get_extension();
+ knownExtensions.insert( extension.casefold() );
+ fileDialogExtensionToPattern (type.pattern, extension);
type.extension= omod;
fileTypeComboBox.append_text(type.name);
fileTypes.push_back(type);
type.extension= omod;
fileTypeComboBox.append_text(type.name);
fileTypes.push_back(type);
}
}
-void findEntryWidgets(Gtk::Container *parent, std::vector<Gtk::Entry *> &result)
-{
- if (!parent)
- return;
- std::vector<Gtk::Widget *> children = parent->get_children();
- for (unsigned int i=0; i<children.size() ; i++)
- {
- Gtk::Widget *child = children[i];
- GtkWidget *wid = child->gobj();
- if (GTK_IS_ENTRY(wid))
- result.push_back((Gtk::Entry *)child);
- else if (GTK_IS_CONTAINER(wid))
- findEntryWidgets((Gtk::Container *)child, result);
- }
-
-}
-
-void findExpanderWidgets(Gtk::Container *parent, std::vector<Gtk::Expander *> &result)
-{
- if (!parent)
- return;
- std::vector<Gtk::Widget *> children = parent->get_children();
- for (unsigned int i=0; i<children.size() ; i++)
- {
- Gtk::Widget *child = children[i];
- GtkWidget *wid = child->gobj();
- if (GTK_IS_EXPANDER(wid))
- result.push_back((Gtk::Expander *)child);
- else if (GTK_IS_CONTAINER(wid))
- findExpanderWidgets((Gtk::Container *)child, result);
- }
-
-}
-
/**
* Constructor
*/
/**
* Constructor
*/
-FileSaveDialogImpl::FileSaveDialogImpl(char const *dir,
- FileDialogType fileTypes,
- char const *title,
- char const *default_key) :
- Gtk::FileChooserDialog(Glib::ustring(title),
- Gtk::FILE_CHOOSER_ACTION_SAVE)
+FileSaveDialogImpl::FileSaveDialogImpl(const Glib::ustring &dir,
+ FileDialogType fileTypes,
+ const Glib::ustring &title,
+ const Glib::ustring &default_key) :
+ FileDialogBase(title, Gtk::FILE_CHOOSER_ACTION_SAVE, fileTypes, "dialogs.save_as")
{
{
- append_extension = (bool)prefs_get_int_attribute("dialogs.save_as", "append_extension", 1);
-
/* One file at a time */
set_select_multiple(false);
/* One file at a time */
set_select_multiple(false);
+#ifdef WITH_GNOME_VFS
+ if (gnome_vfs_initialized()) {
+ set_local_only(false);
+ }
+#endif
+
/* Initalize to Autodetect */
extension = NULL;
/* No filename to start out with */
/* Initalize to Autodetect */
extension = NULL;
/* No filename to start out with */
dialogType = fileTypes;
/* Set the pwd and/or the filename */
dialogType = fileTypes;
/* Set the pwd and/or the filename */
- if (dir != NULL)
- {
+ if (dir.size() > 0)
+ {
Glib::ustring udir(dir);
Glib::ustring::size_type len = udir.length();
// leaving a trailing backslash on the directory name leads to the infamous
// double-directory bug on win32
if (len != 0 && udir[len - 1] == '\\') udir.erase(len - 1);
Glib::ustring udir(dir);
Glib::ustring::size_type len = udir.length();
// leaving a trailing backslash on the directory name leads to the infamous
// double-directory bug on win32
if (len != 0 && udir[len - 1] == '\\') udir.erase(len - 1);
- set_current_folder(udir.c_str());
- }
+ myFilename = udir;
+ }
//###### Add the file types menu
//createFilterMenu();
//###### Do we want the .xxx extension automatically added?
fileTypeCheckbox.set_label(Glib::ustring(_("Append filename extension automatically")));
//###### Add the file types menu
//createFilterMenu();
//###### Do we want the .xxx extension automatically added?
fileTypeCheckbox.set_label(Glib::ustring(_("Append filename extension automatically")));
- fileTypeCheckbox.set_active(append_extension);
+ fileTypeCheckbox.set_active( (bool)prefs_get_int_attribute("dialogs.save_as",
+ "append_extension", 1) );
- fileTypeBox.pack_start(fileTypeCheckbox);
createFileTypeMenu();
fileTypeComboBox.set_size_request(200,40);
fileTypeComboBox.signal_changed().connect(
sigc::mem_fun(*this, &FileSaveDialogImpl::fileTypeChangedCallback) );
createFileTypeMenu();
fileTypeComboBox.set_size_request(200,40);
fileTypeComboBox.signal_changed().connect(
sigc::mem_fun(*this, &FileSaveDialogImpl::fileTypeChangedCallback) );
- fileTypeBox.pack_start(fileTypeComboBox);
-
- set_extra_widget(fileTypeBox);
- //get_vbox()->pack_start(fileTypeBox, false, false, 0);
- //get_vbox()->reorder_child(fileTypeBox, 2);
-
- //###### Add a preview widget
- set_preview_widget(svgPreview);
- set_preview_widget_active(true);
- set_use_preview_label (false);
- //Catch selection-changed events, so we can adjust the text widget
- signal_update_preview().connect(
- sigc::mem_fun(*this, &FileSaveDialogImpl::updatePreviewCallback) );
+ childBox.pack_start( checksBox );
+ childBox.pack_end( fileTypeComboBox );
+ checksBox.pack_start( fileTypeCheckbox );
+ checksBox.pack_start( previewCheckbox );
+ set_extra_widget( childBox );
//Let's do some customization
fileNameEntry = NULL;
//Let's do some customization
fileNameEntry = NULL;
// checkbox.set_sensitive(FALSE);
add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
// checkbox.set_sensitive(FALSE);
add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
- add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK);
+ set_default(*add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK));
show_all_children();
}
show_all_children();
}
/**
* Public factory method. Used in file.cpp
*/
/**
* Public factory method. Used in file.cpp
*/
-FileSaveDialog *FileSaveDialog::create(char const *path,
+FileSaveDialog *FileSaveDialog::create(const Glib::ustring &path,
FileDialogType fileTypes,
FileDialogType fileTypes,
- char const *title,
- char const *default_key)
+ const Glib::ustring &title,
+ const Glib::ustring &default_key)
{
FileSaveDialog *dialog = new FileSaveDialogImpl(path, fileTypes, title, default_key);
return dialog;
{
FileSaveDialog *dialog = new FileSaveDialogImpl(path, fileTypes, title, default_key);
return dialog;
bool
FileSaveDialogImpl::show()
{
bool
FileSaveDialogImpl::show()
{
- Glib::ustring s = Glib::filename_to_utf8 (get_current_folder());
- if (s.length() == 0)
- s = getcwd (NULL, 0);
- set_current_folder(Glib::filename_from_utf8(s)); //hack to force initial dir listing
+ change_path(myFilename);
set_modal (TRUE); //Window
sp_transientize((GtkWidget *)gobj()); //Make transient
gint b = run(); //Dialog
set_modal (TRUE); //Window
sp_transientize((GtkWidget *)gobj()); //Make transient
gint b = run(); //Dialog
if (b == Gtk::RESPONSE_OK)
{
if (b == Gtk::RESPONSE_OK)
{
- int sel = fileTypeComboBox.get_active_row_number ();
- if (sel>=0 && sel< (int)fileTypes.size())
- {
- FileType &type = fileTypes[sel];
- extension = type.extension;
- }
- myFilename = get_filename();
-
- /*
+ updateNameAndExtension();
- // FIXME: Why do we have more code
+ // Store changes of the "Append filename automatically" checkbox back to preferences.
+ prefs_set_int_attribute("dialogs.save_as", "append_extension", fileTypeCheckbox.get_active());
- append_extension = checkbox.get_active();
- prefs_set_int_attribute("dialogs.save_as", "append_extension", append_extension);
+ // Store the last used save-as filetype to preferences.
prefs_set_string_attribute("dialogs.save_as", "default",
prefs_set_string_attribute("dialogs.save_as", "default",
- ( extension != NULL ? extension->get_id() : "" ));
- */
+ ( extension != NULL ? extension->get_id() : "" ));
+
+ cleanup( true );
+
return TRUE;
}
else
{
return TRUE;
}
else
{
+ cleanup( false );
+
return FALSE;
}
}
return FALSE;
}
}
return extension;
}
return extension;
}
+void FileSaveDialogImpl::setSelectionType( Inkscape::Extension::Extension * key )
+{
+ // If no pointer to extension is passed in, look up based on filename extension.
+ if ( !key ) {
+ // Not quite UTF-8 here.
+ gchar *filenameLower = g_ascii_strdown(myFilename.c_str(), -1);
+ for ( int i = 0; !key && (i < (int)fileTypes.size()); i++ ) {
+ Inkscape::Extension::Output *ext = dynamic_cast<Inkscape::Extension::Output*>(fileTypes[i].extension);
+ if ( ext && ext->get_extension() ) {
+ gchar *extensionLower = g_ascii_strdown( ext->get_extension(), -1 );
+ if ( g_str_has_suffix(filenameLower, extensionLower) ) {
+ key = fileTypes[i].extension;
+ }
+ g_free(extensionLower);
+ }
+ }
+ g_free(filenameLower);
+ }
+
+ // Ensure the proper entry in the combo box is selected.
+ if ( key ) {
+ extension = key;
+ gchar const * extensionID = extension->get_id();
+ if ( extensionID ) {
+ for ( int i = 0; i < (int)fileTypes.size(); i++ ) {
+ Inkscape::Extension::Extension *ext = fileTypes[i].extension;
+ if ( ext ) {
+ gchar const * id = ext->get_id();
+ if ( id && ( strcmp(extensionID, id) == 0) ) {
+ int oldSel = fileTypeComboBox.get_active_row_number();
+ if ( i != oldSel ) {
+ fileTypeComboBox.set_active(i);
+ }
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
/**
* Get the file name chosen by the user. Valid after an [OK]
*/
/**
* Get the file name chosen by the user. Valid after an [OK]
*/
-gchar *
+Glib::ustring
FileSaveDialogImpl::getFilename()
{
FileSaveDialogImpl::getFilename()
{
- return g_strdup(myFilename.c_str());
+ return myFilename;
}
}
-/**
- \brief A quick function to turn a standard extension into a searchable
- pattern for the file dialogs
- \param pattern The patter that the extension should be written to
- \param in_file_extension The C string that represents the extension
- This function just goes through the string, and takes all characters
- and puts a [<upper><lower>] so that both are searched and shown in
- the file dialog. This function edits the pattern string to make
- this happen.
-*/
-void
-FileDialogExtensionToPattern (Glib::ustring &pattern, gchar * in_file_extension)
+void
+FileSaveDialogImpl::change_title(const Glib::ustring& title)
{
{
- Glib::ustring tmp(in_file_extension);
+ this->set_title(title);
+}
- for ( guint i = 0; i < tmp.length(); i++ ) {
- Glib::ustring::value_type ch = tmp.at(i);
- if ( Glib::Unicode::isalpha(ch) ) {
- pattern += '[';
- pattern += Glib::Unicode::toupper(ch);
- pattern += Glib::Unicode::tolower(ch);
- pattern += ']';
+/**
+ * Change the default save path location.
+ */
+void
+FileSaveDialogImpl::change_path(const Glib::ustring& path)
+{
+ myFilename = path;
+ if (Glib::file_test(myFilename, Glib::FILE_TEST_IS_DIR)) {
+ //fprintf(stderr,"set_current_folder(%s)\n",myFilename.c_str());
+ set_current_folder(myFilename);
+ } else {
+ //fprintf(stderr,"set_filename(%s)\n",myFilename.c_str());
+ if ( Glib::file_test( myFilename, Glib::FILE_TEST_EXISTS ) ) {
+ set_filename(myFilename);
} else {
} else {
- pattern += ch;
+ std::string dirName = Glib::path_get_dirname( myFilename );
+ if ( dirName != get_current_folder() ) {
+ set_current_folder(dirName);
+ }
+ }
+ Glib::ustring basename = Glib::path_get_basename(myFilename);
+ //fprintf(stderr,"set_current_name(%s)\n",basename.c_str());
+ try {
+ set_current_name( Glib::filename_to_utf8(basename) );
+ } catch ( Glib::ConvertError& e ) {
+ g_warning( "Error converting save filename to UTF-8." );
+ // try a fallback.
+ set_current_name( basename );
+ }
+ }
+}
+
+void FileSaveDialogImpl::updateNameAndExtension()
+{
+ // Pick up any changes the user has typed in.
+ Glib::ustring tmp = get_filename();
+#ifdef WITH_GNOME_VFS
+ if ( tmp.empty() && gnome_vfs_initialized() ) {
+ tmp = get_uri();
+ }
+#endif
+ if ( !tmp.empty() ) {
+ myFilename = tmp;
+ }
+
+ Inkscape::Extension::Output* newOut = extension ? dynamic_cast<Inkscape::Extension::Output*>(extension) : 0;
+ if ( fileTypeCheckbox.get_active() && newOut ) {
+ try {
+ bool appendExtension = true;
+ Glib::ustring utf8Name = Glib::filename_to_utf8( myFilename );
+ Glib::ustring::size_type pos = utf8Name.rfind('.');
+ if ( pos != Glib::ustring::npos ) {
+ Glib::ustring trail = utf8Name.substr( pos );
+ Glib::ustring foldedTrail = trail.casefold();
+ if ( (trail == ".")
+ | (foldedTrail != Glib::ustring( newOut->get_extension() ).casefold()
+ && ( knownExtensions.find(foldedTrail) != knownExtensions.end() ) ) ) {
+ utf8Name = utf8Name.erase( pos );
+ } else {
+ appendExtension = false;
+ }
+ }
+
+ if (appendExtension) {
+ utf8Name = utf8Name + newOut->get_extension();
+ myFilename = Glib::filename_from_utf8( utf8Name );
+ change_path(myFilename);
+ }
+ } catch ( Glib::ConvertError& e ) {
+ // ignore
}
}
}
}
}
}
+
+
+//########################################################################
+//# F I L E E X P O R T
+//########################################################################
+
+
+/**
+ * Our implementation of the FileExportDialog interface.
+ */
+class FileExportDialogImpl : public FileExportDialog, public FileDialogBase
+{
+
+public:
+ FileExportDialogImpl(const Glib::ustring &dir,
+ FileDialogType fileTypes,
+ const Glib::ustring &title,
+ const Glib::ustring &default_key);
+
+ virtual ~FileExportDialogImpl();
+
+ bool show();
+
+ Inkscape::Extension::Extension *getSelectionType();
+
+ Glib::ustring getFilename();
+
+
+ /**
+ * Return the scope of the export. One of the enumerated types
+ * in ScopeType
+ */
+ ScopeType getScope()
+ {
+ if (pageButton.get_active())
+ return SCOPE_PAGE;
+ else if (selectionButton.get_active())
+ return SCOPE_SELECTION;
+ else if (customButton.get_active())
+ return SCOPE_CUSTOM;
+ else
+ return SCOPE_DOCUMENT;
+
+ }
+
+ /**
+ * Return left side of the exported region
+ */
+ double getSourceX()
+ { return sourceX0Spinner.getValue(); }
+
+ /**
+ * Return the top of the exported region
+ */
+ double getSourceY()
+ { return sourceY1Spinner.getValue(); }
+
+ /**
+ * Return the width of the exported region
+ */
+ double getSourceWidth()
+ { return sourceWidthSpinner.getValue(); }
+
+ /**
+ * Return the height of the exported region
+ */
+ double getSourceHeight()
+ { return sourceHeightSpinner.getValue(); }
+
+ /**
+ * Return the units of the coordinates of exported region
+ */
+ Glib::ustring getSourceUnits()
+ { return sourceUnitsSpinner.getUnitAbbr(); }
+
+ /**
+ * Return the width of the destination document
+ */
+ double getDestinationWidth()
+ { return destWidthSpinner.getValue(); }
+
+ /**
+ * Return the height of the destination document
+ */
+ double getDestinationHeight()
+ { return destHeightSpinner.getValue(); }
+
+ /**
+ * Return the height of the exported region
+ */
+ Glib::ustring getDestinationUnits()
+ { return destUnitsSpinner.getUnitAbbr(); }
+
+ /**
+ * Return the destination DPI image resulution, if bitmap
+ */
+ double getDestinationDPI()
+ { return destDPISpinner.getValue(); }
+
+ /**
+ * Return whether we should use Cairo for rendering
+ */
+ bool getUseCairo()
+ { return cairoButton.get_active(); }
+
+ /**
+ * Return whether we should use antialiasing
+ */
+ bool getUseAntialias()
+ { return antiAliasButton.get_active(); }
+
+ /**
+ * Return the background color for exporting
+ */
+ unsigned long getBackground()
+ { return backgroundButton.get_color().get_pixel(); }
+
+private:
+
+ /**
+ * Fix to allow the user to type the file name
+ */
+ Gtk::Entry *fileNameEntry;
+
+ //##########################################
+ //# EXTRA WIDGET -- SOURCE SIDE
+ //##########################################
+
+ Gtk::Frame sourceFrame;
+ Gtk::VBox sourceBox;
+
+ Gtk::HBox scopeBox;
+ Gtk::RadioButtonGroup scopeGroup;
+ Gtk::RadioButton documentButton;
+ Gtk::RadioButton pageButton;
+ Gtk::RadioButton selectionButton;
+ Gtk::RadioButton customButton;
+
+ Gtk::Table sourceTable;
+ Inkscape::UI::Widget::Scalar sourceX0Spinner;
+ Inkscape::UI::Widget::Scalar sourceY0Spinner;
+ Inkscape::UI::Widget::Scalar sourceX1Spinner;
+ Inkscape::UI::Widget::Scalar sourceY1Spinner;
+ Inkscape::UI::Widget::Scalar sourceWidthSpinner;
+ Inkscape::UI::Widget::Scalar sourceHeightSpinner;
+ Inkscape::UI::Widget::UnitMenu sourceUnitsSpinner;
+
+
+ //##########################################
+ //# EXTRA WIDGET -- DESTINATION SIDE
+ //##########################################
+
+ Gtk::Frame destFrame;
+ Gtk::VBox destBox;
+
+ Gtk::Table destTable;
+ Inkscape::UI::Widget::Scalar destWidthSpinner;
+ Inkscape::UI::Widget::Scalar destHeightSpinner;
+ Inkscape::UI::Widget::Scalar destDPISpinner;
+ Inkscape::UI::Widget::UnitMenu destUnitsSpinner;
+
+ Gtk::HBox otherOptionBox;
+ Gtk::CheckButton cairoButton;
+ Gtk::CheckButton antiAliasButton;
+ Gtk::ColorButton backgroundButton;
+
+
+ /**
+ * 'Extra' widget that holds two boxes above
+ */
+ Gtk::HBox exportOptionsBox;
+
+
+ //# Child widgets
+ Gtk::CheckButton fileTypeCheckbox;
+
+ /**
+ * Allow the specification of the output file type
+ */
+ Gtk::ComboBoxText fileTypeComboBox;
+
+
+ /**
+ * Data mirror of the combo box
+ */
+ std::vector<FileType> fileTypes;
+
+
+
+ /**
+ * Callback for user input into fileNameEntry
+ */
+ void fileTypeChangedCallback();
+
+ /**
+ * Create a filter menu for this type of dialog
+ */
+ void createFileTypeMenu();
+
+
+ bool append_extension;
+
+ /**
+ * The extension to use to write this file
+ */
+ Inkscape::Extension::Extension *extension;
+
+ /**
+ * Callback for user input into fileNameEntry
+ */
+ void fileNameEntryChangedCallback();
+
+ /**
+ * Filename that was given
+ */
+ Glib::ustring myFilename;
+};
+
+
+
+
+
+
+/**
+ * Callback for fileNameEntry widget
+ */
+void FileExportDialogImpl::fileNameEntryChangedCallback()
+{
+ if (!fileNameEntry)
+ return;
+
+ Glib::ustring fileName = fileNameEntry->get_text();
+ if (!Glib::get_charset()) //If we are not utf8
+ fileName = Glib::filename_to_utf8(fileName);
+
+ //g_message("User hit return. Text is '%s'\n", fileName.c_str());
+
+ if (!Glib::path_is_absolute(fileName)) {
+ //try appending to the current path
+ // not this way: fileName = get_current_folder() + "/" + fileName;
+ std::vector<Glib::ustring> pathSegments;
+ pathSegments.push_back( get_current_folder() );
+ pathSegments.push_back( fileName );
+ fileName = Glib::build_filename(pathSegments);
+ }
+
+ //g_message("path:'%s'\n", fileName.c_str());
+
+ if (Glib::file_test(fileName, Glib::FILE_TEST_IS_DIR)) {
+ set_current_folder(fileName);
+ } else if (/*Glib::file_test(fileName, Glib::FILE_TEST_IS_REGULAR)*/1) {
+ //dialog with either (1) select a regular file or (2) cd to dir
+ //simulate an 'OK'
+ set_filename(fileName);
+ response(Gtk::RESPONSE_OK);
+ }
+}
+
+
+
+/**
+ * Callback for fileNameEntry widget
+ */
+void FileExportDialogImpl::fileTypeChangedCallback()
+{
+ int sel = fileTypeComboBox.get_active_row_number();
+ if (sel<0 || sel >= (int)fileTypes.size())
+ return;
+ FileType type = fileTypes[sel];
+ //g_message("selected: %s\n", type.name.c_str());
+ Gtk::FileFilter filter;
+ filter.add_pattern(type.pattern);
+ set_filter(filter);
+}
+
+
+
+void FileExportDialogImpl::createFileTypeMenu()
+{
+ Inkscape::Extension::DB::OutputList extension_list;
+ Inkscape::Extension::db.get_output_list(extension_list);
+
+ for (Inkscape::Extension::DB::OutputList::iterator current_item = extension_list.begin();
+ current_item != extension_list.end(); current_item++)
+ {
+ Inkscape::Extension::Output * omod = *current_item;
+
+ // FIXME: would be nice to grey them out instead of not listing them
+ if (omod->deactivated()) continue;
+
+ FileType type;
+ type.name = (_(omod->get_filetypename()));
+ type.pattern = "*";
+ Glib::ustring extension = omod->get_extension();
+ fileDialogExtensionToPattern (type.pattern, extension);
+ type.extension= omod;
+ fileTypeComboBox.append_text(type.name);
+ fileTypes.push_back(type);
+ }
+
+ //#Let user choose
+ FileType guessType;
+ guessType.name = _("Guess from extension");
+ guessType.pattern = "*";
+ guessType.extension = NULL;
+ fileTypeComboBox.append_text(guessType.name);
+ fileTypes.push_back(guessType);
+
+
+ fileTypeComboBox.set_active(0);
+ fileTypeChangedCallback(); //call at least once to set the filter
+}
+
+
+/**
+ * Constructor
+ */
+FileExportDialogImpl::FileExportDialogImpl(const Glib::ustring &dir,
+ FileDialogType fileTypes,
+ const Glib::ustring &title,
+ const Glib::ustring &default_key) :
+ FileDialogBase(title, Gtk::FILE_CHOOSER_ACTION_SAVE, fileTypes, "dialogs.export"),
+ sourceX0Spinner("X0", _("Left edge of source")),
+ sourceY0Spinner("Y0", _("Top edge of source")),
+ sourceX1Spinner("X1", _("Right edge of source")),
+ sourceY1Spinner("Y1", _("Bottom edge of source")),
+ sourceWidthSpinner("Width", _("Source width")),
+ sourceHeightSpinner("Height", _("Source height")),
+ destWidthSpinner("Width", _("Destination width")),
+ destHeightSpinner("Height", _("Destination height")),
+ destDPISpinner("DPI", _("Resolution (dots per inch)"))
+{
+ append_extension = (bool)prefs_get_int_attribute("dialogs.save_as", "append_extension", 1);
+
+ /* One file at a time */
+ set_select_multiple(false);
+
+#ifdef WITH_GNOME_VFS
+ if (gnome_vfs_initialized()) {
+ set_local_only(false);
+ }
+#endif
+
+ /* Initalize to Autodetect */
+ extension = NULL;
+ /* No filename to start out with */
+ myFilename = "";
+
+ /* Set our dialog type (save, export, etc...)*/
+ dialogType = fileTypes;
+
+ /* Set the pwd and/or the filename */
+ if (dir.size()>0)
+ {
+ Glib::ustring udir(dir);
+ Glib::ustring::size_type len = udir.length();
+ // leaving a trailing backslash on the directory name leads to the infamous
+ // double-directory bug on win32
+ if (len != 0 && udir[len - 1] == '\\') udir.erase(len - 1);
+ set_current_folder(udir.c_str());
+ }
+
+ //#########################################
+ //## EXTRA WIDGET -- SOURCE SIDE
+ //#########################################
+
+ //##### Export options buttons/spinners, etc
+ documentButton.set_label(_("Document"));
+ scopeBox.pack_start(documentButton);
+ scopeGroup = documentButton.get_group();
+
+ pageButton.set_label(_("Page"));
+ pageButton.set_group(scopeGroup);
+ scopeBox.pack_start(pageButton);
+
+ selectionButton.set_label(_("Selection"));
+ selectionButton.set_group(scopeGroup);
+ scopeBox.pack_start(selectionButton);
+
+ customButton.set_label(_("Custom"));
+ customButton.set_group(scopeGroup);
+ scopeBox.pack_start(customButton);
+
+ sourceBox.pack_start(scopeBox);
+
+
+
+ //dimension buttons
+ sourceTable.resize(3,3);
+ sourceTable.attach(sourceX0Spinner, 0,1,0,1);
+ sourceTable.attach(sourceY0Spinner, 1,2,0,1);
+ sourceUnitsSpinner.setUnitType(UNIT_TYPE_LINEAR);
+ sourceTable.attach(sourceUnitsSpinner, 2,3,0,1);
+ sourceTable.attach(sourceX1Spinner, 0,1,1,2);
+ sourceTable.attach(sourceY1Spinner, 1,2,1,2);
+ sourceTable.attach(sourceWidthSpinner, 0,1,2,3);
+ sourceTable.attach(sourceHeightSpinner, 1,2,2,3);
+
+ sourceBox.pack_start(sourceTable);
+ sourceFrame.set_label(_("Source"));
+ sourceFrame.add(sourceBox);
+ exportOptionsBox.pack_start(sourceFrame);
+
+
+ //#########################################
+ //## EXTRA WIDGET -- SOURCE SIDE
+ //#########################################
+
+
+ destTable.resize(3,3);
+ destTable.attach(destWidthSpinner, 0,1,0,1);
+ destTable.attach(destHeightSpinner, 1,2,0,1);
+ destUnitsSpinner.setUnitType(UNIT_TYPE_LINEAR);
+ destTable.attach(destUnitsSpinner, 2,3,0,1);
+ destTable.attach(destDPISpinner, 0,1,1,2);
+
+ destBox.pack_start(destTable);
+
+
+ cairoButton.set_label(_("Cairo"));
+ otherOptionBox.pack_start(cairoButton);
+
+ antiAliasButton.set_label(_("Antialias"));
+ otherOptionBox.pack_start(antiAliasButton);
+
+ backgroundButton.set_label(_("Background"));
+ otherOptionBox.pack_start(backgroundButton);
+
+ destBox.pack_start(otherOptionBox);
+
+
+
+
+
+ //###### File options
+ //###### Do we want the .xxx extension automatically added?
+ fileTypeCheckbox.set_label(Glib::ustring(_("Append filename extension automatically")));
+ fileTypeCheckbox.set_active(append_extension);
+ destBox.pack_start(fileTypeCheckbox);
+
+ //###### File type menu
+ createFileTypeMenu();
+ fileTypeComboBox.set_size_request(200,40);
+ fileTypeComboBox.signal_changed().connect(
+ sigc::mem_fun(*this, &FileExportDialogImpl::fileTypeChangedCallback) );
+
+ destBox.pack_start(fileTypeComboBox);
+
+ destFrame.set_label(_("Destination"));
+ destFrame.add(destBox);
+ exportOptionsBox.pack_start(destFrame);
+
+ //##### Put the two boxes and their parent onto the dialog
+ exportOptionsBox.pack_start(sourceFrame);
+ exportOptionsBox.pack_start(destFrame);
+
+ set_extra_widget(exportOptionsBox);
+
+
+
+
+ //Let's do some customization
+ fileNameEntry = NULL;
+ Gtk::Container *cont = get_toplevel();
+ std::vector<Gtk::Entry *> entries;
+ findEntryWidgets(cont, entries);
+ //g_message("Found %d entry widgets\n", entries.size());
+ if (entries.size() >=1 )
+ {
+ //Catch when user hits [return] on the text field
+ fileNameEntry = entries[0];
+ fileNameEntry->signal_activate().connect(
+ sigc::mem_fun(*this, &FileExportDialogImpl::fileNameEntryChangedCallback) );
+ }
+
+ //Let's do more customization
+ std::vector<Gtk::Expander *> expanders;
+ findExpanderWidgets(cont, expanders);
+ //g_message("Found %d expander widgets\n", expanders.size());
+ if (expanders.size() >=1 )
+ {
+ //Always show the file list
+ Gtk::Expander *expander = expanders[0];
+ expander->set_expanded(true);
+ }
+
+
+ //if (extension == NULL)
+ // checkbox.set_sensitive(FALSE);
+
+ add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
+ set_default(*add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK));
+
+ show_all_children();
+}
+
+
+
+/**
+ * Public factory method. Used in file.cpp
+ */
+FileExportDialog *FileExportDialog::create(const Glib::ustring &path,
+ FileDialogType fileTypes,
+ const Glib::ustring &title,
+ const Glib::ustring &default_key)
+{
+ FileExportDialog *dialog = new FileExportDialogImpl(path, fileTypes, title, default_key);
+ return dialog;
+}
+
+
+
+
+
+/**
+ * Destructor
+ */
+FileExportDialogImpl::~FileExportDialogImpl()
+{
+}
+
+
+
+/**
+ * Show this dialog modally. Return true if user hits [OK]
+ */
+bool
+FileExportDialogImpl::show()
+{
+ Glib::ustring s = Glib::filename_to_utf8 (get_current_folder());
+ if (s.length() == 0)
+ s = getcwd (NULL, 0);
+ set_current_folder(Glib::filename_from_utf8(s)); //hack to force initial dir listing
+ set_modal (TRUE); //Window
+ sp_transientize((GtkWidget *)gobj()); //Make transient
+ gint b = run(); //Dialog
+ svgPreview.showNoPreview();
+ hide();
+
+ if (b == Gtk::RESPONSE_OK)
+ {
+ int sel = fileTypeComboBox.get_active_row_number ();
+ if (sel>=0 && sel< (int)fileTypes.size())
+ {
+ FileType &type = fileTypes[sel];
+ extension = type.extension;
+ }
+ myFilename = get_filename();
+#ifdef WITH_GNOME_VFS
+ if ( myFilename.empty() && gnome_vfs_initialized() ) {
+ myFilename = get_uri();
+ }
+#endif
+
+ /*
+
+ // FIXME: Why do we have more code
+
+ append_extension = checkbox.get_active();
+ prefs_set_int_attribute("dialogs.save_as", "append_extension", append_extension);
+ prefs_set_string_attribute("dialogs.save_as", "default",
+ ( extension != NULL ? extension->get_id() : "" ));
+ */
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+/**
+ * Get the file extension type that was selected by the user. Valid after an [OK]
+ */
+Inkscape::Extension::Extension *
+FileExportDialogImpl::getSelectionType()
+{
+ return extension;
+}
+
+
+/**
+ * Get the file name chosen by the user. Valid after an [OK]
+ */
+Glib::ustring
+FileExportDialogImpl::getFilename()
+{
+ return myFilename;
+}
+
+
+
+
} //namespace Dialog
} //namespace UI
} //namespace Inkscape
} //namespace Dialog
} //namespace UI
} //namespace Inkscape