1 /*
2  *  This file is part of RawTherapee.
3  *
4  *  Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
5  *
6  *  RawTherapee is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  RawTherapee is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with RawTherapee.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 #include "iptcpanel.h"
20 #include "clipboard.h"
21 #include "rtimage.h"
22 
23 #include "../rtengine/procparams.h"
24 
25 using namespace rtengine;
26 using namespace rtengine::procparams;
27 
IPTCPanel()28 IPTCPanel::IPTCPanel () :
29     changeList(new rtengine::procparams::IPTCPairs),
30     defChangeList(new rtengine::procparams::IPTCPairs),
31     embeddedData(new rtengine::procparams::IPTCPairs)
32 {
33 
34     set_spacing (4);
35 
36     Gtk::Grid* iptc = Gtk::manage( new Gtk::Grid () );
37     setExpandAlignProperties(iptc, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START);
38     iptc->set_row_spacing(3);
39 
40     int row = 0;
41 
42     Gtk::Label* capl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_DESCRIPTION") + ":") );
43     setExpandAlignProperties(capl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
44     captionText = Gtk::TextBuffer::create ();
45     captionView = Gtk::manage( new Gtk::TextView (captionText) );
46     setExpandAlignProperties(captionView, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
47     Gtk::ScrolledWindow* scrolledWindowc = Gtk::manage( new Gtk::ScrolledWindow() );
48     setExpandAlignProperties(scrolledWindowc, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START);
49     scrolledWindowc->set_min_content_height (100);
50     scrolledWindowc->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
51     scrolledWindowc->add(*captionView);
52     capl->set_tooltip_text (M("IPTCPANEL_DESCRIPTIONHINT"));
53     captionView->set_tooltip_text (M("IPTCPANEL_DESCRIPTIONHINT"));
54     captionView->set_size_request(35, 95);
55     iptc->attach (*capl, 0, row++, 1, 1);
56     iptc->attach (*scrolledWindowc, 0, row++, 1, 1);
57 
58     // --------------------------
59 
60     Gtk::Label* capwl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_DESCRIPTIONWRITER") + ":") );
61     setExpandAlignProperties(capwl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
62     captionWriter = Gtk::manage( new Gtk::Entry () );
63     setExpandAlignProperties(captionWriter, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
64     capwl->set_tooltip_text (M("IPTCPANEL_DESCRIPTIONWRITERHINT"));
65     captionWriter->set_tooltip_text (M("IPTCPANEL_DESCRIPTIONWRITERHINT"));
66     iptc->attach (*capwl, 0, row++, 1, 1);
67     iptc->attach (*captionWriter, 0, row++, 1, 1);
68 
69     // --------------------------
70 
71     Gtk::Label* headl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_HEADLINE") + ":") );
72     setExpandAlignProperties(headl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
73     headline = Gtk::manage( new Gtk::Entry () );
74     setExpandAlignProperties(headline, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_BASELINE);
75     headl->set_tooltip_text (M("IPTCPANEL_HEADLINEHINT"));
76     headline->set_tooltip_text (M("IPTCPANEL_HEADLINEHINT"));
77     iptc->attach (*headl, 0, row++, 1, 1);
78     iptc->attach (*headline, 0, row++, 1, 1);
79 
80     // --------------------------
81 
82     Gtk::Label* instl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_INSTRUCTIONS") + ":") );
83     setExpandAlignProperties(instl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
84     instructions = Gtk::manage( new Gtk::Entry () );
85     setExpandAlignProperties(instructions, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
86     instl->set_tooltip_text (M("IPTCPANEL_INSTRUCTIONSHINT"));
87     instructions->set_tooltip_text (M("IPTCPANEL_INSTRUCTIONSHINT"));
88     iptc->attach (*instl, 0, row++, 1, 1);
89     iptc->attach (*instructions, 0, row++, 1, 1);
90 
91     // --------------------------
92 
93     Gtk::HSeparator* hsep1 = Gtk::manage( new Gtk::HSeparator () );
94     setExpandAlignProperties(hsep1, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
95     iptc->attach (*hsep1, 0, row++, 2, 1);
96 
97     // --------------------------
98 
99     Gtk::Label* keyl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_KEYWORDS") + ":"));
100     setExpandAlignProperties(keyl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
101     keyl->set_tooltip_text (M("IPTCPANEL_KEYWORDSHINT"));
102     keywords = Gtk::manage( new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE) );
103     setExpandAlignProperties(keywords, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START);
104     keywords->set_headers_visible (false);
105     keywords->set_size_request (50, 95);
106     Gtk::ScrolledWindow* scrolledWindowkw = Gtk::manage( new Gtk::ScrolledWindow() );
107     setExpandAlignProperties(scrolledWindowkw, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START);
108     scrolledWindowkw->set_min_content_height (100);
109     scrolledWindowkw->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
110     scrolledWindowkw->add(*keywords);
111     keyword  = Gtk::manage(new MyComboBoxText (true));
112     setExpandAlignProperties(keyword, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
113     keyword->set_size_request(75);
114     keywords->set_tooltip_text (M("IPTCPANEL_KEYWORDSHINT"));
115     keyword->set_tooltip_text (M("IPTCPANEL_KEYWORDSHINT"));
116     addKW = Gtk::manage( new Gtk::Button () );
117     setExpandAlignProperties(addKW, false, true, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
118     delKW = Gtk::manage( new Gtk::Button () );
119     setExpandAlignProperties(delKW, false, true, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
120     Gtk::Image* addKWImg = Gtk::manage( new RTImage ("add-small.png") );
121     setExpandAlignProperties(addKWImg, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
122     Gtk::Image* delKWImg = Gtk::manage( new RTImage ("remove-small.png") );
123     setExpandAlignProperties(delKWImg, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
124     addKW->add (*addKWImg);
125     delKW->add (*delKWImg);
126     Gtk::Grid* kwgrid = Gtk::manage( new Gtk::Grid () );
127     setExpandAlignProperties(kwgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
128     kwgrid->attach (*keyword, 0, 0, 1, 1);
129     kwgrid->attach (*addKW, 1, 0, 1, 1);
130     kwgrid->attach (*delKW, 2, 0, 1, 1);
131     iptc->attach (*keyl, 0, row++, 1, 1);
132     iptc->attach (*kwgrid, 0, row++, 1, 1);
133     // --------------------------
134     iptc->attach (*scrolledWindowkw, 0, row++, 2, 1);
135     // --------------------------
136 
137     Gtk::HSeparator* hsep2 = Gtk::manage( new Gtk::HSeparator () );
138     setExpandAlignProperties(hsep2, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
139     iptc->attach (*hsep2, 0, row++, 2, 1);
140     // --------------------------
141 
142     Gtk::Label* catl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CATEGORY") + ":") );
143     setExpandAlignProperties(catl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
144     category = Gtk::manage(new MyComboBoxText (true));
145     category->set_size_request(75);
146     setExpandAlignProperties(category, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
147     catl->set_tooltip_text (M("IPTCPANEL_CATEGORYHINT"));
148     category->set_tooltip_text (M("IPTCPANEL_CATEGORYHINT"));
149     Gtk::Label* scl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_SUPPCATEGORIES") + ":") );
150     setExpandAlignProperties(scl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
151     suppCategories = Gtk::manage( new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE) );
152     setExpandAlignProperties(suppCategories, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
153     suppCategories->set_headers_visible (false);
154     suppCategories->set_size_request(50, 95);
155     Gtk::ScrolledWindow* scrolledWindowsc = Gtk::manage( new Gtk::ScrolledWindow() );
156     setExpandAlignProperties(scrolledWindowsc, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_START);
157     scrolledWindowsc->set_min_content_height (100);
158     scrolledWindowsc->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
159     scrolledWindowsc->add(*suppCategories);
160     suppCategory  = Gtk::manage(new MyComboBoxText (true));
161     suppCategory->set_size_request(75);
162     setExpandAlignProperties(suppCategory, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
163     scl->set_tooltip_text (M("IPTCPANEL_SUPPCATEGORIESHINT"));
164     suppCategories->set_tooltip_text (M("IPTCPANEL_SUPPCATEGORIESHINT"));
165     suppCategory->set_tooltip_text (M("IPTCPANEL_SUPPCATEGORIESHINT"));
166     addSC = Gtk::manage( new Gtk::Button () );
167     setExpandAlignProperties(addSC, false, true, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
168     delSC = Gtk::manage( new Gtk::Button () );
169     setExpandAlignProperties(delSC, false, true, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
170     Gtk::Image* addSCImg = Gtk::manage( new RTImage ("add-small.png") );
171     setExpandAlignProperties(addSCImg, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
172     Gtk::Image* delSCImg = Gtk::manage( new RTImage ("remove-small.png") );
173     setExpandAlignProperties(delSCImg, false, false, Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER);
174     addSC->add (*addSCImg);
175     delSC->add (*delSCImg);
176     Gtk::Grid* scgrid = Gtk::manage( new Gtk::Grid () );
177     setExpandAlignProperties(scgrid, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
178     scgrid->attach (*suppCategory, 0, 0, 1, 1);
179     scgrid->attach (*addSC, 1, 0, 1, 1);
180     scgrid->attach (*delSC, 2, 0, 1, 1);
181     iptc->attach (*catl, 0, row++, 1, 1);
182     iptc->attach (*category, 0, row++, 1, 1);
183     // --------------------------
184     iptc->attach (*scl, 0, row++, 1, 1);
185     iptc->attach (*scgrid, 0, row++, 1, 1);
186     // --------------------------
187     iptc->attach (*scrolledWindowsc, 0, row++, 2, 1);
188     // --------------------------
189 
190     Gtk::HSeparator* hsep3 = Gtk::manage( new Gtk::HSeparator () );
191     setExpandAlignProperties(hsep3, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
192     iptc->attach (*hsep3, 0, row++, 2, 1);
193     // --------------------------
194 
195     Gtk::Label* creatorLbl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CREATOR") + ":") );
196     setExpandAlignProperties(creatorLbl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
197     creator = Gtk::manage( new Gtk::Entry () );
198     setExpandAlignProperties(creator, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
199     creatorLbl->set_tooltip_text (M("IPTCPANEL_CREATORHINT"));
200     creator->set_tooltip_text (M("IPTCPANEL_CREATORHINT"));
201     iptc->attach (*creatorLbl, 0, row++, 1, 1);
202     iptc->attach (*creator, 0, row++, 1, 1);
203 
204     // --------------------------
205 
206     Gtk::Label* creatorJobTitleLbl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CREATORJOBTITLE") + ":") );
207     setExpandAlignProperties(creatorJobTitleLbl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
208     creatorJobTitle = Gtk::manage(  new Gtk::Entry () );
209     setExpandAlignProperties(creatorJobTitle, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
210     creatorJobTitleLbl->set_tooltip_text (M("IPTCPANEL_CREATORJOBTITLEHINT"));
211     creatorJobTitle->set_tooltip_text (M("IPTCPANEL_CREATORJOBTITLEHINT"));
212     iptc->attach (*creatorJobTitleLbl, 0, row++, 1, 1);
213     iptc->attach (*creatorJobTitle, 0, row++, 1, 1);
214 
215     // --------------------------
216 
217     Gtk::Label* credl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CREDIT") + ":") );
218     setExpandAlignProperties(credl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
219     credit = Gtk::manage( new Gtk::Entry () );
220     setExpandAlignProperties(credit, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
221     credl->set_tooltip_text (M("IPTCPANEL_CREDITHINT"));
222     credit->set_tooltip_text (M("IPTCPANEL_CREDITHINT"));
223     iptc->attach (*credl, 0, row++, 1, 1);
224     iptc->attach (*credit, 0, row++, 1, 1);
225 
226     // --------------------------
227 
228     Gtk::Label* sourl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_SOURCE") + ":") );
229     setExpandAlignProperties(sourl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
230     source = Gtk::manage( new Gtk::Entry () );
231     setExpandAlignProperties(source, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
232     sourl->set_tooltip_text (M("IPTCPANEL_SOURCEHINT"));
233     source->set_tooltip_text (M("IPTCPANEL_SOURCEHINT"));
234     iptc->attach (*sourl, 0, row++, 1, 1);
235     iptc->attach (*source, 0, row++, 1, 1);
236 
237     // --------------------------
238 
239     Gtk::Label* cprl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_COPYRIGHT") + ":") );
240     setExpandAlignProperties(cprl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
241     copyright = Gtk::manage( new Gtk::Entry () );
242     setExpandAlignProperties(copyright, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
243     cprl->set_tooltip_text (M("IPTCPANEL_COPYRIGHTHINT"));
244     copyright->set_tooltip_text (M("IPTCPANEL_COPYRIGHTHINT"));
245     iptc->attach (*cprl, 0, row++, 1, 1);
246     iptc->attach (*copyright, 0, row++, 1, 1);
247 
248     // --------------------------
249 
250     Gtk::HSeparator* hsep4 = Gtk::manage( new Gtk::HSeparator () );
251     setExpandAlignProperties(hsep4, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
252     iptc->attach (*hsep4, 0, row++, 2, 1);
253 
254     // --------------------------
255 
256     Gtk::Label* cityl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_CITY") + ":") );
257     setExpandAlignProperties(cityl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
258     city = Gtk::manage( new Gtk::Entry () );
259     setExpandAlignProperties(city, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
260     cityl->set_tooltip_text (M("IPTCPANEL_CITYHINT"));
261     city->set_tooltip_text (M("IPTCPANEL_CITYHINT"));
262     iptc->attach (*cityl, 0, row++, 1, 1);
263     iptc->attach (*city, 0, row++, 1, 1);
264 
265     // --------------------------
266 
267     Gtk::Label* provl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_PROVINCE") + ":") );
268     setExpandAlignProperties(provl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
269     province = Gtk::manage( new Gtk::Entry () );
270     setExpandAlignProperties(province, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
271     provl->set_tooltip_text (M("IPTCPANEL_PROVINCEHINT"));
272     province->set_tooltip_text (M("IPTCPANEL_PROVINCEHINT"));
273     iptc->attach (*provl, 0, row++, 1, 1);
274     iptc->attach (*province, 0, row++, 1, 1);
275 
276     // --------------------------
277 
278     Gtk::Label* ctrl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_COUNTRY") + ":") );
279     setExpandAlignProperties(ctrl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
280     country = Gtk::manage( new Gtk::Entry () );
281     setExpandAlignProperties(country, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
282     ctrl->set_tooltip_text (M("IPTCPANEL_COUNTRYHINT"));
283     country->set_tooltip_text (M("IPTCPANEL_COUNTRYHINT"));
284     iptc->attach (*ctrl, 0, row++, 1, 1);
285     iptc->attach (*country, 0, row++, 1, 1);
286 
287     // --------------------------
288 
289     Gtk::Label* titll = Gtk::manage( new Gtk::Label (M("IPTCPANEL_TITLE") + ":") );
290     setExpandAlignProperties(titll, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
291     title = Gtk::manage( new Gtk::Entry () );
292     setExpandAlignProperties(title, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
293     titll->set_tooltip_text (M("IPTCPANEL_TITLEHINT"));
294     title->set_tooltip_text (M("IPTCPANEL_TITLEHINT"));
295     iptc->attach (*titll, 0, row++, 1, 1);
296     iptc->attach (*title, 0, row++, 1, 1);
297 
298     // --------------------------
299 
300     Gtk::Label* dcl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_DATECREATED") + ":") );
301     setExpandAlignProperties(dcl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
302     dateCreated = Gtk::manage(  new Gtk::Entry () );
303     setExpandAlignProperties(dateCreated, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
304     dcl->set_tooltip_text (M("IPTCPANEL_DATECREATEDHINT"));
305     dateCreated->set_tooltip_text (M("IPTCPANEL_DATECREATEDHINT"));
306     iptc->attach (*dcl, 0, row++, 1, 1);
307     iptc->attach (*dateCreated, 0, row++, 1, 1);
308 
309     // --------------------------
310 
311     Gtk::Label* trl = Gtk::manage( new Gtk::Label (M("IPTCPANEL_TRANSREFERENCE") + ":") );
312     setExpandAlignProperties(trl, true, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
313     transReference = Gtk::manage( new Gtk::Entry () );
314     setExpandAlignProperties(transReference, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
315     trl->set_tooltip_text (M("IPTCPANEL_TRANSREFERENCEHINT"));
316     transReference->set_tooltip_text (M("IPTCPANEL_TRANSREFERENCEHINT"));
317     iptc->attach (*trl, 0, row++, 1, 1);
318     iptc->attach (*transReference, 0, row++, 1, 1);
319 
320     // --------------------------
321 
322     Gtk::ScrolledWindow* scrolledWindow = Gtk::manage( new Gtk::ScrolledWindow() );
323     setExpandAlignProperties(scrolledWindow, false, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
324     scrolledWindow->set_shadow_type(Gtk::SHADOW_NONE);
325     scrolledWindow->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
326     scrolledWindow->property_window_placement().set_value(Gtk::CORNER_TOP_RIGHT);
327     scrolledWindow->add(*iptc);
328 
329     pack_start (*scrolledWindow);
330 
331     Gtk::Grid* bbox = Gtk::manage( new Gtk::Grid () );
332     setExpandAlignProperties(bbox, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
333 
334     reset = Gtk::manage( new Gtk::Button () );  // M("IPTCPANEL_RESET")
335     reset->get_style_context()->add_class("Left");
336     reset->set_image (*Gtk::manage(new RTImage ("undo.png", "redo.png")));
337     setExpandAlignProperties(reset, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
338     bbox->attach_next_to (*reset, Gtk::POS_LEFT, 1, 1);
339 
340     file = Gtk::manage( new Gtk::Button () );  // M("IPTCPANEL_EMBEDDED")
341     file->get_style_context()->add_class("MiddleH");
342     file->set_image (*Gtk::manage(new RTImage ("folder-open.png")));
343     setExpandAlignProperties(file, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
344     bbox->attach_next_to (*file, Gtk::POS_RIGHT, 1, 1);
345 
346     copy = Gtk::manage( new Gtk::Button () );
347     copy->get_style_context()->add_class("MiddleH");
348     copy->set_image (*Gtk::manage(new RTImage ("copy.png")));
349     setExpandAlignProperties(copy, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
350     bbox->attach_next_to (*copy, Gtk::POS_RIGHT, 1, 1);
351 
352     paste = Gtk::manage( new Gtk::Button () );
353     paste->get_style_context()->add_class("Right");
354     paste->set_image (*Gtk::manage(new RTImage ("paste.png")));
355     setExpandAlignProperties(paste, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
356     bbox->attach_next_to (*paste, Gtk::POS_RIGHT, 1, 1);
357 
358     pack_end (*bbox, Gtk::PACK_SHRINK, 2);
359 
360     reset->set_tooltip_text(M("IPTCPANEL_RESETHINT"));
361     file->set_tooltip_text(M("IPTCPANEL_EMBEDDEDHINT"));
362     copy->set_tooltip_text(M("IPTCPANEL_COPYHINT"));
363     paste->set_tooltip_text(M("IPTCPANEL_PASTEHINT"));
364 
365     reset->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::resetClicked) );
366     file->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::fileClicked) );
367     copy->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::copyClicked) );
368     paste->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::pasteClicked) );
369 
370 
371     addKW->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::addKeyWord) );
372     delKW->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::delKeyWord) );
373     addSC->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::addSuppCategory) );
374     delSC->signal_clicked().connect( sigc::mem_fun(*this, &IPTCPanel::delSuppCategory) );
375     keyword->get_entry()->signal_activate().connect( sigc::mem_fun(*this, &IPTCPanel::addKeyWord) );
376     suppCategory->get_entry()->signal_activate().connect( sigc::mem_fun(*this, &IPTCPanel::addSuppCategory) );
377 
378     conns[0] = captionText->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
379     conns[1] = captionWriter->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
380     conns[2] = headline->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
381     conns[3] = instructions->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
382     conns[4] = category->get_entry()->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
383     conns[5] = creator->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
384     conns[6] = creatorJobTitle->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
385     conns[7] = credit->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
386     conns[8] = source->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
387     conns[9] = copyright->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
388     conns[10] = city->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
389     conns[11] = province->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
390     conns[12] = country->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
391     conns[13] = title->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
392     conns[14] = dateCreated->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
393     conns[15] = transReference->signal_changed().connect( sigc::mem_fun(*this, &IPTCPanel::updateChangeList) );
394 
395     category->get_entry()->set_max_length (3);
396     keyword->get_entry()->set_max_length (64);
397     captionWriter->set_max_length (32);
398     instructions->set_max_length (256);
399     creator->set_max_length (32);
400     creatorJobTitle->set_max_length (32);
401     credit->set_max_length (32);
402     source->set_max_length (32);
403     copyright->set_max_length (128);
404     city->set_max_length (32);
405     province->set_max_length (32);
406     country->set_max_length (64);
407     title->set_max_length (64);
408     dateCreated->set_max_length (8);
409     transReference->set_max_length (32);
410 
411     show_all ();
412 }
413 
read(const ProcParams * pp,const ParamsEdited * pedited)414 void IPTCPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
415 {
416 
417     disableListener ();
418     changeList->clear();
419 
420     if (!pp->iptc.empty()) {
421         *changeList = pp->iptc;
422     } else {
423         *changeList = *embeddedData;
424     }
425 
426     applyChangeList ();
427     enableListener ();
428 }
429 
write(ProcParams * pp,ParamsEdited * pedited)430 void IPTCPanel::write (ProcParams* pp, ParamsEdited* pedited)
431 {
432 
433     pp->iptc = *changeList;
434 }
435 
setDefaults(const ProcParams * defParams,const ParamsEdited * pedited)436 void IPTCPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited)
437 {
438 
439     *defChangeList = defParams->iptc;
440 }
441 
setImageData(const FramesMetaData * id)442 void IPTCPanel::setImageData (const FramesMetaData* id)
443 {
444 
445     if (id) {
446         *embeddedData = id->getIPTCData ();
447     } else {
448         embeddedData->clear ();
449     }
450 
451     file->set_sensitive (!embeddedData->empty());
452 }
453 
notifyListener()454 void IPTCPanel::notifyListener ()
455 {
456 
457     if (listener) {
458         listener->panelChanged (EvIPTC, M("HISTORY_CHANGED"));
459     }
460 }
461 
addKeyWord()462 void IPTCPanel::addKeyWord ()
463 {
464 
465     keyword->get_entry()->select_region (0, keyword->get_entry()->get_text().size());
466 
467     for (unsigned int i = 0; i < keywords->size(); i++)
468         if (keywords->get_text (i) == keyword->get_entry()->get_text()) {
469             return;
470         }
471 
472     keywords->append (keyword->get_entry()->get_text());
473     keyword->prepend (keyword->get_entry()->get_text());
474     std::vector<Glib::ustring> items;
475 
476     for (Gtk::TreeModel::iterator i = keyword->get_model()->children().begin(); i != keyword->get_model()->children().end(); ++i) {
477         Glib::ustring s;
478         i->get_value (0, s);
479         items.push_back (s);
480     }
481 
482     keyword->remove_all ();
483 
484     for (unsigned int i = 0; i < 10 && i < items.size(); i++) {
485         keyword->append (items[i]);
486     }
487 
488     keywords->scroll_to_row (keywords->get_model()->get_path(--keywords->get_model()->children().end()));
489 
490     updateChangeList ();
491 }
492 
delKeyWord()493 void IPTCPanel::delKeyWord ()
494 {
495 
496     std::vector<int> selection = keywords->get_selected ();
497 
498     if (!selection.empty()) {
499         std::vector<Glib::ustring> keep;
500 
501         for (unsigned int i = 0; i < keywords->size(); i++)
502             if (std::find (selection.begin(), selection.end(), i) == selection.end()) {
503                 keep.push_back (keywords->get_text (i));
504             }
505 
506         keywords->clear_items ();
507 
508         for (unsigned int i = 0; i < keep.size(); i++) {
509             keywords->append (keep[i]);
510         }
511     }
512 
513     updateChangeList ();
514 }
515 
addSuppCategory()516 void IPTCPanel::addSuppCategory ()
517 {
518 
519     for (unsigned int i = 0; i < suppCategories->size(); i++)
520         if (suppCategories->get_text (i) == suppCategory->get_entry()->get_text()) {
521             return;
522         }
523 
524     suppCategories->append (suppCategory->get_entry()->get_text());
525     suppCategory->prepend (suppCategory->get_entry()->get_text());
526     std::vector<Glib::ustring> items;
527 
528     for (Gtk::TreeModel::iterator i = suppCategory->get_model()->children().begin(); i != suppCategory->get_model()->children().end(); ++i) {
529         Glib::ustring s;
530         i->get_value (0, s);
531         items.push_back (s);
532     }
533 
534     suppCategory->remove_all ();
535 
536     for (unsigned int i = 0; i < 10 && i < items.size(); i++) {
537         suppCategory->append (items[i]);
538     }
539 
540     suppCategories->scroll_to_row (suppCategories->get_model()->get_path(--suppCategories->get_model()->children().end()));
541     suppCategory->get_entry()->select_region (0, suppCategory->get_entry()->get_text().size());
542 
543     updateChangeList ();
544 }
545 
delSuppCategory()546 void IPTCPanel::delSuppCategory ()
547 {
548 
549     std::vector<int> selection = suppCategories->get_selected ();
550 
551     if (!selection.empty()) {
552         std::vector<Glib::ustring> keep;
553 
554         for (unsigned int i = 0; i < suppCategories->size(); i++)
555             if (std::find (selection.begin(), selection.end(), i) == selection.end()) {
556                 keep.push_back (suppCategories->get_text (i));
557             }
558 
559         suppCategories->clear_items ();
560 
561         for (unsigned int i = 0; i < keep.size(); i++) {
562             suppCategories->append (keep[i]);
563         }
564     }
565 
566     updateChangeList ();
567 }
568 
updateChangeList()569 void IPTCPanel::updateChangeList ()
570 {
571 
572     changeList->clear ();
573     (*changeList)["Caption"        ].push_back (captionText->get_text ());
574     (*changeList)["CaptionWriter"  ].push_back (captionWriter->get_text ());
575     (*changeList)["Headline"       ].push_back (headline->get_text ());
576     (*changeList)["Instructions"   ].push_back (instructions->get_text ());
577 
578     for (unsigned int i = 0; i < keywords->size(); i++) {
579         (*changeList)["Keywords"       ].push_back (keywords->get_text (i));
580     }
581 
582     (*changeList)["Category"       ].push_back (category->get_entry()->get_text ());
583 
584     for (unsigned int i = 0; i < suppCategories->size(); i++) {
585         (*changeList)["SupplementalCategories"].push_back (suppCategories->get_text (i));
586     }
587 
588     (*changeList)["Creator"        ].push_back (creator->get_text ());
589     (*changeList)["CreatorJobTitle"].push_back (creatorJobTitle->get_text ());
590     (*changeList)["Credit"         ].push_back (credit->get_text ());
591     (*changeList)["Source"         ].push_back (source->get_text ());
592     (*changeList)["Copyright"      ].push_back (copyright->get_text ());
593     (*changeList)["City"           ].push_back (city->get_text ());
594     (*changeList)["Province"       ].push_back (province->get_text ());
595     (*changeList)["Country"        ].push_back (country->get_text ());
596     (*changeList)["Title"          ].push_back (title->get_text ());
597     (*changeList)["DateCreated"    ].push_back (dateCreated->get_text ());
598     (*changeList)["TransReference" ].push_back (transReference->get_text ());
599 
600     notifyListener ();
601 }
602 
applyChangeList()603 void IPTCPanel::applyChangeList ()
604 {
605 
606     for (int i = 0; i < 16; i++) {
607         conns[i].block (true);
608     }
609 
610     captionText->set_text ("");
611     captionWriter->set_text ("");
612     headline->set_text ("");
613     instructions->set_text ("");
614     keywords->clear_items ();
615     category->get_entry()->set_text ("");
616     suppCategories->clear_items ();
617     creator->set_text ("");
618     creatorJobTitle->set_text ("");
619     credit->set_text ("");
620     source->set_text ("");
621     copyright->set_text ("");
622     city->set_text ("");
623     province->set_text ("");
624     country->set_text ("");
625     title->set_text ("");
626     dateCreated->set_text ("");
627     transReference->set_text ("");
628     keyword->get_entry()->set_text ("");
629     suppCategory->get_entry()->set_text ("");
630 
631     for (rtengine::procparams::IPTCPairs::const_iterator i = changeList->begin(); i != changeList->end(); ++i) {
632         if (i->first == "Caption" && !i->second.empty()) {
633             captionText->set_text (i->second.at(0));
634         } else if (i->first == "CaptionWriter" && !i->second.empty()) {
635             captionWriter->set_text (i->second.at(0));
636         } else if (i->first == "Headline" && !i->second.empty()) {
637             headline->set_text (i->second.at(0));
638         } else if (i->first == "Instructions" && !i->second.empty()) {
639             instructions->set_text (i->second.at(0));
640         } else if (i->first == "Keywords")
641             for (unsigned int j = 0; j < i->second.size(); j++) {
642                 keywords->append (i->second.at(j));
643             }
644         else if (i->first == "Category" && !i->second.empty()) {
645             category->get_entry()->set_text (i->second.at(0));
646         } else if (i->first == "SupplementalCategories")
647             for (unsigned int j = 0; j < i->second.size(); j++) {
648                 suppCategories->append (i->second.at(j));
649             }
650         else if (i->first == "Creator" && !i->second.empty()) {
651             creator->set_text (i->second.at(0));
652         } else if (i->first == "CreatorJobTitle" && !i->second.empty()) {
653             creatorJobTitle->set_text (i->second.at(0));
654         } else if (i->first == "Credit" && !i->second.empty()) {
655             credit->set_text (i->second.at(0));
656         } else if (i->first == "Source" && !i->second.empty()) {
657             source->set_text (i->second.at(0));
658         } else if (i->first == "Copyright" && !i->second.empty()) {
659             copyright->set_text (i->second.at(0));
660         } else if (i->first == "City" && !i->second.empty()) {
661             city->set_text (i->second.at(0));
662         } else if (i->first == "Province" && !i->second.empty()) {
663             province->set_text (i->second.at(0));
664         } else if (i->first == "Country" && !i->second.empty()) {
665             country->set_text (i->second.at(0));
666         } else if (i->first == "Title" && !i->second.empty()) {
667             title->set_text (i->second.at(0));
668         } else if (i->first == "DateCreated" && !i->second.empty()) {
669             dateCreated->set_text (i->second.at(0));
670         } else if (i->first == "TransReference" && !i->second.empty()) {
671             transReference->set_text (i->second.at(0));
672         }
673     }
674 
675     for (int i = 0; i < 16; i++) {
676         conns[i].block (false);
677     }
678 }
679 
resetClicked()680 void IPTCPanel::resetClicked ()
681 {
682 
683     disableListener ();
684     *changeList = *defChangeList;
685     applyChangeList ();
686     enableListener ();
687     notifyListener ();
688 }
689 
fileClicked()690 void IPTCPanel::fileClicked ()
691 {
692 
693     disableListener ();
694     *changeList = *embeddedData;
695     applyChangeList ();
696     enableListener ();
697     notifyListener ();
698 }
699 
copyClicked()700 void IPTCPanel::copyClicked ()
701 {
702 
703     clipboard.setIPTC (*changeList);
704 }
705 
pasteClicked()706 void IPTCPanel::pasteClicked ()
707 {
708 
709     disableListener ();
710     *changeList = clipboard.getIPTC ();
711     applyChangeList ();
712     enableListener ();
713     notifyListener ();
714 }
715