Code

part of bug #339660; can not use Add/Rename dialog to create layer with no proper...
[inkscape.git] / src / file.cpp
index b2f53b96714f880a5fd6766f55f04ae654086f8f..f2a4884d41325644c96c33ece9a38a54b135870d 100644 (file)
@@ -1,9 +1,7 @@
-#define __SP_FILE_C__
-
-/*
- * File/Print operations
- *
- * Authors:
+/** @file
+ * @brief File/Print operations
+ */
+/* Authors:
  *   Lauris Kaplinski <lauris@kaplinski.com>
  *   Chema Celorio <chema@celorio.com>
  *   bulia byak <buliabyak@users.sf.net>
@@ -18,8 +16,8 @@
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
-/**
- * Note: This file needs to be cleaned up extensively.
+/** @file
+ * @note This file needs to be cleaned up extensively.
  * What it probably needs is to have one .h file for
  * the API, and two or more .cpp files for the implementations.
  */
 # include "config.h"
 #endif
 
+#include <gtk/gtk.h>
 #include <glib/gmem.h>
+#include <glibmm/i18n.h>
 #include <libnr/nr-pixops.h>
 
-#include "document-private.h"
-#include "selection-chemistry.h"
-#include "ui/view/view-widget.h"
+#include "application/application.h"
+#include "application/editor.h"
+#include "desktop.h"
+#include "desktop-handles.h"
+#include "dialogs/export.h"
 #include "dir-util.h"
+#include "document-private.h"
+#include "extension/db.h"
+#include "extension/input.h"
+#include "extension/output.h"
+#include "extension/system.h"
+#include "file.h"
 #include "helper/png-write.h"
-#include "dialogs/export.h"
-#include <glibmm/i18n.h>
+#include "id-clash.h"
+#include "inkscape.h"
 #include "inkscape.h"
-#include "desktop.h"
-#include "selection.h"
 #include "interface.h"
-#include "style.h"
-#include "print.h"
-#include "file.h"
+#include "io/sys.h"
 #include "message.h"
 #include "message-stack.h"
-#include "ui/dialog/filedialog.h"
-#include "ui/dialog/ocaldialogs.h"
-#include "preferences.h"
 #include "path-prefix.h"
-
+#include "preferences.h"
+#include "print.h"
+#include "rdf.h"
+#include "selection-chemistry.h"
+#include "selection.h"
 #include "sp-namedview.h"
-#include "desktop-handles.h"
-
-#include "extension/db.h"
-#include "extension/input.h"
-#include "extension/output.h"
-/* #include "extension/menu.h"  */
-#include "extension/system.h"
-
-#include "io/sys.h"
-#include "application/application.h"
-#include "application/editor.h"
-#include "inkscape.h"
+#include "style.h"
+#include "ui/dialog/filedialog.h"
+#include "ui/dialog/ocaldialogs.h"
+#include "ui/view/view-widget.h"
 #include "uri.h"
-#include "id-clash.h"
-#include "dialogs/rdf.h"
 
 #ifdef WITH_GNOME_VFS
 # include <libgnomevfs/gnome-vfs.h>
 void dump_str(gchar const *str, gchar const *prefix);
 void dump_ustr(Glib::ustring const &ustr);
 
+// what gets passed here is not actually an URI... it is an UTF-8 encoded filename (!)
+static void sp_file_add_recent(gchar const *uri)
+{
+    GtkRecentManager *recent = gtk_recent_manager_get_default();
+    gchar *fn = g_filename_from_utf8(uri, -1, NULL, NULL, NULL);
+    if (fn) {
+        gchar *uri_to_add = g_filename_to_uri(fn, NULL, NULL);
+        if (uri_to_add) {
+            gtk_recent_manager_add_item(recent, uri_to_add);
+            g_free(uri_to_add);
+        }
+        g_free(fn);
+    }
+}
+
 
 /*######################
 ## N E W
@@ -182,6 +192,10 @@ sp_file_open(const Glib::ustring &uri,
              Inkscape::Extension::Extension *key,
              bool add_to_recent, bool replace_empty)
 {
+    SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+    if (desktop)
+        desktop->setWaitingCursor();
+
     SPDocument *doc = NULL;
     try {
         doc = Inkscape::Extension::open(key, uri.c_str());
@@ -191,8 +205,10 @@ sp_file_open(const Glib::ustring &uri,
         doc = NULL;
     }
 
+    if (desktop)
+        desktop->clearWaitingCursor();
+
     if (doc) {
-        SPDesktop *desktop = SP_ACTIVE_DESKTOP;
         SPDocument *existing = desktop ? sp_desktop_document(desktop) : NULL;
 
         if (existing && existing->virgin && replace_empty) {
@@ -219,7 +235,7 @@ sp_file_open(const Glib::ustring &uri,
         sp_namedview_update_layers_from_document(desktop);
 
         if (add_to_recent) {
-            prefs_set_recent_file(SP_DOCUMENT_URI(doc), SP_DOCUMENT_NAME(doc));
+            sp_file_add_recent(SP_DOCUMENT_URI(doc));
         }
 
         return TRUE;
@@ -386,7 +402,7 @@ sp_file_open_dialog(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*d
 
     if(open_path.empty())
     {
-        Glib::ustring attr = prefs->getString("dialogs.open", "path");
+        Glib::ustring attr = prefs->getString("/dialogs/open/path");
         if (!attr.empty()) open_path = attr;
     }
 
@@ -432,7 +448,7 @@ sp_file_open_dialog(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*d
         open_path.append(G_DIR_SEPARATOR_S);
     }
 
-    //# Create a dialog if we don't already have one
+    //# Create a dialog
     Inkscape::UI::Dialog::FileOpenDialog *openDialogInstance =
               Inkscape::UI::Dialog::FileOpenDialog::create(
                  parentWindow, open_path,
@@ -498,7 +514,7 @@ sp_file_open_dialog(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*d
 
         open_path = Glib::path_get_dirname (fileName);
         open_path.append(G_DIR_SEPARATOR_S);
-        prefs->setString("dialogs.open", "path", open_path);
+        prefs->setString("/dialogs/open/path", open_path);
 
         sp_file_open(fileName, selection);
     }
@@ -577,6 +593,9 @@ file_save(Gtk::Window &parentWindow, SPDocument *doc, const Glib::ustring &uri,
         g_free(text);
         g_free(safeUri);
         return FALSE;
+    } catch (Inkscape::Extension::Output::save_cancelled &e) {
+        SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
+        return FALSE;
     } catch (Inkscape::Extension::Output::no_overwrite &e) {
         return sp_file_save_dialog(parentWindow, doc);
     }
@@ -689,7 +708,7 @@ sp_file_save_dialog(Gtk::Window &parentWindow, SPDocument *doc, bool is_copy)
     Glib::ustring default_extension;
     char *attr = (char *)repr->attribute("inkscape:output_extension");
     if (!attr) {
-        Glib::ustring attr2 = prefs->getString("dialogs.save_as", "default");
+        Glib::ustring attr2 = prefs->getString("/dialogs/save_as/default");
         if(!attr2.empty()) default_extension = attr2;
     } else {
         default_extension = attr;
@@ -710,7 +729,7 @@ sp_file_save_dialog(Gtk::Window &parentWindow, SPDocument *doc, bool is_copy)
         if (extension)
             filename_extension = extension->get_extension();
 
-        Glib::ustring attr3 = prefs->getString("dialogs.save_as", "path");
+        Glib::ustring attr3 = prefs->getString("/dialogs/save_as/path");
         if (!attr3.empty())
             save_path = attr3;
 
@@ -793,12 +812,13 @@ sp_file_save_dialog(Gtk::Window &parentWindow, SPDocument *doc, bool is_copy)
 
         success = file_save(parentWindow, doc, fileName, selectionType, TRUE, !is_copy);
 
-        if (success)
-            prefs_set_recent_file(SP_DOCUMENT_URI(doc), SP_DOCUMENT_NAME(doc));
+        if (success) {
+            sp_file_add_recent(SP_DOCUMENT_URI(doc));
+        }
 
         save_path = Glib::path_get_dirname(fileName);
         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-        prefs->setString("dialogs.save_as", "path", save_path);
+        prefs->setString("/dialogs/save_as/path", save_path);
 
         return success;
     }
@@ -935,8 +955,11 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri,
         //        a document:: method to return the current layer.
         //        For now, we just use the root in this case.
         SPObject *place_to_insert;
-        if (desktop) place_to_insert = desktop->currentLayer();
-        else         place_to_insert = SP_DOCUMENT_ROOT(in_doc);
+        if (desktop) {
+            place_to_insert = desktop->currentLayer();
+        } else {
+            place_to_insert = SP_DOCUMENT_ROOT(in_doc);
+        }
 
         // Construct a new object representing the imported image,
         // and insert it into the current document.
@@ -987,15 +1010,15 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri,
             // object" option.
             {
                 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-                bool const saved_pref = prefs->getBool("options.transform", "pattern", true);
-                prefs->setBool("options.transform", "pattern", true);
+                bool const saved_pref = prefs->getBool("/options/transform/pattern", true);
+                prefs->setBool("/options/transform/pattern", true);
                 sp_document_ensure_up_to_date(sp_desktop_document(desktop));
-                boost::optional<Geom::Rect> sel_bbox = selection->bounds();
+                Geom::OptRect sel_bbox = selection->bounds();
                 if (sel_bbox) {
                     Geom::Point m( desktop->point() - sel_bbox->midpoint() );
                     sp_selection_move_relative(selection, m);
                 }
-                prefs->setBool("options.transform", "pattern", saved_pref);
+                prefs->setBool("/options/transform/pattern", saved_pref);
             }
         }
 
@@ -1013,8 +1036,6 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri,
 }
 
 
-static Inkscape::UI::Dialog::FileOpenDialog *importDialogInstance = NULL;
-
 /**
  *  Display an Open dialog, import a resource if OK pressed.
  */
@@ -1027,24 +1048,26 @@ sp_file_import(Gtk::Window &parentWindow)
     if (!doc)
         return;
 
-    if (!importDialogInstance) {
-        importDialogInstance =
+    // Create new dialog (don't use an old one, because parentWindow has probably changed)
+    Inkscape::UI::Dialog::FileOpenDialog *importDialogInstance =
              Inkscape::UI::Dialog::FileOpenDialog::create(
                  parentWindow,
                  import_path,
                  Inkscape::UI::Dialog::IMPORT_TYPES,
                  (char const *)_("Select file to import"));
-    }
 
     bool success = importDialogInstance->show();
-    if (!success)
+    if (!success) {
+        delete importDialogInstance;
         return;
+    }
 
     //# Get file name and extension type
     Glib::ustring fileName = importDialogInstance->getFilename();
-    Inkscape::Extension::Extension *selection =
-        importDialogInstance->getSelectionType();
+    Inkscape::Extension::Extension *selection = importDialogInstance->getSelectionType();
 
+    delete importDialogInstance;
+    importDialogInstance = NULL;
 
     if (fileName.size() > 0) {
 
@@ -1078,8 +1101,6 @@ sp_file_import(Gtk::Window &parentWindow)
 
 #ifdef NEW_EXPORT_DIALOG
 
-static Inkscape::UI::Dialog::FileExportDialog *exportDialogInstance = NULL;
-
 /**
  *  Display an Export dialog, export as the selected type if OK pressed
  */
@@ -1100,7 +1121,7 @@ sp_file_export_dialog(void *widget)
     Glib::ustring default_extension;
     char *attr = (char *)repr->attribute("inkscape:output_extension");
     if (!attr) {
-        Glib::ustring attr2 = prefs->getString("dialogs.save_as", "default");
+        Glib::ustring attr2 = prefs->getString("/dialogs/save_as/default");
         if(!attr2.empty()) default_extension = attr2;
     } else {
         default_extension = attr;
@@ -1118,7 +1139,7 @@ sp_file_export_dialog(void *widget)
         if (extension)
             filename_extension = extension->get_extension();
 
-        Glib::ustring attr3 = prefs->getString("dialogs.save_as", "path");
+        Glib::ustring attr3 = prefs->getString("/dialogs/save_as/path");
         if (!attr3.empty())
             export_path = attr3;
 
@@ -1148,24 +1169,27 @@ sp_file_export_dialog(void *widget)
         export_path = export_path_local;
 
     //# Show the SaveAs dialog
-    if (!exportDialogInstance)
-        exportDialogInstance =
-             Inkscape::UI::Dialog::FileExportDialog::create(
-                 export_path,
-                 Inkscape::UI::Dialog::EXPORT_TYPES,
-                 (char const *) _("Select file to export to"),
-                 default_extension
-            );
+    Inkscape::UI::Dialog::FileExportDialog *exportDialogInstance = 
+        Inkscape::UI::Dialog::FileExportDialog::create(
+            export_path,
+            Inkscape::UI::Dialog::EXPORT_TYPES,
+            (char const *) _("Select file to export to"),
+            default_extension
+        );
 
     bool success = exportDialogInstance->show();
-    if (!success)
+    if (!success) {
+        delete exportDialogInstance;
         return success;
+    }
 
     Glib::ustring fileName = exportDialogInstance->getFilename();
 
     Inkscape::Extension::Extension *selectionType =
         exportDialogInstance->getSelectionType();
 
+    delete exportDialogInstance;
+    exportDialogInstance = NULL;
 
     if (fileName.size() > 0) {
         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
@@ -1177,11 +1201,13 @@ sp_file_export_dialog(void *widget)
 
         success = file_save(doc, fileName, selectionType, TRUE, FALSE);
 
-        if (success)
-            prefs_set_recent_file(SP_DOCUMENT_URI(doc), SP_DOCUMENT_NAME(doc));
+        if (success) {
+            Glib::RefPtr<Gtk::RecentManager> recent = Gtk::RecentManager::get_default();
+            recent->add_item(SP_DOCUMENT_URI(doc));
+        }
 
         export_path = fileName;
-        prefs->setString("dialogs.save_as", "path", export_path);
+        prefs->setString("/dialogs/save_as/path", export_path);
 
         return success;
     }
@@ -1227,8 +1253,6 @@ sp_file_export_to_ocal_dialog(Gtk::Window &parentWindow)
 
     bool success = false;
 
-    static Inkscape::UI::Dialog::FileExportToOCALDialog *exportDialogInstance = NULL;
-    static Inkscape::UI::Dialog::FileExportToOCALPasswordDialog *exportPasswordDialogInstance = NULL;
     static bool gotSuccess = false;
 
     Inkscape::XML::Node *repr = sp_document_repr_root(doc);
@@ -1259,19 +1283,24 @@ sp_file_export_to_ocal_dialog(Gtk::Window &parentWindow)
         export_path = export_path_local;
 
     // Show the Export To OCAL dialog
-    if (!exportDialogInstance)
-        exportDialogInstance = new Inkscape::UI::Dialog::FileExportToOCALDialog(
+    Inkscape::UI::Dialog::FileExportToOCALDialog *exportDialogInstance =
+        new Inkscape::UI::Dialog::FileExportToOCALDialog(
                 parentWindow,
                 Inkscape::UI::Dialog::EXPORT_TYPES,
                 (char const *) _("Select file to export to")
                 );
 
     success = exportDialogInstance->show();
-    if (!success)
+    if (!success) {
+        delete exportDialogInstance;
         return success;
+    }
 
     fileName = exportDialogInstance->getFilename();
 
+    delete exportDialogInstance;
+    exportDialogInstance = NULL;;
+
     fileName.append(filename_extension.c_str());
     if (fileName.size() > 0) {
         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
@@ -1301,28 +1330,33 @@ sp_file_export_to_ocal_dialog(Gtk::Window &parentWindow)
     // Create the uri
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
     Glib::ustring uri = "dav://";
-    Glib::ustring username = prefs->getString("options.ocalusername", "str");
-    Glib::ustring password = prefs->getString("options.ocalpassword", "str");
+    Glib::ustring username = prefs->getString("/options/ocalusername/str");
+    Glib::ustring password = prefs->getString("/options/ocalpassword/str");
     if (username.empty() || password.empty())
     {
+        Inkscape::UI::Dialog::FileExportToOCALPasswordDialog *exportPasswordDialogInstance = NULL;
         if(!gotSuccess)
         {
-            if (!exportPasswordDialogInstance)
-                exportPasswordDialogInstance = new Inkscape::UI::Dialog::FileExportToOCALPasswordDialog(
+            exportPasswordDialogInstance = new Inkscape::UI::Dialog::FileExportToOCALPasswordDialog(
                     parentWindow,
                     (char const *) _("Open Clip Art Login"));
             success = exportPasswordDialogInstance->show();
-            if (!success)
+            if (!success) {
+                delete exportPasswordDialogInstance;
                 return success;
+            }
         }
         username = exportPasswordDialogInstance->getUsername();
         password = exportPasswordDialogInstance->getPassword();
+
+        delete exportPasswordDialogInstance;
+        exportPasswordDialogInstance = NULL;
     }
     uri.append(username);
     uri.append(":");
     uri.append(password);
     uri.append("@");
-    uri.append(prefs->getString("options.ocalurl", "str"));
+    uri.append(prefs->getString("/options/ocalurl/str"));
     uri.append("/dav.php/");
     uri.append(Glib::path_get_basename(fileName));
 
@@ -1372,7 +1406,7 @@ sp_file_import_from_ocal(Gtk::Window &parentWindow)
     if (!doc)
         return;
 
-    static Inkscape::UI::Dialog::FileImportFromOCALDialog *importDialogInstance = NULL;
+    Inkscape::UI::Dialog::FileImportFromOCALDialog *importDialogInstance = NULL;
 
     if (!importDialogInstance) {
         importDialogInstance = new
@@ -1384,13 +1418,17 @@ sp_file_import_from_ocal(Gtk::Window &parentWindow)
     }
 
     bool success = importDialogInstance->show();
-    if (!success)
+    if (!success) {
+        delete importDialogInstance;
         return;
+    }
 
     // Get file name and extension type
     Glib::ustring fileName = importDialogInstance->getFilename();
-    Inkscape::Extension::Extension *selection =
-        importDialogInstance->getSelectionType();
+    Inkscape::Extension::Extension *selection = importDialogInstance->getSelectionType();
+
+    delete importDialogInstance;
+    importDialogInstance = NULL;
 
     if (fileName.size() > 0) {