1 /**\r
2 * Implementation of the file dialog interfaces defined in filedialogimpl.h\r
3 *\r
4 * Authors:\r
5 * Bob Jamison\r
6 * Joel Holdsworth\r
7 * Bruno Dilly\r
8 * Other dudes from The Inkscape Organization\r
9 *\r
10 * Copyright (C) 2004-2007 Bob Jamison\r
11 * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>\r
12 * Copyright (C) 2004-2007 The Inkscape Organization\r
13 * Copyright (C) 2007 Joel Holdsworth\r
14 *\r
15 * Released under GNU GPL, read the file 'COPYING' for more information\r
16 */\r
17 \r
18 #include "filedialog.h"\r
19 \r
20 //General includes\r
21 #include <unistd.h>\r
22 #include <sys/stat.h>\r
23 #include <errno.h>\r
24 #include <set>\r
25 #include <libxml/parser.h>\r
26 #include <libxml/tree.h>\r
27 \r
28 \r
29 //Gtk includes\r
30 #include <glibmm/i18n.h>\r
31 #include <glib/gstdio.h>\r
32 \r
33 //Temporary ugly hack\r
34 //Remove this after the get_filter() calls in\r
35 //show() on both classes are fixed\r
36 #include <gtk/gtkfilechooser.h>\r
37 \r
38 //Another hack\r
39 #include <gtk/gtkentry.h>\r
40 #include <gtk/gtkexpander.h>\r
41 #ifdef WITH_GNOME_VFS\r
42 # include <libgnomevfs/gnome-vfs-init.h> // gnome_vfs_initialized\r
43 #endif\r
44 \r
45 //Inkscape includes\r
46 #include "prefs-utils.h"\r
47 #include <extension/input.h>\r
48 #include <extension/output.h>\r
49 #include <extension/db.h>\r
50 #include "inkscape.h"\r
51 #include "svg-view-widget.h"\r
52 #include "gc-core.h"\r
53 \r
54 //For export dialog\r
55 #include "ui/widget/scalar-unit.h"\r
56 \r
57 namespace Inkscape\r
58 {\r
59 namespace UI\r
60 {\r
61 namespace Dialog\r
62 {
64 /*#########################################################################\r
65 ### Utility\r
66 #########################################################################*/
67 void\r
68 fileDialogExtensionToPattern(Glib::ustring &pattern,\r
69 Glib::ustring &extension);
70 \r
71 void\r
72 findEntryWidgets(Gtk::Container *parent,\r
73 std::vector<Gtk::Entry *> &result);
75 void\r
76 findExpanderWidgets(Gtk::Container *parent,\r
77 std::vector<Gtk::Expander *> &result);\r
78 \r
79 /*#########################################################################\r
80 ### SVG Preview Widget\r
81 #########################################################################*/
83 class FileType\r
84 {\r
85 public:\r
86 FileType() {}\r
87 ~FileType() {}\r
88 Glib::ustring name;\r
89 Glib::ustring pattern;\r
90 Inkscape::Extension::Extension *extension;\r
91 };\r
92 \r
93 /**\r
94 * Simple class for displaying an SVG file in the "preview widget."\r
95 * Currently, this is just a wrapper of the sp_svg_view Gtk widget.\r
96 * Hopefully we will eventually replace with a pure Gtkmm widget.\r
97 */\r
98 class SVGPreview : public Gtk::VBox\r
99 {\r
100 public:\r
101 \r
102 SVGPreview();\r
103 \r
104 ~SVGPreview();\r
105 \r
106 bool setDocument(SPDocument *doc);\r
107 \r
108 bool setFileName(Glib::ustring &fileName);\r
109 \r
110 bool setFromMem(char const *xmlBuffer);\r
111 \r
112 bool set(Glib::ustring &fileName, int dialogType);\r
113 \r
114 bool setURI(URI &uri);\r
115 \r
116 /**\r
117 * Show image embedded in SVG\r
118 */\r
119 void showImage(Glib::ustring &fileName);\r
120 \r
121 /**\r
122 * Show the "No preview" image\r
123 */\r
124 void showNoPreview();\r
125 \r
126 /**\r
127 * Show the "Too large" image\r
128 */\r
129 void showTooLarge(long fileLength);\r
130 \r
131 private:\r
132 /**\r
133 * The svg document we are currently showing\r
134 */\r
135 SPDocument *document;\r
136 \r
137 /**\r
138 * The sp_svg_view widget\r
139 */\r
140 GtkWidget *viewerGtk;\r
141 \r
142 /**\r
143 * are we currently showing the "no preview" image?\r
144 */\r
145 bool showingNoPreview;\r
146 \r
147 };\r
148 \r
149 /*#########################################################################\r
150 ### F I L E D I A L O G B A S E C L A S S\r
151 #########################################################################*/\r
152 \r
153 /**\r
154 * This class is the base implementation for the others. This\r
155 * reduces redundancies and bugs.\r
156 */\r
157 class FileDialogBaseGtk : public Gtk::FileChooserDialog\r
158 {\r
159 public:\r
160 \r
161 /**\r
162 *\r
163 */\r
164 FileDialogBaseGtk(Gtk::Window& parentWindow, const Glib::ustring &title,\r
165 FileDialogType type, gchar const* preferenceBase) :\r
166 Gtk::FileChooserDialog(parentWindow, title),\r
167 preferenceBase(preferenceBase ? preferenceBase : "unknown"),\r
168 dialogType(type)\r
169 {\r
170 internalSetup();\r
171 }\r
172 \r
173 /**\r
174 *\r
175 */\r
176 FileDialogBaseGtk(Gtk::Window& parentWindow, const Glib::ustring &title,\r
177 Gtk::FileChooserAction dialogType, FileDialogType type, gchar const* preferenceBase) :\r
178 Gtk::FileChooserDialog(parentWindow, title, dialogType),\r
179 preferenceBase(preferenceBase ? preferenceBase : "unknown"),\r
180 dialogType(type)\r
181 {\r
182 internalSetup();\r
183 }\r
184 \r
185 /**\r
186 *\r
187 */\r
188 virtual ~FileDialogBaseGtk()\r
189 {}\r
190 \r
191 protected:\r
192 void cleanup( bool showConfirmed );\r
193 \r
194 Glib::ustring preferenceBase;\r
195 /**\r
196 * What type of 'open' are we? (open, import, place, etc)\r
197 */\r
198 FileDialogType dialogType;\r
199 \r
200 /**\r
201 * Our svg preview widget\r
202 */\r
203 SVGPreview svgPreview;\r
204 \r
205 //# Child widgets\r
206 Gtk::CheckButton previewCheckbox;\r
207 \r
208 private:\r
209 void internalSetup();\r
210 \r
211 /**\r
212 * Callback for user changing preview checkbox\r
213 */\r
214 void _previewEnabledCB();\r
215 \r
216 /**\r
217 * Callback for seeing if the preview needs to be drawn\r
218 */\r
219 void _updatePreviewCallback();\r
220 };\r
221 \r
222 \r
223 \r
224 \r
225 /*#########################################################################\r
226 ### F I L E O P E N\r
227 #########################################################################*/\r
228 \r
229 /**\r
230 * Our implementation class for the FileOpenDialog interface..\r
231 */\r
232 class FileOpenDialogImplGtk : public FileOpenDialog, public FileDialogBaseGtk\r
233 {\r
234 public:\r
235 \r
236 FileOpenDialogImplGtk(Gtk::Window& parentWindow,\r
237 const Glib::ustring &dir,\r
238 FileDialogType fileTypes,\r
239 const Glib::ustring &title);\r
240 \r
241 virtual ~FileOpenDialogImplGtk();\r
242 \r
243 bool show();\r
244 \r
245 Inkscape::Extension::Extension *getSelectionType();\r
246 \r
247 Glib::ustring getFilename();\r
248 \r
249 std::vector<Glib::ustring> getFilenames ();\r
250 \r
251 private:\r
252 \r
253 /**\r
254 * Create a filter menu for this type of dialog\r
255 */\r
256 void createFilterMenu();\r
257 \r
258 /**\r
259 * Filter name->extension lookup\r
260 */\r
261 std::map<Glib::ustring, Inkscape::Extension::Extension *> extensionMap;\r
262 \r
263 /**\r
264 * The extension to use to write this file\r
265 */\r
266 Inkscape::Extension::Extension *extension;\r
267 \r
268 /**\r
269 * Filename that was given\r
270 */\r
271 Glib::ustring myFilename;\r
272 \r
273 };\r
274 \r
275 \r
276 \r
277 //########################################################################\r
278 //# F I L E S A V E\r
279 //########################################################################\r
280 \r
281 /**\r
282 * Our implementation of the FileSaveDialog interface.\r
283 */\r
284 class FileSaveDialogImplGtk : public FileSaveDialog, public FileDialogBaseGtk\r
285 {\r
286 \r
287 public:\r
288 FileSaveDialogImplGtk(Gtk::Window &parentWindow, \r
289 const Glib::ustring &dir,\r
290 FileDialogType fileTypes,\r
291 const Glib::ustring &title,\r
292 const Glib::ustring &default_key);\r
293 \r
294 virtual ~FileSaveDialogImplGtk();\r
295 \r
296 bool show();\r
297 \r
298 Inkscape::Extension::Extension *getSelectionType();\r
299 virtual void setSelectionType( Inkscape::Extension::Extension * key );\r
300 \r
301 Glib::ustring getFilename();\r
302 \r
303 void change_title(const Glib::ustring& title);\r
304 void change_path(const Glib::ustring& path);\r
305 void updateNameAndExtension();\r
306 \r
307 private:\r
308 \r
309 /**\r
310 * Fix to allow the user to type the file name\r
311 */\r
312 Gtk::Entry *fileNameEntry;\r
313 \r
314 \r
315 /**\r
316 * Allow the specification of the output file type\r
317 */\r
318 Gtk::ComboBoxText fileTypeComboBox;\r
319 \r
320 \r
321 /**\r
322 * Data mirror of the combo box\r
323 */\r
324 std::vector<FileType> fileTypes;\r
325 \r
326 //# Child widgets\r
327 Gtk::HBox childBox;\r
328 Gtk::VBox checksBox;\r
329 \r
330 Gtk::CheckButton fileTypeCheckbox;\r
331 \r
332 /**\r
333 * Callback for user input into fileNameEntry\r
334 */\r
335 void fileTypeChangedCallback();\r
336 \r
337 /**\r
338 * Create a filter menu for this type of dialog\r
339 */\r
340 void createFileTypeMenu();\r
341 \r
342 \r
343 /**\r
344 * The extension to use to write this file\r
345 */\r
346 Inkscape::Extension::Extension *extension;\r
347 \r
348 /**\r
349 * Callback for user input into fileNameEntry\r
350 */\r
351 void fileNameEntryChangedCallback();\r
352 \r
353 /**\r
354 * Filename that was given\r
355 */\r
356 Glib::ustring myFilename;\r
357 \r
358 /**\r
359 * List of known file extensions.\r
360 */\r
361 std::set<Glib::ustring> knownExtensions;\r
362 };\r
363 \r
364 \r
365 \r
366 \r
367 //########################################################################\r
368 //# F I L E E X P O R T\r
369 //########################################################################\r
370 \r
371 /**\r
372 * Our implementation of the FileExportDialog interface.\r
373 */\r
374 class FileExportDialogImpl : public FileExportDialog, public FileDialogBaseGtk\r
375 {\r
376 \r
377 public:\r
378 FileExportDialogImpl(Gtk::Window& parentWindow,\r
379 const Glib::ustring &dir,\r
380 FileDialogType fileTypes,\r
381 const Glib::ustring &title,\r
382 const Glib::ustring &default_key);\r
383 \r
384 virtual ~FileExportDialogImpl();\r
385 \r
386 bool show();\r
387 \r
388 Inkscape::Extension::Extension *getSelectionType();\r
389 \r
390 Glib::ustring getFilename();\r
391 \r
392 \r
393 /**\r
394 * Return the scope of the export. One of the enumerated types\r
395 * in ScopeType \r
396 */\r
397 ScopeType getScope()\r
398 { \r
399 if (pageButton.get_active())\r
400 return SCOPE_PAGE;\r
401 else if (selectionButton.get_active())\r
402 return SCOPE_SELECTION;\r
403 else if (customButton.get_active())\r
404 return SCOPE_CUSTOM;\r
405 else\r
406 return SCOPE_DOCUMENT;\r
407 \r
408 }\r
409 \r
410 /**\r
411 * Return left side of the exported region\r
412 */\r
413 double getSourceX()\r
414 { return sourceX0Spinner.getValue(); }\r
415 \r
416 /**\r
417 * Return the top of the exported region\r
418 */\r
419 double getSourceY()\r
420 { return sourceY1Spinner.getValue(); }\r
421 \r
422 /**\r
423 * Return the width of the exported region\r
424 */\r
425 double getSourceWidth()\r
426 { return sourceWidthSpinner.getValue(); }\r
427 \r
428 /**\r
429 * Return the height of the exported region\r
430 */\r
431 double getSourceHeight()\r
432 { return sourceHeightSpinner.getValue(); }\r
433 \r
434 /**\r
435 * Return the units of the coordinates of exported region\r
436 */\r
437 Glib::ustring getSourceUnits()\r
438 { return sourceUnitsSpinner.getUnitAbbr(); }\r
439 \r
440 /**\r
441 * Return the width of the destination document\r
442 */\r
443 double getDestinationWidth()\r
444 { return destWidthSpinner.getValue(); }\r
445 \r
446 /**\r
447 * Return the height of the destination document\r
448 */\r
449 double getDestinationHeight()\r
450 { return destHeightSpinner.getValue(); }\r
451 \r
452 /**\r
453 * Return the height of the exported region\r
454 */\r
455 Glib::ustring getDestinationUnits()\r
456 { return destUnitsSpinner.getUnitAbbr(); }\r
457 \r
458 /**\r
459 * Return the destination DPI image resulution, if bitmap\r
460 */\r
461 double getDestinationDPI()\r
462 { return destDPISpinner.getValue(); }\r
463 \r
464 /**\r
465 * Return whether we should use Cairo for rendering\r
466 */\r
467 bool getUseCairo()\r
468 { return cairoButton.get_active(); }\r
469 \r
470 /**\r
471 * Return whether we should use antialiasing\r
472 */\r
473 bool getUseAntialias()\r
474 { return antiAliasButton.get_active(); }\r
475 \r
476 /**\r
477 * Return the background color for exporting\r
478 */\r
479 unsigned long getBackground()\r
480 { return backgroundButton.get_color().get_pixel(); }\r
481 \r
482 private:\r
483 \r
484 /**\r
485 * Fix to allow the user to type the file name\r
486 */\r
487 Gtk::Entry *fileNameEntry;\r
488 \r
489 //##########################################\r
490 //# EXTRA WIDGET -- SOURCE SIDE\r
491 //##########################################\r
492 \r
493 Gtk::Frame sourceFrame;\r
494 Gtk::VBox sourceBox;\r
495 \r
496 Gtk::HBox scopeBox;\r
497 Gtk::RadioButtonGroup scopeGroup;\r
498 Gtk::RadioButton documentButton;\r
499 Gtk::RadioButton pageButton;\r
500 Gtk::RadioButton selectionButton;\r
501 Gtk::RadioButton customButton;\r
502 \r
503 Gtk::Table sourceTable;\r
504 Inkscape::UI::Widget::Scalar sourceX0Spinner;\r
505 Inkscape::UI::Widget::Scalar sourceY0Spinner;\r
506 Inkscape::UI::Widget::Scalar sourceX1Spinner;\r
507 Inkscape::UI::Widget::Scalar sourceY1Spinner;\r
508 Inkscape::UI::Widget::Scalar sourceWidthSpinner;\r
509 Inkscape::UI::Widget::Scalar sourceHeightSpinner;\r
510 Inkscape::UI::Widget::UnitMenu sourceUnitsSpinner;\r
511 \r
512 \r
513 //##########################################\r
514 //# EXTRA WIDGET -- DESTINATION SIDE\r
515 //##########################################\r
516 \r
517 Gtk::Frame destFrame;\r
518 Gtk::VBox destBox;\r
519 \r
520 Gtk::Table destTable;\r
521 Inkscape::UI::Widget::Scalar destWidthSpinner;\r
522 Inkscape::UI::Widget::Scalar destHeightSpinner;\r
523 Inkscape::UI::Widget::Scalar destDPISpinner;\r
524 Inkscape::UI::Widget::UnitMenu destUnitsSpinner;\r
525 \r
526 Gtk::HBox otherOptionBox;\r
527 Gtk::CheckButton cairoButton;\r
528 Gtk::CheckButton antiAliasButton;\r
529 Gtk::ColorButton backgroundButton;\r
530 \r
531 \r
532 /**\r
533 * 'Extra' widget that holds two boxes above\r
534 */\r
535 Gtk::HBox exportOptionsBox;\r
536 \r
537 \r
538 //# Child widgets\r
539 Gtk::CheckButton fileTypeCheckbox;\r
540 \r
541 /**\r
542 * Allow the specification of the output file type\r
543 */\r
544 Gtk::ComboBoxText fileTypeComboBox;\r
545 \r
546 \r
547 /**\r
548 * Data mirror of the combo box\r
549 */\r
550 std::vector<FileType> fileTypes;\r
551 \r
552 \r
553 \r
554 /**\r
555 * Callback for user input into fileNameEntry\r
556 */\r
557 void fileTypeChangedCallback();\r
558 \r
559 /**\r
560 * Create a filter menu for this type of dialog\r
561 */\r
562 void createFileTypeMenu();\r
563 \r
564 \r
565 bool append_extension;\r
566 \r
567 /**\r
568 * The extension to use to write this file\r
569 */\r
570 Inkscape::Extension::Extension *extension;\r
571 \r
572 /**\r
573 * Callback for user input into fileNameEntry\r
574 */\r
575 void fileNameEntryChangedCallback();\r
576 \r
577 /**\r
578 * Filename that was given\r
579 */\r
580 Glib::ustring myFilename;\r
581 };\r
582 \r
583 \r
585 }\r
586 }\r
587 }\r
588 \r
589 /*\r
590 Local Variables:\r
591 mode:c++\r
592 c-file-style:"stroustrup"\r
593 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
594 indent-tabs-mode:nil\r
595 fill-column:99\r
596 End:\r
597 */\r
598 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r