Merge lp:~and471/inkscape/ocal-dialog-improvements into lp:~inkscape.dev/inkscape/trunk
- ocal-dialog-improvements
- Merge into trunk
Status: | Merged | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 11027 | ||||||||||||
Proposed branch: | lp:~and471/inkscape/ocal-dialog-improvements | ||||||||||||
Merge into: | lp:~inkscape.dev/inkscape/trunk | ||||||||||||
Diff against target: |
2095 lines (+1171/-481) 9 files modified
share/icons/Makefile.am (+2/-1) src/file.cpp (+28/-45) src/file.h (+6/-0) src/io/sys.cpp (+9/-0) src/io/sys.h (+2/-0) src/menus-skeleton.h (+0/-2) src/ui/dialog/ocaldialogs.cpp (+892/-350) src/ui/dialog/ocaldialogs.h (+229/-81) src/verbs.cpp (+3/-2) |
||||||||||||
To merge this branch: | bzr merge lp:~and471/inkscape/ocal-dialog-improvements | ||||||||||||
Related bugs: |
|
||||||||||||
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Alex Valavanis | Approve | ||
Andrew (community) | Needs Resubmitting | ||
jazzynico (community) | Needs Fixing | ||
Review via email:
|
Commit message
Description of the change

su_v (suv-lp) wrote : | # |
Testing the branch on OS X 10.5.8 (i386), I get this error when trying to search:
(inkscape:54403): glibmm-CRITICAL **:
unhandled exception (type Glib::Error) in signal handler:
domain: g-io-error-quark
code : 15
what : Operation not supported
Dependencies:
glib2 @2.28.4_0 (active)
glibmm @2.24.2_0 (active)
gtk2 @2.24.3_0+x11 (active)
gtkmm @2.22.0_1 (active)

su_v (suv-lp) wrote : | # |
Clarification: on OS X 10.5.8, the dialog is not functional (no search). Do I need to install additional dependencies, or are there other configure options needed for either Inkscape or the external libraries?

Andrew (and471) wrote : | # |
> Clarification: on OS X 10.5.8, the dialog is not functional (no search). Do I
> need to install additional dependencies, or are there other configure options
> needed for either Inkscape or the external libraries?
I am not entirely sure. The new dialog uses GIO for its file handling stuff, that is what you see in the message, and the only operations it uses are copy and load_contents.

Andrew (and471) wrote : | # |
Possibly you need GVFS (for remote file stuff)? That is the only other thing I can think of

jazzynico (jazzynico) wrote : | # |
On Windows XP, I get some make errors:
-----
src/ui/
src/ui/
src/ui/
src/ui/
src/ui/
-----
Note that Gtk::Spinner is not available in the current Windows devlibs (gtk 2.18...).

jazzynico (jazzynico) wrote : | # |
With the spinner related code commented out, uint (ocaldialogs.h:292) replaced with unsigned int and the OCAL import menu entry uncommented in menus-skeleton.h, it compiles correctly on Windows XP. More tests later...

su_v (suv-lp) wrote : | # |
> Possibly you need GVFS (for remote file stuff)?
> That is the only other thing I can think of
I did not uninstall gvfs (1.6.6) as I need it for the regular builds of lp:inkscape (and it does get linked to inkscape if present).
Could it be related to having gconf configured/
Possibly using Gio requires additional configuration on Mac OS X (maybe Michael can investigate, once the branch has been merged into trunk), or I definitely have to give up on avoiding to install additional (gnome or glib/gtk2-based) system-wide services as root - I'm wondering though how that will impact packaging as osxapp.

su_v (suv-lp) wrote : | # |
Correction (I do have gnome-vfs installed, not gvfs):
- gvfs (1.6.6)
+ gnome-vfs @2.24.4_0

jazzynico (jazzynico) wrote : | # |
Good news, it works on Windows XP (conditions mentioned earlier...). Without the spinner, but at least I can search an import images.

Andrew (and471) wrote : | # |
On 5 April 2011 11:37, ~suv <email address hidden> wrote:
> Correction (I do have gnome-vfs installed, not gvfs):
>
> - gvfs (1.6.6)
> + gnome-vfs @2.24.4_0
> --
> https:/
> You are the owner of lp:~and471/inkscape/ocal-dialog-improvements.
>
Ah, they are not the same though. GNOMEVFS is depreciated and has just
been removed.
--
Andrew

Jon A. Cruz (jon-joncruz) wrote : | # |
On Apr 5, 2011, at 7:39 AM, Andrew wrote:
> On 5 April 2011 11:37, ~suv <email address hidden> wrote:
>> Correction (I do have gnome-vfs installed, not gvfs):
>>
>> - gvfs (1.6.6)
>> + gnome-vfs @2.24.4_0
>> --
>> https:/
>> You are the owner of lp:~and471/inkscape/ocal-dialog-improvements.
>>
>
> Ah, they are not the same though. GNOMEVFS is depreciated and has just
> been removed.
We probably need to note and track that dependency
http://
http://

su_v (suv-lp) wrote : | # |
> Possibly you need GVFS (for remote file stuff)?
Are you sure about gvfs as required dependency? It is not part of the Windows devlibs either [1], only libgsf (which I already had installed from the beginning).
From the README of gvfs:
<quote>
gvfs is a userspace virtual filesystem designed to work with the i/o
abstractions of gio (a library availible in glib >= 2.15.1). It
installs several modules that are automatically used by applications
using the APIs of libgio. There is also fuse support that allows
applications not using gio to access the gvfs filesystems.
The gvfs model differs from e.g. gnome-vfs in that filesystems must
be mounted before they are used. There is a central daemon (gvfsd)
that handles coordinting mounts, and then each mount is (typically)
in its own daemon process (although mounts can share daemon process).
</quote>
I did try and installed gvfs (without gnome support, because I don't run gnome), and rebuilt your branch - with no improvement: same error as before.
(with regard to gvfs (gnome-vfs): note that I don't have the daemon running. Also, it seems an odd dependency to me for the ocal dialog because the README mainly talks about mounting a file system before using it... we don't mount the ocal site, do we?)
[1] <http://

Andrew (and471) wrote : | # |
I am not sure about this, can anyone else shed some light on it?

Andrew (and471) wrote : | # |
Related to OSX:
After speaking with su-v on IRC, I was able to find out that the issue was with the load_contents_async method, however something like copy_async still works. Therefore I will continue to look at this.

su_v (suv-lp) wrote : | # |
JFTR (since it briefly came up on #inkscape): today glibmm was updated in MacPorts to 2.28.0 (from 2.24.2). I rebuilt the ocal-dialog-

su_v (suv-lp) wrote : | # |
As was reported on #inkscape: 'src/menus-

Splex (splex) wrote : | # |
Yes, please remove the gnome dependency.
I just tried building inkscape with this diff applied, and get the following errors:
ui/dialog/
ui/dialog/
ui/dialog/
ui/dialog/
ui/dialog/
ui/dialog/
ui/dialog/
ui/dialog/
make[3]: *** [ui/dialog/
- 10122. By Andrew <email address hidden>
-
uint > unsigned int (so windows builds work)
- 10123. By Andrew <email address hidden>
-
Remove some GNOME_VFS checks
Try to use read_async instead of load_contents_async, not working at the moment :( - 10124. By Andrew <email address hidden>
-
Revert changing to read_async
- 10125. By Andrew <email address hidden>
-
Correct ustring syntax

Andrew (and471) wrote : | # |
Hi can I get a merge now? Otherwise I fear that this will never get merged.

Andrew (and471) : | # |

ScislaC (scislac) wrote : | # |
Have you been able to address all issues brought up? Trust me, we want it merged just as bad as you. :)

jazzynico (jazzynico) wrote : | # |
Now that the devlibs are updated, the Gtk::Spinner use is no longer a problem on Windows.
But as for now, it compiles correctly on Ubuntu 10.10, inkscape trunk revision 10371 (except that I had to download the OCAL.png manually). And I still have the crash reported in the very first comment, when selecting an image in the result list while the preview of another one is still loading.

su_v (suv-lp) wrote : | # |
I did update the checkout of the ocal branch (r10125) and rebuilt it with the same configure and compile options as I use for current trunk (and 0.48.x): at least in my local builds of the Mac OS X port of Inkscape, the new ocal dialog is a major regression i.e. it completely fails, whereas the current version (in stable and trunk) allows to search for and import images from openclipart.org. [1]
I will not vote against the merge (Inkscape users on Mac OS X are still a far smaller number than Windows & Linux), but it might be appreciated if - for the next major release - e.g. the old version could be maintained ifdef'd for darwin/osx (unless of course the migration to gtk+ 3 as well as supporting the upcoming release of Lion will prohibit maintaining parts of the old code base or offer an easier fix/port of GIO-based implementations - upstream or in Inkscape.)
[1] tested on Mac OS X 10.5.8 Leopard (i386)
- 10126. By Andrew <email address hidden>
-
Fixed issues with cancelling downloading of thumbnails and images, all should be well now :)

Andrew (and471) wrote : | # |
Okay I have fixed the problem JazzyNico described. All should be ready to merge now.

Andrew (and471) wrote : | # |
Just one issue is there, that the Ocal.png needs to be put into the Makefile so it is installed, however I am not experienced with Make so could someone do this when they merge?

jazzynico (jazzynico) wrote : | # |
It would be more consistent to add the icon in the general share/icons/

ScislaC (scislac) wrote : | # |
If there is any modification to the icons.svg file, please be sure to read this first:

jazzynico (jazzynico) wrote : | # |
Hum, please forget my previous stupid comment. I just didn't remember the OCAL.png file is not an icon...

jazzynico (jazzynico) wrote : | # |
Tested again on Ubuntu 10.10, Inkscape trunk revision 10495.
Crash fix confirmed. Thanks!
Tests on Windows XP planned later...
Ah, just a small diff error with verbs.cpp. Could you please fix it?

jazzynico (jazzynico) wrote : | # |
Found another crasher, reproduced on Ubuntu 10.10 and Windows XP.
Steps:
1. Launch OCAL import.
2. Search something (used "skull").
3. Select the first result in the search list.
4. Search something else (used "pirate").
Backtrace:
Program received signal SIGSEGV, Segmentation fault.
0x005d3430 in Gtk::TreePath:
(gdb) bt
#0 0x005d3430 in Gtk::TreePath:
#1 0x0853b32f in Inkscape:
#2 0x08547ce7 in sigc::bound_
#3 0x085472c9 in sigc::adaptor_
#4 0x0854617b in sigc::internal:
#5 0x00c6d19b in Glib::SignalPro
#6 0x019fef2c in g_cclosure_
invocation_
#7 0x019ef412 in g_closure_invoke (closure=0xaa6ed88, return_value=0x0, n_param_values=1, param_values=
invocation_
#8 0x01a05f78 in signal_
emission_
#9 0x01a06fac in g_signal_
at /build/
#10 0x01a07275 in g_signal_
at /build/

Andrew (and471) wrote : | # |
Hi, sorry for my long absense form this but I have just fixed the issue that JazzyNico reported above.
The branch is ready for merging into trunk. Please someone do it quickly! :)

Andrew (and471) : | # |

su_v (suv-lp) wrote : | # |
> The branch is ready for merging into trunk. Please someone do it quickly!
I repeat my concerns expressed earlier: if doable, please maintain the old dialog in Inkscape's sources for osx users: the new GIO-based dialog fails on OS X and merging the branch as is removes a long-supported feature from that port of Inkscape.
This comment is based on building inkscape from a local branch of 'ocal-dialog-
Chillida:bin su_v$ ./inkscape -V
Inkscape 0.48+devel r10129 (Dec 28 2011)
Chillida:bin su_v$ ./inkscape
Hi!
(inkscape:40831): glibmm-CRITICAL **:
unhandled exception (type Glib::Error) in signal handler:
domain: g-io-error-quark
code : 15
what : Operation not supported
Chillida:bin su_v$ port installed glib2 glibmm gtk2 gtkmm
The following ports are currently installed:
glib2 @2.30.2_2 (active)
glibmm @2.28.2_0 (active)
gtk2 @2.24.8_1+x11 (active)
gtkmm @2.24.2_0 (active)
Chillida:bin su_v$

Andrew (and471) wrote : | # |
I am not sure how to do the above/whether the main devs want that sort of thing. Decision please?

su_v (suv-lp) wrote : | # |
@ScislaC - any comments?

ScislaC (scislac) wrote : | # |
Andrew: For all intensive purposes, ~suv is as much of a main dev as the rest of us regular contributors. We have a long standing policy of not breaking features on a platform that has previously supported them if it can be avoided.
As ~suv mentioned, supporting the old dialog on osx is an option (make it conditional based on platform during compile time), however, this is still somewhat kludgy because different platforms will have different experiences... but nothing "breaks".
Either way, it's a good idea to find out why glibmm on OSX has this issue and to file an upstream bug report or add to one if it already exists. If we're possibly sitting on an unknown issue, we're only hurting ourselves. Likewise, if we're possibly another "me too", that could be extra motivation for upstream to fix it.

Andrew (and471) wrote : | # |
Essentially I had given up on this for 6 months, as I didn't have the time for it, and I have finally managed to fix it for most platforms.
I have no idea how to fix the issue that ~suv describes and wouldn't even know where to begin. I did ask for help on the mailing list 6 months ago but got no help.
I don't have the time now to devote to fixing this and I really do fear that this will forever remain unmerged. If I am truly honest, this experience has made it seems like it is really hard to contribute to Inkscape, which sucks because I love the program and wanted to make it better.

su_v (suv-lp) wrote : | # |
As mentioned earlier, "I will not vote against the merge", and I'm sorry if my tests have slowed down the process of getting highly appreciated new contributions merged into trunk.
I was speaking up a) because I was eager to test the new improvements ;) and b) because it might otherwise go unnoticed (and will potentially only get back on the radar with later efforts to migrate Inkscape from the deprecated (?) gnome-vfs to gio - bug #715215).

ScislaC (scislac) wrote : | # |
Andrew: We definitely don't want you to have a bad experience contributing to the project. ~suv did bump the thread on the mailing list again today and if we're lucky, maybe we can get Jon Cruz to help us merge this in a way that is still OSX friendly. I'll be honest that this is a more unusual case than most contributions as it has issues that are platform specific, while most aspects of Inkscape are usually more platform agnostic. Please don't be discouraged by this, we will see what we can do to get this merged in the near future. :)

