Code

SPDocument->Document
[inkscape.git] / src / file.cpp
2 /** @file
3  * @brief File/Print operations
4  */
5 /* Authors:
6  *   Lauris Kaplinski <lauris@kaplinski.com>
7  *   Chema Celorio <chema@celorio.com>
8  *   bulia byak <buliabyak@users.sf.net>
9  *   Bruno Dilly <bruno.dilly@gmail.com>
10  *   Stephen Silver <sasilver@users.sourceforge.net>
11  *
12  * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>
13  * Copyright (C) 1999-2008 Authors
14  * Copyright (C) 2004 David Turner
15  * Copyright (C) 2001-2002 Ximian, Inc.
16  *
17  * Released under GNU GPL, read the file 'COPYING' for more information
18  */
20 /** @file
21  * @note This file needs to be cleaned up extensively.
22  * What it probably needs is to have one .h file for
23  * the API, and two or more .cpp files for the implementations.
24  */
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 #include <gtk/gtk.h>
31 #include <glib/gmem.h>
32 #include <glibmm/i18n.h>
33 #include <libnr/nr-pixops.h>
35 #include "application/application.h"
36 #include "application/editor.h"
37 #include "desktop.h"
38 #include "desktop-handles.h"
39 #include "dialogs/export.h"
40 #include "dir-util.h"
41 #include "document-private.h"
42 #include "extension/db.h"
43 #include "extension/input.h"
44 #include "extension/output.h"
45 #include "extension/system.h"
46 #include "file.h"
47 #include "helper/png-write.h"
48 #include "id-clash.h"
49 #include "inkscape.h"
50 #include "inkscape.h"
51 #include "interface.h"
52 #include "io/sys.h"
53 #include "message.h"
54 #include "message-stack.h"
55 #include "path-prefix.h"
56 #include "preferences.h"
57 #include "print.h"
58 #include "rdf.h"
59 #include "selection-chemistry.h"
60 #include "selection.h"
61 #include "sp-namedview.h"
62 #include "style.h"
63 #include "ui/dialog/filedialog.h"
64 #include "ui/dialog/ocaldialogs.h"
65 #include "ui/view/view-widget.h"
66 #include "uri.h"
67 #include "xml/rebase-hrefs.h"
69 #include "streams-handles.h"
70 #include "streams-webdav.h"
71 #include "streams-ftp.h"
72 #include "streams-http.h"
74 //#include "buffersystem.h"
75 #include <cstring>
77 #ifdef WITH_GNOME_VFS
78 # include <libgnomevfs/gnome-vfs.h>
79 #endif
81 #ifdef WITH_INKBOARD
82 #include "jabber_whiteboard/session-manager.h"
83 #endif
85 #ifdef WIN32
86 #include <windows.h>
87 #endif
89 //#define INK_DUMP_FILENAME_CONV 1
90 #undef INK_DUMP_FILENAME_CONV
92 //#define INK_DUMP_FOPEN 1
93 #undef INK_DUMP_FOPEN
95 void dump_str(gchar const *str, gchar const *prefix);
96 void dump_ustr(Glib::ustring const &ustr);
98 // what gets passed here is not actually an URI... it is an UTF-8 encoded filename (!)
99 static void sp_file_add_recent(gchar const *uri)
101     if(uri == NULL) {
102         g_warning("sp_file_add_recent: uri == NULL");
103         return;
104     }
105     GtkRecentManager *recent = gtk_recent_manager_get_default();
106     gchar *fn = g_filename_from_utf8(uri, -1, NULL, NULL, NULL);
107     if (fn) {
108         gchar *uri_to_add = g_filename_to_uri(fn, NULL, NULL);
109         if (uri_to_add) {
110             gtk_recent_manager_add_item(recent, uri_to_add);
111             g_free(uri_to_add);
112         }
113         g_free(fn);
114     }
118 /*######################
119 ## N E W
120 ######################*/
122 /**
123  * Create a blank document and add it to the desktop
124  */
125 SPDesktop*
126 sp_file_new(const Glib::ustring &templ)
128     char *templName = NULL;
129     if (templ.size()>0)
130         templName = (char *)templ.c_str();
131     Document *doc = sp_document_new(templName, TRUE, true);
132     g_return_val_if_fail(doc != NULL, NULL);
134     SPDesktop *dt;
135     if (Inkscape::NSApplication::Application::getNewGui())
136     {
137         dt = Inkscape::NSApplication::Editor::createDesktop (doc);
138     } else {
139         SPViewWidget *dtw = sp_desktop_widget_new(sp_document_namedview(doc, NULL));
140         g_return_val_if_fail(dtw != NULL, NULL);
141         sp_document_unref(doc);
143         sp_create_window(dtw, TRUE);
144         dt = static_cast<SPDesktop*>(dtw->view);
145         sp_namedview_window_from_document(dt);
146         sp_namedview_update_layers_from_document(dt);
147     }
148     return dt;
151 SPDesktop*
152 sp_file_new_default()
154     std::list<gchar *> sources;
155     sources.push_back( profile_path("templates") ); // first try user's local dir
156     sources.push_back( g_strdup(INKSCAPE_TEMPLATESDIR) ); // then the system templates dir
158     while (!sources.empty()) {
159         gchar *dirname = sources.front();
160         if ( Inkscape::IO::file_test( dirname, (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) ) ) {
162             // TRANSLATORS: default.svg is localizable - this is the name of the default document
163             //  template. This way you can localize the default pagesize, translate the name of
164             //  the default layer, etc. If you wish to localize this file, please create a
165             //  localized share/templates/default.xx.svg file, where xx is your language code.
166             char *default_template = g_build_filename(dirname, _("default.svg"), NULL);
167             if (Inkscape::IO::file_test(default_template, G_FILE_TEST_IS_REGULAR)) {
168                 return sp_file_new(default_template);
169             }
170         }
171         g_free(dirname);
172         sources.pop_front();
173     }
175     return sp_file_new("");
179 /*######################
180 ## D E L E T E
181 ######################*/
183 /**
184  *  Perform document closures preceding an exit()
185  */
186 void
187 sp_file_exit()
189     sp_ui_close_all();
190     // no need to call inkscape_exit here; last document being closed will take care of that
194 /*######################
195 ## O P E N
196 ######################*/
198 /**
199  *  Open a file, add the document to the desktop
200  *
201  *  \param replace_empty if true, and the current desktop is empty, this document
202  *  will replace the empty one.
203  */
204 bool
205 sp_file_open(const Glib::ustring &uri,
206              Inkscape::Extension::Extension *key,
207              bool add_to_recent, bool replace_empty)
209     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
210     if (desktop)
211         desktop->setWaitingCursor();
213     Document *doc = NULL;
214     try {
215         doc = Inkscape::Extension::open(key, uri.c_str());
216     } catch (Inkscape::Extension::Input::no_extension_found &e) {
217         doc = NULL;
218     } catch (Inkscape::Extension::Input::open_failed &e) {
219         doc = NULL;
220     }
222     if (desktop)
223         desktop->clearWaitingCursor();
225     if (doc) {
226         Document *existing = desktop ? sp_desktop_document(desktop) : NULL;
228         if (existing && existing->virgin && replace_empty) {
229             // If the current desktop is empty, open the document there
230             sp_document_ensure_up_to_date (doc);
231             desktop->change_document(doc);
232             sp_document_resized_signal_emit (doc, sp_document_width(doc), sp_document_height(doc));
233         } else {
234             if (!Inkscape::NSApplication::Application::getNewGui()) {
235                 // create a whole new desktop and window
236                 SPViewWidget *dtw = sp_desktop_widget_new(sp_document_namedview(doc, NULL));
237                 sp_create_window(dtw, TRUE);
238                 desktop = static_cast<SPDesktop*>(dtw->view);
239             } else {
240                 desktop = Inkscape::NSApplication::Editor::createDesktop (doc);
241             }
242         }
244         doc->virgin = FALSE;
245         // everyone who cares now has a reference, get rid of ours
246         sp_document_unref(doc);
247         // resize the window to match the document properties
248         sp_namedview_window_from_document(desktop);
249         sp_namedview_update_layers_from_document(desktop);
251         if (add_to_recent) {
252             sp_file_add_recent(SP_DOCUMENT_URI(doc));
253         }
255         return TRUE;
256     } else {
257         gchar *safeUri = Inkscape::IO::sanitizeString(uri.c_str());
258         gchar *text = g_strdup_printf(_("Failed to load the requested file %s"), safeUri);
259         sp_ui_error_dialog(text);
260         g_free(text);
261         g_free(safeUri);
262         return FALSE;
263     }
269 //NOTE1
270 bool
271 sp_file_open_uri(const Inkscape::URI &uri,
272              Inkscape::Extension::Extension *key,
273              bool add_to_recent, bool replace_empty)
275     Document *doc = NULL;
276     try {
277         doc = Inkscape::Extension::open(key, uri.toNativeFilename());
278     } catch (Inkscape::Extension::Input::no_extension_found &e) {
279         doc = NULL;
280     } catch (Inkscape::Extension::Input::open_failed &e) {
281         doc = NULL;
282     }
283   
284     //FIXME1 KLUDGE switch
286     //WebDAV
287     /*
288       if (std::strstr(uri.toString(), "http") != NULL)
289       {
290       if (strcmp(uri.toString(), "/http") >= 5//FIXME3 skip begining '/'
291       || 
292       strcmp(uri.toString(), "http") >= 4
293       )
294         {
295         
296         std::cout<<"+++ 'http' uri.toString->"<<uri.toString()<<std::endl;
297         
298         Inkscape::WebDAVBuffer wbuf;
299         Inkscape::iwebdavstream *iws = new Inkscape::iwebdavstream(wbuf);
300         Inkscape::BufferSystem bs(iws);
301         bs.onInputStream();       
302         }
303         
304         } else*/
305     std::cout<<"--> FTP , HTTP etc."<<std::endl;
307     //FTP
308     if (std::strstr(uri.toString(), "ftp") != NULL)
309     {
310         if (strcmp(uri.toString(), "/ftp") >= 4//FIXME3 skip begining '/'
311             || 
312             strcmp(uri.toString(), "ftp") >= 3
313             )
314         {
315              std::cout<<"+++ 'ftp' uri.toString->"<<uri.toString()<<std::endl;
316             
317             Inkscape::FTPBuffer wbuf;
318             Inkscape::iftpstream *iws = new Inkscape::iftpstream(wbuf);
319             char *buf = new char[8192]; 
320             *iws >> buf;
321             std::cout<<"buf->"<<buf<<std::endl;
323             //Inkscape::BufferSystem bs(iws);
324             //bs.onInputStream(); 
325         }
326         //HTTP
327     }  else if (std::strstr(uri.toString(), "http") != NULL)
328     {
329         if (strcmp(uri.toString(), "/http") >= 5//FIXME3 skip begining '/'
330             || 
331             strcmp(uri.toString(), "http") >= 4
332             )
333         {
334              std::cout<<"+++ 'http' uri.toString->"<<uri.toString()<<std::endl;
335             
336 /*            Inkscape::HTTPBuffer wbuf;
337             Inkscape::ihttpstream *iws = new Inkscape::ihttpstream(wbuf);
338             char *buf = new char[8192]; 
339             *iws >> buf;
340             std::cout<<"buf->"<<buf<<std::endl;
341 */
342             //Inkscape::BufferSystem bs(iws);
343             //bs.onInputStream(); 
344         }
346     } /*else  if ()
347     {
348     
349     } */
350    
353     if (doc) {
354         SPDesktop *desktop = SP_ACTIVE_DESKTOP;
355         Document *existing = desktop ? sp_desktop_document(desktop) : NULL;
357         if (existing && existing->virgin && replace_empty) {
358             // If the current desktop is empty, open the document there
359             sp_document_ensure_up_to_date (doc);
360             desktop->change_document(doc);
361             sp_document_resized_signal_emit (doc, sp_document_width(doc), sp_document_height(doc));
362         } else {
363             if (!Inkscape::NSApplication::Application::getNewGui()) {
364                 // create a whole new desktop and window
365                 SPViewWidget *dtw = sp_desktop_widget_new(sp_document_namedview(doc, NULL));
366                 sp_create_window(dtw, TRUE);
367                 desktop = static_cast<SPDesktop*>(dtw->view);
368             } else {
369                 desktop = Inkscape::NSApplication::Editor::createDesktop (doc);
370             }
371         }
373         doc->virgin = FALSE;
374         // everyone who cares now has a reference, get rid of ours
375         sp_document_unref(doc);
376         // resize the window to match the document properties
377         sp_namedview_window_from_document(desktop);
378         sp_namedview_update_layers_from_document(desktop);
380         if (add_to_recent) {
381 //--tullarisc            prefs_set_recent_file(SP_DOCUMENT_URI(doc), SP_DOCUMENT_NAME(doc));
382         }
384         return TRUE;
385     } else {
386         //FIXME 1
387         //gchar *safeUri = Inkscape::IO::sanitizeString(uri.toNativeFilename());
388         //gchar *text = g_strdup_printf(_("Failed to load the requested file %s"), safeUri);
389         //sp_ui_error_dialog(text);
390         //g_free(text);
391         //g_free(safeUri);
392         return FALSE;
393     }
397 /**
398  *  Handle prompting user for "do you want to revert"?  Revert on "OK"
399  */
400 void
401 sp_file_revert_dialog()
403     SPDesktop  *desktop = SP_ACTIVE_DESKTOP;
404     g_assert(desktop != NULL);
406     Document *doc = sp_desktop_document(desktop);
407     g_assert(doc != NULL);
409     Inkscape::XML::Node     *repr = sp_document_repr_root(doc);
410     g_assert(repr != NULL);
412     gchar const *uri = doc->uri;
413     if (!uri) {
414         desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved yet.  Cannot revert."));
415         return;
416     }
418     bool do_revert = true;
419     if (doc->isModifiedSinceSave()) {
420         gchar *text = g_strdup_printf(_("Changes will be lost!  Are you sure you want to reload document %s?"), uri);
422         bool response = desktop->warnDialog (text);
423         g_free(text);
425         if (!response) {
426             do_revert = false;
427         }
428     }
430     bool reverted;
431     if (do_revert) {
432         // Allow overwriting of current document.
433         doc->virgin = TRUE;
435         // remember current zoom and view
436         double zoom = desktop->current_zoom();
437         Geom::Point c = desktop->get_display_area().midpoint();
439         reverted = sp_file_open(uri,NULL);
440         if (reverted) {
441             // restore zoom and view
442             desktop->zoom_absolute(c[Geom::X], c[Geom::Y], zoom);
443         }
444     } else {
445         reverted = false;
446     }
448     if (reverted) {
449         desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Document reverted."));
450     } else {
451         desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not reverted."));
452     }
455 void dump_str(gchar const *str, gchar const *prefix)
457     Glib::ustring tmp;
458     tmp = prefix;
459     tmp += " [";
460     size_t const total = strlen(str);
461     for (unsigned i = 0; i < total; i++) {
462         gchar *const tmp2 = g_strdup_printf(" %02x", (0x0ff & str[i]));
463         tmp += tmp2;
464         g_free(tmp2);
465     }
467     tmp += "]";
468     g_message("%s", tmp.c_str());
471 void dump_ustr(Glib::ustring const &ustr)
473     char const *cstr = ustr.c_str();
474     char const *data = ustr.data();
475     Glib::ustring::size_type const byteLen = ustr.bytes();
476     Glib::ustring::size_type const dataLen = ustr.length();
477     Glib::ustring::size_type const cstrLen = strlen(cstr);
479     g_message("   size: %lu\n   length: %lu\n   bytes: %lu\n    clen: %lu",
480               gulong(ustr.size()), gulong(dataLen), gulong(byteLen), gulong(cstrLen) );
481     g_message( "  ASCII? %s", (ustr.is_ascii() ? "yes":"no") );
482     g_message( "  UTF-8? %s", (ustr.validate() ? "yes":"no") );
484     try {
485         Glib::ustring tmp;
486         for (Glib::ustring::size_type i = 0; i < ustr.bytes(); i++) {
487             tmp = "    ";
488             if (i < dataLen) {
489                 Glib::ustring::value_type val = ustr.at(i);
490                 gchar* tmp2 = g_strdup_printf( (((val & 0xff00) == 0) ? "  %02x" : "%04x"), val );
491                 tmp += tmp2;
492                 g_free( tmp2 );
493             } else {
494                 tmp += "    ";
495             }
497             if (i < byteLen) {
498                 int val = (0x0ff & data[i]);
499                 gchar *tmp2 = g_strdup_printf("    %02x", val);
500                 tmp += tmp2;
501                 g_free( tmp2 );
502                 if ( val > 32 && val < 127 ) {
503                     tmp2 = g_strdup_printf( "   '%c'", (gchar)val );
504                     tmp += tmp2;
505                     g_free( tmp2 );
506                 } else {
507                     tmp += "    . ";
508                 }
509             } else {
510                 tmp += "       ";
511             }
513             if ( i < cstrLen ) {
514                 int val = (0x0ff & cstr[i]);
515                 gchar* tmp2 = g_strdup_printf("    %02x", val);
516                 tmp += tmp2;
517                 g_free(tmp2);
518                 if ( val > 32 && val < 127 ) {
519                     tmp2 = g_strdup_printf("   '%c'", (gchar) val);
520                     tmp += tmp2;
521                     g_free( tmp2 );
522                 } else {
523                     tmp += "    . ";
524                 }
525             } else {
526                 tmp += "            ";
527             }
529             g_message( "%s", tmp.c_str() );
530         }
531     } catch (...) {
532         g_message("XXXXXXXXXXXXXXXXXX Exception" );
533     }
534     g_message("---------------");
537 /**
538  *  Display an file Open selector.  Open a document if OK is pressed.
539  *  Can select single or multiple files for opening.
540  * NOTE1
541  */
542 void
543 sp_file_open_dialog(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*data*/)
545     //# Get the current directory for finding files
546     static Glib::ustring open_path;
547     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
549     if(open_path.empty())
550     {
551         Glib::ustring attr = prefs->getString("/dialogs/open/path");
552         if (!attr.empty()) open_path = attr;
553     }
555     //# Test if the open_path directory exists
556     if (!Inkscape::IO::file_test(open_path.c_str(),
557               (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
558         open_path = "";
560 #ifdef WIN32
561     //# If no open path, default to our win32 documents folder
562     if (open_path.empty())
563     {
564         // The path to the My Documents folder is read from the
565         // value "HKEY_CURRENT_USER\Software\Windows\CurrentVersion\Explorer\Shell Folders\Personal"
566         HKEY key = NULL;
567         if(RegOpenKeyExA(HKEY_CURRENT_USER,
568             "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
569             0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
570         {
571             WCHAR utf16path[_MAX_PATH];
572             DWORD value_type;
573             DWORD data_size = sizeof(utf16path);
574             if(RegQueryValueExW(key, L"Personal", NULL, &value_type,
575                 (BYTE*)utf16path, &data_size) == ERROR_SUCCESS)
576             {
577                 g_assert(value_type == REG_SZ);
578                 gchar *utf8path = g_utf16_to_utf8(
579                     (const gunichar2*)utf16path, -1, NULL, NULL, NULL);
580                 if(utf8path)
581                 {
582                     open_path = Glib::ustring(utf8path);
583                     g_free(utf8path);
584                 }
585             }
586         }
587     }
588 #endif
590     //# If no open path, default to our home directory
591     if (open_path.empty())
592     {
593         open_path = g_get_home_dir();
594         open_path.append(G_DIR_SEPARATOR_S);
595     }
597     //# Create a dialog
598     Inkscape::UI::Dialog::FileOpenDialog *openDialogInstance =
599               Inkscape::UI::Dialog::FileOpenDialog::create(
600                  parentWindow, open_path,
601                  Inkscape::UI::Dialog::SVG_TYPES,
602                  _("Select file to open"));
604     //# Show the dialog
605     bool const success = openDialogInstance->show();
607     //# Save the folder the user selected for later
608     open_path = openDialogInstance->getCurrentDirectory();
610     if (!success)
611     {
612         delete openDialogInstance;
613         return;
614     }
616     //# User selected something.  Get name and type
617     Glib::ustring fileName = openDialogInstance->getFilename();
619     Inkscape::Extension::Extension *selection =
620             openDialogInstance->getSelectionType();
622     //# Code to check & open if multiple files.
623     std::vector<Glib::ustring> flist = openDialogInstance->getFilenames();
625     //# We no longer need the file dialog object - delete it
626     delete openDialogInstance;
627     openDialogInstance = NULL;
629     //# Iterate through filenames if more than 1
630     if (flist.size() > 1)
631     {
632         for (unsigned int i = 0; i < flist.size(); i++)
633         {
634             fileName = flist[i];
636             Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
637             if ( newFileName.size() > 0 )
638                 fileName = newFileName;
639             else
640                 g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" );
642 #ifdef INK_DUMP_FILENAME_CONV
643             g_message("Opening File %s\n", fileName.c_str());
644 #endif
645             sp_file_open(fileName, selection);
646         }
648         return;
649     }
652     if (!fileName.empty())
653     {
654         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
656         if ( newFileName.size() > 0)
657             fileName = newFileName;
658         else
659             g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" );
661         open_path = Glib::path_get_dirname (fileName);
662         open_path.append(G_DIR_SEPARATOR_S);
663         prefs->setString("/dialogs/open/path", open_path);
665         sp_file_open_uri(Inkscape::URI(fileName.c_str()), selection);
666     }
668     return;
672 /*######################
673 ## V A C U U M
674 ######################*/
676 /**
677  * Remove unreferenced defs from the defs section of the document.
678  */
681 void
682 sp_file_vacuum()
684     Document *doc = SP_ACTIVE_DOCUMENT;
686     unsigned int diff = vacuum_document (doc);
688     sp_document_done(doc, SP_VERB_FILE_VACUUM,
689                      _("Vacuum &lt;defs&gt;"));
691     SPDesktop *dt = SP_ACTIVE_DESKTOP;
692     if (diff > 0) {
693         dt->messageStack()->flashF(Inkscape::NORMAL_MESSAGE,
694                 ngettext("Removed <b>%i</b> unused definition in &lt;defs&gt;.",
695                          "Removed <b>%i</b> unused definitions in &lt;defs&gt;.",
696                          diff),
697                 diff);
698     } else {
699         dt->messageStack()->flash(Inkscape::NORMAL_MESSAGE,  _("No unused definitions in &lt;defs&gt;."));
700     }
705 /*######################
706 ## S A V E
707 ######################*/
709 /**
710  * This 'save' function called by the others below
711  *
712  * \param    official  whether to set :output_module and :modified in the
713  *                     document; is true for normal save, false for temporary saves
714  */
715 static bool
716 file_save(Gtk::Window &parentWindow, Document *doc, const Glib::ustring &uri,
717           Inkscape::Extension::Extension *key, bool saveas, bool official)
719     if (!doc || uri.size()<1) //Safety check
720         return false;
722     try {
723         Inkscape::Extension::save(key, doc, uri.c_str(),
724                  false,
725                  saveas, official);
726     } catch (Inkscape::Extension::Output::no_extension_found &e) {
727         gchar *safeUri = Inkscape::IO::sanitizeString(uri.c_str());
728         gchar *text = g_strdup_printf(_("No Inkscape extension found to save document (%s).  This may have been caused by an unknown filename extension."), safeUri);
729         SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
730         sp_ui_error_dialog(text);
731         g_free(text);
732         g_free(safeUri);
733         return FALSE;
734     } catch (Inkscape::Extension::Output::save_failed &e) {
735         gchar *safeUri = Inkscape::IO::sanitizeString(uri.c_str());
736         gchar *text = g_strdup_printf(_("File %s could not be saved."), safeUri);
737         SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
738         sp_ui_error_dialog(text);
739         g_free(text);
740         g_free(safeUri);
741         return FALSE;
742     } catch (Inkscape::Extension::Output::save_cancelled &e) {
743         SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
744         return FALSE;
745     } catch (Inkscape::Extension::Output::no_overwrite &e) {
746         return sp_file_save_dialog(parentWindow, doc);
747     }
749     SP_ACTIVE_DESKTOP->event_log->rememberFileSave();
750     SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Document saved."));
751     return true;
754 /*
755  * Used only for remote saving using VFS and a specific uri. Gets the file at the /tmp.
756  */
757 bool
758 file_save_remote(Document */*doc*/,
759     #ifdef WITH_GNOME_VFS
760                  const Glib::ustring &uri,
761     #else
762                  const Glib::ustring &/*uri*/,
763     #endif
764                  Inkscape::Extension::Extension */*key*/, bool /*saveas*/, bool /*official*/)
766 #ifdef WITH_GNOME_VFS
768 #define BUF_SIZE 8192
769     gnome_vfs_init();
771     GnomeVFSHandle    *from_handle = NULL;
772     GnomeVFSHandle    *to_handle = NULL;
773     GnomeVFSFileSize  bytes_read;
774     GnomeVFSFileSize  bytes_written;
775     GnomeVFSResult    result;
776     guint8 buffer[8192];
778     gchar* uri_local = g_filename_from_utf8( uri.c_str(), -1, NULL, NULL, NULL);
780     if ( uri_local == NULL ) {
781         g_warning( "Error converting filename to locale encoding.");
782     }
784     // Gets the temp file name.
785     Glib::ustring fileName = Glib::get_tmp_dir ();
786     fileName.append(G_DIR_SEPARATOR_S);
787     fileName.append((gnome_vfs_uri_extract_short_name(gnome_vfs_uri_new(uri_local))));
789     // Open the temp file to send.
790     result = gnome_vfs_open (&from_handle, fileName.c_str(), GNOME_VFS_OPEN_READ);
792     if (result != GNOME_VFS_OK) {
793         g_warning("Could not find the temp saving.");
794         return false;
795     }
797     result = gnome_vfs_create (&to_handle, uri_local, GNOME_VFS_OPEN_WRITE, FALSE, GNOME_VFS_PERM_USER_ALL);
798     result = gnome_vfs_open (&to_handle, uri_local, GNOME_VFS_OPEN_WRITE);
800     if (result != GNOME_VFS_OK) {
801         g_warning("file creating: %s", gnome_vfs_result_to_string(result));
802         return false;
803     }
805     while (1) {
807         result = gnome_vfs_read (from_handle, buffer, 8192, &bytes_read);
809         if ((result == GNOME_VFS_ERROR_EOF) &&(!bytes_read)){
810             result = gnome_vfs_close (from_handle);
811             result = gnome_vfs_close (to_handle);
812             return true;
813         }
815         if (result != GNOME_VFS_OK) {
816             g_warning("%s", gnome_vfs_result_to_string(result));
817             return false;
818         }
819         result = gnome_vfs_write (to_handle, buffer, bytes_read, &bytes_written);
820         if (result != GNOME_VFS_OK) {
821             g_warning("%s", gnome_vfs_result_to_string(result));
822             return false;
823         }
826         if (bytes_read != bytes_written){
827             return false;
828         }
830     }
831     return true;
832 #else
833     // in case we do not have GNOME_VFS
834     return false;
835 #endif
840 /**
841  *  Display a SaveAs dialog.  Save the document if OK pressed.
842  *
843  * \param    ascopy  (optional) wether to set the documents->uri to the new filename or not
844  */
845 bool
846 sp_file_save_dialog(Gtk::Window &parentWindow, Document *doc, bool is_copy)
849     Inkscape::XML::Node *repr = sp_document_repr_root(doc);
850     Inkscape::Extension::Output *extension = 0;
851     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
853     //# Get the default extension name
854     Glib::ustring default_extension;
855     char *attr = (char *)repr->attribute("inkscape:output_extension");
856     if (!attr) {
857         Glib::ustring attr2 = prefs->getString("/dialogs/save_as/default");
858         if(!attr2.empty()) default_extension = attr2;
859     } else {
860         default_extension = attr;
861     }
862     //g_message("%s: extension name: '%s'", __FUNCTION__, default_extension);
864     Glib::ustring save_path;
865     Glib::ustring save_loc;
867     if (doc->uri == NULL) {
868         char formatBuf[256];
869         int i = 1;
871         Glib::ustring filename_extension = ".svg";
872         extension = dynamic_cast<Inkscape::Extension::Output *>
873               (Inkscape::Extension::db.get(default_extension.c_str()));
874         //g_warning("%s: extension ptr: 0x%x", __FUNCTION__, (unsigned int)extension);
875         if (extension)
876             filename_extension = extension->get_extension();
878         Glib::ustring attr3 = prefs->getString("/dialogs/save_as/path");
879         if (!attr3.empty())
880             save_path = attr3;
882         if (!Inkscape::IO::file_test(save_path.c_str(),
883               (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
884             save_path = "";
886         if (save_path.size()<1)
887             save_path = g_get_home_dir();
889         save_loc = save_path;
890         save_loc.append(G_DIR_SEPARATOR_S);
891         snprintf(formatBuf, 255, _("drawing%s"), filename_extension.c_str());
892         save_loc.append(formatBuf);
894         while (Inkscape::IO::file_test(save_loc.c_str(), G_FILE_TEST_EXISTS)) {
895             save_loc = save_path;
896             save_loc.append(G_DIR_SEPARATOR_S);
897             snprintf(formatBuf, 255, _("drawing-%d%s"), i++, filename_extension.c_str());
898             save_loc.append(formatBuf);
899         }
900     } else {
901         save_loc = Glib::build_filename(Glib::path_get_dirname(doc->uri),
902                                         Glib::path_get_basename(doc->uri));
903     }
905     // convert save_loc from utf-8 to locale
906     // is this needed any more, now that everything is handled in
907     // Inkscape::IO?
908     Glib::ustring save_loc_local = Glib::filename_from_utf8(save_loc);
910     if ( save_loc_local.size() > 0)
911         save_loc = save_loc_local;
913     //# Show the SaveAs dialog
914     char const * dialog_title;
915     if (is_copy) {
916         dialog_title = (char const *) _("Select file to save a copy to");
917     } else {
918         dialog_title = (char const *) _("Select file to save to");
919     }
920     gchar* doc_title = doc->root->title();
921     Inkscape::UI::Dialog::FileSaveDialog *saveDialog =
922         Inkscape::UI::Dialog::FileSaveDialog::create(
923             parentWindow,
924             save_loc,
925             Inkscape::UI::Dialog::SVG_TYPES,
926             dialog_title,
927             default_extension,
928             doc_title ? doc_title : ""
929             );
931     saveDialog->setSelectionType(extension);
933     bool success = saveDialog->show();
934     if (!success) {
935         delete saveDialog;
936         return success;
937     }
939     // set new title here (call RDF to ensure metadata and title element are updated)
940     rdf_set_work_entity(doc, rdf_find_entity("title"), saveDialog->getDocTitle().c_str());
941     // free up old string
942     if(doc_title) g_free(doc_title);
944     Glib::ustring fileName = saveDialog->getFilename();
945     Inkscape::Extension::Extension *selectionType = saveDialog->getSelectionType();
947     delete saveDialog;
949     saveDialog = 0;
951     if (fileName.size() > 0) {
952         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
954         if ( newFileName.size()>0 )
955             fileName = newFileName;
956         else
957             g_warning( "Error converting save filename to UTF-8." );
959         success = file_save(parentWindow, doc, fileName, selectionType, TRUE, !is_copy);
961         if (success && SP_DOCUMENT_URI(doc)) {
962             sp_file_add_recent(SP_DOCUMENT_URI(doc));
963         }
965         save_path = Glib::path_get_dirname(fileName);
966         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
967         prefs->setString("/dialogs/save_as/path", save_path);
969         return success;
970     }
973     return false;
977 /**
978  * Save a document, displaying a SaveAs dialog if necessary.
979  */
980 bool
981 sp_file_save_document(Gtk::Window &parentWindow, Document *doc)
983     bool success = true;
985     if (doc->isModifiedSinceSave()) {
986         Inkscape::XML::Node *repr = sp_document_repr_root(doc);
987         if ( doc->uri == NULL
988             || repr->attribute("inkscape:output_extension") == NULL )
989         {
990             return sp_file_save_dialog(parentWindow, doc, FALSE);
991         } else {
992             gchar const *fn = g_strdup(doc->uri);
993             gchar const *ext = repr->attribute("inkscape:output_extension");
994             success = file_save(parentWindow, doc, fn, Inkscape::Extension::db.get(ext), FALSE, TRUE);
995             g_free((void *) fn);
996         }
997     } else {
998         SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No changes need to be saved."));
999         success = TRUE;
1000     }
1002     return success;
1006 /**
1007  * Save a document.
1008  */
1009 bool
1010 sp_file_save(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*data*/)
1012     if (!SP_ACTIVE_DOCUMENT)
1013         return false;
1015     SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, _("Saving document..."));
1017     sp_namedview_document_from_window(SP_ACTIVE_DESKTOP);
1018     return sp_file_save_document(parentWindow, SP_ACTIVE_DOCUMENT);
1022 /**
1023  *  Save a document, always displaying the SaveAs dialog.
1024  */
1025 bool
1026 sp_file_save_as(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*data*/)
1028     if (!SP_ACTIVE_DOCUMENT)
1029         return false;
1030     sp_namedview_document_from_window(SP_ACTIVE_DESKTOP);
1031     return sp_file_save_dialog(parentWindow, SP_ACTIVE_DOCUMENT, FALSE);
1036 /**
1037  *  Save a copy of a document, always displaying a sort of SaveAs dialog.
1038  */
1039 bool
1040 sp_file_save_a_copy(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*data*/)
1042     if (!SP_ACTIVE_DOCUMENT)
1043         return false;
1044     sp_namedview_document_from_window(SP_ACTIVE_DESKTOP);
1045     return sp_file_save_dialog(parentWindow, SP_ACTIVE_DOCUMENT, TRUE);
1049 /*######################
1050 ## I M P O R T
1051 ######################*/
1053 /**
1054  *  Import a resource.  Called by sp_file_import()
1055  */
1056 void
1057 file_import(Document *in_doc, const Glib::ustring &uri,
1058                Inkscape::Extension::Extension *key)
1060     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
1062     //DEBUG_MESSAGE( fileImport, "file_import( in_doc:%p uri:[%s], key:%p", in_doc, uri, key );
1063     Document *doc;
1064     try {
1065         doc = Inkscape::Extension::open(key, uri.c_str());
1066     } catch (Inkscape::Extension::Input::no_extension_found &e) {
1067         doc = NULL;
1068     } catch (Inkscape::Extension::Input::open_failed &e) {
1069         doc = NULL;
1070     }
1072     if (doc != NULL) {
1073         Inkscape::XML::rebase_hrefs((Inkscape::XML::Document *)doc, in_doc->base, true);
1074         Inkscape::XML::Document *xml_in_doc = sp_document_repr_doc(in_doc);
1076         prevent_id_clashes(doc, in_doc);
1078         SPObject *in_defs = SP_DOCUMENT_DEFS(in_doc);
1079         Inkscape::XML::Node *last_def = SP_OBJECT_REPR(in_defs)->lastChild();
1081         SPCSSAttr *style = sp_css_attr_from_object(SP_DOCUMENT_ROOT(doc));
1083         // Count the number of top-level items in the imported document.
1084         guint items_count = 0;
1085         for (SPObject *child = sp_object_first_child(SP_DOCUMENT_ROOT(doc));
1086              child != NULL; child = SP_OBJECT_NEXT(child))
1087         {
1088             if (SP_IS_ITEM(child)) items_count++;
1089         }
1091         // Create a new group if necessary.
1092         Inkscape::XML::Node *newgroup = NULL;
1093         if ((style && style->firstChild()) || items_count > 1) {
1094             newgroup = xml_in_doc->createElement("svg:g");
1095             sp_repr_css_set(newgroup, style, "style");
1096         }
1098         // Determine the place to insert the new object.
1099         // This will be the current layer, if possible.
1100         // FIXME: If there's no desktop (command line run?) we need
1101         //        a document:: method to return the current layer.
1102         //        For now, we just use the root in this case.
1103         SPObject *place_to_insert;
1104         if (desktop) {
1105             place_to_insert = desktop->currentLayer();
1106         } else {
1107             place_to_insert = SP_DOCUMENT_ROOT(in_doc);
1108         }
1110         // Construct a new object representing the imported image,
1111         // and insert it into the current document.
1112         SPObject *new_obj = NULL;
1113         for (SPObject *child = sp_object_first_child(SP_DOCUMENT_ROOT(doc));
1114              child != NULL; child = SP_OBJECT_NEXT(child) )
1115         {
1116             if (SP_IS_ITEM(child)) {
1117                 Inkscape::XML::Node *newitem = SP_OBJECT_REPR(child)->duplicate(xml_in_doc);
1119                 // convert layers to groups, and make sure they are unlocked
1120                 // FIXME: add "preserve layers" mode where each layer from
1121                 //        import is copied to the same-named layer in host
1122                 newitem->setAttribute("inkscape:groupmode", NULL);
1123                 newitem->setAttribute("sodipodi:insensitive", NULL);
1125                 if (newgroup) newgroup->appendChild(newitem);
1126                 else new_obj = place_to_insert->appendChildRepr(newitem);
1127             }
1129             // don't lose top-level defs or style elements
1130             else if (SP_OBJECT_REPR(child)->type() == Inkscape::XML::ELEMENT_NODE) {
1131                 const gchar *tag = SP_OBJECT_REPR(child)->name();
1132                 if (!strcmp(tag, "svg:defs")) {
1133                     for (SPObject *x = sp_object_first_child(child);
1134                          x != NULL; x = SP_OBJECT_NEXT(x))
1135                     {
1136                         SP_OBJECT_REPR(in_defs)->addChild(SP_OBJECT_REPR(x)->duplicate(xml_in_doc), last_def);
1137                     }
1138                 }
1139                 else if (!strcmp(tag, "svg:style")) {
1140                     SP_DOCUMENT_ROOT(in_doc)->appendChildRepr(SP_OBJECT_REPR(child)->duplicate(xml_in_doc));
1141                 }
1142             }
1143         }
1144         if (newgroup) new_obj = place_to_insert->appendChildRepr(newgroup);
1146         // release some stuff
1147         if (newgroup) Inkscape::GC::release(newgroup);
1148         if (style) sp_repr_css_attr_unref(style);
1150         // select and move the imported item
1151         if (new_obj && SP_IS_ITEM(new_obj)) {
1152             Inkscape::Selection *selection = sp_desktop_selection(desktop);
1153             selection->set(SP_ITEM(new_obj));
1155             // preserve parent and viewBox transformations
1156             // c2p is identity matrix at this point unless sp_document_ensure_up_to_date is called
1157             sp_document_ensure_up_to_date(doc);
1158             Geom::Matrix affine = SP_ROOT(SP_DOCUMENT_ROOT(doc))->c2p * sp_item_i2doc_affine(SP_ITEM(place_to_insert)).inverse();
1159             sp_selection_apply_affine(selection, desktop->dt2doc() * affine * desktop->doc2dt(), true, false);
1161             // move to mouse pointer
1162             {
1163                 sp_document_ensure_up_to_date(sp_desktop_document(desktop));
1164                 Geom::OptRect sel_bbox = selection->bounds();
1165                 if (sel_bbox) {
1166                     Geom::Point m( desktop->point() - sel_bbox->midpoint() );
1167                     sp_selection_move_relative(selection, m, false);
1168                 }
1169             }
1170         }
1172         sp_document_unref(doc);
1173         sp_document_done(in_doc, SP_VERB_FILE_IMPORT,
1174                          _("Import"));
1176     } else {
1177         gchar *text = g_strdup_printf(_("Failed to load the requested file %s"), uri.c_str());
1178         sp_ui_error_dialog(text);
1179         g_free(text);
1180     }
1182     return;
1186 /**
1187  *  Display an Open dialog, import a resource if OK pressed.
1188  */
1189 void
1190 sp_file_import(Gtk::Window &parentWindow)
1192     static Glib::ustring import_path;
1194     Document *doc = SP_ACTIVE_DOCUMENT;
1195     if (!doc)
1196         return;
1198     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1200     if(import_path.empty())
1201     {
1202         Glib::ustring attr = prefs->getString("/dialogs/import/path");
1203         if (!attr.empty()) import_path = attr;
1204     }
1206     //# Test if the import_path directory exists
1207     if (!Inkscape::IO::file_test(import_path.c_str(),
1208               (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
1209         import_path = "";
1211     //# If no open path, default to our home directory
1212     if (import_path.empty())
1213     {
1214         import_path = g_get_home_dir();
1215         import_path.append(G_DIR_SEPARATOR_S);
1216     }
1218     // Create new dialog (don't use an old one, because parentWindow has probably changed)
1219     Inkscape::UI::Dialog::FileOpenDialog *importDialogInstance =
1220              Inkscape::UI::Dialog::FileOpenDialog::create(
1221                  parentWindow,
1222                  import_path,
1223                  Inkscape::UI::Dialog::IMPORT_TYPES,
1224                  (char const *)_("Select file to import"));
1226     bool success = importDialogInstance->show();
1227     if (!success) {
1228         delete importDialogInstance;
1229         return;
1230     }
1232     //# Get file name and extension type
1233     Glib::ustring fileName = importDialogInstance->getFilename();
1234     Inkscape::Extension::Extension *selection = importDialogInstance->getSelectionType();
1236     delete importDialogInstance;
1237     importDialogInstance = NULL;
1239     if (fileName.size() > 0) {
1241         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
1243         if ( newFileName.size() > 0)
1244             fileName = newFileName;
1245         else
1246             g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" );
1248         import_path = Glib::path_get_dirname (fileName);
1249         import_path.append(G_DIR_SEPARATOR_S);
1250         prefs->setString("/dialogs/import/path", import_path);
1252         file_import(doc, fileName, selection);
1253     }
1255     return;
1260 /*######################
1261 ## E X P O R T
1262 ######################*/
1264 //#define NEW_EXPORT_DIALOG
1268 #ifdef NEW_EXPORT_DIALOG
1270 /**
1271  *  Display an Export dialog, export as the selected type if OK pressed
1272  */
1273 bool
1274 sp_file_export_dialog(void *widget)
1276     //# temp hack for 'doc' until we can switch to this dialog
1277     Document *doc = SP_ACTIVE_DOCUMENT;
1279     Glib::ustring export_path;
1280     Glib::ustring export_loc;
1282     Inkscape::XML::Node *repr = sp_document_repr_root(doc);
1283     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1284     Inkscape::Extension::Output *extension;
1286     //# Get the default extension name
1287     Glib::ustring default_extension;
1288     char *attr = (char *)repr->attribute("inkscape:output_extension");
1289     if (!attr) {
1290         Glib::ustring attr2 = prefs->getString("/dialogs/save_as/default");
1291         if(!attr2.empty()) default_extension = attr2;
1292     } else {
1293         default_extension = attr;
1294     }
1295     //g_message("%s: extension name: '%s'", __FUNCTION__, default_extension);
1297     if (doc->uri == NULL)
1298         {
1299         char formatBuf[256];
1301         Glib::ustring filename_extension = ".svg";
1302         extension = dynamic_cast<Inkscape::Extension::Output *>
1303               (Inkscape::Extension::db.get(default_extension.c_str()));
1304         //g_warning("%s: extension ptr: 0x%x", __FUNCTION__, (unsigned int)extension);
1305         if (extension)
1306             filename_extension = extension->get_extension();
1308         Glib::ustring attr3 = prefs->getString("/dialogs/save_as/path");
1309         if (!attr3.empty())
1310             export_path = attr3;
1312         if (!Inkscape::IO::file_test(export_path.c_str(),
1313               (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
1314             export_path = "";
1316         if (export_path.size()<1)
1317             export_path = g_get_home_dir();
1319         export_loc = export_path;
1320         export_loc.append(G_DIR_SEPARATOR_S);
1321         snprintf(formatBuf, 255, _("drawing%s"), filename_extension.c_str());
1322         export_loc.append(formatBuf);
1324         }
1325     else
1326         {
1327         export_path = Glib::path_get_dirname(doc->uri);
1328         }
1330     // convert save_loc from utf-8 to locale
1331     // is this needed any more, now that everything is handled in
1332     // Inkscape::IO?
1333     Glib::ustring export_path_local = Glib::filename_from_utf8(export_path);
1334     if ( export_path_local.size() > 0)
1335         export_path = export_path_local;
1337     //# Show the SaveAs dialog
1338     Inkscape::UI::Dialog::FileExportDialog *exportDialogInstance =
1339         Inkscape::UI::Dialog::FileExportDialog::create(
1340             export_path,
1341             Inkscape::UI::Dialog::EXPORT_TYPES,
1342             (char const *) _("Select file to export to"),
1343             default_extension
1344         );
1346     bool success = exportDialogInstance->show();
1347     if (!success) {
1348         delete exportDialogInstance;
1349         return success;
1350     }
1352     Glib::ustring fileName = exportDialogInstance->getFilename();
1354     Inkscape::Extension::Extension *selectionType =
1355         exportDialogInstance->getSelectionType();
1357     delete exportDialogInstance;
1358     exportDialogInstance = NULL;
1360     if (fileName.size() > 0) {
1361         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
1363         if ( newFileName.size()>0 )
1364             fileName = newFileName;
1365         else
1366             g_warning( "Error converting save filename to UTF-8." );
1368         success = file_save(doc, fileName, selectionType, TRUE, FALSE);
1370         if (success) {
1371             Glib::RefPtr<Gtk::RecentManager> recent = Gtk::RecentManager::get_default();
1372             recent->add_item(SP_DOCUMENT_URI(doc));
1373         }
1375         export_path = fileName;
1376         prefs->setString("/dialogs/save_as/path", export_path);
1378         return success;
1379     }
1382     return false;
1385 #else
1387 /**
1388  *
1389  */
1390 bool
1391 sp_file_export_dialog(void */*widget*/)
1393     sp_export_dialog();
1394     return true;
1397 #endif
1399 /*######################
1400 ## E X P O R T  T O  O C A L
1401 ######################*/
1403 /**
1404  *  Display an Export dialog, export as the selected type if OK pressed
1405  */
1406 bool
1407 sp_file_export_to_ocal_dialog(Gtk::Window &parentWindow)
1410    if (!SP_ACTIVE_DOCUMENT)
1411         return false;
1413     Document *doc = SP_ACTIVE_DOCUMENT;
1415     Glib::ustring export_path;
1416     Glib::ustring export_loc;
1417     Glib::ustring fileName;
1418     Inkscape::Extension::Extension *selectionType;
1420     bool success = false;
1422     static bool gotSuccess = false;
1424     Inkscape::XML::Node *repr = sp_document_repr_root(doc);
1425     (void)repr;
1427     if (!doc->uri && !doc->isModifiedSinceSave())
1428         return false;
1430     //  Get the default extension name
1431     Glib::ustring default_extension = "org.inkscape.output.svg.inkscape";
1432     char formatBuf[256];
1434     Glib::ustring filename_extension = ".svg";
1435     selectionType = Inkscape::Extension::db.get(default_extension.c_str());
1437     export_path = Glib::get_tmp_dir ();
1439     export_loc = export_path;
1440     export_loc.append(G_DIR_SEPARATOR_S);
1441     snprintf(formatBuf, 255, _("drawing%s"), filename_extension.c_str());
1442     export_loc.append(formatBuf);
1444     // convert save_loc from utf-8 to locale
1445     // is this needed any more, now that everything is handled in
1446     // Inkscape::IO?
1447     Glib::ustring export_path_local = Glib::filename_from_utf8(export_path);
1448     if ( export_path_local.size() > 0)
1449         export_path = export_path_local;
1451     // Show the Export To OCAL dialog
1452     Inkscape::UI::Dialog::FileExportToOCALDialog *exportDialogInstance =
1453         new Inkscape::UI::Dialog::FileExportToOCALDialog(
1454                 parentWindow,
1455                 Inkscape::UI::Dialog::EXPORT_TYPES,
1456                 (char const *) _("Select file to export to")
1457                 );
1459     success = exportDialogInstance->show();
1460     if (!success) {
1461         delete exportDialogInstance;
1462         return success;
1463     }
1465     fileName = exportDialogInstance->getFilename();
1467     delete exportDialogInstance;
1468     exportDialogInstance = NULL;;
1470     fileName.append(filename_extension.c_str());
1471     if (fileName.size() > 0) {
1472         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
1474         if ( newFileName.size()>0 )
1475             fileName = newFileName;
1476         else
1477             g_warning( "Error converting save filename to UTF-8." );
1478     }
1479     Glib::ustring filePath = export_path;
1480     filePath.append(G_DIR_SEPARATOR_S);
1481     filePath.append(Glib::path_get_basename(fileName));
1483     fileName = filePath;
1485     success = file_save(parentWindow, doc, filePath, selectionType, FALSE, FALSE);
1487     if (!success){
1488         gchar *text = g_strdup_printf(_("Error saving a temporary copy"));
1489         sp_ui_error_dialog(text);
1491         return success;
1492     }
1494     // Start now the submition
1496     // Create the uri
1497     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1498     Glib::ustring uri = "dav://";
1499     Glib::ustring username = prefs->getString("/options/ocalusername/str");
1500     Glib::ustring password = prefs->getString("/options/ocalpassword/str");
1501     if (username.empty() || password.empty())
1502     {
1503         Inkscape::UI::Dialog::FileExportToOCALPasswordDialog *exportPasswordDialogInstance = NULL;
1504         if(!gotSuccess)
1505         {
1506             exportPasswordDialogInstance = new Inkscape::UI::Dialog::FileExportToOCALPasswordDialog(
1507                     parentWindow,
1508                     (char const *) _("Open Clip Art Login"));
1509             success = exportPasswordDialogInstance->show();
1510             if (!success) {
1511                 delete exportPasswordDialogInstance;
1512                 return success;
1513             }
1514         }
1515         username = exportPasswordDialogInstance->getUsername();
1516         password = exportPasswordDialogInstance->getPassword();
1518         delete exportPasswordDialogInstance;
1519         exportPasswordDialogInstance = NULL;
1520     }
1521     uri.append(username);
1522     uri.append(":");
1523     uri.append(password);
1524     uri.append("@");
1525     uri.append(prefs->getString("/options/ocalurl/str"));
1526     uri.append("/dav.php/");
1527     uri.append(Glib::path_get_basename(fileName));
1529     // Save as a remote file using the dav protocol.
1530     success = file_save_remote(doc, uri, selectionType, FALSE, FALSE);
1531     remove(fileName.c_str());
1532     if (!success)
1533     {
1534         gchar *text = g_strdup_printf(_("Error exporting the document. Verify if the server name, username and password are correct, if the server has support for webdav and verify if you didn't forget to choose a license."));
1535         sp_ui_error_dialog(text);
1536     }
1537     else
1538         gotSuccess = true;
1540     return success;
1543 /**
1544  * Export the current document to OCAL
1545  */
1546 void
1547 sp_file_export_to_ocal(Gtk::Window &parentWindow)
1550     // Try to execute the new code and return;
1551     if (!SP_ACTIVE_DOCUMENT)
1552         return;
1553     bool success = sp_file_export_to_ocal_dialog(parentWindow);
1554     if (success)
1555         SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, _("Document exported..."));
1559 /*######################
1560 ## I M P O R T  F R O M  O C A L
1561 ######################*/
1563 /**
1564  * Display an ImportToOcal Dialog, and the selected document from OCAL
1565  */
1566 void
1567 sp_file_import_from_ocal(Gtk::Window &parentWindow)
1569     static Glib::ustring import_path;
1571     Document *doc = SP_ACTIVE_DOCUMENT;
1572     if (!doc)
1573         return;
1575     Inkscape::UI::Dialog::FileImportFromOCALDialog *importDialogInstance = NULL;
1577     if (!importDialogInstance) {
1578         importDialogInstance = new
1579              Inkscape::UI::Dialog::FileImportFromOCALDialog(
1580                  parentWindow,
1581                  import_path,
1582                  Inkscape::UI::Dialog::IMPORT_TYPES,
1583                  (char const *)_("Import From Open Clip Art Library"));
1584     }
1586     bool success = importDialogInstance->show();
1587     if (!success) {
1588         delete importDialogInstance;
1589         return;
1590     }
1592     // Get file name and extension type
1593     Glib::ustring fileName = importDialogInstance->getFilename();
1594     Inkscape::Extension::Extension *selection = importDialogInstance->getSelectionType();
1596     delete importDialogInstance;
1597     importDialogInstance = NULL;
1599     if (fileName.size() > 0) {
1601         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
1603         if ( newFileName.size() > 0)
1604             fileName = newFileName;
1605         else
1606             g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" );
1608         import_path = fileName;
1609         if (import_path.size()>0)
1610             import_path.append(G_DIR_SEPARATOR_S);
1612         file_import(doc, fileName, selection);
1613     }
1615     return;
1618 /*######################
1619 ## P R I N T
1620 ######################*/
1623 /**
1624  *  Print the current document, if any.
1625  */
1626 void
1627 sp_file_print(Gtk::Window& parentWindow)
1629     Document *doc = SP_ACTIVE_DOCUMENT;
1630     if (doc)
1631         sp_print_document(parentWindow, doc);
1634 /**
1635  * Display what the drawing would look like, if
1636  * printed.
1637  */
1638 void
1639 sp_file_print_preview(gpointer /*object*/, gpointer /*data*/)
1642     Document *doc = SP_ACTIVE_DOCUMENT;
1643     if (doc)
1644         sp_print_preview_document(doc);
1649 /*
1650   Local Variables:
1651   mode:c++
1652   c-file-style:"stroustrup"
1653   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1654   indent-tabs-mode:nil
1655   fill-column:99
1656   End:
1657 */
1658 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :