Code

fix for crash bug 607557
[inkscape.git] / src / ui / dialog / filedialogimpl-gtkmm.cpp
index 6ad7179383abfd59df45d4311be59953a7c42b26..6f83a706faaa3d6475660db532972b34fcbdeeae 100644 (file)
@@ -1,7 +1,7 @@
-/**
- * Implementation of the file dialog interfaces defined in filedialogimpl.h
- *
- * Authors:
+/** @file
+ * @brief Implementation of the file dialog interfaces defined in filedialogimpl.h
+ */
+/* Authors:
  *   Bob Jamison
  *   Joel Holdsworth
  *   Bruno Dilly
@@ -9,8 +9,8 @@
  *
  * Copyright (C) 2004-2007 Bob Jamison
  * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>
+ * Copyright (C) 2007-2008 Joel Holdsworth
  * Copyright (C) 2004-2007 The Inkscape Organization
- * Copyright (C) 2007 Joel Holdsworth
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
@@ -24,6 +24,7 @@
 #include "interface.h"
 #include "io/sys.h"
 #include "path-prefix.h"
+#include "preferences.h"
 
 #ifdef WITH_GNOME_VFS
 # include <libgnomevfs/gnome-vfs.h>
@@ -205,7 +206,26 @@ void SVGPreview::showImage(Glib::ustring &theFileName)
     gint previewHeight = 600;
 
     //Get some image info. Smart pointer does not need to be deleted
-    Glib::RefPtr<Gdk::Pixbuf> img = Gdk::Pixbuf::create_from_file(fileName);
+    Glib::RefPtr<Gdk::Pixbuf> img(NULL);
+    try {
+        img = Gdk::Pixbuf::create_from_file(fileName);
+    }
+    catch (const Glib::FileError & e)
+    {
+        g_message("caught Glib::FileError in SVGPreview::showImage");
+        return;
+    }
+    catch (const Gdk::PixbufError & e)
+    {
+        g_message("Gdk::PixbufError in SVGPreview::showImage");
+        return;
+    }
+    catch (...)
+    {
+        g_message("Caught ... in SVGPreview::showImage");
+        return;
+    }
+
     gint imgWidth  = img->get_width();
     gint imgHeight = img->get_height();
 
@@ -251,7 +271,7 @@ void SVGPreview::showImage(Glib::ustring &theFileName)
           "<text\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"
+          "    font-family:Sans\"\n"
           "  x=\"10\" y=\"26\">%d x %d</text>\n" //# VALUES HERE
           "</svg>\n\n";
 
@@ -354,7 +374,7 @@ void SVGPreview::showNoPreview()
           "style=\"font-size:32.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"
+          "font-family:Sans;text-anchor:middle;writing-mode:lr\"\n"
           "x=\"190\" y=\"240\">%s</text></g>\n"  //# VALUE HERE
           "</svg>\n\n";
 
@@ -451,13 +471,13 @@ void SVGPreview::showTooLarge(long fileLength)
           "style=\"font-size:32.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"
+          "font-family:Sans;text-anchor:middle;writing-mode:lr\"\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"
+          "font-family:Sans;text-anchor:middle;writing-mode:lr\"\n"
           "x=\"180\" y=\"245\">%s</text>\n" //# VALUE HERE
           "</svg>\n\n";
 
@@ -476,55 +496,6 @@ void SVGPreview::showTooLarge(long fileLength)
 
 }
 
-
-/**
- * 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)
-        return false;
-    int strpos = strLen-1;
-    for (int extpos = extLen-1 ; extpos>=0 ; extpos--, strpos--)
-        {
-        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] )
-                {
-                return false;
-                }
-            }
-        }
-    return true;
-}
-
-
-/**
- * Return true if the image is loadable by Gdk, else false
- */
-static bool
-isValidImageFile(Glib::ustring &fileName)
-{
-    std::vector<Gdk::PixbufFormat>formats = Gdk::Pixbuf::get_formats();
-    for (unsigned int i=0; i<formats.size(); i++)
-        {
-        Gdk::PixbufFormat format = formats[i];
-        std::vector<Glib::ustring>extensions = format.get_extensions();
-        for (unsigned int j=0; j<extensions.size(); j++)
-            {
-            Glib::ustring ext = extensions[j];
-            if (hasSuffix(fileName, ext))
-                return true;
-            }
-        }
-    return false;
-}
-
 bool SVGPreview::set(Glib::ustring &fileName, int dialogType)
 {
 
@@ -550,7 +521,7 @@ bool SVGPreview::set(Glib::ustring &fileName, int dialogType)
             return FALSE;
             }
         long fileLen = info.st_size;
