Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / file.cpp
1 /** @file
2  * @brief File/Print operations
3  */
4 /* Authors:
5  *   Lauris Kaplinski <lauris@kaplinski.com>
6  *   Chema Celorio <chema@celorio.com>
7  *   bulia byak <buliabyak@users.sf.net>
8  *   Bruno Dilly <bruno.dilly@gmail.com>
9  *   Stephen Silver <sasilver@users.sourceforge.net>
10  *   Jon A. Cruz <jon@joncruz.org>
11  *   Abhishek Sharma
12  *
13  * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>
14  * Copyright (C) 1999-2008 Authors
15  * Copyright (C) 2004 David Turner
16  * Copyright (C) 2001-2002 Ximian, Inc.
17  *
18  * Released under GNU GPL, read the file 'COPYING' for more information
19  */
21 /** @file
22  * @note This file needs to be cleaned up extensively.
23  * What it probably needs is to have one .h file for
24  * the API, and two or more .cpp files for the implementations.
25  */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
31 #include <gtk/gtk.h>
32 #include <glib/gmem.h>
33 #include <glibmm/i18n.h>
34 #include <libnr/nr-pixops.h>
36 #include "desktop.h"
37 #include "desktop-handles.h"
38 #include "dialogs/export.h"
39 #include "dir-util.h"
40 #include "document-private.h"
41 #include "extension/db.h"
42 #include "extension/input.h"
43 #include "extension/output.h"
44 #include "extension/system.h"
45 #include "file.h"
46 #include "helper/png-write.h"
47 #include "id-clash.h"
48 #include "inkscape.h"
49 #include "inkscape.h"
50 #include "interface.h"
51 #include "io/sys.h"
52 #include "message.h"
53 #include "message-stack.h"
54 #include "path-prefix.h"
55 #include "preferences.h"
56 #include "print.h"
57 #include "rdf.h"
58 #include "selection-chemistry.h"
59 #include "selection.h"
60 #include "sp-namedview.h"
61 #include "style.h"
62 #include "ui/dialog/ocaldialogs.h"
63 #include "ui/view/view-widget.h"
64 #include "uri.h"
65 #include "xml/rebase-hrefs.h"
67 using Inkscape::DocumentUndo;
69 #ifdef WITH_GNOME_VFS
70 # include <libgnomevfs/gnome-vfs.h>
71 #endif
73 #ifdef WITH_DBUS
74 #include "extension/dbus/dbus-init.h"
75 #endif
77 //#ifdef WITH_INKBOARD
78 //#include "jabber_whiteboard/session-manager.h"
79 //#endif
81 #ifdef WIN32
82 #include <windows.h>
83 #endif
85 //#define INK_DUMP_FILENAME_CONV 1
86 #undef INK_DUMP_FILENAME_CONV
88 //#define INK_DUMP_FOPEN 1
89 #undef INK_DUMP_FOPEN
91 void dump_str(gchar const *str, gchar const *prefix);
92 void dump_ustr(Glib::ustring const &ustr);
94 // what gets passed here is not actually an URI... it is an UTF-8 encoded filename (!)
95 static void sp_file_add_recent(gchar const *uri)
96 {
97     if(uri == NULL) {
98         g_warning("sp_file_add_recent: uri == NULL");
99         return;
100     }
101     GtkRecentManager *recent = gtk_recent_manager_get_default();
102     gchar *fn = g_filename_from_utf8(uri, -1, NULL, NULL, NULL);
103     if (fn) {
104         gchar *uri_to_add = g_filename_to_uri(fn, NULL, NULL);
105         if (uri_to_add) {
106             gtk_recent_manager_add_item(recent, uri_to_add);
107             g_free(uri_to_add);
108         }
109         g_free(fn);
110     }
114 /*######################
115 ## N E W
116 ######################*/
118 /**
119  * Create a blank document and add it to the desktop
120  */
121 SPDesktop *sp_file_new(const Glib::ustring &templ)
123     SPDocument *doc = SPDocument::createNewDoc( !templ.empty() ? templ.c_str() : 0 , TRUE, true );
124     g_return_val_if_fail(doc != NULL, NULL);
126     SPViewWidget *dtw = sp_desktop_widget_new(sp_document_namedview(doc, NULL));
127     g_return_val_if_fail(dtw != NULL, NULL);
128     doc->doUnref();
130     sp_create_window(dtw, TRUE);
131     SPDesktop *dt = static_cast<SPDesktop *>(dtw->view);
132     sp_namedview_window_from_document(dt);
133     sp_namedview_update_layers_from_document(dt);
135 #ifdef WITH_DBUS
136     Inkscape::Extension::Dbus::dbus_init_desktop_interface(dt);
137 #endif
139     return dt;
142 SPDesktop* sp_file_new_default()
144     std::list<gchar *> sources;
145     sources.push_back( profile_path("templates") ); // first try user's local dir
146     sources.push_back( g_strdup(INKSCAPE_TEMPLATESDIR) ); // then the system templates dir
147     std::list<gchar const*> baseNames;
148     gchar const* localized = _("default.svg");
149     if (strcmp("default.svg", localized) != 0) {
150         baseNames.push_back(localized);
151     }
152     baseNames.push_back("default.svg");
153     gchar *foundTemplate = 0;
155     for (std::list<gchar const*>::iterator nameIt = baseNames.begin(); (nameIt != baseNames.end()) && !foundTemplate; ++nameIt) {
156         for (std::list<gchar *>::iterator it = sources.begin(); (it != sources.end()) && !foundTemplate; ++it) {
157             gchar *dirname = *it;
158             if ( Inkscape::IO::file_test( dirname, (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR) ) ) {
160                 // TRANSLATORS: default.svg is localizable - this is the name of the default document
161                 //  template. This way you can localize the default pagesize, translate the name of
162                 //  the default layer, etc. If you wish to localize this file, please create a
163                 //  localized share/templates/default.xx.svg file, where xx is your language code.
164                 char *tmp = g_build_filename(dirname, *nameIt, NULL);
165                 if (Inkscape::IO::file_test(tmp, G_FILE_TEST_IS_REGULAR)) {
166                     foundTemplate = tmp;
167                 } else {
168                     g_free(tmp);
169                 }
170             }
171         }
172     }
174     for (std::list<gchar *>::iterator it = sources.begin(); it != sources.end(); ++it) {
175         g_free(*it);
176     }
178     SPDesktop* desk = sp_file_new(foundTemplate ? foundTemplate : "");
179     if (foundTemplate) {
180         g_free(foundTemplate);
181         foundTemplate = 0;
182     }
183     return desk;
187 /*######################
188 ## D E L E T E
189 ######################*/
191 /**
192  *  Perform document closures preceding an exit()
193  */
194 void
195 sp_file_exit()
197     sp_ui_close_all();
198     // no need to call inkscape_exit here; last document being closed will take care of that
202 /*######################
203 ## O P E N
204 ######################*/
206 /**
207  *  Open a file, add the document to the desktop
208  *
209  *  \param replace_empty if true, and the current desktop is empty, this document
210  *  will replace the empty one.
211  */
212 bool
213 sp_file_open(const Glib::ustring &uri,
214              Inkscape::Extension::Extension *key,
215              bool add_to_recent, bool replace_empty)
217     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
218     if (desktop)
219         desktop->setWaitingCursor();
221     SPDocument *doc = NULL;
222     try {
223         doc = Inkscape::Extension::open(key, uri.c_str());
224     } catch (Inkscape::Extension::Input::no_extension_found &e) {
225         doc = NULL;
226     } catch (Inkscape::Extension::Input::open_failed &e) {
227         doc = NULL;
228     }
230     if (desktop)
231         desktop->clearWaitingCursor();
233     if (doc) {
234         SPDocument *existing = desktop ? sp_desktop_document(desktop) : NULL;
236         if (existing && existing->virgin && replace_empty) {
237             // If the current desktop is empty, open the document there
238             doc->ensureUpToDate();
239             desktop->change_document(doc);
240             doc->emitResizedSignal(doc->getWidth(), doc->getHeight());
241         } else {
242             // create a whole new desktop and window
243             SPViewWidget *dtw = sp_desktop_widget_new(sp_document_namedview(doc, NULL));
244             sp_create_window(dtw, TRUE);
245             desktop = static_cast<SPDesktop*>(dtw->view);
246         }
248         doc->virgin = FALSE;
249         // everyone who cares now has a reference, get rid of ours
250         doc->doUnref();
251         // resize the window to match the document properties
252         sp_namedview_window_from_document(desktop);
253         sp_namedview_update_layers_from_document(desktop);
255         if (add_to_recent) {
256             sp_file_add_recent( doc->getURI() );
257         }
259         return TRUE;
260     } else {
261         gchar *safeUri = Inkscape::IO::sanitizeString(uri.c_str());
262         gchar *text = g_strdup_printf(_("Failed to load the requested file %s"), safeUri);
263         sp_ui_error_dialog(text);
264         g_free(text);
265         g_free(safeUri);
266         return FALSE;
267     }
270 /**
271  *  Handle prompting user for "do you want to revert"?  Revert on "OK"
272  */
273 void sp_file_revert_dialog()
275     SPDesktop  *desktop = SP_ACTIVE_DESKTOP;
276     g_assert(desktop != NULL);
278     SPDocument *doc = sp_desktop_document(desktop);
279     g_assert(doc != NULL);
281     Inkscape::XML::Node *repr = doc->getReprRoot();
282     g_assert(repr != NULL);
284     gchar const *uri = doc->getURI();
285     if (!uri) {
286         desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved yet.  Cannot revert."));
287         return;
288     }
290     bool do_revert = true;
291     if (doc->isModifiedSinceSave()) {
292         gchar *text = g_strdup_printf(_("Changes will be lost!  Are you sure you want to reload document %s?"), uri);
294         bool response = desktop->warnDialog (text);
295         g_free(text);
297         if (!response) {
298             do_revert = false;
299         }
300     }
302     bool reverted;
303     if (do_revert) {
304         // Allow overwriting of current document.
305         doc->virgin = TRUE;
307         // remember current zoom and view
308         double zoom = desktop->current_zoom();
309         Geom::Point c = desktop->get_display_area().midpoint();
311         reverted = sp_file_open(uri,NULL);
312         if (reverted) {
313             // restore zoom and view
314             desktop->zoom_absolute(c[Geom::X], c[Geom::Y], zoom);
315         }
316     } else {
317         reverted = false;
318     }
320     if (reverted) {
321         desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Document reverted."));
322     } else {
323         desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not reverted."));
324     }
327 void dump_str(gchar const *str, gchar const *prefix)
329     Glib::ustring tmp;
330     tmp = prefix;
331     tmp += " [";
332     size_t const total = strlen(str);
333     for (unsigned i = 0; i < total; i++) {
334         gchar *const tmp2 = g_strdup_printf(" %02x", (0x0ff & str[i]));
335         tmp += tmp2;
336         g_free(tmp2);
337     }
339     tmp += "]";
340     g_message("%s", tmp.c_str());
343 void dump_ustr(Glib::ustring const &ustr)
345     char const *cstr = ustr.c_str();
346     char const *data = ustr.data();
347     Glib::ustring::size_type const byteLen = ustr.bytes();
348     Glib::ustring::size_type const dataLen = ustr.length();
349     Glib::ustring::size_type const cstrLen = strlen(cstr);
351     g_message("   size: %lu\n   length: %lu\n   bytes: %lu\n    clen: %lu",
352               gulong(ustr.size()), gulong(dataLen), gulong(byteLen), gulong(cstrLen) );
353     g_message( "  ASCII? %s", (ustr.is_ascii() ? "yes":"no") );
354     g_message( "  UTF-8? %s", (ustr.validate() ? "yes":"no") );
356     try {
357         Glib::ustring tmp;
358         for (Glib::ustring::size_type i = 0; i < ustr.bytes(); i++) {
359             tmp = "    ";
360             if (i < dataLen) {
361                 Glib::ustring::value_type val = ustr.at(i);
362                 gchar* tmp2 = g_strdup_printf( (((val & 0xff00) == 0) ? "  %02x" : "%04x"), val );
363                 tmp += tmp2;
364                 g_free( tmp2 );
365             } else {
366                 tmp += "    ";
367             }
369             if (i < byteLen) {
370                 int val = (0x0ff & data[i]);
371                 gchar *tmp2 = g_strdup_printf("    %02x", val);
372                 tmp += tmp2;
373                 g_free( tmp2 );
374                 if ( val > 32 && val < 127 ) {
375                     tmp2 = g_strdup_printf( "   '%c'", (gchar)val );
376                     tmp += tmp2;
377                     g_free( tmp2 );
378                 } else {
379                     tmp += "    . ";
380                 }
381             } else {
382                 tmp += "       ";
383             }
385             if ( i < cstrLen ) {
386                 int val = (0x0ff & cstr[i]);
387                 gchar* tmp2 = g_strdup_printf("    %02x", val);
388                 tmp += tmp2;
389                 g_free(tmp2);
390                 if ( val > 32 && val < 127 ) {
391                     tmp2 = g_strdup_printf("   '%c'", (gchar) val);
392                     tmp += tmp2;
393                     g_free( tmp2 );
394                 } else {
395                     tmp += "    . ";
396                 }
397             } else {
398                 tmp += "            ";
399             }
401             g_message( "%s", tmp.c_str() );
402         }
403     } catch (...) {
404         g_message("XXXXXXXXXXXXXXXXXX Exception" );
405     }
406     g_message("---------------");
409 /**
410  *  Display an file Open selector.  Open a document if OK is pressed.
411  *  Can select single or multiple files for opening.
412  */
413 void
414 sp_file_open_dialog(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*data*/)
416     //# Get the current directory for finding files
417     static Glib::ustring open_path;
418     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
420     if(open_path.empty())
421     {
422         Glib::ustring attr = prefs->getString("/dialogs/open/path");
423         if (!attr.empty()) open_path = attr;
424     }
426     //# Test if the open_path directory exists
427     if (!Inkscape::IO::file_test(open_path.c_str(),
428               (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
429         open_path = "";
431 #ifdef WIN32
432     //# If no open path, default to our win32 documents folder
433     if (open_path.empty())
434     {
435         // The path to the My Documents folder is read from the
436         // value "HKEY_CURRENT_USER\Software\Windows\CurrentVersion\Explorer\Shell Folders\Personal"
437         HKEY key = NULL;
438         if(RegOpenKeyExA(HKEY_CURRENT_USER,
439             "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
440             0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS)
441         {
442             WCHAR utf16path[_MAX_PATH];
443             DWORD value_type;
444             DWORD data_size = sizeof(utf16path);
445             if(RegQueryValueExW(key, L"Personal", NULL, &value_type,
446                 (BYTE*)utf16path, &data_size) == ERROR_SUCCESS)
447             {
448                 g_assert(value_type == REG_SZ);
449                 gchar *utf8path = g_utf16_to_utf8(
450                     (const gunichar2*)utf16path, -1, NULL, NULL, NULL);
451                 if(utf8path)
452                 {
453                     open_path = Glib::ustring(utf8path);
454                     g_free(utf8path);
455                 }
456             }
457         }
458     }
459 #endif
461     //# If no open path, default to our home directory
462     if (open_path.empty())
463     {
464         open_path = g_get_home_dir();
465         open_path.append(G_DIR_SEPARATOR_S);
466     }
468     //# Create a dialog
469     Inkscape::UI::Dialog::FileOpenDialog *openDialogInstance =
470               Inkscape::UI::Dialog::FileOpenDialog::create(
471                  parentWindow, open_path,
472                  Inkscape::UI::Dialog::SVG_TYPES,
473                  _("Select file to open"));
475     //# Show the dialog
476     bool const success = openDialogInstance->show();
478     //# Save the folder the user selected for later
479     open_path = openDialogInstance->getCurrentDirectory();
481     if (!success)
482     {
483         delete openDialogInstance;
484         return;
485     }
487     //# User selected something.  Get name and type
488     Glib::ustring fileName = openDialogInstance->getFilename();
490     Inkscape::Extension::Extension *selection =
491             openDialogInstance->getSelectionType();
493     //# Code to check & open if multiple files.
494     std::vector<Glib::ustring> flist = openDialogInstance->getFilenames();
496     //# We no longer need the file dialog object - delete it
497     delete openDialogInstance;
498     openDialogInstance = NULL;
500     //# Iterate through filenames if more than 1
501     if (flist.size() > 1)
502     {
503         for (unsigned int i = 0; i < flist.size(); i++)
504         {
505             fileName = flist[i];
507             Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
508             if ( newFileName.size() > 0 )
509                 fileName = newFileName;
510             else
511                 g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" );
513 #ifdef INK_DUMP_FILENAME_CONV
514             g_message("Opening File %s\n", fileName.c_str());
515 #endif
516             sp_file_open(fileName, selection);
517         }
519         return;
520     }
523     if (!fileName.empty())
524     {
525         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
527         if ( newFileName.size() > 0)
528             fileName = newFileName;
529         else
530             g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" );
532         open_path = Glib::path_get_dirname (fileName);
533         open_path.append(G_DIR_SEPARATOR_S);
534         prefs->setString("/dialogs/open/path", open_path);
536         sp_file_open(fileName, selection);
537     }
539     return;
543 /*######################
544 ## V A C U U M
545 ######################*/
547 /**
548  * Remove unreferenced defs from the defs section of the document.
549  */
550 void sp_file_vacuum()
552     SPDocument *doc = SP_ACTIVE_DOCUMENT;
554     unsigned int diff = doc->vacuumDocument();
556     DocumentUndo::done(doc, SP_VERB_FILE_VACUUM,
557                        _("Vacuum &lt;defs&gt;"));
559     SPDesktop *dt = SP_ACTIVE_DESKTOP;
560     if (diff > 0) {
561         dt->messageStack()->flashF(Inkscape::NORMAL_MESSAGE,
562                 ngettext("Removed <b>%i</b> unused definition in &lt;defs&gt;.",
563                          "Removed <b>%i</b> unused definitions in &lt;defs&gt;.",
564                          diff),
565                 diff);
566     } else {
567         dt->messageStack()->flash(Inkscape::NORMAL_MESSAGE,  _("No unused definitions in &lt;defs&gt;."));
568     }
573 /*######################
574 ## S A V E
575 ######################*/
577 /**
578  * This 'save' function called by the others below
579  *
580  * \param    official  whether to set :output_module and :modified in the
581  *                     document; is true for normal save, false for temporary saves
582  */
583 static bool
584 file_save(Gtk::Window &parentWindow, SPDocument *doc, const Glib::ustring &uri,
585           Inkscape::Extension::Extension *key, bool checkoverwrite, bool official,
586           Inkscape::Extension::FileSaveMethod save_method)
588     if (!doc || uri.size()<1) //Safety check
589         return false;
591     try {
592         Inkscape::Extension::save(key, doc, uri.c_str(),
593                                   false,
594                                   checkoverwrite, official,
595                                   save_method);
596     } catch (Inkscape::Extension::Output::no_extension_found &e) {
597         gchar *safeUri = Inkscape::IO::sanitizeString(uri.c_str());
598         gchar *text = g_strdup_printf(_("No Inkscape extension found to save document (%s).  This may have been caused by an unknown filename extension."), safeUri);
599         SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
600         sp_ui_error_dialog(text);
601         g_free(text);
602         g_free(safeUri);
603         return FALSE;
604     } catch (Inkscape::Extension::Output::file_read_only &e) {
605         gchar *safeUri = Inkscape::IO::sanitizeString(uri.c_str());
606         gchar *text = g_strdup_printf(_("File %s is write protected. Please remove write protection and try again."), safeUri);
607         SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
608         sp_ui_error_dialog(text);
609         g_free(text);
610         g_free(safeUri);
611         return FALSE;
612     } catch (Inkscape::Extension::Output::save_failed &e) {
613         gchar *safeUri = Inkscape::IO::sanitizeString(uri.c_str());
614         gchar *text = g_strdup_printf(_("File %s could not be saved."), safeUri);
615         SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
616         sp_ui_error_dialog(text);
617         g_free(text);
618         g_free(safeUri);
619         return FALSE;
620     } catch (Inkscape::Extension::Output::save_cancelled &e) {
621         SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
622         return FALSE;
623     } catch (Inkscape::Extension::Output::no_overwrite &e) {
624         return sp_file_save_dialog(parentWindow, doc, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS);
625     } catch (...) {
626         SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
627         return FALSE;
628     }
630     SP_ACTIVE_DESKTOP->event_log->rememberFileSave();
631     SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Document saved."));
632     return true;
635 /*
636  * Used only for remote saving using VFS and a specific uri. Gets the file at the /tmp.
637  */
638 bool
639 file_save_remote(SPDocument */*doc*/,
640     #ifdef WITH_GNOME_VFS
641                  const Glib::ustring &uri,
642     #else
643                  const Glib::ustring &/*uri*/,
644     #endif
645                  Inkscape::Extension::Extension */*key*/, bool /*saveas*/, bool /*official*/)
647 #ifdef WITH_GNOME_VFS
649 #define BUF_SIZE 8192
650     gnome_vfs_init();
652     GnomeVFSHandle    *from_handle = NULL;
653     GnomeVFSHandle    *to_handle = NULL;
654     GnomeVFSFileSize  bytes_read;
655     GnomeVFSFileSize  bytes_written;
656     GnomeVFSResult    result;
657     guint8 buffer[8192];
659     gchar* uri_local = g_filename_from_utf8( uri.c_str(), -1, NULL, NULL, NULL);
661     if ( uri_local == NULL ) {
662         g_warning( "Error converting filename to locale encoding.");
663     }
665     // Gets the temp file name.
666     Glib::ustring fileName = Glib::get_tmp_dir ();
667     fileName.append(G_DIR_SEPARATOR_S);
668     fileName.append((gnome_vfs_uri_extract_short_name(gnome_vfs_uri_new(uri_local))));
670     // Open the temp file to send.
671     result = gnome_vfs_open (&from_handle, fileName.c_str(), GNOME_VFS_OPEN_READ);
673     if (result != GNOME_VFS_OK) {
674         g_warning("Could not find the temp saving.");
675         return false;
676     }
678     result = gnome_vfs_create (&to_handle, uri_local, GNOME_VFS_OPEN_WRITE, FALSE, GNOME_VFS_PERM_USER_ALL);
679     result = gnome_vfs_open (&to_handle, uri_local, GNOME_VFS_OPEN_WRITE);
681     if (result != GNOME_VFS_OK) {
682         g_warning("file creating: %s", gnome_vfs_result_to_string(result));
683         return false;
684     }
686     while (1) {
688         result = gnome_vfs_read (from_handle, buffer, 8192, &bytes_read);
690         if ((result == GNOME_VFS_ERROR_EOF) &&(!bytes_read)){
691             result = gnome_vfs_close (from_handle);
692             result = gnome_vfs_close (to_handle);
693             return true;
694         }
696         if (result != GNOME_VFS_OK) {
697             g_warning("%s", gnome_vfs_result_to_string(result));
698             return false;
699         }
700         result = gnome_vfs_write (to_handle, buffer, bytes_read, &bytes_written);
701         if (result != GNOME_VFS_OK) {
702             g_warning("%s", gnome_vfs_result_to_string(result));
703             return false;
704         }
707         if (bytes_read != bytes_written){
708             return false;
709         }
711     }
712     return true;
713 #else
714     // in case we do not have GNOME_VFS
715     return false;
716 #endif
721 /**
722  *  Display a SaveAs dialog.  Save the document if OK pressed.
723  */
724 bool
725 sp_file_save_dialog(Gtk::Window &parentWindow, SPDocument *doc, Inkscape::Extension::FileSaveMethod save_method)
727     Inkscape::Extension::Output *extension = 0;
728     bool is_copy = (save_method == Inkscape::Extension::FILE_SAVE_METHOD_SAVE_COPY);
730     // Note: default_extension has the format "org.inkscape.output.svg.inkscape", whereas
731     //       filename_extension only uses ".svg"
732     Glib::ustring default_extension;
733     Glib::ustring filename_extension = ".svg";
735     default_extension= Inkscape::Extension::get_file_save_extension(save_method);
736     //g_message("%s: extension name: '%s'", __FUNCTION__, default_extension);
738     extension = dynamic_cast<Inkscape::Extension::Output *>
739         (Inkscape::Extension::db.get(default_extension.c_str()));
741     if (extension)
742         filename_extension = extension->get_extension();
744     Glib::ustring save_path;
745     Glib::ustring save_loc;
747     save_path = Inkscape::Extension::get_file_save_path(doc, save_method);
749     if (!Inkscape::IO::file_test(save_path.c_str(),
750           (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
751         save_path = "";
753     if (save_path.size()<1)
754         save_path = g_get_home_dir();
756     save_loc = save_path;
757     save_loc.append(G_DIR_SEPARATOR_S);
759     // TODO fixed buffer is bad:
760     char formatBuf[256];
761     int i = 1;
762     if ( !doc->getURI() ) {
763         // We are saving for the first time; create a unique default filename
764         snprintf(formatBuf, 255, _("drawing%s"), filename_extension.c_str());
765         save_loc.append(formatBuf);
767         while (Inkscape::IO::file_test(save_loc.c_str(), G_FILE_TEST_EXISTS)) {
768             save_loc = save_path;
769             save_loc.append(G_DIR_SEPARATOR_S);
770             snprintf(formatBuf, 255, _("drawing-%d%s"), i++, filename_extension.c_str());
771             save_loc.append(formatBuf);
772         }
773     } else {
774         snprintf(formatBuf, 255, _("%s"), Glib::path_get_basename(doc->getURI()).c_str());
775         save_loc.append(formatBuf);
776     }
778     // convert save_loc from utf-8 to locale
779     // is this needed any more, now that everything is handled in
780     // Inkscape::IO?
781     Glib::ustring save_loc_local = Glib::filename_from_utf8(save_loc);
783     if ( save_loc_local.size() > 0)
784         save_loc = save_loc_local;
786     //# Show the SaveAs dialog
787     char const * dialog_title;
788     if (is_copy) {
789         dialog_title = (char const *) _("Select file to save a copy to");
790     } else {
791         dialog_title = (char const *) _("Select file to save to");
792     }
793     gchar* doc_title = doc->root->title();
794     Inkscape::UI::Dialog::FileSaveDialog *saveDialog =
795         Inkscape::UI::Dialog::FileSaveDialog::create(
796             parentWindow,
797             save_loc,
798             Inkscape::UI::Dialog::SVG_TYPES,
799             dialog_title,
800             default_extension,
801             doc_title ? doc_title : "",
802             save_method
803             );
805     saveDialog->setSelectionType(extension);
807     bool success = saveDialog->show();
808     if (!success) {
809         delete saveDialog;
810         return success;
811     }
813     // set new title here (call RDF to ensure metadata and title element are updated)
814     rdf_set_work_entity(doc, rdf_find_entity("title"), saveDialog->getDocTitle().c_str());
815     // free up old string
816     if(doc_title) g_free(doc_title);
818     Glib::ustring fileName = saveDialog->getFilename();
819     Inkscape::Extension::Extension *selectionType = saveDialog->getSelectionType();
821     delete saveDialog;
823     saveDialog = 0;
825     if (fileName.size() > 0) {
826         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
828         if ( newFileName.size()>0 )
829             fileName = newFileName;
830         else
831             g_warning( "Error converting save filename to UTF-8." );
833         // FIXME: does the argument !is_copy really convey the correct meaning here?
834         success = file_save(parentWindow, doc, fileName, selectionType, TRUE, !is_copy, save_method);
836         if (success && doc->getURI()) {
837             sp_file_add_recent( doc->getURI() );
838         }
840         save_path = Glib::path_get_dirname(fileName);
841         Inkscape::Extension::store_save_path_in_prefs(save_path, save_method);
843         return success;
844     }
847     return false;
851 /**
852  * Save a document, displaying a SaveAs dialog if necessary.
853  */
854 bool
855 sp_file_save_document(Gtk::Window &parentWindow, SPDocument *doc)
857     bool success = true;
859     if (doc->isModifiedSinceSave()) {
860         if ( doc->getURI() == NULL )
861         {
862             // Hier sollte in Argument mitgegeben werden, das anzeigt, da� das Dokument das erste
863             // Mal gespeichert wird, so da� als default .svg ausgew�hlt wird und nicht die zuletzt
864             // benutzte "Save as ..."-Endung
865             return sp_file_save_dialog(parentWindow, doc, Inkscape::Extension::FILE_SAVE_METHOD_INKSCAPE_SVG);
866         } else {
867             Glib::ustring extension = Inkscape::Extension::get_file_save_extension(Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS);
868             Glib::ustring fn = g_strdup(doc->getURI());
869             // Try to determine the extension from the uri; this may not lead to a valid extension,
870             // but this case is caught in the file_save method below (or rather in Extension::save()
871             // further down the line).
872             Glib::ustring ext = "";
873             Glib::ustring::size_type pos = fn.rfind('.');
874             if (pos != Glib::ustring::npos) {
875                 // FIXME: this could/should be more sophisticated (see FileSaveDialog::appendExtension()),
876                 // but hopefully it's a reasonable workaround for now
877                 ext = fn.substr( pos );
878             }
879             success = file_save(parentWindow, doc, fn, Inkscape::Extension::db.get(ext.c_str()), FALSE, TRUE, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS);
880             if (success == false) {
881                 // give the user the chance to change filename or extension
882                 return sp_file_save_dialog(parentWindow, doc, Inkscape::Extension::FILE_SAVE_METHOD_INKSCAPE_SVG);
883             }
884         }
885     } else {
886         SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No changes need to be saved."));
887         success = TRUE;
888     }
890     return success;
894 /**
895  * Save a document.
896  */
897 bool
898 sp_file_save(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*data*/)
900     if (!SP_ACTIVE_DOCUMENT)
901         return false;
903     SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, _("Saving document..."));
905     sp_namedview_document_from_window(SP_ACTIVE_DESKTOP);
906     return sp_file_save_document(parentWindow, SP_ACTIVE_DOCUMENT);
910 /**
911  *  Save a document, always displaying the SaveAs dialog.
912  */
913 bool
914 sp_file_save_as(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*data*/)
916     if (!SP_ACTIVE_DOCUMENT)
917         return false;
918     sp_namedview_document_from_window(SP_ACTIVE_DESKTOP);
919     return sp_file_save_dialog(parentWindow, SP_ACTIVE_DOCUMENT, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS);
924 /**
925  *  Save a copy of a document, always displaying a sort of SaveAs dialog.
926  */
927 bool
928 sp_file_save_a_copy(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*data*/)
930     if (!SP_ACTIVE_DOCUMENT)
931         return false;
932     sp_namedview_document_from_window(SP_ACTIVE_DESKTOP);
933     return sp_file_save_dialog(parentWindow, SP_ACTIVE_DOCUMENT, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_COPY);
937 /*######################
938 ## I M P O R T
939 ######################*/
941 /**
942  *  Import a resource.  Called by sp_file_import()
943  */
944 void
945 file_import(SPDocument *in_doc, const Glib::ustring &uri,
946                Inkscape::Extension::Extension *key)
948     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
950     //DEBUG_MESSAGE( fileImport, "file_import( in_doc:%p uri:[%s], key:%p", in_doc, uri, key );
951     SPDocument *doc;
952     try {
953         doc = Inkscape::Extension::open(key, uri.c_str());
954     } catch (Inkscape::Extension::Input::no_extension_found &e) {
955         doc = NULL;
956     } catch (Inkscape::Extension::Input::open_failed &e) {
957         doc = NULL;
958     }
960     if (doc != NULL) {
961         Inkscape::XML::rebase_hrefs(doc, in_doc->getBase(), true);
962         Inkscape::XML::Document *xml_in_doc = in_doc->getReprDoc();
964         prevent_id_clashes(doc, in_doc);
966         SPObject *in_defs = SP_DOCUMENT_DEFS(in_doc);
967         Inkscape::XML::Node *last_def = SP_OBJECT_REPR(in_defs)->lastChild();
969         SPCSSAttr *style = sp_css_attr_from_object(doc->getRoot());
971         // Count the number of top-level items in the imported document.
972         guint items_count = 0;
973         for ( SPObject *child = doc->getRoot()->firstChild(); child; child = child->getNext()) {
974             if (SP_IS_ITEM(child)) {
975                 items_count++;
976             }
977         }
979         // Create a new group if necessary.
980         Inkscape::XML::Node *newgroup = NULL;
981         if ((style && style->firstChild()) || items_count > 1) {
982             newgroup = xml_in_doc->createElement("svg:g");
983             sp_repr_css_set(newgroup, style, "style");
984         }
986         // Determine the place to insert the new object.
987         // This will be the current layer, if possible.
988         // FIXME: If there's no desktop (command line run?) we need
989         //        a document:: method to return the current layer.
990         //        For now, we just use the root in this case.
991         SPObject *place_to_insert;
992         if (desktop) {
993             place_to_insert = desktop->currentLayer();
994         } else {
995             place_to_insert = in_doc->getRoot();
996         }
998         // Construct a new object representing the imported image,
999         // and insert it into the current document.
1000         SPObject *new_obj = NULL;
1001         for ( SPObject *child = doc->getRoot()->firstChild(); child; child = child->getNext() ) {
1002             if (SP_IS_ITEM(child)) {
1003                 Inkscape::XML::Node *newitem = SP_OBJECT_REPR(child)->duplicate(xml_in_doc);
1005                 // convert layers to groups, and make sure they are unlocked
1006                 // FIXME: add "preserve layers" mode where each layer from
1007                 //        import is copied to the same-named layer in host
1008                 newitem->setAttribute("inkscape:groupmode", NULL);
1009                 newitem->setAttribute("sodipodi:insensitive", NULL);
1011                 if (newgroup) newgroup->appendChild(newitem);
1012                 else new_obj = place_to_insert->appendChildRepr(newitem);
1013             }
1015             // don't lose top-level defs or style elements
1016             else if (SP_OBJECT_REPR(child)->type() == Inkscape::XML::ELEMENT_NODE) {
1017                 const gchar *tag = SP_OBJECT_REPR(child)->name();
1018                 if (!strcmp(tag, "svg:defs")) {
1019                     for ( SPObject *x = child->firstChild(); x; x = x->getNext() ) {
1020                         SP_OBJECT_REPR(in_defs)->addChild(SP_OBJECT_REPR(x)->duplicate(xml_in_doc), last_def);
1021                     }
1022                 }
1023                 else if (!strcmp(tag, "svg:style")) {
1024                     in_doc->getRoot()->appendChildRepr(SP_OBJECT_REPR(child)->duplicate(xml_in_doc));
1025                 }
1026             }
1027         }
1028         if (newgroup) new_obj = place_to_insert->appendChildRepr(newgroup);
1030         // release some stuff
1031         if (newgroup) Inkscape::GC::release(newgroup);
1032         if (style) sp_repr_css_attr_unref(style);
1034         // select and move the imported item
1035         if (new_obj && SP_IS_ITEM(new_obj)) {
1036             Inkscape::Selection *selection = sp_desktop_selection(desktop);
1037             selection->set(SP_ITEM(new_obj));
1039             // preserve parent and viewBox transformations
1040             // c2p is identity matrix at this point unless ensureUpToDate is called
1041             doc->ensureUpToDate();
1042             Geom::Matrix affine = SP_ROOT(doc->getRoot())->c2p * SP_ITEM(place_to_insert)->i2doc_affine().inverse();
1043             sp_selection_apply_affine(selection, desktop->dt2doc() * affine * desktop->doc2dt(), true, false);
1045             // move to mouse pointer
1046             {
1047                 sp_desktop_document(desktop)->ensureUpToDate();
1048                 Geom::OptRect sel_bbox = selection->bounds();
1049                 if (sel_bbox) {
1050                     Geom::Point m( desktop->point() - sel_bbox->midpoint() );
1051                     sp_selection_move_relative(selection, m, false);
1052                 }
1053             }
1054         }
1056         doc->doUnref();
1057         DocumentUndo::done(in_doc, SP_VERB_FILE_IMPORT,
1058                            _("Import"));
1060     } else {
1061         gchar *text = g_strdup_printf(_("Failed to load the requested file %s"), uri.c_str());
1062         sp_ui_error_dialog(text);
1063         g_free(text);
1064     }
1066     return;
1070 /**
1071  *  Display an Open dialog, import a resource if OK pressed.
1072  */
1073 void
1074 sp_file_import(Gtk::Window &parentWindow)
1076     static Glib::ustring import_path;
1078     SPDocument *doc = SP_ACTIVE_DOCUMENT;
1079     if (!doc)
1080         return;
1082     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1084     if(import_path.empty())
1085     {
1086         Glib::ustring attr = prefs->getString("/dialogs/import/path");
1087         if (!attr.empty()) import_path = attr;
1088     }
1090     //# Test if the import_path directory exists
1091     if (!Inkscape::IO::file_test(import_path.c_str(),
1092               (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
1093         import_path = "";
1095     //# If no open path, default to our home directory
1096     if (import_path.empty())
1097     {
1098         import_path = g_get_home_dir();
1099         import_path.append(G_DIR_SEPARATOR_S);
1100     }
1102     // Create new dialog (don't use an old one, because parentWindow has probably changed)
1103     Inkscape::UI::Dialog::FileOpenDialog *importDialogInstance =
1104              Inkscape::UI::Dialog::FileOpenDialog::create(
1105                  parentWindow,
1106                  import_path,
1107                  Inkscape::UI::Dialog::IMPORT_TYPES,
1108                  (char const *)_("Select file to import"));
1110     bool success = importDialogInstance->show();
1111     if (!success) {
1112         delete importDialogInstance;
1113         return;
1114     }
1116     //# Get file name and extension type
1117     Glib::ustring fileName = importDialogInstance->getFilename();
1118     Inkscape::Extension::Extension *selection = importDialogInstance->getSelectionType();
1120     delete importDialogInstance;
1121     importDialogInstance = NULL;
1123     if (fileName.size() > 0) {
1125         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
1127         if ( newFileName.size() > 0)
1128             fileName = newFileName;
1129         else
1130             g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" );
1132         import_path = Glib::path_get_dirname (fileName);
1133         import_path.append(G_DIR_SEPARATOR_S);
1134         prefs->setString("/dialogs/import/path", import_path);
1136         file_import(doc, fileName, selection);
1137     }
1139     return;
1144 /*######################
1145 ## E X P O R T
1146 ######################*/
1149 #ifdef NEW_EXPORT_DIALOG
1151 /**
1152  *  Display an Export dialog, export as the selected type if OK pressed
1153  */
1154 bool
1155 sp_file_export_dialog(Gtk::Window &parentWindow)
1157     //# temp hack for 'doc' until we can switch to this dialog
1158     SPDocument *doc = SP_ACTIVE_DOCUMENT;
1160     Glib::ustring export_path;
1161     Glib::ustring export_loc;
1163     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1164     Inkscape::Extension::Output *extension;
1166     //# Get the default extension name
1167     Glib::ustring default_extension = prefs->getString("/dialogs/save_export/default");
1168     if(default_extension.empty()) {
1169         // FIXME: Is this a good default? Should there be a macro for the string?
1170         default_extension = "org.inkscape.output.png.cairo";
1171     }
1172     //g_message("%s: extension name: '%s'", __FUNCTION__, default_extension);
1174     if (doc->uri == NULL)
1175         {
1176         char formatBuf[256];
1178         Glib::ustring filename_extension = ".svg";
1179         extension = dynamic_cast<Inkscape::Extension::Output *>
1180               (Inkscape::Extension::db.get(default_extension.c_str()));
1181         //g_warning("%s: extension ptr: 0x%x", __FUNCTION__, (unsigned int)extension);
1182         if (extension)
1183             filename_extension = extension->get_extension();
1185         Glib::ustring attr3 = prefs->getString("/dialogs/save_export/path");
1186         if (!attr3.empty())
1187             export_path = attr3;
1189         if (!Inkscape::IO::file_test(export_path.c_str(),
1190               (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)))
1191             export_path = "";
1193         if (export_path.size()<1)
1194             export_path = g_get_home_dir();
1196         export_loc = export_path;
1197         export_loc.append(G_DIR_SEPARATOR_S);
1198         snprintf(formatBuf, 255, _("drawing%s"), filename_extension.c_str());
1199         export_loc.append(formatBuf);
1201         }
1202     else
1203         {
1204         export_path = Glib::path_get_dirname(doc->uri);
1205         }
1207     // convert save_loc from utf-8 to locale
1208     // is this needed any more, now that everything is handled in
1209     // Inkscape::IO?
1210     Glib::ustring export_path_local = Glib::filename_from_utf8(export_path);
1211     if ( export_path_local.size() > 0)
1212         export_path = export_path_local;
1214     //# Show the Export dialog
1215     Inkscape::UI::Dialog::FileExportDialog *exportDialogInstance =
1216         Inkscape::UI::Dialog::FileExportDialog::create(
1217             parentWindow,
1218             export_path,
1219             Inkscape::UI::Dialog::EXPORT_TYPES,
1220             (char const *) _("Select file to export to"),
1221             default_extension
1222         );
1224     bool success = exportDialogInstance->show();
1225     if (!success) {
1226         delete exportDialogInstance;
1227         return success;
1228     }
1230     Glib::ustring fileName = exportDialogInstance->getFilename();
1232     Inkscape::Extension::Extension *selectionType =
1233         exportDialogInstance->getSelectionType();
1235     delete exportDialogInstance;
1236     exportDialogInstance = NULL;
1238     if (fileName.size() > 0) {
1239         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
1241         if ( newFileName.size()>0 )
1242             fileName = newFileName;
1243         else
1244             g_warning( "Error converting save filename to UTF-8." );
1246         success = file_save(parentWindow, doc, fileName, selectionType, TRUE, FALSE, Inkscape::Extension::FILE_SAVE_METHOD_EXPORT);
1248         if (success) {
1249             Glib::RefPtr<Gtk::RecentManager> recent = Gtk::RecentManager::get_default();
1250             recent->add_item( doc->getURI() );
1251         }
1253         export_path = fileName;
1254         prefs->setString("/dialogs/save_export/path", export_path);
1256         return success;
1257     }
1260     return false;
1263 #else
1265 /**
1266  *
1267  */
1268 bool
1269 sp_file_export_dialog(Gtk::Window &/*parentWindow*/)
1271     sp_export_dialog();
1272     return true;
1275 #endif
1277 /*######################
1278 ## E X P O R T  T O  O C A L
1279 ######################*/
1281 /**
1282  *  Display an Export dialog, export as the selected type if OK pressed
1283  */
1284 /*
1285 bool
1286 sp_file_export_to_ocal_dialog(Gtk::Window &parentWindow)
1289    if (!SP_ACTIVE_DOCUMENT)
1290         return false;
1292     SPDocument *doc = SP_ACTIVE_DOCUMENT;
1294     Glib::ustring export_path;
1295     Glib::ustring export_loc;
1296     Glib::ustring fileName;
1297     Inkscape::Extension::Extension *selectionType;
1299     bool success = false;
1301     static bool gotSuccess = false;
1303     Inkscape::XML::Node *repr = doc->getReprRoot();
1304     (void)repr;
1306     if (!doc->uri && !doc->isModifiedSinceSave())
1307         return false;
1309     //  Get the default extension name
1310     Glib::ustring default_extension = "org.inkscape.output.svg.inkscape";
1311     char formatBuf[256];
1313     Glib::ustring filename_extension = ".svg";
1314     selectionType = Inkscape::Extension::db.get(default_extension.c_str());
1316     export_path = Glib::get_tmp_dir ();
1318     export_loc = export_path;
1319     export_loc.append(G_DIR_SEPARATOR_S);
1320     snprintf(formatBuf, 255, _("drawing%s"), filename_extension.c_str());
1321     export_loc.append(formatBuf);
1323     // convert save_loc from utf-8 to locale
1324     // is this needed any more, now that everything is handled in
1325     // Inkscape::IO?
1326     Glib::ustring export_path_local = Glib::filename_from_utf8(export_path);
1327     if ( export_path_local.size() > 0)
1328         export_path = export_path_local;
1330     // Show the Export To OCAL dialog
1331     Inkscape::UI::Dialog::FileExportToOCALDialog *exportDialogInstance =
1332         new Inkscape::UI::Dialog::FileExportToOCALDialog(
1333                 parentWindow,
1334                 Inkscape::UI::Dialog::EXPORT_TYPES,
1335                 (char const *) _("Select file to export to")
1336                 );
1338     success = exportDialogInstance->show();
1339     if (!success) {
1340         delete exportDialogInstance;
1341         return success;
1342     }
1344     fileName = exportDialogInstance->getFilename();
1346     delete exportDialogInstance;
1347     exportDialogInstance = NULL;;
1349     fileName.append(filename_extension.c_str());
1350     if (fileName.size() > 0) {
1351         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
1353         if ( newFileName.size()>0 )
1354             fileName = newFileName;
1355         else
1356             g_warning( "Error converting save filename to UTF-8." );
1357     }
1358     Glib::ustring filePath = export_path;
1359     filePath.append(G_DIR_SEPARATOR_S);
1360     filePath.append(Glib::path_get_basename(fileName));
1362     fileName = filePath;
1364     success = file_save(parentWindow, doc, filePath, selectionType, FALSE, FALSE, Inkscape::Extension::FILE_SAVE_METHOD_EXPORT);
1366     if (!success){
1367         gchar *text = g_strdup_printf(_("Error saving a temporary copy"));
1368         sp_ui_error_dialog(text);
1370         return success;
1371     }
1373     // Start now the submition
1375     // Create the uri
1376     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1377     Glib::ustring uri = "dav://";
1378     Glib::ustring username = prefs->getString("/options/ocalusername/str");
1379     Glib::ustring password = prefs->getString("/options/ocalpassword/str");
1380     if (username.empty() || password.empty())
1381     {
1382         Inkscape::UI::Dialog::FileExportToOCALPasswordDialog *exportPasswordDialogInstance = NULL;
1383         if(!gotSuccess)
1384         {
1385             exportPasswordDialogInstance = new Inkscape::UI::Dialog::FileExportToOCALPasswordDialog(
1386                     parentWindow,
1387                     (char const *) _("Open Clip Art Login"));
1388             success = exportPasswordDialogInstance->show();
1389             if (!success) {
1390                 delete exportPasswordDialogInstance;
1391                 return success;
1392             }
1393         }
1394         username = exportPasswordDialogInstance->getUsername();
1395         password = exportPasswordDialogInstance->getPassword();
1397         delete exportPasswordDialogInstance;
1398         exportPasswordDialogInstance = NULL;
1399     }
1400     uri.append(username);
1401     uri.append(":");
1402     uri.append(password);
1403     uri.append("@");
1404     uri.append(prefs->getString("/options/ocalurl/str"));
1405     uri.append("/dav.php/");
1406     uri.append(Glib::path_get_basename(fileName));
1408     // Save as a remote file using the dav protocol.
1409     success = file_save_remote(doc, uri, selectionType, FALSE, FALSE);
1410     remove(fileName.c_str());
1411     if (!success)
1412     {
1413         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."));
1414         sp_ui_error_dialog(text);
1415     }
1416     else
1417         gotSuccess = true;
1419     return success;
1421 */
1422 /**
1423  * Export the current document to OCAL
1424  */
1425 /*
1426 void
1427 sp_file_export_to_ocal(Gtk::Window &parentWindow)
1430     // Try to execute the new code and return;
1431     if (!SP_ACTIVE_DOCUMENT)
1432         return;
1433     bool success = sp_file_export_to_ocal_dialog(parentWindow);
1434     if (success)
1435         SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::IMMEDIATE_MESSAGE, _("Document exported..."));
1437 */
1439 /*######################
1440 ## I M P O R T  F R O M  O C A L
1441 ######################*/
1443 /**
1444  * Display an ImportToOcal Dialog, and the selected document from OCAL
1445  */
1446 void
1447 sp_file_import_from_ocal(Gtk::Window &parentWindow)
1449     static Glib::ustring import_path;
1451     SPDocument *doc = SP_ACTIVE_DOCUMENT;
1452     if (!doc)
1453         return;
1455     Inkscape::UI::Dialog::FileImportFromOCALDialog *importDialogInstance = NULL;
1457     if (!importDialogInstance) {
1458         importDialogInstance = new
1459              Inkscape::UI::Dialog::FileImportFromOCALDialog(
1460                  parentWindow,
1461                  import_path,
1462                  Inkscape::UI::Dialog::IMPORT_TYPES,
1463                  (char const *)_("Import From Open Clip Art Library"));
1464     }
1466     bool success = importDialogInstance->show();
1467     if (!success) {
1468         delete importDialogInstance;
1469         return;
1470     }
1472     // Get file name and extension type
1473     Glib::ustring fileName = importDialogInstance->getFilename();
1474     Inkscape::Extension::Extension *selection = importDialogInstance->getSelectionType();
1476     delete importDialogInstance;
1477     importDialogInstance = NULL;
1479     if (fileName.size() > 0) {
1481         Glib::ustring newFileName = Glib::filename_to_utf8(fileName);
1483         if ( newFileName.size() > 0)
1484             fileName = newFileName;
1485         else
1486             g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" );
1488         import_path = fileName;
1489         if (import_path.size()>0)
1490             import_path.append(G_DIR_SEPARATOR_S);
1492         file_import(doc, fileName, selection);
1493     }
1495     return;
1498 /*######################
1499 ## P R I N T
1500 ######################*/
1503 /**
1504  *  Print the current document, if any.
1505  */
1506 void
1507 sp_file_print(Gtk::Window& parentWindow)
1509     SPDocument *doc = SP_ACTIVE_DOCUMENT;
1510     if (doc)
1511         sp_print_document(parentWindow, doc);
1514 /**
1515  * Display what the drawing would look like, if
1516  * printed.
1517  */
1518 void
1519 sp_file_print_preview(gpointer /*object*/, gpointer /*data*/)
1522     SPDocument *doc = SP_ACTIVE_DOCUMENT;
1523     if (doc)
1524         sp_print_preview_document(doc);
1529 /*
1530   Local Variables:
1531   mode:c++
1532   c-file-style:"stroustrup"
1533   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1534   indent-tabs-mode:nil
1535   fill-column:99
1536   End:
1537 */
1538 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :