]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormBibtex.C
Wrap most of the frontend code up inside namespace lyx::frontend.
[lyx.git] / src / frontends / xforms / FormBibtex.C
1 /**
2  * \file FormBibtex.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Angus Leeming
7  * \author John Levon
8  * \author Herbert Voß
9  * \author Rob Lahaye
10  *
11  * Full author contact details are available in file CREDITS.
12  */
13
14 #include <config.h>
15
16 #include "FormBibtex.h"
17 #include "ControlBibtex.h"
18 #include "forms/form_bibtex.h"
19
20 #include "Tooltips.h"
21 #include "xforms_helpers.h"
22 #include "xformsBC.h"
23
24 #include "support/filetools.h"
25 #include "support/globbing.h"
26 #include "support/lstrings.h"
27 #include "support/lyxalgo.h"
28
29 #include "lyx_forms.h"
30
31 using std::vector;
32 using std::string;
33
34 namespace lyx {
35
36 using support::ChangeExtension;
37 using support::compare;
38 using support::contains;
39 using support::FileFilterList;
40 using support::getStringFromVector;
41 using support::getVectorFromString;
42 using support::OnlyFilename;
43 using support::prefixIs;
44 using support::split;
45
46 namespace frontend {
47
48
49 typedef FormController<ControlBibtex, FormView<FD_bibtex> > base_class;
50
51 FormBibtex::FormBibtex(Dialog & parent)
52         : base_class(parent, _("BibTeX Database"))
53 {}
54
55
56 void FormBibtex::build()
57 {
58         dialog_.reset(build_bibtex(this));
59
60         // Manage the ok, apply, restore and cancel/close buttons
61         bcview().setOK(dialog_->button_ok);
62         bcview().setApply(dialog_->button_apply);
63         bcview().setCancel(dialog_->button_close);
64         bcview().setRestore(dialog_->button_restore);
65
66         // disable for read-only documents
67         bcview().addReadOnly(dialog_->input_database);
68         bcview().addReadOnly(dialog_->button_database_browse);
69         bcview().addReadOnly(dialog_->button_style_browse);
70         bcview().addReadOnly(dialog_->button_rescan);
71         bcview().addReadOnly(dialog_->input_style);
72         bcview().addReadOnly(dialog_->check_bibtotoc);
73         bcview().addReadOnly(dialog_->choice_btprint);
74
75         // trigger an input event for cut&paste with middle mouse button.
76         setPrehandler(dialog_->input_database);
77         setPrehandler(dialog_->input_style);
78
79         fl_set_input_return(dialog_->input_database, FL_RETURN_CHANGED);
80         fl_set_input_return(dialog_->input_style, FL_RETURN_CHANGED);
81
82         // callback for double click in browser
83         fl_set_browser_dblclick_callback(dialog_->browser_styles,
84                                          C_FormDialogView_InputCB, 2);
85
86         fl_addto_choice(dialog_->choice_btprint,
87                         _(" all cited references "
88                           "| all uncited references "
89                           "| all references ").c_str());
90
91         // set up the tooltips
92         string str = _("The database you want to cite from. Insert it "
93                        "without the default extension \".bib\". Use comma "
94                        "to separate databases.");
95         tooltips().init(dialog_->button_database_browse, str);
96
97         str = _("Browse directory for BibTeX stylefiles");
98         tooltips().init(dialog_->button_style_browse, str);
99
100         str = _("The BibTeX style to use (only one allowed). Insert it without "
101                 "the default extension \".bst\" and without path.");
102         tooltips().init(dialog_->input_style, str);
103
104         str = _("Select if the bibliography should appear in the Table "
105                 "of Contents");
106         tooltips().init(dialog_->check_bibtotoc, str);
107
108         str = _("Double click to choose a BibTeX style from the list.");
109         tooltips().init(dialog_->browser_styles, str);
110
111 #if FL_VERSION == 0 || (FL_REVISION == 0 && FL_FIXLEVEL == 0)
112         // Work-around xforms' bug; enable tooltips for browser widgets.
113         setPrehandler(dialog_->browser_styles);
114 #endif
115
116         str = _("Updates your TeX system for a new bibstyle list. Only "
117                 "the styles which are in directories where TeX finds them "
118                 "are listed!");
119         tooltips().init(dialog_->button_rescan, str);
120
121         str = _("The bibliography section contains...");
122         tooltips().init(dialog_->choice_btprint, str);
123 }
124
125
126 ButtonPolicy::SMInput FormBibtex::input(FL_OBJECT * ob, long ob_value)
127 {
128         if (ob == dialog_->button_database_browse) {
129                 // When browsing, take the first file only
130                 string const in_name = getString(dialog_->input_database);
131                 FileFilterList const
132                         filter(_("*.bib| BibTeX Databases (*.bib)"));
133                 string out_name =
134                         controller().browse("", _("Select Database"),
135                                             filter);
136                 if (!out_name.empty()) {
137                         // add the database to any existing ones
138                         if (!in_name.empty())
139                                 out_name = in_name + ',' + out_name;
140
141                         fl_set_input(dialog_->input_database, out_name.c_str());
142                 }
143
144         } else if (ob == dialog_->button_style_browse) {
145                 string const in_name = getString(dialog_->input_style);
146                 FileFilterList const
147                         filter(_("*.bst| BibTeX Styles (*.bst)"));
148                 string const style = controller()
149                         .browse(in_name, _("Select BibTeX-Style"), filter);
150                 if (!style.empty()) {
151                         fl_set_input(dialog_->input_style, style.c_str());
152                 }
153
154         } else if (ob == dialog_->browser_styles && ob_value == 2) {
155                 // double clicked in styles browser
156                 string const style = getString(dialog_->browser_styles);
157                 if (style.empty()) {
158                         return ButtonPolicy::SMI_NOOP;
159                 } else {
160                         fl_set_input(dialog_->input_style,
161                                         ChangeExtension(style, "").c_str());
162                 }
163                 // reset the browser so that the following
164                 // single-click callback doesn't do anything
165                 fl_deselect_browser(dialog_->browser_styles);
166
167         } else if (ob == dialog_->button_rescan) {
168                 fl_clear_browser(dialog_->browser_styles);
169                 controller().rescanBibStyles();
170                 vector<string> styles;
171                 controller().getBibStyles(styles);
172                 fl_add_browser_line(dialog_->browser_styles,
173                                     getStringFromVector(styles, "\n").c_str());
174         }
175
176         // with an empty database nothing makes sense ...
177         if (!compare(fl_get_input(dialog_->input_database), "")) {
178                 return ButtonPolicy::SMI_NOOP;
179         }
180
181         return ButtonPolicy::SMI_VALID;
182 }
183
184
185 void FormBibtex::update()
186 {
187         fl_set_input(dialog_->input_database,
188                      controller().params().getContents().c_str());
189
190         string bibtotoc = "bibtotoc";
191         string bibstyle = controller().params().getOptions();
192
193         bool const bibtopic = controller().usingBibtopic();
194         bool const bibtotoc_exists = prefixIs(bibstyle, bibtotoc);
195         fl_set_button(dialog_->check_bibtotoc, bibtotoc_exists && !bibtopic);
196         setEnabled(dialog_->check_bibtotoc, !bibtopic);
197         if (bibtotoc_exists) {
198                 if (contains(bibstyle, ',')) { // bibstyle exists?
199                         bibstyle = split(bibstyle, bibtotoc, ',');
200                 } else {
201                         bibstyle.erase();
202                 }
203         }
204         fl_set_input(dialog_->input_style, bibstyle.c_str());
205
206         string btprint = controller().params().getSecOptions();
207         int btp = 1;
208         if (btprint == "btPrintNotCited")
209                 btp = 2;
210         else if (btprint == "btPrintAll")
211                 btp = 3;
212
213         fl_set_choice(dialog_->choice_btprint, btp);
214         setEnabled(dialog_->choice_btprint, bibtopic);
215
216         vector<string> styles;
217         controller().getBibStyles(styles);
218
219         fl_clear_browser(dialog_->browser_styles);
220         fl_add_browser_line(dialog_->browser_styles,
221                             getStringFromVector(styles, "\n").c_str());
222 }
223
224 namespace {
225
226 string const unique_and_no_extensions(string const & str_in)
227 {
228         vector<string> dbase = getVectorFromString(str_in);
229         for (vector<string>::iterator it = dbase.begin();
230              it != dbase.end(); ++it) {
231                 *it = ChangeExtension(*it, string());
232         }
233         eliminate_duplicates(dbase);
234         return getStringFromVector(dbase);
235 }
236
237 } // namespace anon
238
239
240 void FormBibtex::apply()
241 {
242         string const db = getString(dialog_->input_database);
243         if (db.empty()) {
244                 // no database -> no bibtex-command and no options!
245                 controller().params().setContents("");
246                 controller().params().setOptions("");
247                 controller().params().setSecOptions("");
248                 return;
249         }
250
251         controller().params().setContents(unique_and_no_extensions(db));
252
253         // empty is valid!
254         string bibstyle = getString(dialog_->input_style);
255         if (!bibstyle.empty()) {
256                 // save the BibTeX style without any ".bst" extension
257                 bibstyle = ChangeExtension(OnlyFilename(bibstyle), "");
258         }
259
260         bool const addtotoc = fl_get_button(dialog_->check_bibtotoc);
261         string const bibtotoc = addtotoc ? "bibtotoc" : "";
262         if (addtotoc && !bibstyle.empty()) {
263                 // Both bibtotoc and style.
264                 controller().params().setOptions(bibtotoc + ',' + bibstyle);
265
266         } else {
267                 // At least one of addtotoc and bibstyle is empty.
268                 // No harm to output both!
269                 controller().params().setOptions(bibtotoc + bibstyle);
270         }
271
272         // bibtopic allows three kinds of sections:
273         // 1. sections that include all cited references of the database(s)
274         // 2. sec. that include all uncited references of the database(s)
275         // 3. sec. that include all references of the database(s), cited or not
276         if (controller().usingBibtopic()){
277                 int btp = fl_get_choice(dialog_->choice_btprint);
278                 switch (btp) {
279                 case 1:
280                         controller().params().setSecOptions("btPrintCited");
281                         break;
282                 case 2:
283                         controller().params().setSecOptions("btPrintNotCited");
284                         break;
285                 case 3:
286                         controller().params().setSecOptions("btPrintAll");
287                         break;
288                 }
289         }
290
291         else
292                 controller().params().setSecOptions("");
293
294 }
295
296 } // namespace frontend
297 } // namespace lyx