-        if (fileLen > 0x150000L)
+        if (fileLen > 0xA00000L)
             {
             showingNoPreview = false;
             showTooLarge(fileLen);
@@ -600,9 +571,8 @@ SVGPreview::~SVGPreview()
 
 void FileDialogBaseGtk::internalSetup()
 {
-    bool enablePreview =
-        (bool)prefs_get_int_attribute( preferenceBase.c_str(),
-             "enable_preview", 1 );
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    bool enablePreview = prefs->getBool( preferenceBase + "/enable_preview", true);
 
     previewCheckbox.set_label( Glib::ustring(_("Enable preview")) );
     previewCheckbox.set_active( enablePreview );
@@ -624,9 +594,9 @@ void FileDialogBaseGtk::internalSetup()
 
 void FileDialogBaseGtk::cleanup( bool showConfirmed )
 {
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
     if ( showConfirmed )
-        prefs_set_int_attribute( preferenceBase.c_str(),
-               "enable_preview", previewCheckbox.get_active() );
+        prefs->setBool( preferenceBase + "/enable_preview", previewCheckbox.get_active() );
 }
 
 
@@ -658,7 +628,7 @@ void FileDialogBaseGtk::_updatePreviewCallback()
         return;
     }
 
-    svgPreview.set(fileName, dialogType);
+    svgPreview.set(fileName, _dialogType);
 }
 
 
@@ -673,7 +643,7 @@ FileOpenDialogImplGtk::FileOpenDialogImplGtk(Gtk::Window& parentWindow,
                                        const Glib::ustring &dir,
                                        FileDialogType fileTypes,
                                        const Glib::ustring &title) :
-    FileDialogBaseGtk(parentWindow, title, fileTypes, "dialogs.open")
+    FileDialogBaseGtk(parentWindow, title, Gtk::FILE_CHOOSER_ACTION_OPEN, fileTypes, "/dialogs/open")
 {
 
 
@@ -693,7 +663,7 @@ FileOpenDialogImplGtk::FileOpenDialogImplGtk(Gtk::Window& parentWindow,
     myFilename = "";
 
     /* Set our dialog type (open, import, etc...)*/
-    dialogType = fileTypes;
+    _dialogType = fileTypes;
 
 
     /* Set the pwd and/or the filename */
@@ -716,11 +686,13 @@ FileOpenDialogImplGtk::FileOpenDialogImplGtk(Gtk::Window& parentWindow,
 
     add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
     set_default(*add_button(Gtk::Stock::OPEN,   Gtk::RESPONSE_OK));
-       
-       //###### Allow easy access to our examples folder                
-    if(Inkscape::IO::file_test(INKSCAPE_EXAMPLESDIR,
-               (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
-       {
+
+    //###### Allow easy access to our examples folder
+    if ( Inkscape::IO::file_test(INKSCAPE_EXAMPLESDIR, G_FILE_TEST_EXISTS)
+         && Inkscape::IO::file_test(INKSCAPE_EXAMPLESDIR, G_FILE_TEST_IS_DIR)
+         && g_path_is_absolute(INKSCAPE_EXAMPLESDIR)
+        )
+    {
         add_shortcut_folder(INKSCAPE_EXAMPLESDIR);
     }
 }
@@ -751,6 +723,16 @@ void FileOpenDialogImplGtk::createFilterMenu()
     extensionMap[Glib::ustring(_("All Images"))]=NULL;
     add_filter(allImageFilter);
 
+    Gtk::FileFilter allVectorFilter;
+    allVectorFilter.set_name(_("All Vectors"));
+    extensionMap[Glib::ustring(_("All Vectors"))]=NULL;
+    add_filter(allVectorFilter);
+
+    Gtk::FileFilter allBitmapFilter;
+    allBitmapFilter.set_name(_("All Bitmaps"));
+    extensionMap[Glib::ustring(_("All Bitmaps"))]=NULL;
+    add_filter(allBitmapFilter);
+
     //patterns added dynamically below
     Inkscape::Extension::DB::InputList extension_list;
     Inkscape::Extension::db.get_input_list(extension_list);
@@ -778,6 +760,29 @@ void FileOpenDialogImplGtk::createFilterMenu()
         allInkscapeFilter.add_pattern(upattern);
         if ( strncmp("image", imod->get_mimetype(), 5)==0 )
             allImageFilter.add_pattern(upattern);
+
+        // uncomment this to find out all mime types supported by Inkscape import/open
+        // g_print ("%s\n", imod->get_mimetype());
+
+        // I don't know of any other way to define "bitmap" formats other than by listing them
+        if ( 
+            strncmp("image/png", imod->get_mimetype(), 9)==0 ||
+            strncmp("image/jpeg", imod->get_mimetype(), 10)==0 ||
+            strncmp("image/gif", imod->get_mimetype(), 9)==0 ||
+            strncmp("image/x-icon", imod->get_mimetype(), 12)==0 ||
+            strncmp("image/x-navi-animation", imod->get_mimetype(), 22)==0 ||
+            strncmp("image/x-cmu-raster", imod->get_mimetype(), 18)==0 ||
+            strncmp("image/x-xpixmap", imod->get_mimetype(), 15)==0 ||
+            strncmp("image/bmp", imod->get_mimetype(), 9)==0 ||
+            strncmp("image/vnd.wap.wbmp", imod->get_mimetype(), 18)==0 ||
+            strncmp("image/tiff", imod->get_mimetype(), 10)==0 ||
+            strncmp("image/x-xbitmap", imod->get_mimetype(), 15)==0 ||
+            strncmp("image/x-tga", imod->get_mimetype(), 11)==0 ||
+            strncmp("image/x-pcx", imod->get_mimetype(), 11)==0 
+           )
+            allBitmapFilter.add_pattern(upattern);
+        else 
+            allVectorFilter.add_pattern(upattern);
     }
 
     return;
@@ -789,10 +794,6 @@ void FileOpenDialogImplGtk::createFilterMenu()
 bool
 FileOpenDialogImplGtk::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
@@ -845,7 +846,7 @@ FileOpenDialogImplGtk::getSelectionType()
 Glib::ustring
 FileOpenDialogImplGtk::getFilename (void)
 {
-    return g_strdup(myFilename.c_str());
+    return myFilename;
 }
 
 
@@ -862,7 +863,10 @@ std::vector<Glib::ustring>FileOpenDialogImplGtk::getFilenames()
     return result;
 }
 
-
+Glib::ustring FileOpenDialogImplGtk::getCurrentDirectory()
+{
+    return get_current_folder();
+}
 
 
 
@@ -874,13 +878,19 @@ std::vector<Glib::ustring>FileOpenDialogImplGtk::getFilenames()
 /**
  * Constructor
  */
-FileSaveDialogImplGtk::FileSaveDialogImplGtk(Gtk::Window &parentWindow,
-            const Glib::ustring &dir,
-            FileDialogType fileTypes,
-            const Glib::ustring &title,
-            const Glib::ustring &default_key) :
-    FileDialogBaseGtk(parentWindow, title, Gtk::FILE_CHOOSER_ACTION_SAVE, fileTypes, "dialogs.save_as")
+FileSaveDialogImplGtk::FileSaveDialogImplGtk( Gtk::Window &parentWindow,
+                                              const Glib::ustring &dir,
+                                              FileDialogType fileTypes,
+                                              const Glib::ustring &title,
+                                              const Glib::ustring &/*default_key*/,
+                                              const gchar* docTitle,
+                                              const Inkscape::Extension::FileSaveMethod save_method) :
+    FileDialogBaseGtk(parentWindow, title, Gtk::FILE_CHOOSER_ACTION_SAVE, fileTypes,
+                      (save_method == Inkscape::Extension::FILE_SAVE_METHOD_SAVE_COPY) ? "/dialogs/save_copy" : "/dialogs/save_as"),
+    save_method(save_method)
 {
+    FileSaveDialog::myDocTitle = docTitle;
+
     /* One file at a time */
     set_select_multiple(false);
 
@@ -896,7 +906,7 @@ FileSaveDialogImplGtk::FileSaveDialogImplGtk(Gtk::Window &parentWindow,
     myFilename = "";
 
     /* Set our dialog type (save, export, etc...)*/
-    dialogType = fileTypes;
+    _dialogType = fileTypes;
 
     /* Set the pwd and/or the filename */
     if (dir.size() > 0)
@@ -913,9 +923,13 @@ FileSaveDialogImplGtk::FileSaveDialogImplGtk(Gtk::Window &parentWindow,
     //createFilterMenu();
 
     //###### Do we want the .xxx extension automatically added?
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
     fileTypeCheckbox.set_label(Glib::ustring(_("Append filename extension automatically")));
-    fileTypeCheckbox.set_active( (bool)prefs_get_int_attribute("dialogs.save_as",
-                                                               "append_extension", 1) );
+    if (save_method == Inkscape::Extension::FILE_SAVE_METHOD_SAVE_COPY) {
+        fileTypeCheckbox.set_active(prefs->getBool("/dialogs/save_copy/append_extension", true));
+    } else {
+        fileTypeCheckbox.set_active(prefs->getBool("/dialogs/save_as/append_extension", true));
+    }
 
     createFileTypeMenu();
     fileTypeComboBox.set_size_request(200,40);
@@ -955,6 +969,17 @@ FileSaveDialogImplGtk::FileSaveDialogImplGtk(Gtk::Window &parentWindow,
         expander->set_expanded(true);
         }
 
+    // allow easy access to the user's own templates folder
+    gchar *templates = profile_path ("templates");
+    if ( Inkscape::IO::file_test(templates, G_FILE_TEST_EXISTS)
+         && Inkscape::IO::file_test(templates, G_FILE_TEST_IS_DIR)
+         && g_path_is_absolute(templates)
+        )
+    {
+        add_shortcut_folder(templates);
+    }
+    g_free (templates);
+
 
     //if (extension == NULL)
     //    checkbox.set_sensitive(FALSE);
@@ -1086,27 +1111,26 @@ FileSaveDialogImplGtk::show()
     set_preview_widget_active(false);
     hide();
 
-    if (b == Gtk::RESPONSE_OK)
-        {
+    if (b == Gtk::RESPONSE_OK) {
         updateNameAndExtension();
-
+        Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+        
         // Store changes of the "Append filename automatically" checkbox back to preferences.
-        prefs_set_int_attribute("dialogs.save_as", "append_extension", fileTypeCheckbox.get_active());
+        if (save_method == Inkscape::Extension::FILE_SAVE_METHOD_SAVE_COPY) {
+            prefs->setBool("/dialogs/save_copy/append_extension", fileTypeCheckbox.get_active());
+        } else {
+            prefs->setBool("/dialogs/save_as/append_extension", fileTypeCheckbox.get_active());
+        }
 
-        // Store the last used save-as filetype to preferences.
-        prefs_set_string_attribute("dialogs.save_as", "default",
-                                   ( extension != NULL ? extension->get_id() : "" ));
+        Inkscape::Extension::store_file_extension_in_prefs ((extension != NULL ? extension->get_id() : "" ), save_method);
 
         cleanup( true );
 
         return TRUE;
-        }
-    else
-        {
+    } else {
         cleanup( false );
-
         return FALSE;
-        }
+    }
 }
 
 
@@ -1160,22 +1184,17 @@ void FileSaveDialogImplGtk::setSelectionType( Inkscape::Extension::Extension * k
     }
 }
 
-
-/**
- * Get the file name chosen by the user.   Valid after an [OK]
- */
-Glib::ustring
-FileSaveDialogImplGtk::getFilename()
+Glib::ustring FileSaveDialogImplGtk::getCurrentDirectory()
 {
-    return myFilename;
+    return get_current_folder();
 }
 
 
-void
+/*void
 FileSaveDialogImplGtk::change_title(const Glib::ustring& title)
 {
-    this->set_title(title);
-}
+    set_title(title);
+}*/
 
 /**
   * Change the default save path location.
@@ -1184,6 +1203,7 @@ void
 FileSaveDialogImplGtk::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);
@@ -1224,34 +1244,15 @@ void FileSaveDialogImplGtk::updateNameAndExtension()
 
     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
-        }
+        // Append the file extension if it's not already present and display it in the file name entry field
+        appendExtension(myFilename, newOut);
+        change_path(myFilename);
     }
 }
 
 
+#ifdef NEW_EXPORT_DIALOG
+
 //########################################################################
 //# F I L E     E X P O R T
 //########################################################################
@@ -1350,12 +1351,12 @@ void FileExportDialogImpl::createFileTypeMenu()
 /**
  * Constructor
  */
-FileExportDialogImpl::FileExportDialogImpl(Gtk::Window& parentWindow,
-            const Glib::ustring &dir,
-            FileDialogType fileTypes,
-            const Glib::ustring &title,
-            const Glib::ustring &default_key) :
-            FileDialogBaseGtk(parentWindow, title, Gtk::FILE_CHOOSER_ACTION_SAVE, fileTypes, "dialogs.export"),
+FileExportDialogImpl::FileExportDialogImpl( Gtk::Window& parentWindow,
+                                            const Glib::ustring &dir,
+                                            FileDialogType fileTypes,
+                                            const Glib::ustring &title,
+                                            const Glib::ustring &/*default_key*/ ) :
+            FileDialogBaseGtk(parentWindow, 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")),
@@ -1366,7 +1367,8 @@ FileExportDialogImpl::FileExportDialogImpl(Gtk::Window& parentWindow,
             destHeightSpinner("Height",   _("Destination height")),
             destDPISpinner("DPI",         _("Resolution (dots per inch)"))
 {
-    append_extension = (bool)prefs_get_int_attribute("dialogs.save_as", "append_extension", 1);
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    append_extension = prefs->getBool("/dialogs/save_export/append_extension", true);
 
     /* One file at a time */
     set_select_multiple(false);
@@ -1383,7 +1385,7 @@ FileExportDialogImpl::FileExportDialogImpl(Gtk::Window& parentWindow,
     myFilename = "";
 
     /* Set our dialog type (save, export, etc...)*/
-    dialogType = fileTypes;
+    _dialogType = fileTypes;
 
     /* Set the pwd and/or the filename */
     if (dir.size()>0)
@@ -1575,9 +1577,9 @@ FileExportDialogImpl::show()
         // 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() : "" ));
+        Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+        prefs->setBool("/dialogs/save_export/append_extension", append_extension);
+        prefs->setBool("/dialogs/save_export/default", ( extension != NULL ? extension->get_id() : "" ));
         */
         return TRUE;
         }
@@ -1607,6 +1609,8 @@ FileExportDialogImpl::getFilename()
     return myFilename;
 }
 
+#endif // NEW_EXPORT_DIALOG
+
 
 } //namespace Dialog
 } //namespace UI
@@ -1621,4 +1625,4 @@ FileExportDialogImpl::getFilename()
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :