Code

search and reset buttons added to ocal related features. fixed signals in import...
[inkscape.git] / src / ui / dialog / ocaldialogs.cpp
1 /**
2  * Implementation of the ocal dialog interfaces defined in ocaldialog.h
3  *
4  * Authors:
5  *   Bruno Dilly
6  *   Other dudes from The Inkscape Organization
7  *
8  * Copyright (C) 2007 Bruno Dilly <bruno.dilly@gmail.com>
9  *
10  * Released under GNU GPL, read the file 'COPYING' for more information
11  */
13 #ifdef HAVE_CONFIG_H
14 # include <config.h>
15 #endif
17 #include "ocaldialogs.h"
18 #include "filedialogimpl-gtkmm.h"
19 #include "interface.h"
20 #include "gc-core.h"
21 #include <dialogs/dialog-events.h>
23 namespace Inkscape
24 {
25 namespace UI
26 {
27 namespace Dialog
28 {
30 //########################################################################
31 //# F I L E    E X P O R T   T O   O C A L
32 //########################################################################
35 /**
36  * Public factory method.  Used in file.cpp
37  */
39  FileExportToOCALDialog *FileExportToOCALDialog::create(Gtk::Window& parentWindow, 
40                                            FileDialogType fileTypes,
41                                            const Glib::ustring &title)
42 {
43     FileExportToOCALDialog *dialog = new FileExportToOCALDialogImpl(parentWindow, fileTypes, title);
44     return dialog;
45 }
47 //########################################################################
48 //# F I L E    E X P O R T   T O   O C A L   P A S S W O R D
49 //########################################################################
52 /**
53  * Public factory method.  Used in file.cpp
54  */
56 FileExportToOCALPasswordDialog *FileExportToOCALPasswordDialog::create(Gtk::Window& parentWindow,
57                                                         const Glib::ustring &title)
58 {
59     FileExportToOCALPasswordDialog *dialog = new FileExportToOCALPasswordDialogImpl(parentWindow, title);
60     return dialog;
61 }
64 //#########################################################################
65 //### F I L E    I M P O R T  F R O M  O C A L
66 //#########################################################################
68 /**
69  * Public factory.  Called by file.cpp.
70  */
71 FileImportFromOCALDialog *FileImportFromOCALDialog::create(Gtk::Window &parentWindow,
72                                        const Glib::ustring &path,
73                                        FileDialogType fileTypes,
74                                        const Glib::ustring &title)
75 {
76     FileImportFromOCALDialog *dialog = new FileImportFromOCALDialogImplGtk(parentWindow, path, fileTypes, title);
77     return dialog;
78 }
81 //########################################################################
82 //# F I L E    E X P O R T   T O   O C A L
83 //########################################################################
87 /**
88  * Callback for fileNameEntry widget
89  */
90 void FileExportToOCALDialogImpl::fileNameEntryChangedCallback()
91 {
92     if (!fileNameEntry)
93         return;
95     Glib::ustring fileName = fileNameEntry->get_text();
96     if (!Glib::get_charset()) //If we are not utf8
97         fileName = Glib::filename_to_utf8(fileName);
99     myFilename = fileName;
100     response(Gtk::RESPONSE_OK);
106 /**
107  * Constructor
108  */
109 FileExportToOCALDialogImpl::FileExportToOCALDialogImpl(Gtk::Window &parentWindow,
110             FileDialogType fileTypes,
111             const Glib::ustring &title) :
112     FileDialogOCALBase(title)
114     /*
115      * Start Taking the vertical Box and putting a Label
116      * and a Entry to take the filename
117      * Later put the extension selection and checkbox (?)
118      */
119     /* Initalize to Autodetect */
120     extension = NULL;
121     /* No filename to start out with */
122     myFilename = "";
124     /* Set our dialog type (save, export, etc...)*/
125     dialogType = fileTypes;
126     Gtk::VBox *vbox = get_vbox();
128     Gtk::Label *fileLabel = new Gtk::Label(_("File"));
130     fileNameEntry = new Gtk::Entry();
131     fileNameEntry->set_text(myFilename);
132     fileNameEntry->set_max_length(252); // I am giving the extension approach.
133     fileBox.pack_start(*fileLabel);
134     fileBox.pack_start(*fileNameEntry, Gtk::PACK_EXPAND_WIDGET, 3);
135     vbox->pack_start(fileBox);
137     //Let's do some customization
138     fileNameEntry = NULL;
139     Gtk::Container *cont = get_toplevel();
140     std::vector<Gtk::Entry *> entries;
141     findEntryWidgets(cont, entries);
142     if (entries.size() >=1 )
143         {
144         //Catch when user hits [return] on the text field
145         fileNameEntry = entries[0];
146         fileNameEntry->signal_activate().connect(
147              sigc::mem_fun(*this, &FileExportToOCALDialogImpl::fileNameEntryChangedCallback) );
148         }
150     add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
151     set_default(*add_button(Gtk::Stock::SAVE,   Gtk::RESPONSE_OK));
153     show_all_children();
158 /**
159  * Destructor
160  */
161 FileExportToOCALDialogImpl::~FileExportToOCALDialogImpl()
165 /**
166  * Show this dialog modally.  Return true if user hits [OK]
167  */
168 bool
169 FileExportToOCALDialogImpl::show()
171     set_modal (TRUE);                      //Window
172     sp_transientize((GtkWidget *)gobj());  //Make transient
173     gint b = run();                        //Dialog
174     hide();
176     if (b == Gtk::RESPONSE_OK)
177     {
178         return TRUE;
179         }
180     else
181         {
182         return FALSE;
183         }
186 /**
187  * Get the file name chosen by the user.   Valid after an [OK]
188  */
189 Glib::ustring
190 FileExportToOCALDialogImpl::getFilename()
192     myFilename = fileNameEntry->get_text();
193     if (!Glib::get_charset()) //If we are not utf8
194         myFilename = Glib::filename_to_utf8(myFilename);
196     return myFilename;
200 void
201 FileExportToOCALDialogImpl::change_title(const Glib::ustring& title)
203     this->set_title(title);
207 //########################################################################
208 //# F I L E    E X P O R T   T O   O C A L   P A S S W O R D
209 //########################################################################
212 /**
213  * Constructor
214  */
215 FileExportToOCALPasswordDialogImpl::FileExportToOCALPasswordDialogImpl(Gtk::Window &parentWindow,
216                              const Glib::ustring &title) : FileDialogOCALBase(title)
218     /*
219      * Start Taking the vertical Box and putting 2 Labels
220      * and 2 Entries to take the username and password
221      */
222     /* No username and password to start out with */
223     myUsername = "";
224     myPassword = "";
226     Gtk::VBox *vbox = get_vbox();
228     Gtk::Label *userLabel = new Gtk::Label(_("Username:"));
229     Gtk::Label *passLabel = new Gtk::Label(_("Password:"));
231     usernameEntry = new Gtk::Entry();
232     usernameEntry->set_text(myUsername);
233     usernameEntry->set_max_length(255);
235     passwordEntry = new Gtk::Entry();
236     passwordEntry->set_text(myPassword);
237     passwordEntry->set_max_length(255);
238     passwordEntry->set_invisible_char('*');
239     passwordEntry->set_visibility(false);
240     passwordEntry->set_activates_default(true);
242     userBox.pack_start(*userLabel);
243     userBox.pack_start(*usernameEntry, Gtk::PACK_EXPAND_WIDGET, 3);
244     vbox->pack_start(userBox);
246     passBox.pack_start(*passLabel);
247     passBox.pack_start(*passwordEntry, Gtk::PACK_EXPAND_WIDGET, 3);
248     vbox->pack_start(passBox);
249     
250     add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
251     set_default(*add_button(Gtk::Stock::OK,   Gtk::RESPONSE_OK));
253     show_all_children();
257 /**
258  * Destructor
259  */
260 FileExportToOCALPasswordDialogImpl::~FileExportToOCALPasswordDialogImpl()
264 /**
265  * Show this dialog modally.  Return true if user hits [OK]
266  */
267 bool
268 FileExportToOCALPasswordDialogImpl::show()
270     set_modal (TRUE);                      //Window
271     sp_transientize((GtkWidget *)gobj());  //Make transient
272     gint b = run();                        //Dialog
273     hide();
275     if (b == Gtk::RESPONSE_OK)
276     {
277         return TRUE;
278     }
279     else
280     {
281         return FALSE;
282     }
285 /**
286  * Get the username.   Valid after an [OK]
287  */
288 Glib::ustring
289 FileExportToOCALPasswordDialogImpl::getUsername()
291     myUsername = usernameEntry->get_text();
292     return myUsername;
295 /**
296  * Get the password.   Valid after an [OK]
297  */
298 Glib::ustring
299 FileExportToOCALPasswordDialogImpl::getPassword()
301     myPassword = passwordEntry->get_text();
302     return myPassword;
305 void
306 FileExportToOCALPasswordDialogImpl::change_title(const Glib::ustring& title)
308     this->set_title(title);
312 //#########################################################################
313 //### F I L E   I M P O R T   F R O M   O C A L
314 //#########################################################################
316 /*
317  * Calalback for cursor chage
318  */
319 void FileListViewText::on_cursor_changed()
321     // create file path
322     myFilename = Glib::get_tmp_dir();
323     myFilename.append(G_DIR_SEPARATOR_S);
324     std::vector<Gtk::TreeModel::Path> pathlist;
325     pathlist = this->get_selection()->get_selected_rows();
326     std::vector<int> posArray(1);
327     posArray = pathlist[0].get_indices();
328     myFilename.append(get_text(posArray[0], 2));
330 #ifdef WITH_GNOME_VFS
331     gnome_vfs_init();
332     GnomeVFSHandle    *from_handle = NULL;
333     GnomeVFSHandle    *to_handle = NULL;
334     GnomeVFSFileSize  bytes_read;
335     GnomeVFSFileSize  bytes_written;
336     GnomeVFSResult    result;
337     guint8 buffer[8192];
339     //get file url
340     Glib::ustring fileUrl = get_text(posArray[0], 1); //http url
342     //Glib::ustring fileUrl = "dav://"; //dav url
343     //fileUrl.append(prefs_get_string_attribute("options.ocalurl", "str"));
344     //fileUrl.append("/dav.php/");
345     //fileUrl.append(get_text(posArray[0], 3)); //author dir
346     //fileUrl.append("/");
347     //fileUrl.append(get_text(posArray[0], 2)); //filename
349     if (!Glib::get_charset()) //If we are not utf8
350         fileUrl = Glib::filename_to_utf8(fileUrl);
352     // verifies if the file wasn't previously downloaded
353     if(gnome_vfs_open(&to_handle, myFilename.c_str(), GNOME_VFS_OPEN_READ) == GNOME_VFS_ERROR_NOT_FOUND)
354     {
355         // open the temp file to receive
356         result = gnome_vfs_open (&to_handle, myFilename.c_str(), GNOME_VFS_OPEN_WRITE);
357         if (result == GNOME_VFS_ERROR_NOT_FOUND){
358             result = gnome_vfs_create (&to_handle, myFilename.c_str(), GNOME_VFS_OPEN_WRITE, FALSE, GNOME_VFS_PERM_USER_ALL);
359         }
360         if (result != GNOME_VFS_OK) {
361             g_warning("Error creating temp file: %s", gnome_vfs_result_to_string(result));
362             return;
363         }
364         result = gnome_vfs_open (&from_handle, fileUrl.c_str(), GNOME_VFS_OPEN_READ);
365         if (result != GNOME_VFS_OK) {
366             g_warning("Could not find the file in Open Clip Art Library.");
367             return;
368         }
369         // copy the file
370         while (1) {
371             result = gnome_vfs_read (from_handle, buffer, 8192, &bytes_read);
372             if ((result == GNOME_VFS_ERROR_EOF) &&(!bytes_read)){
373                 result = gnome_vfs_close (from_handle);
374                 result = gnome_vfs_close (to_handle);
375                 break;
376             }
377             if (result != GNOME_VFS_OK) {
378                 g_warning("%s", gnome_vfs_result_to_string(result));
379                 return;
380             }
381             result = gnome_vfs_write (to_handle, buffer, bytes_read, &bytes_written);
382             if (result != GNOME_VFS_OK) {
383                 g_warning("%s", gnome_vfs_result_to_string(result));
384                 return;
385             }
386             if (bytes_read != bytes_written){
387                 g_warning("Bytes read not equal to bytes written");
388                 return;
389             }
390         }
391     }
392     else
393     {
394         gnome_vfs_close(to_handle);
395     }
396     myPreview->showImage(myFilename);
397     myLabel->set_text(get_text(posArray[0], 4));
398 #endif
402 /*
403  * Callback for row activated
404  */
405 void FileListViewText::on_row_activated(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column)
407     this->on_cursor_changed();
408     myButton->activate();
412 /*
413  * Returns the selected filename
414  */
415 Glib::ustring FileListViewText::getFilename()
417     return myFilename;
420 /**
421  * Callback for user input into searchTagEntry
422  */
423 void FileImportFromOCALDialogImplGtk::searchTagEntryChangedCallback()
425     if (!searchTagEntry)
426         return;
428     notFoundLabel->hide();
429     descriptionLabel->set_text("");
431     Glib::ustring searchTag = searchTagEntry->get_text();
432     // create the ocal uri to get rss feed
433     Glib::ustring uri = "http://";
434     uri.append(prefs_get_string_attribute("options.ocalurl", "str"));
435     uri.append("/media/feed/rss/");
436     uri.append(searchTag);
437     if (!Glib::get_charset()) //If we are not utf8
438         uri = Glib::filename_to_utf8(uri);
440 #ifdef WITH_GNOME_VFS
442     // get the rss feed
443     gnome_vfs_init();
444     GnomeVFSHandle    *from_handle = NULL;
445     GnomeVFSHandle    *to_handle = NULL;
446     GnomeVFSFileSize  bytes_read;
447     GnomeVFSFileSize  bytes_written;
448     GnomeVFSResult    result;
449     guint8 buffer[8192];
451     // create the temp file name
452     Glib::ustring fileName = Glib::get_tmp_dir ();
453     fileName.append(G_DIR_SEPARATOR_S);
454     fileName.append("ocalfeed.xml");
456     // open the temp file to receive
457     result = gnome_vfs_open (&to_handle, fileName.c_str(), GNOME_VFS_OPEN_WRITE);
458     if (result == GNOME_VFS_ERROR_NOT_FOUND){
459         result = gnome_vfs_create (&to_handle, fileName.c_str(), GNOME_VFS_OPEN_WRITE, FALSE, GNOME_VFS_PERM_USER_ALL);
460     }
461     if (result != GNOME_VFS_OK) {
462         g_warning("Error creating temp file: %s", gnome_vfs_result_to_string(result));
463         return;
464     }
466     // open the rss feed
467     result = gnome_vfs_open (&from_handle, uri.c_str(), GNOME_VFS_OPEN_READ);
468     if (result != GNOME_VFS_OK) {
469         sp_ui_error_dialog(_("Failed to receive the Open Clip Art Library RSS feed. Verify if the server name is correct in Configuration->Misc (e.g.: openclipart.org)"));
470         return;
471     }
473     // copy the file
474     while (1) {
476         result = gnome_vfs_read (from_handle, buffer, 8192, &bytes_read);
478         if ((result == GNOME_VFS_ERROR_EOF) &&(!bytes_read)){
479             result = gnome_vfs_close (from_handle);
480             result = gnome_vfs_close (to_handle);
481             break;
482         }
484         if (result != GNOME_VFS_OK) {
485             g_warning("%s", gnome_vfs_result_to_string(result));
486             return;
487         }
488         result = gnome_vfs_write (to_handle, buffer, bytes_read, &bytes_written);
489         if (result != GNOME_VFS_OK) {
490             g_warning("%s", gnome_vfs_result_to_string(result));
491             return;
492         }
494         if (bytes_read != bytes_written){
495             g_warning("Bytes read not equal to bytes written");
496             return;
497         }
499     }
501     // create the resulting xml document tree
502     // this initialize the library and test mistakes between compiled and shared library used
503     LIBXML_TEST_VERSION 
504     xmlDoc *doc = NULL;
505     xmlNode *root_element = NULL;
506     doc = xmlReadFile(fileName.c_str(), NULL, 0);
507     if (doc == NULL) {
508         g_warning("Failed to parse %s\n", fileName.c_str());
509     return;
510     }
511     
512     // get the root element node
513     root_element = xmlDocGetRootElement(doc);
515     // clear the fileslist
516     filesList->clear_items();
517     filesList->set_sensitive(false);
519     // print all xml the element names
520     print_xml_element_names(root_element);
522     if (filesList->size() == 0)
523     {
524         notFoundLabel->show();
525         filesList->set_sensitive(false);
526     }
527     else
528         filesList->set_sensitive(true);
530     // free the document
531     xmlFreeDoc(doc);
532     // free the global variables that may have been allocated by the parser
533     xmlCleanupParser();
534     return;
535 #endif    
538 /**
539  * Prints the names of the all the xml elements 
540  * that are siblings or children of a given xml node
541  */
542 void FileImportFromOCALDialogImplGtk::print_xml_element_names(xmlNode * a_node)
544     xmlNode *cur_node = NULL;
545     guint row_num = 0;
546     for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
547         // get itens information
548         if (strcmp((const char*)cur_node->name, "rss")) //avoid the root
549             if (cur_node->type == XML_ELEMENT_NODE && !strcmp((const char*)cur_node->parent->name, "item"))
550             {
551                 if (!strcmp((const char*)cur_node->name, "title"))
552                 {
553                     xmlChar *title = xmlNodeGetContent(cur_node);
554                     row_num = filesList->append_text((const char*)title);
555                     xmlFree(title);
556                 }
557 #ifdef WITH_GNOME_VFS
558                 else if (!strcmp((const char*)cur_node->name, "enclosure"))
559                 {
560                     xmlChar *urlattribute = xmlGetProp(cur_node, (xmlChar*)"url");
561                     filesList->set_text(row_num, 1, (const char*)urlattribute);
562                     gchar *tmp_file;
563                     tmp_file = gnome_vfs_uri_extract_short_path_name(gnome_vfs_uri_new((const char*)urlattribute));
564                     filesList->set_text(row_num, 2, (const char*)tmp_file);
565                     xmlFree(urlattribute);
566                 }
567                 else if (!strcmp((const char*)cur_node->name, "creator"))
568                 {
569                     filesList->set_text(row_num, 3, (const char*)xmlNodeGetContent(cur_node));
570                 }
571                 else if (!strcmp((const char*)cur_node->name, "description"))
572                 {
573                     filesList->set_text(row_num, 4, (const char*)xmlNodeGetContent(cur_node));
574                 }
575 #endif
576             }
577         print_xml_element_names(cur_node->children);
578     }
581 /**
582  * Constructor.  Not called directly.  Use the factory.
583  */
584 FileImportFromOCALDialogImplGtk::FileImportFromOCALDialogImplGtk(Gtk::Window& parentWindow, 
585                                        const Glib::ustring &dir,
586                                        FileDialogType fileTypes,
587                                        const Glib::ustring &title) :
588      FileDialogOCALBase(title)
590     // Initalize to Autodetect
591     extension = NULL;
592     // No filename to start out with
593     Glib::ustring searchTag = "";
595     dialogType = fileTypes;
596     Gtk::VBox *vbox = get_vbox();
597     Gtk::Label *tagLabel = new Gtk::Label(_("Search Tag"));
598     notFoundLabel = new Gtk::Label(_("No files matched your search"));
599     descriptionLabel = new Gtk::Label();
600     descriptionLabel->set_max_width_chars(60);
601     descriptionLabel->set_single_line_mode(false);
602     messageBox.pack_start(*notFoundLabel);
603     descriptionBox.pack_start(*descriptionLabel);
604     searchTagEntry = new Gtk::Entry();
605     searchTagEntry->set_text(searchTag);
606     searchTagEntry->set_max_length(255);
607     searchButton = new Gtk::Button(_("Search"));
608     tagBox.pack_start(*tagLabel);
609     tagBox.pack_start(*searchTagEntry, Gtk::PACK_EXPAND_WIDGET, 3);
610     tagBox.pack_start(*searchButton);
611     filesPreview = new SVGPreview();
612     filesPreview->showNoPreview();
613     // add the buttons in the bottom of the dialog
614     add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
615     okButton = add_button(Gtk::Stock::OPEN,   Gtk::RESPONSE_OK);
616     // sets the okbutton to default
617     set_default(*okButton);
618     filesList = new FileListViewText(5, *filesPreview, *descriptionLabel, *okButton);
619     filesList->set_sensitive(false);
620     // add the listview inside a ScrolledWindow
621     listScrolledWindow.add(*filesList);
622     // only show the scrollbars when they are necessary:
623     listScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
624     filesList->set_column_title(0, _("Files Found"));
625     listScrolledWindow.set_size_request(400, 180);
626     filesList->get_column(1)->set_visible(false); // file url
627     filesList->get_column(2)->set_visible(false); // tmp file path
628     filesList->get_column(3)->set_visible(false); // author dir
629     filesList->get_column(4)->set_visible(false); // file description
630     filesBox.pack_start(listScrolledWindow);
631     filesBox.pack_start(*filesPreview);
632     vbox->pack_start(tagBox);
633     vbox->pack_start(messageBox);
634     vbox->pack_start(filesBox);
635     vbox->pack_start(descriptionBox);
637     //Let's do some customization
638     searchTagEntry = NULL;
639     Gtk::Container *cont = get_toplevel();
640     std::vector<Gtk::Entry *> entries;
641     findEntryWidgets(cont, entries);
642     if (entries.size() >=1 )
643     {
644     //Catch when user hits [return] on the text field
645         searchTagEntry = entries[0];
646         searchTagEntry->signal_activate().connect(
647               sigc::mem_fun(*this, &FileImportFromOCALDialogImplGtk::searchTagEntryChangedCallback));
648     }
650     searchButton->signal_clicked().connect(
651             sigc::mem_fun(*this, &FileImportFromOCALDialogImplGtk::searchTagEntryChangedCallback));
653     show_all_children();
654     notFoundLabel->hide();
657 /**
658  * Destructor
659  */
660 FileImportFromOCALDialogImplGtk::~FileImportFromOCALDialogImplGtk()
665 /**
666  * Show this dialog modally.  Return true if user hits [OK]
667  */
668 bool
669 FileImportFromOCALDialogImplGtk::show()
671     set_modal (TRUE);                      //Window
672     sp_transientize((GtkWidget *)gobj());  //Make transient
673     gint b = run();                        //Dialog
674     hide();
676     if (b == Gtk::RESPONSE_OK)
677     {
678         return TRUE;
679     }
680     else
681     {
682         return FALSE;
683     }
687 /**
688  * Get the file extension type that was selected by the user. Valid after an [OK]
689  */
690 Inkscape::Extension::Extension *
691 FileImportFromOCALDialogImplGtk::getSelectionType()
693     return extension;
697 /**
698  * Get the file name chosen by the user.   Valid after an [OK]
699  */
700 Glib::ustring
701 FileImportFromOCALDialogImplGtk::getFilename (void)
703     return filesList->getFilename();
707 } //namespace Dialog
708 } //namespace UI
709 } //namespace Inkscape
713 /*
714   Local Variables:
715   mode:c++
716   c-file-style:"stroustrup"
717   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
718   indent-tabs-mode:nil
719   fill-column:99
720   End:
721 */
722 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :