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