jazzynico (jazzynico) wrote : | # |
Just tested the latest version, and the dialog no longer crashes on Ubuntu 11.04.
There are still two very minor "bugs":
1. Is printf("%s\n", "Hi!"); in ocaldialogs.cpp absolutely necessary? ;)
2. When testing multi-images import with Ctrl (that doesn't work, but it's not really a bug, just a missing feature), the preview window always show the n-1 image.
Thanks for your efforts. The new dialog is a real improvement. I'm sure we'll find a solution so that it's merged before 0.49 is out.

jazzynico (jazzynico) wrote : | # |
Andrew, it would be very disappointing to see all your work lost just because you don't have time to investigate more. Would you mind giving write access to your branches (OCAL and gallery) to the Inkscape Developers group, so that we can work on it?

Andrew (and471) wrote : | # |
I would love to but as I am not in that group, I cannot change it in Launchpad to be so

su_v (suv-lp) wrote : | # |
> Andrew, it would be very disappointing to see all your work lost just because
> you don't have time to investigate more. Would you mind giving write access to
> your branches (OCAL and gallery) to the Inkscape Developers group, so that we
> can work on it?
As mentioned before, I'm not "voting against" the merge - I just want to make sure the issue on OS X is known.
Proposing to merge the ocal branch as is (as long as the two branches haven't diverged too much) and deal with the GIO issues on OS X in trunk (maybe disable the dialog on darwin platforms for the next release if not solved in time).
@ScislaC - would you agree to this?
For the gallery dialog, could the compromise to keep the version with the update button and not rely on monitoring the directory for changes (which failed on OS X, also due to features in GIO apparently not (yet) supported in GTK2 on Mac OS X) be agreed on?
<http://

Alex Valavanis (valavanisalex) wrote : | # |
OK, I've gone ahead and merged this. It seems like a massive improvement for linux, and it would be a shame to lose all this excellent work. I suggest that we thoroughly test the merged version and try to work out the remaining issues together in trunk as suv proposed.
If anyone disagrees strongly with this, we can always revert.

Andrew (and471) wrote : | # |
Thankyou! :)
Preview Diff
1 | === modified file 'share/icons/Makefile.am' |
2 | --- share/icons/Makefile.am 2010-02-05 18:41:32 +0000 |
3 | +++ share/icons/Makefile.am 2011-12-27 21:09:25 +0000 |
4 | @@ -38,7 +38,8 @@ |
5 | feSpecularLighting-icon.png \ |
6 | feSpecularLighting-icon.svg \ |
7 | feTurbulence-icon.png \ |
8 | - feTurbulence-icon.svg |
9 | + feTurbulence-icon.svg \ |
10 | + OCAL.png |
11 | |
12 | icons_DATA = \ |
13 | $(pixmaps) \ |
14 | |
15 | === added file 'share/icons/OCAL.png' |
16 | Binary files share/icons/OCAL.png 1970-01-01 00:00:00 +0000 and share/icons/OCAL.png 2011-12-27 21:09:25 +0000 differ |
17 | === modified file 'src/file.cpp' |
18 | --- src/file.cpp 2011-12-08 11:53:54 +0000 |
19 | +++ src/file.cpp 2011-12-27 21:09:25 +0000 |
20 | @@ -1125,7 +1125,7 @@ |
21 | return; |
22 | } |
23 | |
24 | - //# Get file name and extension type |
25 | + // Get file name and extension type |
26 | Glib::ustring fileName = importDialogInstance->getFilename(); |
27 | Inkscape::Extension::Extension *selection = importDialogInstance->getSelectionType(); |
28 | |
29 | @@ -1340,8 +1340,8 @@ |
30 | export_path = export_path_local; |
31 | |
32 | // Show the Export To OCAL dialog |
33 | - Inkscape::UI::Dialog::FileExportToOCALDialog *exportDialogInstance = |
34 | - new Inkscape::UI::Dialog::FileExportToOCALDialog( |
35 | + Inkscape::UI::Dialog::OCAL:ExportDialog *exportDialogInstance = |
36 | + new Inkscape::UI::Dialog::OCAL:ExportDialog |
37 | parentWindow, |
38 | Inkscape::UI::Dialog::EXPORT_TYPES, |
39 | (char const *) _("Select file to export to") |
40 | @@ -1452,11 +1452,23 @@ |
41 | ## I M P O R T F R O M O C A L |
42 | ######################*/ |
43 | |
44 | +Inkscape::UI::Dialog::OCAL::ImportDialog* import_ocal_dialog = NULL; |
45 | + |
46 | /** |
47 | - * Display an ImportToOcal Dialog, and the selected document from OCAL |
48 | + * Display an ImportFromOcal Dialog, and the selected document from OCAL |
49 | */ |
50 | +void on_import_from_ocal_response(Glib::ustring filename) |
51 | +{ |
52 | + SPDocument *doc = SP_ACTIVE_DOCUMENT; |
53 | + |
54 | + if (!filename.empty()) { |
55 | + Inkscape::Extension::Extension *selection = import_ocal_dialog->get_selection_type(); |
56 | + file_import(doc, filename, selection); |
57 | + } |
58 | +} |
59 | + |
60 | void |
61 | -sp_file_import_from_ocal(Gtk::Window &parentWindow) |
62 | +sp_file_import_from_ocal(Gtk::Window &parent_window) |
63 | { |
64 | static Glib::ustring import_path; |
65 | |
66 | @@ -1464,47 +1476,18 @@ |
67 | if (!doc) |
68 | return; |
69 | |
70 | - Inkscape::UI::Dialog::FileImportFromOCALDialog *importDialogInstance = NULL; |
71 | - |
72 | - if (!importDialogInstance) { |
73 | - importDialogInstance = new |
74 | - Inkscape::UI::Dialog::FileImportFromOCALDialog( |
75 | - parentWindow, |
76 | - import_path, |
77 | + if (import_ocal_dialog == NULL) { |
78 | + import_ocal_dialog = new |
79 | + Inkscape::UI::Dialog::OCAL::ImportDialog( |
80 | + parent_window, |
81 | Inkscape::UI::Dialog::IMPORT_TYPES, |
82 | - (char const *)_("Import From Open Clip Art Library")); |
83 | - } |
84 | - |
85 | - bool success = importDialogInstance->show(); |
86 | - if (!success) { |
87 | - delete importDialogInstance; |
88 | - return; |
89 | - } |
90 | - |
91 | - // Get file name and extension type |
92 | - Glib::ustring fileName = importDialogInstance->getFilename(); |
93 | - Inkscape::Extension::Extension *selection = importDialogInstance->getSelectionType(); |
94 | - |
95 | - delete importDialogInstance; |
96 | - importDialogInstance = NULL; |
97 | - |
98 | - if (fileName.size() > 0) { |
99 | - |
100 | - Glib::ustring newFileName = Glib::filename_to_utf8(fileName); |
101 | - |
102 | - if ( newFileName.size() > 0) |
103 | - fileName = newFileName; |
104 | - else |
105 | - g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" ); |
106 | - |
107 | - import_path = fileName; |
108 | - if (import_path.size()>0) |
109 | - import_path.append(G_DIR_SEPARATOR_S); |
110 | - |
111 | - file_import(doc, fileName, selection); |
112 | - } |
113 | - |
114 | - return; |
115 | + (char const *)_("Import Clip Art")); |
116 | + |
117 | + import_ocal_dialog->signal_response().connect( |
118 | + sigc::ptr_fun(&on_import_from_ocal_response)); |
119 | + } |
120 | + |
121 | + import_ocal_dialog->show_all(); |
122 | } |
123 | |
124 | /*###################### |
125 | |
126 | === modified file 'src/file.h' |
127 | --- src/file.h 2011-12-08 11:53:54 +0000 |
128 | +++ src/file.h 2011-12-27 21:09:25 +0000 |
129 | @@ -20,6 +20,7 @@ |
130 | #include <gtk/gtk.h> |
131 | |
132 | #include "extension/system.h" |
133 | +#include "ui/dialog/ocaldialogs.h" |
134 | |
135 | struct SPDesktop; |
136 | struct SPDocument; |
137 | @@ -166,6 +167,11 @@ |
138 | /** |
139 | * Import a document from OCAL |
140 | */ |
141 | +void on_import_from_ocal_response(Glib::ustring filename); |
142 | + |
143 | +/** |
144 | + * Import a document from OCAL |
145 | + */ |
146 | void sp_file_import_from_ocal (Gtk::Window &parentWindow ); |
147 | |
148 | |
149 | |
150 | === modified file 'src/io/sys.cpp' |
151 | --- src/io/sys.cpp 2011-12-08 11:53:54 +0000 |
152 | +++ src/io/sys.cpp 2011-12-27 21:09:25 +0000 |
153 | @@ -355,6 +355,15 @@ |
154 | return result; |
155 | } |
156 | |
157 | +/* |
158 | + * Returns the file extension of a path/filename |
159 | + */ |
160 | +Glib::ustring Inkscape::IO::get_file_extension(Glib::ustring path) |
161 | +{ |
162 | + Glib::ustring::size_type period_location = path.find_last_of("."); |
163 | + return path.substr(period_location); |
164 | +} |
165 | + |
166 | /* |
167 | Local Variables: |
168 | mode:c++ |
169 | |
170 | === modified file 'src/io/sys.h' |
171 | --- src/io/sys.h 2011-12-08 11:53:54 +0000 |
172 | +++ src/io/sys.h 2011-12-27 21:09:25 +0000 |
173 | @@ -59,6 +59,8 @@ |
174 | int* standard_output, |
175 | int* standard_error); |
176 | |
177 | +Glib::ustring get_file_extension(Glib::ustring path); |
178 | + |
179 | } |
180 | } |
181 | |
182 | |
183 | === modified file 'src/menus-skeleton.h' |
184 | --- src/menus-skeleton.h 2011-06-22 21:40:59 +0000 |
185 | +++ src/menus-skeleton.h 2011-12-27 21:09:25 +0000 |
186 | @@ -27,10 +27,8 @@ |
187 | " <separator/>\n" |
188 | " <verb verb-id=\"FileImport\" />\n" |
189 | " <verb verb-id=\"FileExport\" />\n" |
190 | -#ifdef WITH_GNOME_VFS |
191 | " <verb verb-id=\"FileImportFromOCAL\" />\n" |
192 | //" <verb verb-id=\"FileExportToOCAL\" />\n" |
193 | -#endif |
194 | " <separator/>\n" |
195 | " <verb verb-id=\"FilePrint\" />\n" |
196 | " <separator/>\n" |
197 | |
198 | === modified file 'src/ui/dialog/ocaldialogs.cpp' |
199 | --- src/ui/dialog/ocaldialogs.cpp 2011-10-03 07:24:15 +0000 |
200 | +++ src/ui/dialog/ocaldialogs.cpp 2011-12-27 21:09:25 +0000 |
201 | @@ -5,6 +5,7 @@ |
202 | /* Authors: |
203 | * Bruno Dilly |
204 | * Other dudes from The Inkscape Organization |
205 | + * Andrew Higginson |
206 | * |
207 | * Copyright (C) 2007 Bruno Dilly <bruno.dilly@gmail.com> |
208 | * |
209 | @@ -20,6 +21,7 @@ |
210 | #include <errno.h> // errno |
211 | #include <string.h> // strerror() |
212 | |
213 | +#include "path-prefix.h" |
214 | #include "ocaldialogs.h" |
215 | #include "filedialogimpl-gtkmm.h" |
216 | #include "interface.h" |
217 | @@ -34,6 +36,8 @@ |
218 | { |
219 | namespace Dialog |
220 | { |
221 | +namespace OCAL |
222 | +{ |
223 | |
224 | //######################################################################## |
225 | //# F I L E E X P O R T T O O C A L |
226 | @@ -43,7 +47,7 @@ |
227 | * Callback for fileNameEntry widget |
228 | */ |
229 | /* |
230 | -void FileExportToOCALDialog::fileNameEntryChangedCallback() |
231 | +void ExportDialog::fileNameEntryChangedCallback() |
232 | { |
233 | if (!fileNameEntry) |
234 | return; |
235 | @@ -60,10 +64,10 @@ |
236 | * Constructor |
237 | */ |
238 | /* |
239 | -FileExportToOCALDialog::FileExportToOCALDialog(Gtk::Window &parentWindow, |
240 | +ExportDialog::ExportDialog(Gtk::Window &parentWindow, |
241 | FileDialogType fileTypes, |
242 | const Glib::ustring &title) : |
243 | - FileDialogOCALBase(title, parentWindow) |
244 | + FileDialogBase(title, parentWindow) |
245 | { |
246 | */ |
247 | /* |
248 | @@ -103,7 +107,7 @@ |
249 | //Catch when user hits [return] on the text field |
250 | fileNameEntry = entries[0]; |
251 | fileNameEntry->signal_activate().connect( |
252 | - sigc::mem_fun(*this, &FileExportToOCALDialog::fileNameEntryChangedCallback) ); |
253 | + sigc::mem_fun(*this, &ExportDialog::fileNameEntryChangedCallback) ); |
254 | } |
255 | |
256 | add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); |
257 | @@ -116,7 +120,7 @@ |
258 | * Destructor |
259 | */ |
260 | /* |
261 | -FileExportToOCALDialog::~FileExportToOCALDialog() |
262 | +ExportDialog::~ExportDialog() |
263 | { |
264 | } |
265 | */ |
266 | @@ -125,7 +129,7 @@ |
267 | */ |
268 | /* |
269 | bool |
270 | -FileExportToOCALDialog::show() |
271 | +ExportDialog::show() |
272 | { |
273 | set_modal (TRUE); //Window |
274 | sp_transientize((GtkWidget *)gobj()); //Make transient |
275 | @@ -147,7 +151,7 @@ |
276 | */ |
277 | /* |
278 | Glib::ustring |
279 | -FileExportToOCALDialog::getFilename() |
280 | +ExportDialog::get_filename() |
281 | { |
282 | myFilename = fileNameEntry->get_text(); |
283 | if (!Glib::get_charset()) //If we are not utf8 |
284 | @@ -158,7 +162,7 @@ |
285 | |
286 | |
287 | void |
288 | -FileExportToOCALDialog::change_title(const Glib::ustring& title) |
289 | +ExportDialog::change_title(const Glib::ustring& title) |
290 | { |
291 | this->set_title(title); |
292 | } |
293 | @@ -173,8 +177,8 @@ |
294 | * Constructor |
295 | */ |
296 | /* |
297 | -FileExportToOCALPasswordDialog::FileExportToOCALPasswordDialog(Gtk::Window &parentWindow, |
298 | - const Glib::ustring &title) : FileDialogOCALBase(title, parentWindow) |
299 | +ExportPasswordDialog::ExportPasswordDialog(Gtk::Window &parentWindow, |
300 | + const Glib::ustring &title) : FileDialogBase(title, parentWindow) |
301 | { |
302 | */ |
303 | /* |
304 | @@ -221,7 +225,7 @@ |
305 | * Destructor |
306 | */ |
307 | /* |
308 | -FileExportToOCALPasswordDialog::~FileExportToOCALPasswordDialog() |
309 | +ExportPasswordDialog::~ExportPasswordDialog() |
310 | { |
311 | } |
312 | */ |
313 | @@ -230,7 +234,7 @@ |
314 | */ |
315 | /* |
316 | bool |
317 | -FileExportToOCALPasswordDialog::show() |
318 | +ExportPasswordDialog::show() |
319 | { |
320 | set_modal (TRUE); //Window |
321 | sp_transientize((GtkWidget *)gobj()); //Make transient |
322 | @@ -252,7 +256,7 @@ |
323 | */ |
324 | /* |
325 | Glib::ustring |
326 | -FileExportToOCALPasswordDialog::getUsername() |
327 | +ExportPasswordDialog::getUsername() |
328 | { |
329 | myUsername = usernameEntry->get_text(); |
330 | return myUsername; |
331 | @@ -263,14 +267,14 @@ |
332 | */ |
333 | /* |
334 | Glib::ustring |
335 | -FileExportToOCALPasswordDialog::getPassword() |
336 | +ExportPasswordDialog::getPassword() |
337 | { |
338 | myPassword = passwordEntry->get_text(); |
339 | return myPassword; |
340 | } |
341 | |
342 | void |
343 | -FileExportToOCALPasswordDialog::change_title(const Glib::ustring& title) |
344 | +ExportPasswordDialog::change_title(const Glib::ustring& title) |
345 | { |
346 | this->set_title(title); |
347 | } |
348 | @@ -280,408 +284,946 @@ |
349 | //### F I L E I M P O R T F R O M O C A L |
350 | //######################################################################### |
351 | |
352 | +WrapLabel::WrapLabel() : Gtk::Label() |
353 | +{ |
354 | + signal_size_allocate().connect(sigc::mem_fun(*this, &WrapLabel::_on_size_allocate)); |
355 | +} |
356 | + |
357 | +void WrapLabel::_on_size_allocate(Gtk::Allocation& allocation) |
358 | +{ |
359 | + set_size_request(allocation.get_width(), -1); |
360 | +} |
361 | + |
362 | + |
363 | +LoadingBox::LoadingBox() : Gtk::EventBox() |
364 | +{ |
365 | + set_visible_window(false); |
366 | + draw_spinner = false; |
367 | + spinner_step = 0; |
368 | + signal_expose_event().connect(sigc::mem_fun(*this, &LoadingBox::_on_expose_event), false); |
369 | +} |
370 | + |
371 | +bool LoadingBox::_on_expose_event(GdkEventExpose* event) |
372 | +{ |
373 | + Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context(); |
374 | + |
375 | + // Draw shadow |
376 | + int x = get_allocation().get_x(); |
377 | + int y = get_allocation().get_y(); |
378 | + int width = get_allocation().get_width(); |
379 | + int height = get_allocation().get_height(); |
380 | + |
381 | + get_style()->paint_shadow(get_window(), get_state(), Gtk::SHADOW_IN, |
382 | + Gdk::Rectangle(x, y, width, height), |
383 | + *this, Glib::ustring("viewport"), x, y, width, height); |
384 | + |
385 | + if (draw_spinner) { |
386 | + int spinner_size = 16; |
387 | + int spinner_x = x + (width - spinner_size) / 2; |
388 | + int spinner_y = y + (height - spinner_size) / 2; |
389 | + |
390 | + // FIXME: Gtk::Style::paint_spinner not yet in gtkmm |
391 | + gtk_paint_spinner(gtk_widget_get_style(GTK_WIDGET(gobj())), |
392 | + gtk_widget_get_window(GTK_WIDGET(gobj())), |
393 | + gtk_widget_get_state(GTK_WIDGET(gobj())), NULL, GTK_WIDGET(gobj()), |
394 | + NULL, spinner_step, spinner_x, spinner_y, spinner_size, spinner_size); |
395 | + } |
396 | + |
397 | + return false; |
398 | +} |
399 | + |
400 | +void LoadingBox::start() |
401 | +{ |
402 | + // Timeout hasn't been stopped, so must be disconnected |
403 | + if ((draw_spinner != false) & (timeout != NULL)) { |
404 | + timeout.disconnect(); |
405 | + } |
406 | + |
407 | + draw_spinner = true; |
408 | + timeout = Glib::signal_timeout().connect(sigc::mem_fun(*this, &LoadingBox::on_timeout), 80); |
409 | +} |
410 | + |
411 | +void LoadingBox::stop() |
412 | +{ |
413 | + draw_spinner = false; |
414 | +} |
415 | + |
416 | +bool LoadingBox::on_timeout() { |
417 | + if (draw_spinner) { |
418 | + |
419 | + if (spinner_step == 11) { |
420 | + spinner_step = 0; |
421 | + } else { |
422 | + spinner_step ++; |
423 | + } |
424 | + |
425 | + queue_draw(); |
426 | + return true; |
427 | + } |
428 | + return false; |
429 | +} |
430 | + |
431 | +PreviewWidget::PreviewWidget() : Gtk::VBox(false, 12) |
432 | +{ |
433 | + box_loading = new LoadingBox(); |
434 | + image = new Gtk::Image(); |
435 | + |
436 | + label_title = new WrapLabel(); |
437 | + label_description = new WrapLabel(); |
438 | + label_time = new WrapLabel(); |
439 | + |
440 | + pack_start(*box_loading, false, false); |
441 | + pack_start(*image, false, false); |
442 | + pack_start(*label_title, false, false); |
443 | + pack_start(*label_description, false, false); |
444 | + pack_start(*label_time, false, false); |
445 | + |
446 | + label_title->set_line_wrap(true); |
447 | + label_title->set_line_wrap_mode(Pango::WRAP_WORD_CHAR); |
448 | + label_title->set_justify(Gtk::JUSTIFY_CENTER); |
449 | + label_description->set_line_wrap(true); |
450 | + label_description->set_line_wrap_mode(Pango::WRAP_WORD_CHAR); |
451 | + label_description->set_justify(Gtk::JUSTIFY_CENTER); |
452 | + label_time->set_line_wrap(true); |
453 | + label_time->set_line_wrap_mode(Pango::WRAP_WORD_CHAR); |
454 | + label_time->set_justify(Gtk::JUSTIFY_CENTER); |
455 | + |
456 | + box_loading->set_no_show_all(true); |
457 | + image->set_no_show_all(true); |
458 | + label_title->set_size_request(90, -1); |
459 | + label_description->set_size_request(90, -1); |
460 | + label_time->set_size_request(90, -1); |
461 | + box_loading->set_size_request(90, 90); |
462 | + set_border_width(12); |
463 | + |
464 | + signal_expose_event().connect(sigc::mem_fun(*this, &PreviewWidget::_on_expose_event), false); |
465 | + |
466 | + clear(); |
467 | +} |
468 | + |
469 | +void PreviewWidget::set_metadata(Glib::ustring description, Glib::ustring creator, |
470 | + Glib::ustring time) |
471 | +{ |
472 | + label_title->set_markup(g_markup_printf_escaped("<b>%s</b>", description.c_str())); |
473 | + label_description->set_markup(g_markup_printf_escaped("%s", creator.c_str())); |
474 | + label_time->set_markup(g_markup_printf_escaped("<small>%s</small>", time.c_str())); |
475 | + |
476 | + show_box_loading(); |
477 | +} |
478 | + |
479 | +void PreviewWidget::show_box_loading() |
480 | +{ |
481 | + box_loading->show(); |
482 | + box_loading->start(); |
483 | +} |
484 | + |
485 | +void PreviewWidget::hide_box_loading() |
486 | +{ |
487 | + box_loading->hide(); |
488 | + box_loading->stop(); |
489 | +} |
490 | + |
491 | +void PreviewWidget::set_image(std::string path) |
492 | +{ |
493 | + image->set(path); |
494 | + hide_box_loading(); |
495 | + image->show(); |
496 | +} |
497 | + |
498 | +void PreviewWidget::clear() |
499 | +{ |
500 | + label_title->set_markup(""); |
501 | + label_description->set_markup(""); |
502 | + label_time->set_markup(""); |
503 | + |
504 | + box_loading->hide(); |
505 | + image->hide(); |
506 | +} |
507 | + |
508 | +bool PreviewWidget::_on_expose_event(GdkEventExpose* event) |
509 | +{ |
510 | + Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context(); |
511 | + |
512 | + // Draw background |
513 | + int x = get_allocation().get_x(); |
514 | + int y = get_allocation().get_y(); |
515 | + int width = get_allocation().get_width(); |
516 | + int height = get_allocation().get_height(); |
517 | + Gdk::Color background_fill = get_style()->get_base(get_state()); |
518 | + |
519 | + cr->rectangle(x, y, width, height); |
520 | + Gdk::Cairo::set_source_color(cr, background_fill); |
521 | + cr->fill(); |
522 | + |
523 | + return false; |
524 | +} |
525 | + |
526 | +StatusWidget::StatusWidget() : Gtk::HBox(false, 6) |
527 | +{ |
528 | + image = new Gtk::Image(Gtk::Stock::DIALOG_ERROR, Gtk::ICON_SIZE_MENU); |
529 | + spinner = new Gtk::Spinner(); |
530 | + label = new Gtk::Label(); |
531 | + |
532 | + image->set_no_show_all(true); |
533 | + spinner->set_no_show_all(true); |
534 | + label->set_no_show_all(true); |
535 | + |
536 | + pack_start(*image, false, false); |
537 | + pack_start(*spinner, false, false); |
538 | + pack_start(*label, false, false); |
539 | +} |
540 | + |
541 | +void StatusWidget::clear() |
542 | +{ |
543 | + spinner->hide(); |
544 | + image->hide(); |
545 | + label->hide(); |
546 | +} |
547 | + |
548 | +void StatusWidget::set_info(Glib::ustring text) |
549 | +{ |
550 | + spinner->hide(); |
551 | + image->show(); |
552 | + label->show(); |
553 | + image->set(Gtk::Stock::DIALOG_INFO, Gtk::ICON_SIZE_MENU); |
554 | + label->set_text(text); |
555 | +} |
556 | + |
557 | +void StatusWidget::set_error(Glib::ustring text) |
558 | +{ |
559 | + spinner->hide(); |
560 | + image->show(); |
561 | + label->show(); |
562 | + image->set(Gtk::Stock::DIALOG_ERROR, Gtk::ICON_SIZE_MENU); |
563 | + label->set_text(text); |
564 | +} |
565 | + |
566 | +void StatusWidget::start_process(Glib::ustring text) |
567 | +{ |
568 | + image->hide(); |
569 | + spinner->show(); |
570 | + label->show(); |
571 | + label->set_text(text); |
572 | + spinner->start(); |
573 | + show_all(); |
574 | +} |
575 | + |
576 | +void StatusWidget::end_process() |
577 | +{ |
578 | + spinner->stop(); |
579 | + spinner->hide(); |
580 | + label->hide(); |
581 | + clear(); |
582 | +} |
583 | + |
584 | +SearchEntry::SearchEntry() : Gtk::Entry() |
585 | +{ |
586 | + signal_changed().connect(sigc::mem_fun(*this, &SearchEntry::_on_changed)); |
587 | + signal_icon_press().connect(sigc::mem_fun(*this, &SearchEntry::_on_icon_pressed)); |
588 | + |
589 | + set_icon_from_stock(Gtk::Stock::FIND, Gtk::ENTRY_ICON_PRIMARY); |
590 | + gtk_entry_set_icon_from_stock(gobj(), GTK_ENTRY_ICON_SECONDARY, NULL); |
591 | +} |
592 | + |
593 | +void SearchEntry::_on_icon_pressed(Gtk::EntryIconPosition icon_position, const GdkEventButton* event) |
594 | +{ |
595 | + if (icon_position == Gtk::ENTRY_ICON_SECONDARY) { |
596 | + grab_focus(); |
597 | + set_text(""); |
598 | + } else if (icon_position == Gtk::ENTRY_ICON_PRIMARY) { |
599 | + select_region(0, -1); |
600 | + grab_focus(); |
601 | + } |
602 | +} |
603 | + |
604 | +void SearchEntry::_on_changed() |
605 | +{ |
606 | + if (get_text().empty()) { |
607 | + gtk_entry_set_icon_from_stock(gobj(), GTK_ENTRY_ICON_SECONDARY, NULL); |
608 | + } else { |
609 | + set_icon_from_stock(Gtk::Stock::CLEAR, Gtk::ENTRY_ICON_SECONDARY); |
610 | + } |
611 | +} |
612 | + |
613 | +BaseBox::BaseBox() : Gtk::EventBox() |
614 | +{ |
615 | + signal_expose_event().connect(sigc::mem_fun(*this, &BaseBox::_on_expose_event), false); |
616 | + set_visible_window(false); |
617 | +} |
618 | + |
619 | +bool BaseBox::_on_expose_event(GdkEventExpose* event) |
620 | +{ |
621 | + Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context(); |
622 | + |
623 | + // Draw background and shadow |
624 | + int x = get_allocation().get_x(); |
625 | + int y = get_allocation().get_y(); |
626 | + int width = get_allocation().get_width(); |
627 | + int height = get_allocation().get_height(); |
628 | + Gdk::Color background_fill = get_style()->get_base(get_state()); |
629 | + |
630 | + cr->rectangle(x, y, width, height); |
631 | + Gdk::Cairo::set_source_color(cr, background_fill); |
632 | + cr->fill(); |
633 | + |
634 | + get_style()->paint_shadow(get_window(), get_state(), Gtk::SHADOW_IN, |
635 | + Gdk::Rectangle(x, y, width, height), |
636 | + *this, Glib::ustring("viewport"), x, y, width, height); |
637 | + |
638 | + return false; |
639 | +} |
640 | + |
641 | +LogoArea::LogoArea() : Gtk::EventBox() |
642 | +{ |
643 | + // Try to load the OCAL logo, but if the file is not found, degrade gracefully |
644 | + try { |
645 | + std::string logo_path = Glib::build_filename(INKSCAPE_PIXMAPDIR, "OCAL.png"); |
646 | + logo_mask = Cairo::ImageSurface::create_from_png(logo_path); |
647 | + draw_logo = true; |
648 | + } catch(Cairo::logic_error) { |
649 | + logo_mask = Cairo::ImageSurface::create(Cairo::FORMAT_ARGB32, 1,1); |
650 | + draw_logo = false; |
651 | + } |
652 | + signal_expose_event().connect(sigc::mem_fun(*this, &LogoArea::_on_expose_event)); |
653 | + set_visible_window(false); |
654 | +} |
655 | + |
656 | +bool LogoArea::_on_expose_event(GdkEventExpose* event) |
657 | +{ |
658 | + if (draw_logo) { |
659 | + int x = get_allocation().get_x(); |
660 | + int y = get_allocation().get_y(); |
661 | + int width = get_allocation().get_width(); |
662 | + int height = get_allocation().get_height(); |
663 | + int x_logo = x + (width - 220) / 2; |
664 | + int y_logo = y + (height - 76) / 2; |
665 | + |
666 | + Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context(); |
667 | + |
668 | + // Draw logo, we mask [read fill] it with the mid colour from the |
669 | + // user's GTK theme |
670 | + Gdk::Color logo_fill = get_style()->get_mid(get_state()); |
671 | + |
672 | + Gdk::Cairo::set_source_color(cr, logo_fill); |
673 | + cr->mask(logo_mask, x_logo, y_logo); |
674 | + } |
675 | + |
676 | + return false; |
677 | +} |
678 | + |
679 | +SearchResultList::SearchResultList(guint columns_count) : ListViewText(columns_count) |
680 | +{ |
681 | + set_headers_visible(false); |
682 | + set_column_title(RESULTS_COLUMN_MARKUP, _("Clipart found")); |
683 | + |
684 | + Gtk::CellRenderer* cr_markup = get_column_cell_renderer(RESULTS_COLUMN_MARKUP); |
685 | + cr_markup->set_property("ellipsize", Pango::ELLIPSIZE_END); |
686 | + get_column(RESULTS_COLUMN_MARKUP)->clear_attributes(*cr_markup); |
687 | + get_column(RESULTS_COLUMN_MARKUP)->add_attribute(*cr_markup, |
688 | + "markup", RESULTS_COLUMN_MARKUP); |
689 | + |
690 | + // Hide all columns except for the MARKUP column |
691 | + for (int i = 0; i < RESULTS_COLUMN_LENGTH; i++) { |
692 | + if (i != RESULTS_COLUMN_MARKUP) { |
693 | + get_column(i)->set_visible(false); |
694 | + } |
695 | + } |
696 | +} |
697 | + |
698 | +void ImportDialog::on_list_results_selection_changed() |
699 | +{ |
700 | + std::vector<Gtk::TreeModel::Path> pathlist; |
701 | + pathlist = list_results->get_selection()->get_selected_rows(); |
702 | + std::vector<int> posArray(1); |
703 | + |
704 | + // If nothing is selected, then return |
705 | + if (((int) pathlist.size()) < 1) { |
706 | + return; |
707 | + } |
708 | + posArray = pathlist[0].get_indices(); |
709 | + int row = posArray[0]; |
710 | + |
711 | + Glib::ustring guid = list_results->get_text(row, RESULTS_COLUMN_GUID); |
712 | + |
713 | + bool item_selected = (!guid.empty()); |
714 | + button_import->set_sensitive(item_selected); |
715 | +} |
716 | + |
717 | + |
718 | +void ImportDialog::on_button_import_clicked() { |
719 | + std::vector<Gtk::TreeModel::Path> pathlist; |
720 | + pathlist = list_results->get_selection()->get_selected_rows(); |
721 | + std::vector<int> posArray(1); |
722 | + |
723 | + // If nothing is selected, then return |
724 | + if (((int) pathlist.size()) < 1) { |
725 | + return; |
726 | + } |
727 | + posArray = pathlist[0].get_indices(); |
728 | + int row = posArray[0]; |
729 | + |
730 | + button_import->set_sensitive(false); |
731 | + button_close->hide(); |
732 | + button_cancel->show(); |
733 | + widget_status->start_process(_("Downloading image...")); |
734 | + download_resource(TYPE_IMAGE, row); |
735 | +} |
736 | + |
737 | /* |
738 | - * Calalback for cursor chage |
739 | + * Callback for cursor change |
740 | */ |
741 | -void FileListViewText::on_cursor_changed() |
742 | +void ImportDialog::on_list_results_cursor_changed() |
743 | { |
744 | std::vector<Gtk::TreeModel::Path> pathlist; |
745 | - pathlist = this->get_selection()->get_selected_rows(); |
746 | + pathlist = list_results->get_selection()->get_selected_rows(); |
747 | std::vector<int> posArray(1); |
748 | + |
749 | + // If nothing is selected, then return |
750 | + if (((int) pathlist.size()) < 1) { |
751 | + return; |
752 | + } |
753 | posArray = pathlist[0].get_indices(); |
754 | - |
755 | -#ifdef WITH_GNOME_VFS |
756 | - gnome_vfs_init(); |
757 | - GnomeVFSHandle *from_handle = NULL; |
758 | - GnomeVFSHandle *to_handle = NULL; |
759 | - GnomeVFSFileSize bytes_read; |
760 | - GnomeVFSFileSize bytes_written; |
761 | - GnomeVFSResult result; |
762 | - guint8 buffer[8192]; |
763 | - Glib::ustring fileUrl; |
764 | - |
765 | - // FIXME: this would be better as a per-user OCAL cache of files |
766 | - // instead of filling /tmp with downloads. |
767 | - // |
768 | - // create file path |
769 | - const std::string tmptemplate = "ocal-"; |
770 | - std::string tmpname; |
771 | - int fd = Inkscape::IO::file_open_tmp(tmpname, tmptemplate); |
772 | - if (fd<0) { |
773 | - g_warning("Error creating temp file"); |
774 | - return; |
775 | - } |
776 | - close(fd); |
777 | - // make sure we don't collide with other users on the same machine |
778 | - myFilename = tmpname; |
779 | - myFilename.append("-"); |
780 | - myFilename.append(get_text(posArray[0], 2)); |
781 | - // rename based on original image's name, retaining extension |
782 | - if (rename(tmpname.c_str(),myFilename.c_str())<0) { |
783 | - unlink(tmpname.c_str()); |
784 | - g_warning("Error creating destination file '%s': %s", myFilename.c_str(), strerror(errno)); |
785 | - goto failquit; |
786 | - } |
787 | - |
788 | - //get file url |
789 | - fileUrl = get_text(posArray[0], 1); //http url |
790 | - |
791 | - //Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
792 | - //Glib::ustring fileUrl = "dav://"; //dav url |
793 | - //fileUrl.append(prefs->getString("/options/ocalurl/str")); |
794 | - //fileUrl.append("/dav.php/"); |
795 | - //fileUrl.append(get_text(posArray[0], 3)); //author dir |
796 | - //fileUrl.append("/"); |
797 | - //fileUrl.append(get_text(posArray[0], 2)); //filename |
798 | - |
799 | - if (!Glib::get_charset()) //If we are not utf8 |
800 | - fileUrl = Glib::filename_to_utf8(fileUrl); |
801 | - |
802 | - { |
803 | - // open the temp file to receive |
804 | - result = gnome_vfs_open (&to_handle, myFilename.c_str(), GNOME_VFS_OPEN_WRITE); |
805 | - if (result == GNOME_VFS_ERROR_NOT_FOUND){ |
806 | - result = gnome_vfs_create (&to_handle, myFilename.c_str(), GNOME_VFS_OPEN_WRITE, FALSE, GNOME_VFS_PERM_USER_ALL); |
807 | - } |
808 | - if (result != GNOME_VFS_OK) { |
809 | - g_warning("Error creating temp file '%s': %s", myFilename.c_str(), gnome_vfs_result_to_string(result)); |
810 | - goto fail; |
811 | - } |
812 | - result = gnome_vfs_open (&from_handle, fileUrl.c_str(), GNOME_VFS_OPEN_READ); |
813 | - if (result != GNOME_VFS_OK) { |
814 | - g_warning("Could not find the file in Open Clip Art Library."); |
815 | - goto fail; |
816 | - } |
817 | - // copy the file |
818 | - while (1) { |
819 | - result = gnome_vfs_read (from_handle, buffer, 8192, &bytes_read); |
820 | - if ((result == GNOME_VFS_ERROR_EOF) &&(!bytes_read)){ |
821 | - result = gnome_vfs_close (from_handle); |
822 | - result = gnome_vfs_close (to_handle); |
823 | - break; |
824 | - } |
825 | - if (result != GNOME_VFS_OK) { |
826 | - g_warning("%s", gnome_vfs_result_to_string(result)); |
827 | - goto fail; |
828 | - } |
829 | - result = gnome_vfs_write (to_handle, buffer, bytes_read, &bytes_written); |
830 | - if (result != GNOME_VFS_OK) { |
831 | - g_warning("%s", gnome_vfs_result_to_string(result)); |
832 | - goto fail; |
833 | - } |
834 | - if (bytes_read != bytes_written){ |
835 | - g_warning("Bytes read not equal to bytes written"); |
836 | - goto fail; |
837 | - } |
838 | - } |
839 | - } |
840 | - myPreview->showImage(myFilename); |
841 | - myLabel->set_text(get_text(posArray[0], 4)); |
842 | -#endif |
843 | - return; |
844 | -fail: |
845 | - unlink(myFilename.c_str()); |
846 | -failquit: |
847 | - myFilename = ""; |
848 | -} |
849 | - |
850 | + int row = posArray[0]; |
851 | + |
852 | + if (downloading_thumbnail) { |
853 | + cancellable_thumbnail->cancel(); |
854 | + cancelled_thumbnail = true; |
855 | + } |
856 | + |
857 | + update_preview(row); |
858 | + downloading_thumbnail = true; |
859 | + download_resource(TYPE_THUMBNAIL, row); |
860 | +} |
861 | +void ImportDialog::update_preview(int row) |
862 | +{ |
863 | + Glib::ustring description = list_results->get_text(row, RESULTS_COLUMN_DESCRIPTION); |
864 | + Glib::ustring creator = list_results->get_text(row, RESULTS_COLUMN_CREATOR); |
865 | + Glib::ustring date = list_results->get_text(row, RESULTS_COLUMN_DATE); |
866 | + |
867 | + preview_files->clear(); |
868 | + preview_files->set_metadata(description, creator, date); |
869 | +} |
870 | + |
871 | + |
872 | +std::string ImportDialog::get_temporary_dir(ResourceType type) |
873 | +{ |
874 | + std::string ocal_tmp_dir = Glib::build_filename(Glib::get_tmp_dir(), |
875 | + "openclipart"); |
876 | + |
877 | + if (type == TYPE_THUMBNAIL) { |
878 | + return Glib::build_filename(ocal_tmp_dir, "thumbnails"); |
879 | + } else { |
880 | + return Glib::build_filename(ocal_tmp_dir, "images"); |
881 | + } |
882 | +} |
883 | + |
884 | +void ImportDialog::create_temporary_dirs() |
885 | +{ |
886 | + // Make sure the temporary directories exists, if not, create them |
887 | + std::string ocal_tmp_thumbnail_dir = get_temporary_dir(TYPE_THUMBNAIL); |
888 | + std::string ocal_tmp_image_dir = get_temporary_dir(TYPE_IMAGE); |
889 | + |
890 | + if (!Glib::file_test(ocal_tmp_thumbnail_dir, Glib::FILE_TEST_EXISTS)) { |
891 | + Glib::RefPtr<Gio::File> directory = Gio::File::create_for_path(ocal_tmp_thumbnail_dir); |
892 | + directory->make_directory_with_parents(); |
893 | + } |
894 | + |
895 | + if (!Glib::file_test(ocal_tmp_image_dir, Glib::FILE_TEST_EXISTS)) { |
896 | + Glib::RefPtr<Gio::File> directory = Gio::File::create_for_path(ocal_tmp_image_dir); |
897 | + directory->make_directory_with_parents(); |
898 | + } |
899 | +} |
900 | + |
901 | +void ImportDialog::download_resource(ResourceType type, int row) |
902 | +{ |
903 | + // Get Temporary Directory |
904 | + std::string ocal_tmp_dir = get_temporary_dir(type); |
905 | + |
906 | + // Make a unique filename for the clipart, in the form 'GUID.extension' |
907 | + Glib::ustring guid = list_results->get_text(row, RESULTS_COLUMN_GUID); |
908 | + Glib::ustring original_filename; |
909 | + |
910 | + if (type == TYPE_IMAGE) { |
911 | + original_filename = list_results->get_text(row, RESULTS_COLUMN_FILENAME); |
912 | + } else { |
913 | + original_filename = list_results->get_text(row, RESULTS_COLUMN_THUMBNAIL_FILENAME); |
914 | + } |
915 | + Glib::ustring extension = Inkscape::IO::get_file_extension(original_filename); |
916 | + |
917 | + Glib::ustring filename = Glib::ustring::compose("%1%2", guid, extension); |
918 | + std::string path = Glib::build_filename(ocal_tmp_dir, filename.c_str()); |
919 | + Glib::RefPtr<Gio::File> file_local = Gio::File::create_for_path(path); |
920 | + |
921 | + // If the file has already been downloaded, use it |
922 | + if (Glib::file_test(path, Glib::FILE_TEST_EXISTS)) { |
923 | + if (type == TYPE_IMAGE) { |
924 | + on_image_downloaded(path, true); |
925 | + } else { |
926 | + on_thumbnail_downloaded(path, true); |
927 | + } |
928 | + return; |
929 | + } |
930 | + |
931 | + // Get Remote File URL and get the respective cancellable object |
932 | + Glib::ustring url; |
933 | + Glib::RefPtr<Gio::Cancellable> cancellable; |
934 | + |
935 | + if (type == TYPE_IMAGE) { |
936 | + url = list_results->get_text(row, RESULTS_COLUMN_URL); |
937 | + cancellable_image = Gio::Cancellable::create(); |
938 | + cancellable = cancellable_image; |
939 | + } else { |
940 | + url = list_results->get_text(row, RESULTS_COLUMN_THUMBNAIL_URL); |
941 | + cancellable_thumbnail = Gio::Cancellable::create(); |
942 | + cancellable = cancellable_thumbnail; |
943 | + } |
944 | + |
945 | + Glib::RefPtr<Gio::File> file_remote = Gio::File::create_for_uri(url); |
946 | + |
947 | + // Download it asynchronously |
948 | + file_remote->copy_async(file_local, |
949 | + sigc::bind<Glib::RefPtr<Gio::File>, Glib::ustring, ResourceType>( |
950 | + sigc::mem_fun(*this, &ImportDialog::on_resource_downloaded), |
951 | + file_remote, path, type), cancellable, |
952 | + Gio::FILE_COPY_OVERWRITE); |
953 | +} |
954 | + |
955 | +void ImportDialog::on_resource_downloaded(const Glib::RefPtr<Gio::AsyncResult>& result, |
956 | + Glib::RefPtr<Gio::File> file_remote, Glib::ustring path, ResourceType resource) |
957 | +{ |
958 | + bool success; |
959 | + |
960 | + try { |
961 | + success = file_remote->copy_finish(result); |
962 | + } catch(Glib::Error) { |
963 | + success = false; |
964 | + } |
965 | + |
966 | + if (resource == TYPE_IMAGE) { |
967 | + on_image_downloaded(path, success); |
968 | + } else { |
969 | + on_thumbnail_downloaded(path, success); |
970 | + } |
971 | +} |
972 | + |
973 | +void ImportDialog::on_image_downloaded(Glib::ustring path, bool success) |
974 | +{ |
975 | + button_import->set_sensitive(true); |
976 | + button_close->show(); |
977 | + button_cancel->hide(); |
978 | + |
979 | + // If anything went wrong, show an error message if the user didn't do it |
980 | + if (!success && !cancelled_image) { |
981 | + widget_status->set_error(_("Could not download image")); |
982 | + } |
983 | + if (!success) { |
984 | + widget_status->clear(); |
985 | + return; |
986 | + } |
987 | + |
988 | + try { |
989 | + widget_status->clear(); |
990 | + m_signal_response.emit(path); |
991 | + widget_status->set_info(_("Clipart downloaded successfully")); |
992 | + } catch(Glib::Error) { |
993 | + success = false; |
994 | + } |
995 | + |
996 | + cancelled_image = false; |
997 | +} |
998 | + |
999 | +void ImportDialog::on_thumbnail_downloaded(Glib::ustring path, bool success) |
1000 | +{ |
1001 | + downloading_thumbnail = false; |
1002 | + |
1003 | + // If anything went wrong, show an error message if the user didn't do it |
1004 | + if (!success && !cancelled_thumbnail) { |
1005 | + widget_status->set_error(_("Could not download thumbnail file")); |
1006 | + return; |
1007 | + } |
1008 | + if (!success) { |
1009 | + widget_status->clear(); |
1010 | + return; |
1011 | + } |
1012 | + |
1013 | + try { |
1014 | + widget_status->clear(); |
1015 | + preview_files->set_image(path); |
1016 | + } catch(Glib::Error) { |
1017 | + success = false; |
1018 | + } |
1019 | + |
1020 | + cancelled_thumbnail = false; |
1021 | +} |
1022 | |
1023 | /* |
1024 | * Callback for row activated |
1025 | */ |
1026 | -void FileListViewText::on_row_activated(const Gtk::TreeModel::Path& /*path*/, Gtk::TreeViewColumn* /*column*/) |
1027 | -{ |
1028 | - this->on_cursor_changed(); |
1029 | - myButton->activate(); |
1030 | -} |
1031 | - |
1032 | - |
1033 | -/* |
1034 | - * Returns the selected filename |
1035 | - */ |
1036 | -Glib::ustring FileListViewText::getFilename() |
1037 | -{ |
1038 | - return myFilename; |
1039 | -} |
1040 | - |
1041 | - |
1042 | -#ifdef WITH_GNOME_VFS |
1043 | -/** |
1044 | - * Read callback for xmlReadIO(), used below |
1045 | - */ |
1046 | -static int vfs_read_callback (GnomeVFSHandle *handle, char* buf, int nb) |
1047 | -{ |
1048 | - GnomeVFSFileSize ndone; |
1049 | - GnomeVFSResult result; |
1050 | - |
1051 | - result = gnome_vfs_read (handle, buf, nb, &ndone); |
1052 | - |
1053 | - if (result == GNOME_VFS_OK) { |
1054 | - return (int)ndone; |
1055 | - } else { |
1056 | - if (result != GNOME_VFS_ERROR_EOF) { |
1057 | - sp_ui_error_dialog(_("Error while reading the Open Clip Art RSS feed")); |
1058 | - g_warning("%s\n", gnome_vfs_result_to_string(result)); |
1059 | - } |
1060 | - return -1; |
1061 | - } |
1062 | -} |
1063 | -#endif |
1064 | - |
1065 | - |
1066 | -/** |
1067 | - * Callback for user input into searchTagEntry |
1068 | - */ |
1069 | -void FileImportFromOCALDialog::searchTagEntryChangedCallback() |
1070 | -{ |
1071 | - if (!searchTagEntry) |
1072 | - return; |
1073 | - |
1074 | - notFoundLabel->hide(); |
1075 | - descriptionLabel->set_text(""); |
1076 | - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
1077 | - |
1078 | - Glib::ustring searchTag = searchTagEntry->get_text(); |
1079 | - // create the ocal uri to get rss feed |
1080 | - Glib::ustring uri = "http://"; |
1081 | - uri.append(prefs->getString("/options/ocalurl/str")); |
1082 | - uri.append("/media/feed/rss/"); |
1083 | - uri.append(searchTag); |
1084 | - if (!Glib::get_charset()) //If we are not utf8 |
1085 | - uri = Glib::filename_to_utf8(uri); |
1086 | - |
1087 | -#ifdef WITH_GNOME_VFS |
1088 | - |
1089 | - // open the rss feed |
1090 | - gnome_vfs_init(); |
1091 | - GnomeVFSHandle *from_handle = NULL; |
1092 | - GnomeVFSResult result; |
1093 | - |
1094 | - result = gnome_vfs_open (&from_handle, uri.c_str(), GNOME_VFS_OPEN_READ); |
1095 | - if (result != GNOME_VFS_OK) { |
1096 | - sp_ui_error_dialog(_("Failed to receive the Open Clip Art Library RSS feed. Verify if the server name is correct in Configuration->Import/Export (e.g.: openclipart.org)")); |
1097 | - return; |
1098 | - } |
1099 | - |
1100 | - // create the resulting xml document tree |
1101 | - // this initialize the library and test mistakes between compiled and shared library used |
1102 | - LIBXML_TEST_VERSION |
1103 | - xmlDoc *doc = NULL; |
1104 | - xmlNode *root_element = NULL; |
1105 | - |
1106 | - doc = xmlReadIO ((xmlInputReadCallback) vfs_read_callback, |
1107 | - (xmlInputCloseCallback) gnome_vfs_close, from_handle, uri.c_str(), NULL, |
1108 | - XML_PARSE_RECOVER + XML_PARSE_NOWARNING + XML_PARSE_NOERROR); |
1109 | - if (doc == NULL) { |
1110 | - sp_ui_error_dialog(_("Server supplied malformed Clip Art feed")); |
1111 | - g_warning("Failed to parse %s\n", uri.c_str()); |
1112 | - return; |
1113 | - } |
1114 | - |
1115 | - // get the root element node |
1116 | - root_element = xmlDocGetRootElement(doc); |
1117 | - |
1118 | - // clear the fileslist |
1119 | - filesList->clear_items(); |
1120 | - filesList->set_sensitive(false); |
1121 | - |
1122 | - // print all xml the element names |
1123 | - print_xml_element_names(root_element); |
1124 | - |
1125 | - if (filesList->size() == 0) |
1126 | - { |
1127 | - notFoundLabel->show(); |
1128 | - filesList->set_sensitive(false); |
1129 | - } |
1130 | - else |
1131 | - filesList->set_sensitive(true); |
1132 | - |
1133 | - // free the document |
1134 | - xmlFreeDoc(doc); |
1135 | - // free the global variables that may have been allocated by the parser |
1136 | - xmlCleanupParser(); |
1137 | - return; |
1138 | -#endif |
1139 | -} |
1140 | - |
1141 | +void ImportDialog::on_list_results_row_activated(const Gtk::TreeModel::Path& path, |
1142 | + Gtk::TreeViewColumn* column) |
1143 | +{ |
1144 | + on_list_results_cursor_changed(); |
1145 | + button_import->signal_clicked(); |
1146 | +} |
1147 | |
1148 | /** |
1149 | * Prints the names of the all the xml elements |
1150 | * that are siblings or children of a given xml node |
1151 | */ |
1152 | -void FileImportFromOCALDialog::print_xml_element_names(xmlNode * a_node) |
1153 | +void SearchResultList::populate_from_xml(xmlNode * a_node) |
1154 | { |
1155 | xmlNode *cur_node = NULL; |
1156 | guint row_num = 0; |
1157 | + |
1158 | for (cur_node = a_node; cur_node; cur_node = cur_node->next) { |
1159 | - // get itens information |
1160 | - if (strcmp((const char*)cur_node->name, "rss")) //avoid the root |
1161 | + // Get items information |
1162 | + if (strcmp((const char*)cur_node->name, "rss")) // Avoid the root |
1163 | if (cur_node->type == XML_ELEMENT_NODE && !strcmp((const char*)cur_node->parent->name, "item")) |
1164 | { |
1165 | if (!strcmp((const char*)cur_node->name, "title")) |
1166 | { |
1167 | - xmlChar *title = xmlNodeGetContent(cur_node); |
1168 | - row_num = filesList->append_text((const char*)title); |
1169 | + row_num = append_text(""); |
1170 | + xmlChar *xml_title = xmlNodeGetContent(cur_node); |
1171 | + char* title = (char*) xml_title; |
1172 | + |
1173 | + set_text(row_num, RESULTS_COLUMN_TITLE, title); |
1174 | xmlFree(title); |
1175 | } |
1176 | -#ifdef WITH_GNOME_VFS |
1177 | - else if (!strcmp((const char*)cur_node->name, "enclosure")) |
1178 | + else if (!strcmp((const char*)cur_node->name, "pubDate")) |
1179 | { |
1180 | - xmlChar *urlattribute = xmlGetProp(cur_node, (xmlChar*)"url"); |
1181 | - filesList->set_text(row_num, 1, (const char*)urlattribute); |
1182 | - gchar *tmp_file; |
1183 | - tmp_file = gnome_vfs_uri_extract_short_path_name(gnome_vfs_uri_new((const char*)urlattribute)); |
1184 | - filesList->set_text(row_num, 2, (const char*)tmp_file); |
1185 | - xmlFree(urlattribute); |
1186 | + xmlChar *xml_date = xmlNodeGetContent(cur_node); |
1187 | + char* date = (char*) xml_date; |
1188 | + |
1189 | + set_text(row_num, RESULTS_COLUMN_DATE, date); |
1190 | + xmlFree(xml_date); |
1191 | } |
1192 | else if (!strcmp((const char*)cur_node->name, "creator")) |
1193 | { |
1194 | - filesList->set_text(row_num, 3, (const char*)xmlNodeGetContent(cur_node)); |
1195 | + xmlChar *xml_creator = xmlNodeGetContent(cur_node); |
1196 | + char* creator = (char*) xml_creator; |
1197 | + |
1198 | + set_text(row_num, RESULTS_COLUMN_CREATOR, creator); |
1199 | + xmlFree(xml_creator); |
1200 | } |
1201 | else if (!strcmp((const char*)cur_node->name, "description")) |
1202 | { |
1203 | - filesList->set_text(row_num, 4, (const char*)xmlNodeGetContent(cur_node)); |
1204 | - } |
1205 | -#endif |
1206 | + xmlChar *xml_description = xmlNodeGetContent(cur_node); |
1207 | + //char* final_description; |
1208 | + char* stripped_description = g_strstrip((char*) xml_description); |
1209 | + |
1210 | + if (!strcmp(stripped_description, "")) { |
1211 | + stripped_description = _("No description"); |
1212 | + } |
1213 | + |
1214 | + //GRegex* regex = g_regex_new(g_regex_escape_string(stripped_description, -1)); |
1215 | + //final_description = g_regex_replace_literal(regex, "\n", -1, 0, " "); |
1216 | + |
1217 | + set_text(row_num, RESULTS_COLUMN_DESCRIPTION, stripped_description); |
1218 | + xmlFree(xml_description); |
1219 | + } |
1220 | + else if (!strcmp((const char*)cur_node->name, "enclosure")) |
1221 | + { |
1222 | + xmlChar *xml_url = xmlGetProp(cur_node, (xmlChar*) "url"); |
1223 | + char* url = (char*) xml_url; |
1224 | + char* filename = g_path_get_basename(url); |
1225 | + |
1226 | + set_text(row_num, RESULTS_COLUMN_URL, url); |
1227 | + set_text(row_num, RESULTS_COLUMN_FILENAME, filename); |
1228 | + xmlFree(xml_url); |
1229 | + } |
1230 | + else if (!strcmp((const char*)cur_node->name, "thumbnail")) |
1231 | + { |
1232 | + xmlChar *xml_thumbnail_url = xmlGetProp(cur_node, (xmlChar*) "url"); |
1233 | + char* thumbnail_url = (char*) xml_thumbnail_url; |
1234 | + char* thumbnail_filename = g_path_get_basename(thumbnail_url); |
1235 | + |
1236 | + set_text(row_num, RESULTS_COLUMN_THUMBNAIL_URL, thumbnail_url); |
1237 | + set_text(row_num, RESULTS_COLUMN_THUMBNAIL_FILENAME, thumbnail_filename); |
1238 | + xmlFree(xml_thumbnail_url); |
1239 | + } |
1240 | + else if (!strcmp((const char*)cur_node->name, "guid")) |
1241 | + { |
1242 | + xmlChar *xml_guid = xmlNodeGetContent(cur_node); |
1243 | + char* guid_url = (char*) xml_guid; |
1244 | + char* guid = g_path_get_basename(guid_url); |
1245 | + |
1246 | + set_text(row_num, RESULTS_COLUMN_GUID, guid); |
1247 | + xmlFree(xml_guid); |
1248 | + } |
1249 | } |
1250 | - print_xml_element_names(cur_node->children); |
1251 | - } |
1252 | + populate_from_xml(cur_node->children); |
1253 | + } |
1254 | +} |
1255 | + |
1256 | +/** |
1257 | + * Callback for user input into entry_search |
1258 | + */ |
1259 | +void ImportDialog::on_button_search_clicked() |
1260 | +{ |
1261 | + on_entry_search_activated(); |
1262 | +} |
1263 | + |
1264 | +void ImportDialog::on_button_close_clicked() |
1265 | +{ |
1266 | + hide(); |
1267 | +} |
1268 | + |
1269 | +void ImportDialog::on_button_cancel_clicked() |
1270 | +{ |
1271 | + cancellable_image->cancel(); |
1272 | + cancelled_image = true; |
1273 | +} |
1274 | + |
1275 | +/** |
1276 | + * Callback for user input into entry_search |
1277 | + */ |
1278 | +void ImportDialog::on_entry_search_activated() |
1279 | +{ |
1280 | + preview_files->clear(); |
1281 | + widget_status->start_process(_("Searching clipart...")); |
1282 | + |
1283 | + notebook_content->set_current_page(NOTEBOOK_PAGE_LOGO); |
1284 | + |
1285 | + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); |
1286 | + |
1287 | + Glib::ustring search_keywords = entry_search->get_text(); |
1288 | + |
1289 | + // Create the URI to the OCAL RSS feed |
1290 | + Glib::ustring xml_uri = Glib::ustring::compose("http://%1/media/feed/rss/%2", |
1291 | + prefs->getString("/options/ocalurl/str"), search_keywords); |
1292 | + // If we are not UTF8 |
1293 | + if (!Glib::get_charset()) { |
1294 | + xml_uri = Glib::filename_to_utf8(xml_uri); |
1295 | + } |
1296 | + |
1297 | + // Open the RSS feed |
1298 | + Glib::RefPtr<Gio::File> xml_file = Gio::File::create_for_uri(xml_uri); |
1299 | + |
1300 | + xml_file->load_contents_async( |
1301 | + sigc::bind<Glib::RefPtr<Gio::File> , Glib::ustring>( |
1302 | + sigc::mem_fun(*this, &ImportDialog::on_xml_file_read), |
1303 | + xml_file, xml_uri) |
1304 | + ); |
1305 | +} |
1306 | + |
1307 | +void ImportDialog::on_xml_file_read(const Glib::RefPtr<Gio::AsyncResult>& result, |
1308 | + Glib::RefPtr<Gio::File> xml_file, Glib::ustring xml_uri) |
1309 | +{ |
1310 | + widget_status->end_process(); |
1311 | + |
1312 | + char* data; |
1313 | + gsize length; |
1314 | + |
1315 | + bool sucess = xml_file->load_contents_finish(result, data, length); |
1316 | + if (!sucess) { |
1317 | + widget_status->set_error(_("Could not connect to the Open Clip Art Library")); |
1318 | + return; |
1319 | + } |
1320 | + |
1321 | + // Create the resulting xml document tree |
1322 | + // Initialize libxml and test mistakes between compiled and shared library used |
1323 | + LIBXML_TEST_VERSION |
1324 | + xmlDoc *doc = NULL; |
1325 | + xmlNode *root_element = NULL; |
1326 | + |
1327 | + doc = xmlReadMemory(data, (int) length, xml_uri.c_str(), NULL, |
1328 | + XML_PARSE_RECOVER + XML_PARSE_NOWARNING + XML_PARSE_NOERROR); |
1329 | + |
1330 | + if (doc == NULL) { |
1331 | + // If nothing is returned, no results could be found |
1332 | + if (length == 0) { |
1333 | + notebook_content->set_current_page(NOTEBOOK_PAGE_NOT_FOUND); |
1334 | + update_label_no_search_results(); |
1335 | + } else { |
1336 | + widget_status->set_error(_("Could not parse search results")); |
1337 | + } |
1338 | + return; |
1339 | + } |
1340 | + |
1341 | + // Get the root element node |
1342 | + root_element = xmlDocGetRootElement(doc); |
1343 | + |
1344 | + // Clear and populate the list_results |
1345 | + list_results->clear_items(); |
1346 | + list_results->populate_from_xml(root_element); |
1347 | + |
1348 | + // Populate the MARKUP column with the title & description of the clipart |
1349 | + for (guint i = 0; i <= list_results->size() - 1; i++) { |
1350 | + Glib::ustring title = list_results->get_text(i, RESULTS_COLUMN_TITLE); |
1351 | + Glib::ustring description = list_results->get_text(i, RESULTS_COLUMN_DESCRIPTION); |
1352 | + char* markup = g_markup_printf_escaped("<b>%s</b>\n<span size=\"small\">%s</span>", |
1353 | + title.c_str(), description.c_str()); |
1354 | + list_results->set_text(i, RESULTS_COLUMN_MARKUP, markup); |
1355 | + } |
1356 | + notebook_content->set_current_page(NOTEBOOK_PAGE_RESULTS); |
1357 | + |
1358 | + // free the document |
1359 | + xmlFreeDoc(doc); |
1360 | + // free the global variables that may have been allocated by the parser |
1361 | + xmlCleanupParser(); |
1362 | +} |
1363 | + |
1364 | + |
1365 | +void ImportDialog::update_label_no_search_results() |
1366 | +{ |
1367 | + Glib::ustring keywords = Glib::Markup::escape_text(entry_search->get_text()); |
1368 | + Gdk::Color grey = entry_search->get_style()->get_text_aa(entry_search->get_state()); |
1369 | + |
1370 | + Glib::ustring markup = Glib::ustring::compose( |
1371 | + "<span size=\"large\">%1 <b>%2</b> %3</span>\n<span color=\"%4\">%5</span>", |
1372 | + _("No clipart named"), keywords, _("was found."), grey.to_string(), |
1373 | + _("Please make sure all keywords are spelled correctly, or try again with different keywords.")); |
1374 | + |
1375 | + label_not_found->set_markup(markup); |
1376 | } |
1377 | |
1378 | /** |
1379 | * Constructor. Not called directly. Use the factory. |
1380 | */ |
1381 | -FileImportFromOCALDialog::FileImportFromOCALDialog(Gtk::Window& parentWindow, |
1382 | - const Glib::ustring &/*dir*/, |
1383 | - FileDialogType fileTypes, |
1384 | +ImportDialog::ImportDialog(Gtk::Window& parent_window, FileDialogType file_types, |
1385 | const Glib::ustring &title) : |
1386 | - FileDialogOCALBase(title, parentWindow) |
1387 | + FileDialogBase(title, parent_window) |
1388 | { |
1389 | + printf("%s\n", "Hi!"); |
1390 | // Initalize to Autodetect |
1391 | extension = NULL; |
1392 | // No filename to start out with |
1393 | - Glib::ustring searchTag = ""; |
1394 | - |
1395 | - dialogType = fileTypes; |
1396 | - Gtk::VBox *vbox = get_vbox(); |
1397 | - Gtk::Label *tagLabel = new Gtk::Label(_("Search for:")); |
1398 | - notFoundLabel = new Gtk::Label(_("No files matched your search")); |
1399 | - descriptionLabel = new Gtk::Label(); |
1400 | - descriptionLabel->set_max_width_chars(260); |
1401 | - descriptionLabel->set_size_request(500, -1); |
1402 | - descriptionLabel->set_single_line_mode(false); |
1403 | - descriptionLabel->set_line_wrap(true); |
1404 | - messageBox.pack_start(*notFoundLabel); |
1405 | - descriptionBox.pack_start(*descriptionLabel); |
1406 | - searchTagEntry = new Gtk::Entry(); |
1407 | - searchTagEntry->set_text(searchTag); |
1408 | - searchTagEntry->set_max_length(255); |
1409 | - searchButton = new Gtk::Button(_("Search")); |
1410 | - tagBox.pack_start(*tagLabel); |
1411 | - tagBox.pack_start(*searchTagEntry, Gtk::PACK_EXPAND_WIDGET, 3); |
1412 | - tagBox.pack_start(*searchButton); |
1413 | - filesPreview = new SVGPreview(); |
1414 | - filesPreview->showNoPreview(); |
1415 | - // add the buttons in the bottom of the dialog |
1416 | - add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); |
1417 | - okButton = add_button(Gtk::Stock::OPEN, Gtk::RESPONSE_OK); |
1418 | - // sets the okbutton to default |
1419 | - set_default(*okButton); |
1420 | - filesList = new FileListViewText(5, *filesPreview, *descriptionLabel, *okButton); |
1421 | - filesList->set_sensitive(false); |
1422 | - // add the listview inside a ScrolledWindow |
1423 | - listScrolledWindow.add(*filesList); |
1424 | - // only show the scrollbars when they are necessary: |
1425 | - listScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); |
1426 | - filesList->set_column_title(0, _("Files found")); |
1427 | - listScrolledWindow.set_size_request(400, 180); |
1428 | - filesList->get_column(1)->set_visible(false); // file url |
1429 | - filesList->get_column(2)->set_visible(false); // tmp file path |
1430 | - filesList->get_column(3)->set_visible(false); // author dir |
1431 | - filesList->get_column(4)->set_visible(false); // file description |
1432 | - filesBox.pack_start(listScrolledWindow); |
1433 | - filesBox.pack_start(*filesPreview); |
1434 | - vbox->pack_start(tagBox, false, false); |
1435 | - vbox->pack_start(messageBox); |
1436 | - vbox->pack_start(filesBox); |
1437 | - vbox->pack_start(descriptionBox); |
1438 | - |
1439 | - //Let's do some customization |
1440 | - searchTagEntry = NULL; |
1441 | - Gtk::Container *cont = get_toplevel(); |
1442 | - std::vector<Gtk::Entry *> entries; |
1443 | - findEntryWidgets(cont, entries); |
1444 | - if (entries.size() >=1 ) |
1445 | - { |
1446 | - //Catch when user hits [return] on the text field |
1447 | - searchTagEntry = entries[0]; |
1448 | - searchTagEntry->signal_activate().connect( |
1449 | - sigc::mem_fun(*this, &FileImportFromOCALDialog::searchTagEntryChangedCallback)); |
1450 | - } |
1451 | - |
1452 | - searchButton->signal_clicked().connect( |
1453 | - sigc::mem_fun(*this, &FileImportFromOCALDialog::searchTagEntryChangedCallback)); |
1454 | + Glib::ustring search_keywords = ""; |
1455 | + |
1456 | + dialogType = file_types; |
1457 | + |
1458 | + // Creation |
1459 | + Gtk::VBox *vbox = new Gtk::VBox(false, 0); |
1460 | + Gtk::HButtonBox *hbuttonbox_bottom = new Gtk::HButtonBox(); |
1461 | + Gtk::HBox *hbox_bottom = new Gtk::HBox(false, 12); |
1462 | + BaseBox *basebox_logo = new BaseBox(); |
1463 | + BaseBox *basebox_no_search_results = new BaseBox(); |
1464 | + label_not_found = new Gtk::Label(); |
1465 | + label_description = new Gtk::Label(); |
1466 | + entry_search = new SearchEntry(); |
1467 | + button_search = new Gtk::Button(_("Search")); |
1468 | + Gtk::HButtonBox* hbuttonbox_search = new Gtk::HButtonBox(); |
1469 | + Gtk::ScrolledWindow* scrolledwindow_preview = new Gtk::ScrolledWindow(); |
1470 | + preview_files = new PreviewWidget(); |
1471 | + /// Add the buttons in the bottom of the dialog |
1472 | + button_cancel = new Gtk::Button(Gtk::Stock::CANCEL); |
1473 | + button_close = new Gtk::Button(_("Close")); |
1474 | + button_import = new Gtk::Button(_("Import")); |
1475 | + list_results = new SearchResultList(RESULTS_COLUMN_LENGTH); |
1476 | + drawingarea_logo = new LogoArea(); |
1477 | + notebook_content = new Gtk::Notebook(); |
1478 | + widget_status = new StatusWidget(); |
1479 | + |
1480 | + downloading_thumbnail = false; |
1481 | + cancelled_thumbnail = false; |
1482 | + cancelled_image = false; |
1483 | + |
1484 | + // Packing |
1485 | + add(*vbox); |
1486 | + vbox->pack_start(hbox_tags, false, false); |
1487 | + vbox->pack_start(hbox_files, true, true); |
1488 | + vbox->pack_start(*hbox_bottom, false, false); |
1489 | + basebox_logo->add(*drawingarea_logo); |
1490 | + basebox_no_search_results->add(*label_not_found); |
1491 | + hbox_bottom->pack_start(*widget_status, true, true); |
1492 | + hbox_bottom->pack_start(*hbuttonbox_bottom, true, true); |
1493 | + hbuttonbox_bottom->pack_start(*button_cancel, false, false); |
1494 | + hbuttonbox_bottom->pack_start(*button_close, false, false); |
1495 | + hbuttonbox_bottom->pack_start(*button_import, false, false); |
1496 | + hbuttonbox_search->pack_start(*button_search, false, false); |
1497 | + hbox_tags.pack_start(*entry_search, true, true); |
1498 | + hbox_tags.pack_start(*hbuttonbox_search, false, false); |
1499 | + hbox_files.pack_start(*notebook_content, true, true); |
1500 | + scrolledwindow_preview->add(*preview_files); |
1501 | + hbox_files.pack_start(*scrolledwindow_preview, true, true); |
1502 | + |
1503 | + notebook_content->insert_page(*basebox_logo, NOTEBOOK_PAGE_LOGO); |
1504 | + notebook_content->insert_page(scrolledwindow_list, NOTEBOOK_PAGE_RESULTS); |
1505 | + notebook_content->insert_page(*basebox_no_search_results, NOTEBOOK_PAGE_NOT_FOUND); |
1506 | + |
1507 | + // Properties |
1508 | + set_border_width(12); |
1509 | + set_default_size(480, 330); |
1510 | + vbox->set_spacing(12); |
1511 | + hbuttonbox_bottom->set_spacing(6); |
1512 | + hbuttonbox_bottom->set_layout(Gtk::BUTTONBOX_END); |
1513 | + button_import->set_sensitive(false); |
1514 | + entry_search->set_max_length(255); |
1515 | + hbox_tags.set_spacing(6); |
1516 | + preview_files->clear(); |
1517 | + notebook_content->set_current_page(NOTEBOOK_PAGE_LOGO); |
1518 | + /// Add the listview inside a ScrolledWindow |
1519 | + scrolledwindow_list.add(*list_results); |
1520 | + scrolledwindow_list.set_shadow_type(Gtk::SHADOW_IN); |
1521 | + /// Only show the scrollbars when they are necessary |
1522 | + scrolledwindow_list.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); |
1523 | + preview_files->set_size_request(120, -1); |
1524 | + hbox_files.set_spacing(12); |
1525 | + label_not_found->set_line_wrap(true); |
1526 | + label_not_found->set_line_wrap_mode(Pango::WRAP_WORD); |
1527 | + label_not_found->set_justify(Gtk::JUSTIFY_CENTER); |
1528 | + label_not_found->set_size_request(260, -1); |
1529 | + scrolledwindow_preview->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); |
1530 | + notebook_content->set_show_tabs(false); |
1531 | + notebook_content->set_show_border(false); |
1532 | + button_cancel->set_no_show_all(true); |
1533 | + button_close->set_no_show_all(true); |
1534 | + button_close->show(); |
1535 | + button_cancel->hide(); |
1536 | + |
1537 | + // Signals |
1538 | + entry_search->signal_activate().connect( |
1539 | + sigc::mem_fun(*this, &ImportDialog::on_entry_search_activated)); |
1540 | + button_import->signal_clicked().connect( |
1541 | + sigc::mem_fun(*this, &ImportDialog::on_button_import_clicked)); |
1542 | + button_close->signal_clicked().connect( |
1543 | + sigc::mem_fun(*this, &ImportDialog::on_button_close_clicked)); |
1544 | + button_cancel->signal_clicked().connect( |
1545 | + sigc::mem_fun(*this, &ImportDialog::on_button_cancel_clicked)); |
1546 | + button_search->signal_clicked().connect( |
1547 | + sigc::mem_fun(*this, &ImportDialog::on_button_search_clicked)); |
1548 | + list_results->signal_cursor_changed().connect( |
1549 | + sigc::mem_fun(*this, &ImportDialog::on_list_results_cursor_changed)); |
1550 | + list_results->signal_row_activated().connect( |
1551 | + sigc::mem_fun(*this, &ImportDialog::on_list_results_row_activated)); |
1552 | + list_results->get_selection()->signal_changed().connect( |
1553 | + sigc::mem_fun(*this, &ImportDialog::on_list_results_selection_changed)); |
1554 | |
1555 | show_all_children(); |
1556 | - notFoundLabel->hide(); |
1557 | + entry_search->grab_focus(); |
1558 | + |
1559 | + // Create the temporary directories that will be needed later |
1560 | + create_temporary_dirs(); |
1561 | } |
1562 | |
1563 | /** |
1564 | * Destructor |
1565 | */ |
1566 | -FileImportFromOCALDialog::~FileImportFromOCALDialog() |
1567 | -{ |
1568 | - |
1569 | -} |
1570 | - |
1571 | -/** |
1572 | - * Show this dialog modally. Return true if user hits [OK] |
1573 | - */ |
1574 | -bool |
1575 | -FileImportFromOCALDialog::show() |
1576 | -{ |
1577 | - set_modal (TRUE); //Window |
1578 | - sp_transientize((GtkWidget *)gobj()); //Make transient |
1579 | - gint b = run(); //Dialog |
1580 | - hide(); |
1581 | - |
1582 | - if (b == Gtk::RESPONSE_OK) |
1583 | - { |
1584 | - return TRUE; |
1585 | - } |
1586 | - else |
1587 | - { |
1588 | - return FALSE; |
1589 | - } |
1590 | -} |
1591 | - |
1592 | +ImportDialog::~ImportDialog() |
1593 | +{ |
1594 | + |
1595 | +} |
1596 | |
1597 | /** |
1598 | * Get the file extension type that was selected by the user. Valid after an [OK] |
1599 | */ |
1600 | Inkscape::Extension::Extension * |
1601 | -FileImportFromOCALDialog::getSelectionType() |
1602 | +ImportDialog::get_selection_type() |
1603 | { |
1604 | return extension; |
1605 | } |
1606 | |
1607 | - |
1608 | -/** |
1609 | - * Get the file name chosen by the user. Valid after an [OK] |
1610 | - */ |
1611 | -Glib::ustring |
1612 | -FileImportFromOCALDialog::getFilename (void) |
1613 | +ImportDialog::type_signal_response ImportDialog::signal_response() |
1614 | { |
1615 | - return filesList->getFilename(); |
1616 | + return m_signal_response; |
1617 | } |
1618 | |
1619 | |
1620 | +} //namespace OCAL |
1621 | } //namespace Dialog |
1622 | } //namespace UI |
1623 | } //namespace Inkscape |
1624 | |
1625 | - |
1626 | - |
1627 | /* |
1628 | Local Variables: |
1629 | mode:c++ |
1630 | |
1631 | === modified file 'src/ui/dialog/ocaldialogs.h' |
1632 | --- src/ui/dialog/ocaldialogs.h 2011-06-03 10:44:52 +0000 |
1633 | +++ src/ui/dialog/ocaldialogs.h 2011-12-27 21:09:25 +0000 |
1634 | @@ -4,6 +4,7 @@ |
1635 | /* Authors: |
1636 | * Bruno Dilly <bruno.dilly@gmail.com> |
1637 | * Inkscape Guys |
1638 | + * Andrew Higginson |
1639 | * |
1640 | * Copyright (C) 2007 Bruno Dilly <bruno.dilly@gmail.com> |
1641 | * Released under GNU GPL, read the file 'COPYING' for more information |
1642 | @@ -52,6 +53,7 @@ |
1643 | //For export dialog |
1644 | #include "ui/widget/scalar-unit.h" |
1645 | |
1646 | +#include <dialogs/dialog-events.h> |
1647 | |
1648 | namespace Inkscape |
1649 | { |
1650 | @@ -59,7 +61,8 @@ |
1651 | { |
1652 | namespace Dialog |
1653 | { |
1654 | - |
1655 | +namespace OCAL |
1656 | +{ |
1657 | /*######################################################################### |
1658 | ### F I L E D I A L O G O C A L B A S E C L A S S |
1659 | #########################################################################*/ |
1660 | @@ -67,20 +70,32 @@ |
1661 | /** |
1662 | * This class is the base implementation for export to OCAL. |
1663 | */ |
1664 | -class FileDialogOCALBase : public Gtk::Dialog |
1665 | +class FileDialogBase : public Gtk::Window |
1666 | { |
1667 | public: |
1668 | |
1669 | /** |
1670 | * Constructor |
1671 | */ |
1672 | - FileDialogOCALBase(const Glib::ustring &title, Gtk::Window& parent) : Gtk::Dialog(title, parent, true) |
1673 | - {} |
1674 | + FileDialogBase(const Glib::ustring &title, Gtk::Window& parent) : Gtk::Window(Gtk::WINDOW_TOPLEVEL) |
1675 | + { |
1676 | + set_title(title); |
1677 | + sp_transientize((GtkWidget*) gobj()); |
1678 | + |
1679 | + // Allow shrinking of window so labels wrap correctly |
1680 | + set_resizable(true); |
1681 | + |
1682 | + Gdk::Geometry geom; |
1683 | + geom.min_width = 480; |
1684 | + geom.min_height = 320; |
1685 | + |
1686 | + set_geometry_hints(*this, geom, Gdk::HINT_MIN_SIZE); |
1687 | + } |
1688 | |
1689 | /* |
1690 | * Destructor |
1691 | */ |
1692 | - virtual ~FileDialogOCALBase() |
1693 | + virtual ~FileDialogBase() |
1694 | {} |
1695 | |
1696 | protected: |
1697 | @@ -101,10 +116,10 @@ |
1698 | |
1699 | |
1700 | /** |
1701 | - * Our implementation of the FileExportToOCALDialog interface. |
1702 | + * Our implementation of the ExportDialog interface. |
1703 | */ |
1704 | /* |
1705 | -class FileExportToOCALDialog : public FileDialogOCALBase |
1706 | +class ExportDialog : public FileDialogBase |
1707 | { |
1708 | |
1709 | public: |
1710 | @@ -116,7 +131,7 @@ |
1711 | * @param key a list of file types from which the user can select |
1712 | */ |
1713 | /* |
1714 | - FileExportToOCALDialog(Gtk::Window& parentWindow, |
1715 | + ExportDialog(Gtk::Window& parentWindow, |
1716 | FileDialogType fileTypes, |
1717 | const Glib::ustring &title); |
1718 | */ |
1719 | @@ -125,7 +140,7 @@ |
1720 | * Perform any necessary cleanups. |
1721 | */ |
1722 | /* |
1723 | - ~FileExportToOCALDialog(); |
1724 | + ~ExportDialog(); |
1725 | */ |
1726 | /** |
1727 | * Show an SaveAs file selector. |
1728 | @@ -181,7 +196,7 @@ |
1729 | /* |
1730 | std::set<Glib::ustring> knownExtensions; |
1731 | |
1732 | -}; //FileExportToOCAL |
1733 | +}; //ExportDialog |
1734 | */ |
1735 | |
1736 | //######################################################################## |
1737 | @@ -190,10 +205,10 @@ |
1738 | |
1739 | |
1740 | /** |
1741 | - * Our implementation of the FileExportToOCALPasswordDialog interface. |
1742 | + * Our implementation of the ExportPasswordDialog interface. |
1743 | */ |
1744 | /* |
1745 | -class FileExportToOCALPasswordDialog : public FileDialogOCALBase |
1746 | +class ExportPasswordDialog : public FileDialogBase |
1747 | { |
1748 | |
1749 | public: |
1750 | @@ -203,7 +218,7 @@ |
1751 | * @param title the title of the dialog |
1752 | */ |
1753 | /* |
1754 | - FileExportToOCALPasswordDialog(Gtk::Window& parentWindow, |
1755 | + ExportPasswordDialog(Gtk::Window& parentWindow, |
1756 | const Glib::ustring &title); |
1757 | */ |
1758 | /** |
1759 | @@ -211,7 +226,7 @@ |
1760 | * Perform any necessary cleanups. |
1761 | */ |
1762 | /* |
1763 | - ~FileExportToOCALPasswordDialog(); |
1764 | + ~ExportPasswordDialog(); |
1765 | */ |
1766 | |
1767 | /** |
1768 | @@ -246,7 +261,7 @@ |
1769 | Gtk::HBox userBox; |
1770 | Gtk::HBox passBox; |
1771 | |
1772 | -}; //FileExportToOCALPassword |
1773 | +}; //ExportPasswordDialog |
1774 | */ |
1775 | |
1776 | |
1777 | @@ -254,34 +269,147 @@ |
1778 | //### F I L E I M P O R T F R O M O C A L |
1779 | //######################################################################### |
1780 | |
1781 | -/** |
1782 | - * Our implementation class for filesListView |
1783 | - */ |
1784 | -class FileListViewText : public Gtk::ListViewText |
1785 | -{ |
1786 | -public: |
1787 | - FileListViewText(guint columns_count, SVGPreview& filesPreview, Gtk::Label& description, Gtk::Button& okButton) |
1788 | - :ListViewText(columns_count) |
1789 | - { |
1790 | - myPreview = &filesPreview; |
1791 | - myLabel = &description; |
1792 | - myButton = &okButton; |
1793 | - } |
1794 | - Glib::ustring getFilename(); |
1795 | -protected: |
1796 | - void on_row_activated(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column); |
1797 | - void on_cursor_changed(); |
1798 | -private: |
1799 | - Glib::ustring myFilename; |
1800 | - SVGPreview *myPreview; |
1801 | - Gtk::Label *myLabel; |
1802 | - Gtk::Button *myButton; |
1803 | -}; |
1804 | - |
1805 | -/** |
1806 | - * Our implementation class for the FileImportFromOCALDialog interface.. |
1807 | - */ |
1808 | -class FileImportFromOCALDialog : public FileDialogOCALBase |
1809 | +class WrapLabel : public Gtk::Label |
1810 | +{ |
1811 | +public: |
1812 | + WrapLabel(); |
1813 | + |
1814 | +private: |
1815 | + void _on_size_allocate(Gtk::Allocation& allocation); |
1816 | +}; |
1817 | + |
1818 | +class LoadingBox : public Gtk::EventBox |
1819 | +{ |
1820 | +public: |
1821 | + LoadingBox(); |
1822 | + |
1823 | + void start(); |
1824 | + void stop(); |
1825 | + |
1826 | +private: |
1827 | + unsigned int spinner_step; |
1828 | + sigc::connection timeout; |
1829 | + bool draw_spinner; |
1830 | + bool _on_expose_event(GdkEventExpose* event); |
1831 | + bool on_timeout(); |
1832 | +}; |
1833 | + |
1834 | +class PreviewWidget : public Gtk::VBox |
1835 | +{ |
1836 | +public: |
1837 | + PreviewWidget(); |
1838 | + |
1839 | + void set_metadata(Glib::ustring description, Glib::ustring creator, Glib::ustring time); |
1840 | + void show_box_loading(); |
1841 | + void hide_box_loading(); |
1842 | + void set_image(std::string path); |
1843 | + void clear(); |
1844 | + bool _on_expose_event(GdkEventExpose* event); |
1845 | + |
1846 | +private: |
1847 | + LoadingBox* box_loading; |
1848 | + Gtk::Image* image; |
1849 | + |
1850 | + WrapLabel* label_title; |
1851 | + WrapLabel* label_description; |
1852 | + WrapLabel* label_time; |
1853 | +}; |
1854 | + |
1855 | +/** |
1856 | + * A Widget that contains an status icon and a message |
1857 | + */ |
1858 | +class StatusWidget : public Gtk::HBox |
1859 | +{ |
1860 | +public: |
1861 | + StatusWidget(); |
1862 | + |
1863 | + void clear(); |
1864 | + void set_error(Glib::ustring text); |
1865 | + void set_info(Glib::ustring text); |
1866 | + void start_process(Glib::ustring text); |
1867 | + void end_process(); |
1868 | + |
1869 | + Gtk::Spinner* spinner; |
1870 | + Gtk::Image* image; |
1871 | + Gtk::Label* label; |
1872 | +}; |
1873 | + |
1874 | +/** |
1875 | + * A Gtk::Entry with search & clear icons |
1876 | + */ |
1877 | +class SearchEntry : public Gtk::Entry |
1878 | +{ |
1879 | +public: |
1880 | + SearchEntry(); |
1881 | + |
1882 | +private: |
1883 | + void _on_icon_pressed(Gtk::EntryIconPosition icon_position, const GdkEventButton* event); |
1884 | + void _on_changed(); |
1885 | +}; |
1886 | + |
1887 | +/** |
1888 | + * A box which paints an overlay of the OCAL logo |
1889 | + */ |
1890 | +class LogoArea : public Gtk::EventBox |
1891 | +{ |
1892 | +public: |
1893 | + LogoArea(); |
1894 | +private: |
1895 | + bool _on_expose_event(GdkEventExpose* event); |
1896 | + bool draw_logo; |
1897 | + Cairo::RefPtr<Cairo::ImageSurface> logo_mask; |
1898 | +}; |
1899 | + |
1900 | +/** |
1901 | + * A box filled with the Base colour from the user's GTK theme, and a border |
1902 | + */ |
1903 | +class BaseBox : public Gtk::EventBox |
1904 | +{ |
1905 | +public: |
1906 | + BaseBox(); |
1907 | +private: |
1908 | + bool _on_expose_event(GdkEventExpose* event); |
1909 | +}; |
1910 | + |
1911 | +enum { |
1912 | + RESULTS_COLUMN_MARKUP, |
1913 | + RESULTS_COLUMN_TITLE, |
1914 | + RESULTS_COLUMN_DESCRIPTION, |
1915 | + RESULTS_COLUMN_CREATOR, |
1916 | + RESULTS_COLUMN_DATE, |
1917 | + RESULTS_COLUMN_FILENAME, |
1918 | + RESULTS_COLUMN_THUMBNAIL_FILENAME, |
1919 | + RESULTS_COLUMN_URL, |
1920 | + RESULTS_COLUMN_THUMBNAIL_URL, |
1921 | + RESULTS_COLUMN_GUID, |
1922 | + RESULTS_COLUMN_LENGTH, |
1923 | +}; |
1924 | + |
1925 | +enum { |
1926 | + NOTEBOOK_PAGE_LOGO, |
1927 | + NOTEBOOK_PAGE_RESULTS, |
1928 | + NOTEBOOK_PAGE_NOT_FOUND, |
1929 | +}; |
1930 | + |
1931 | +enum ResourceType { |
1932 | + TYPE_THUMBNAIL, |
1933 | + TYPE_IMAGE, |
1934 | +}; |
1935 | + |
1936 | +/** |
1937 | + * The TreeView which holds the search results |
1938 | + */ |
1939 | +class SearchResultList : public Gtk::ListViewText |
1940 | +{ |
1941 | +public: |
1942 | + SearchResultList(guint columns_count); |
1943 | + void populate_from_xml(xmlNode* a_node); |
1944 | +}; |
1945 | + |
1946 | +/** |
1947 | + * The Import Dialog |
1948 | + */ |
1949 | +class ImportDialog : public FileDialogBase |
1950 | { |
1951 | public: |
1952 | /** |
1953 | @@ -290,16 +418,14 @@ |
1954 | * @param fileTypes one of FileDialogTypes |
1955 | * @param title the title of the dialog |
1956 | */ |
1957 | - FileImportFromOCALDialog(Gtk::Window& parentWindow, |
1958 | - const Glib::ustring &dir, |
1959 | - FileDialogType fileTypes, |
1960 | - const Glib::ustring &title); |
1961 | + ImportDialog(Gtk::Window& parent_window, FileDialogType file_types, |
1962 | + const Glib::ustring &title); |
1963 | |
1964 | /** |
1965 | * Destructor. |
1966 | * Perform any necessary cleanups. |
1967 | */ |
1968 | - ~FileImportFromOCALDialog(); |
1969 | + ~ImportDialog(); |
1970 | |
1971 | /** |
1972 | * Show an OpenFile file selector. |
1973 | @@ -312,51 +438,73 @@ |
1974 | * @return a pointer to a string if successful (which must |
1975 | * be later freed with g_free(), else NULL. |
1976 | */ |
1977 | - Inkscape::Extension::Extension *getSelectionType(); |
1978 | - |
1979 | - Glib::ustring getFilename(); |
1980 | + Inkscape::Extension::Extension *get_selection_type(); |
1981 | + |
1982 | + typedef sigc::signal<void, Glib::ustring> type_signal_response; |
1983 | + type_signal_response signal_response(); |
1984 | + |
1985 | +protected: |
1986 | + type_signal_response m_signal_response; |
1987 | |
1988 | private: |
1989 | - |
1990 | - /** |
1991 | - * Allow the user to type the tag to be searched |
1992 | - */ |
1993 | - Gtk::Entry *searchTagEntry; |
1994 | - FileListViewText *filesList; |
1995 | - SVGPreview *filesPreview; |
1996 | - Gtk::Label *notFoundLabel; |
1997 | - Gtk::Label *descriptionLabel; |
1998 | - Gtk::Button *searchButton; |
1999 | - Gtk::Button *okButton; |
2000 | + Glib::ustring filename_image; |
2001 | + Glib::ustring filename_thumbnail; |
2002 | + SearchEntry *entry_search; |
2003 | + LogoArea *drawingarea_logo; |
2004 | + SearchResultList *list_results; |
2005 | + PreviewWidget *preview_files; |
2006 | + Gtk::Label *label_not_found; |
2007 | + Gtk::Label *label_description; |
2008 | + Gtk::Button *button_search; |
2009 | + Gtk::Button *button_import; |
2010 | + Gtk::Button *button_close; |
2011 | + Gtk::Button *button_cancel; |
2012 | + StatusWidget *widget_status; |
2013 | |
2014 | // Child widgets |
2015 | - Gtk::HBox tagBox; |
2016 | - Gtk::HBox filesBox; |
2017 | - Gtk::HBox messageBox; |
2018 | - Gtk::HBox descriptionBox; |
2019 | - Gtk::ScrolledWindow listScrolledWindow; |
2020 | + Gtk::Notebook *notebook_content; |
2021 | + Gtk::HBox hbox_tags; |
2022 | + Gtk::HBox hbox_files; |
2023 | + Gtk::ScrolledWindow scrolledwindow_list; |
2024 | Glib::RefPtr<Gtk::TreeSelection> selection; |
2025 | |
2026 | - /** |
2027 | - * Callback for user input into searchTagEntry |
2028 | - */ |
2029 | - void searchTagEntryChangedCallback(); |
2030 | - |
2031 | - |
2032 | - /** |
2033 | - * Prints the names of the all the xml elements |
2034 | - * that are siblings or children of a given xml node |
2035 | - */ |
2036 | - void print_xml_element_names(xmlNode * a_node); |
2037 | + Glib::RefPtr<Gio::Cancellable> cancellable_image; |
2038 | + Glib::RefPtr<Gio::Cancellable> cancellable_thumbnail; |
2039 | + bool downloading_thumbnail; |
2040 | + bool cancelled_thumbnail; |
2041 | + bool cancelled_image; |
2042 | + |
2043 | + void update_label_no_search_results(); |
2044 | + void update_preview(int row); |
2045 | + void on_list_results_cursor_changed(); |
2046 | + |
2047 | + void download_resource(ResourceType type, int row); |
2048 | + void on_resource_downloaded(const Glib::RefPtr<Gio::AsyncResult>& result, |
2049 | + Glib::RefPtr<Gio::File> file_remote, Glib::ustring path, ResourceType resource); |
2050 | + void on_image_downloaded(Glib::ustring path, bool success); |
2051 | + void on_thumbnail_downloaded(Glib::ustring path, bool success); |
2052 | + void on_list_results_row_activated(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column); |
2053 | + void on_button_import_clicked(); |
2054 | + void on_button_close_clicked(); |
2055 | + void on_button_cancel_clicked(); |
2056 | + void on_button_search_clicked(); |
2057 | + void on_entry_search_activated(); |
2058 | + void on_list_results_selection_changed(); |
2059 | + void on_xml_file_read(const Glib::RefPtr<Gio::AsyncResult>& result, |
2060 | + Glib::RefPtr<Gio::File> xml_file, Glib::ustring xml_uri); |
2061 | + void create_temporary_dirs(); |
2062 | + std::string get_temporary_dir(ResourceType type); |
2063 | + |
2064 | |
2065 | /** |
2066 | * The extension to use to write this file |
2067 | */ |
2068 | Inkscape::Extension::Extension *extension; |
2069 | |
2070 | -}; //FileImportFromOCALDialog |
2071 | - |
2072 | - |
2073 | +}; //ImportDialog |
2074 | + |
2075 | + |
2076 | +} //namespace OCAL |
2077 | } //namespace Dialog |
2078 | } //namespace UI |
2079 | } //namespace Inkscape |
2080 | |
2081 | === modified file 'src/verbs.cpp' |
2082 | --- src/verbs.cpp 2011-10-03 03:44:17 +0000 |
2083 | +++ src/verbs.cpp 2011-12-27 21:09:25 +0000 |
2084 | @@ -2192,8 +2192,9 @@ |
2085 | N_("Import a bitmap or SVG image into this document"), INKSCAPE_ICON("document-import")), |
2086 | new FileVerb(SP_VERB_FILE_EXPORT, "FileExport", N_("_Export Bitmap..."), |
2087 | N_("Export this document or a selection as a bitmap image"), INKSCAPE_ICON("document-export")), |
2088 | - new FileVerb(SP_VERB_FILE_IMPORT_FROM_OCAL, "FileImportFromOCAL", N_("Import From Open Clip Art Library"), N_("Import a document from Open Clip Art Library"), INKSCAPE_ICON("document-import-ocal")), |
2089 | -// new FileVerb(SP_VERB_FILE_EXPORT_TO_OCAL, "FileExportToOCAL", N_("Export To Open Clip Art Library"), N_("Export this document to Open Clip Art Library"), INKSCAPE_ICON("document-export-ocal")), |
2090 | + new FileVerb(SP_VERB_FILE_IMPORT_FROM_OCAL, "FileImportFromOCAL", N_("Import Clip Art..."), |
2091 | + N_("Import clipart from Open Clip Art Library"), INKSCAPE_ICON("document-import-ocal")), |
2092 | +// new FileVerb(SP_VERB_FILE_EXPORT_TO_OCAL, "FileExportToOCAL", N_("Export To Open Clip Art Library"), N_("Export this document to Open Clip Art Library"), INKSCAPE_ICON_DOCUMENT_EXPORT_OCAL), |
2093 | new FileVerb(SP_VERB_FILE_NEXT_DESKTOP, "NextWindow", N_("N_ext Window"), |
2094 | N_("Switch to the next document window"), INKSCAPE_ICON("window-next")), |
2095 | new FileVerb(SP_VERB_FILE_PREV_DESKTOP, "PrevWindow", N_("P_revious Window"), |
Patched and compiled with no problem on Ubuntu 10.10 with the current trunk (10145).
Seems to work very well. Nice dialog design, image search is rather fast and download time very short compared to the older (current...) implementation. I really like it!
But a crasher, when selecting an image in the result list while another one is still downloading. Backtrace:
----- e::is_cancelled () const () from /usr/lib/ libgiomm- 2.4.so. 1 e::is_cancelled () const () from /usr/lib/ libgiomm- 2.4.so. 1 :UI::Dialog: :OCAL:: ImportDialog: :on_thumbnail_ downloaded (this=0xa9edc10, path=..., success=false) ocaldialogs. cpp:822 :UI::Dialog: :OCAL:: ImportDialog: :on_resource_ downloaded (this=0xa9edc10, result=..., file_remote=..., path=..., Inkscape: :UI::Dialog: :OCAL:: TYPE_THUMBNAIL) at ui/dialog/ ocaldialogs. cpp:788 sigc++- 2.0/sigc+ +/functors/ mem_fun. h:2055 )<Glib: :RefPtr< Gio::AsyncResul t>&, Glib::RefPtr< Gio::File> &, Glib::ustring&, Inkscape: :UI::Dialog: :OCAL:: ResourceType& > (rep=0xaa097c0, sigc++- 2.0/sigc+ +/adaptors/ adaptor_ trait.h: 144 )<Glib: :RefPtr< Gio::AsyncResul t>&> (rep=0xaa097c0, a_1=...) at /usr/include/ sigc++- 2.0/sigc+ +/adaptors/ bind.h: 1523 :slot_call1< sigc::bind_ functor< -0x000000000000 00001, sigc::bound_ mem_functor4< void, Inkscape: :UI::Dialog: :OCAL:: ImportDialog, Glib::RefPtr< Gio::AsyncResul t> const&, Glib::RefPtr< Gio::File> , Glib::ustring, Inkscape: :UI::Dialog: :OCAL:: ResourceType> , Glib::RefPtr< Gio::File> , Glib::ustring, Inkscape: :UI::Dialog: :OCAL:: ResourceType, sigc::nil, sigc::nil, sigc::nil, sigc::nil>, void, Glib::RefPtr< Gio::AsyncResul t>&>::call_ it (rep=0xaa097c0, a_1=...) sigc++- 2.0/sigc+ +/functors/ slot.h: 137 y_async_ callback( _GObject* , _GAsyncResult*, void*) () from /usr/lib/ libgiomm- 2.4.so. 1 async_result_ complete (simple=0xaa3bc18) at /build/ buildd/ glib2.0- 2.26.1/ gio/gsimpleasyn cresult. c:692 buildd/ glib2.0- 2.26.1/ gio/gsimpleasyn cresult. c:702 0xaa3bc18) at /build/ buildd/ glib2.0- 2.26.1/ glib/gmain. c:4254 buildd/ glib2.0- 2.26.1/ glib/gmain. c:2149 context_ dispatch (context=0x8c7e7e8) at /build/ buildd/ glib2.0- 2.26.1/ glib/gmain. c:2702 context_ iterate (context=0x8c7e7e8, block=<value optimised out>, dispatch=1, self=0x8c2c9b8) buildd/ glib2.0- 2.26.1/ glib/gmain. c:2780 buildd/ glib2.0- 2.26.1/ glib/gmain. c:2988 buildd/ gtk+2.0- 2.22.0/ gtk/gtkmain. c:1237 :run_impl( ) () from /usr/lib/ libgtkmm- 2.4.so. 1 libgtkmm- 2.4.s.. .
Program received signal SIGSEGV, Segmentation fault.
0x007b6545 in Gio::Cancellabl
(gdb) bt
#0 0x007b6545 in Gio::Cancellabl
#1 0x08639326 in Inkscape:
at ui/dialog/
#2 0x08639411 in Inkscape:
resource=
#3 0x08640a4d in operator() (rep=0xaa097c0, a_1=...) at /usr/include/
#4 operator(
a_1=...) at /usr/include/
#5 operator(
#6 sigc::internal:
at /usr/include/
#7 0x007ffa01 in Gio::SignalProx
#8 0x00d1857f in g_simple_
#9 0x00d185ed in complete_in_idle_cb (data=0xaa3bc18) at /build/
#10 0x01d3e841 in g_idle_dispatch (source=0xa9dcf68, callback=0, user_data=
#11 0x01d40855 in g_main_dispatch (context=0x8c7e7e8) at /build/
#12 g_main_
#13 0x01d44668 in g_main_
at /build/
#14 0x01d44ba7 in g_main_loop_run (loop=0x994a330) at /build/
#15 0x00a051d9 in IA__gtk_main () at /build/
#16 0x005593b7 in Gtk::Main:
#17 0x005591b2 in Gtk::Main::run() () from /usr/lib/