Code

now that selection description includes style (filtered, clipped), we need to update...
[inkscape.git] / src / inkscape.cpp
index 9264e6010ffed299e44fc1c927136ef21c93c670..ae52589046ec1c34b5dbc2db3b156f4665fdc5a6 100644 (file)
@@ -1,9 +1,7 @@
-#define __INKSCAPE_C__
-
-/*
- * Interface to main application
- *
- * Authors:
+/** @file
+ * @brief Legacy interface to main application
+ */
+/* Authors:
  *   Lauris Kaplinski <lauris@kaplinski.com>
  *   bulia byak <buliabyak@users.sf.net>
  *
@@ -18,7 +16,7 @@
 #endif
 
 
-#include <set>
+#include <map>
 #include "debug/simple-event.h"
 #include "debug/event-tracker.h"
 
@@ -37,38 +35,33 @@ using Inkscape::Extension::Internal::PrintWin32;
 # include <shlobj.h>
 #endif
 
-#include <signal.h>
-
-#include <gtk/gtkmain.h>
-#include <gtk/gtkmessagedialog.h>
-#include <glib.h>
+#include <cstring>
 #include <glib/gstdio.h>
-
+#include <glib.h>
 #include <glibmm/i18n.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtkmessagedialog.h>
+#include <signal.h>
 #include <string>
-#include <cstring>
-#include "helper/sp-marshal.h"
-#include "dialogs/debugdialog.h"
-#include "dialogs/input.h"
 #include "application/application.h"
 #include "application/editor.h"
-
-
-#include "document.h"
 #include "desktop.h"
 #include "desktop-handles.h"
-#include "selection.h"
+#include "dialogs/input.h"
+#include "document.h"
 #include "event-context.h"
-#include "inkscape-private.h"
-#include "xml/repr.h"
-#include "preferences.h"
-#include "io/sys.h"
-#include "message-stack.h"
-
-#include "extension/init.h"
 #include "extension/db.h"
+#include "extension/init.h"
 #include "extension/output.h"
 #include "extension/system.h"
+#include "helper/sp-marshal.h"
+#include "inkscape-private.h"
+#include "io/sys.h"
+#include "message-stack.h"
+#include "preferences.h"
+#include "selection.h"
+#include "ui/dialog/debug.h"
+#include "xml/repr.h"
 
 static Inkscape::Application *inkscape = NULL;
 
@@ -110,8 +103,7 @@ static void inkscape_deactivate_desktop_private (Inkscape::Application *inkscape
 struct Inkscape::Application {
     GObject object;
     Inkscape::XML::Document *menus;
-    std::multiset<SPDocument *> document_set;
-    GSList *documents;
+    std::map<SPDocument *, int> document_set;
     GSList *desktops;
     gchar *argv0;
     gboolean dialogs_toggle;
@@ -148,12 +140,8 @@ static void (* fpe_handler)  (int) = SIG_DFL;
 static void (* ill_handler)  (int) = SIG_DFL;
 static void (* bus_handler)  (int) = SIG_DFL;
 
-#ifdef WIN32
 #define INKSCAPE_PROFILE_DIR "Inkscape"
-#else
-#define INKSCAPE_PROFILE_DIR ".inkscape"
-#endif
-
+#define INKSCAPE_LEGACY_PROFILE_DIR ".inkscape"
 #define MENUS_FILE "menus.xml"
 
 
@@ -298,7 +286,7 @@ typedef int uid_t;
  */
 static gint inkscape_autosave(gpointer)
 {
-    if (!inkscape->documents) { // nothing to autosave
+    if (inkscape->document_set.empty()) { // nothing to autosave
         return TRUE;
     }
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -308,7 +296,7 @@ static gint inkscape_autosave(gpointer)
 
     Glib::ustring autosave_dir;
     {
-        Glib::ustring tmp = prefs->getString("options.autosave", "path");
+        Glib::ustring tmp = prefs->getString("/options/autosave/path");
         if (!tmp.empty()) {
             autosave_dir = tmp;
         } else {
@@ -327,16 +315,19 @@ static gint inkscape_autosave(gpointer)
     gchar sptstr[256];
     strftime(sptstr, 256, "%Y_%m_%d_%H_%M_%S", sptm);
 
-    gint autosave_max = prefs->getInt("options.autosave", "max", 10);
+    gint autosave_max = prefs->getInt("/options/autosave/max", 10);
 
     gint docnum = 0;
 
     SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Autosaving documents..."));
-    for (GSList *docList = inkscape->documents; docList; docList = docList->next) {
+    for (std::map<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
+          iter != inkscape->document_set.end();
+          ++iter) {
+
+        SPDocument *doc = iter->first;
+
         ++docnum;
 
-        // TODO replace this with SP_DOCUMENT() when linking issues are addressed:
-        SPDocument *doc = static_cast<SPDocument *>(docList->data);
         Inkscape::XML::Node *repr = sp_document_repr_root(doc);
         // g_debug("Document %d: \"%s\" %s", docnum, doc ? doc->name : "(null)", doc ? (doc->isModifiedSinceSave() ? "(dirty)" : "(clean)") : "(null)");
 
@@ -440,14 +431,14 @@ void inkscape_autosave_init()
         autosave_timeout_id = 0;
     }
 
-    // g_debug("options.autosave.enable = %d", prefs->getBool("options.autosave", "enable", true));
+    // g_debug("options.autosave.enable = %d", prefs->getBool("/options/autosave/enable", true));
     // Is autosave enabled?
-    if (!prefs->getBool("options.autosave", "enable", true)){
+    if (!prefs->getBool("/options/autosave/enable", true)){
         autosave_timeout_id = 0;
     } else {
         // Turn on autosave
-        guint32 timeout = prefs->getInt("options.autosave", "interval", 10) * 60;
-        // g_debug("options.autosave.interval = %d", prefs->getInt("options.autosave", "interval", 10));
+        guint32 timeout = prefs->getInt("/options/autosave/interval", 10) * 60;
+        // g_debug("options.autosave.interval = %d", prefs->getInt("/options/autosave/interval", 10));
 #if GLIB_CHECK_VERSION(2,14,0)
         autosave_timeout_id = g_timeout_add_seconds(timeout, inkscape_autosave, NULL);
 #else
@@ -466,11 +457,10 @@ inkscape_init (SPObject * object)
         g_assert_not_reached ();
     }
 
-    new (&inkscape->document_set) std::multiset<SPDocument *>();
+    new (&inkscape->document_set) std::map<SPDocument *, int>();
 
     inkscape->menus = sp_repr_read_mem (_(menus_skeleton), MENUS_SKELETON_SIZE, NULL);
 
-    inkscape->documents = NULL;
     inkscape->desktops = NULL;
 
     inkscape->dialogs_toggle = TRUE;
@@ -483,11 +473,6 @@ inkscape_dispose (GObject *object)
 {
     Inkscape::Application *inkscape = (Inkscape::Application *) object;
 
-    while (inkscape->documents) {
-        // we don't otherwise unref, so why here?
-        sp_document_unref((SPDocument *)inkscape->documents->data);
-    }
-
     g_assert (!inkscape->desktops);
 
     Inkscape::Preferences::unload();
@@ -498,7 +483,7 @@ inkscape_dispose (GObject *object)
         inkscape->menus = NULL;
     }
 
-    inkscape->document_set.~multiset();
+    inkscape->document_set.~map();
 
     G_OBJECT_CLASS (parent_class)->dispose (object);
 
@@ -597,10 +582,11 @@ inkscape_crash_handler (int /*signum*/)
     gint count = 0;
     GSList *savednames = NULL;
     GSList *failednames = NULL;
-    for (GSList *l = inkscape->documents; l != NULL; l = l->next) {
-        SPDocument *doc;
+    for (std::map<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
+          iter != inkscape->document_set.end();
+          ++iter) {
+        SPDocument *doc = iter->first;
         Inkscape::XML::Node *repr;
-        doc = (SPDocument *) l->data;
         repr = sp_document_repr_root (doc);
         if (doc->isModifiedSinceSave()) {
             const gchar *docname, *d0, *d;
@@ -629,20 +615,20 @@ inkscape_crash_handler (int /*signum*/)
 
             if (!docname || !*docname) docname = "emergency";
             // try saving to the profile location
-            g_snprintf (c, 1024, "%.256s.%s.%d", docname, sptstr, count);
+            g_snprintf (c, 1024, "%.256s.%s.%d.svg", docname, sptstr, count);
             gchar * location = homedir_path(c);
             Inkscape::IO::dump_fopen_call(location, "E");
             file = Inkscape::IO::fopen_utf8name(location, "w");
             g_free(location);
             if (!file) {
                 // try saving to /tmp
-                g_snprintf (c, 1024, "/tmp/inkscape-%.256s.%s.%d", docname, sptstr, count);
+                g_snprintf (c, 1024, "/tmp/inkscape-%.256s.%s.%d.svg", docname, sptstr, count);
                 Inkscape::IO::dump_fopen_call(c, "G");
                 file = Inkscape::IO::fopen_utf8name(c, "w");
             }
             if (!file) {
                 // try saving to the current directory
-                g_snprintf (c, 1024, "inkscape-%.256s.%s.%d", docname, sptstr, count);
+                g_snprintf (c, 1024, "inkscape-%.256s.%s.%d.svg", docname, sptstr, count);
                 Inkscape::IO::dump_fopen_call(c, "F");
                 file = Inkscape::IO::fopen_utf8name(c, "w");
             }
@@ -764,30 +750,36 @@ inkscape_application_init (const gchar *argv0, gboolean use_gui)
     inkscape->argv0 = g_strdup(argv0);
 
     /* Load the preferences and menus; Later menu layout should be merged into prefs */
-    Inkscape::Preferences::use_gui = use_gui;
-    Inkscape::Preferences::load();
     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+    prefs->load(use_gui, false);
     inkscape_load_menus(inkscape);
     sp_input_load_from_preferences();
+    
+    /* set language for user interface according setting in preferences */
+    Glib::ustring ui_language = prefs->getString("/ui/language");
+    if(!ui_language.empty())
+    {
+        setenv("LANGUAGE", ui_language, 1);
+    }
 
     /* DebugDialog redirection.  On Linux, default to OFF, on Win32, default to ON.
-        * Use only if use_gui is enabled
-        */
+     * Use only if use_gui is enabled
+     */
 #ifdef WIN32
 #define DEFAULT_LOG_REDIRECT true
 #else
 #define DEFAULT_LOG_REDIRECT false
 #endif
 
-    if (use_gui == TRUE && prefs->getBool("dialogs.debug", "redirect", DEFAULT_LOG_REDIRECT))
+    if (use_gui == TRUE && prefs->getBool("/dialogs/debug/redirect", DEFAULT_LOG_REDIRECT))
     {
-               Inkscape::UI::Dialogs::DebugDialog::getInstance()->captureLogMessages();
+        Inkscape::UI::Dialog::DebugDialog::getInstance()->captureLogMessages();
     }
 
     /* Check for global remapping of Alt key */
     if(use_gui)
     {
-        inkscape_mapalt(guint(prefs->getInt("options.mapalt", "value", 0)));
+        inkscape_mapalt(guint(prefs->getInt("/options/mapalt/value", 0)));
     }
 
     /* Initialize the extensions */
@@ -832,15 +824,6 @@ bool inkscape_load_menus (Inkscape::Application */*inkscape*/)
     return false;
 }
 
-/**
- * @deprecated Use the Preferences class instead, and try not to use _getNode
- */
-Inkscape::XML::Node *inkscape_get_repr(Inkscape::Application */*inkscape*/, const gchar *key)
-{
-    Inkscape::Preferences *ps = Inkscape::Preferences::get();
-    return ps->_getNode(key);
-}
-
 
 void
 inkscape_selection_modified (Inkscape::Selection *selection, guint flags)
@@ -1191,11 +1174,18 @@ inkscape_add_document (SPDocument *document)
 
     if (!Inkscape::NSApplication::Application::getNewGui())
     {
-        if ( inkscape->document_set.find(document) == inkscape->document_set.end() ) {
-
-            inkscape->documents = g_slist_append (inkscape->documents, document);
+        // try to insert the pair into the list
+        if (!(inkscape->document_set.insert(std::make_pair(document, 1)).second)) {
+            //insert failed, this key (document) is already in the list
+            for (std::map<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
+                   iter != inkscape->document_set.end();
+                   ++iter) {
+                if (iter->first == document) {
+                    // found this document in list, increase its count
+                    iter->second ++;
+                }
+           }
         }
-        inkscape->document_set.insert(document);
     }
     else
     {
@@ -1204,17 +1194,28 @@ inkscape_add_document (SPDocument *document)
 }
 
 
-
-void
+// returns true if this was last reference to this document, so you can delete it
+bool
 inkscape_remove_document (SPDocument *document)
 {
-    g_return_if_fail (document != NULL);
+    g_return_val_if_fail (document != NULL, false);
 
     if (!Inkscape::NSApplication::Application::getNewGui())
     {
-        inkscape->document_set.erase(document);
-        if ( inkscape->document_set.find(document) != inkscape->document_set.end() ) {
-            inkscape->documents = g_slist_remove (inkscape->documents, document);
+        for (std::map<SPDocument*,int>::iterator iter = inkscape->document_set.begin();
+                  iter != inkscape->document_set.end();
+                  ++iter) {
+            if (iter->first == document) {
+                // found this document in list, decrease its count
+                iter->second --;
+                if (iter->second < 1) {
+                    // this was the last one, remove the pair from list
+                    inkscape->document_set.erase (iter);
+                    return true;
+                } else {
+                    return false;
+                }
+            }
         }
     }
     else
@@ -1222,7 +1223,7 @@ inkscape_remove_document (SPDocument *document)
         Inkscape::NSApplication::Editor::removeDocument (document);
     }
 
-    return;
+    return false;
 }
 
 SPDesktop *
@@ -1315,8 +1316,7 @@ homedir_path(const char *filename)
         homedir = g_get_home_dir();
     }
     if (!homedir) {
-// TODO check this. It looks broken
-        gchar * path = g_path_get_dirname(INKSCAPE->argv0);
+        homedir = g_path_get_dirname(INKSCAPE->argv0);
     }
     return g_build_filename(homedir, filename, NULL);
 }
@@ -1375,13 +1375,27 @@ profile_path(const char *filename)
                 }
                 */
             }
+
+            if (prefdir) {
+                prefdir = g_build_filename(prefdir, INKSCAPE_PROFILE_DIR, NULL);
+            }
         }
 #endif
         if (!prefdir) {
-            prefdir = homedir_path(NULL);
+            prefdir = g_build_filename(g_get_user_config_dir(), INKSCAPE_PROFILE_DIR, NULL);
+            gchar * legacyDir = homedir_path(INKSCAPE_LEGACY_PROFILE_DIR);
+
+            // TODO here is a point to hook in preference migration
+
+            if ( !Inkscape::IO::file_test( prefdir, G_FILE_TEST_EXISTS ) && Inkscape::IO::file_test( legacyDir, G_FILE_TEST_EXISTS ) ) {
+                prefdir = legacyDir;
+            } else {
+                g_free(legacyDir);
+                legacyDir = 0;
+            }
         }
     }
-    return g_build_filename(prefdir, INKSCAPE_PROFILE_DIR, filename, NULL);
+    return g_build_filename(prefdir, filename, NULL);
 }
 
 Inkscape::XML::Node *