]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/FormBibtex.C
Tiny clean-ups.
[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/lstrings.h"
26 #include "support/lyxalgo.h"
27
28 #include "lyx_forms.h"
29
30 using lyx::support::ChangeExtension;
31 using lyx::support::compare;
32 using lyx::support::contains;
33 using lyx::support::getStringFromVector;
34 using lyx::support::getVectorFromString;
35 using lyx::support::OnlyFilename;
36 using lyx::support::prefixIs;
37 using lyx::support::split;
38
39 using std::vector;
40 using std::string;
41
42
43 typedef FormController<ControlBibtex, FormView<FD_bibtex> > base_class;
44
45 FormBibtex::FormBibtex(Dialog & parent)
46         : base_class(parent, _("BibTeX Database"))
47 {}
48
49
50 void FormBibtex::build()
51 {
52         dialog_.reset(build_bibtex(this));
53
54         // Manage the ok, apply, restore and cancel/close buttons
55         bcview().setOK(dialog_->button_ok);
56         bcview().setApply(dialog_->button_apply);
57         bcview().setCancel(dialog_->button_close);
58         bcview().setRestore(dialog_->button_restore);
59
60         // disable for read-only documents
61         bcview().addReadOnly(dialog_->input_database);
62         bcview().addReadOnly(dialog_->button_database_browse);
63         bcview().addReadOnly(dialog_->button_style_browse);
64         bcview().addReadOnly(dialog_->button_rescan);
65         bcview().addReadOnly(dialog_->input_style);
66         bcview().addReadOnly(dialog_->check_bibtotoc);
67
68         // trigger an input event for cut&paste with middle mouse button.
69         setPrehandler(dialog_->input_database);
70         setPrehandler(dialog_->input_style);
71
72         fl_set_input_return(dialog_->input_database, FL_RETURN_CHANGED);
73         fl_set_input_return(dialog_->input_style, FL_RETURN_CHANGED);
74
75         // callback for double click in browser
76         fl_set_browser_dblclick_callback(dialog_->browser_styles,
77                                          C_FormDialogView_InputCB, 2);
78
79         // set up the tooltips
80         string str = _("The database you want to cite from. Insert it "
81                        "without the default extension \".bib\". Use comma "
82                        "to separate databases.");
83         tooltips().init(dialog_->button_database_browse, str);
84
85         str = _("Browse directory for BibTeX stylefiles");
86         tooltips().init(dialog_->button_style_browse, str);
87
88         str = _("The BibTeX style to use (only one allowed). Insert it without "
89                 "the default extension \".bst\" and without path.");
90         tooltips().init(dialog_->input_style, str);
91
92         str = _("Select if the bibliography should appear in the Table "
93                 "of Contents");
94         tooltips().init(dialog_->check_bibtotoc, str);
95
96         str = _("Double click to choose a BibTeX style from the list.");
97         tooltips().init(dialog_->browser_styles, str);
98
99 #if FL_VERSION == 0 || (FL_REVISION == 0 && FL_FIXLEVEL == 0)
100         // Work-around xforms' bug; enable tooltips for browser widgets.
101         setPrehandler(dialog_->browser_styles);
102 #endif
103
104         str = _("Updates your TeX system for a new bibstyle list. Only "
105                 "the styles which are in directories where TeX finds them "
106                 "are listed!");
107         tooltips().init(dialog_->button_rescan, str);
108 }
109
110
111 ButtonPolicy::SMInput FormBibtex::input(FL_OBJECT * ob, long ob_value)
112 {
113         if (ob == dialog_->button_database_browse) {
114                 // When browsing, take the first file only
115                 string const in_name = getString(dialog_->input_database);
116                 string out_name =
117                         controller().Browse("",
118                                 _("Select Database"),
119                                 _("*.bib| BibTeX Databases (*.bib)"));
120                 if (!out_name.empty()) {
121                         // add the database to any existing ones
122                         if (!in_name.empty())
123                                 out_name = in_name + ',' + out_name;
124
125                         fl_set_input(dialog_->input_database, out_name.c_str());
126                 }
127
128         } else if (ob == dialog_->button_style_browse) {
129                 string const in_name = getString(dialog_->input_style);
130                 string const style = controller().Browse(in_name,
131                                         _("Select BibTeX-Style"),
132                                         _("*.bst| BibTeX Styles (*.bst)"));
133                 if (!style.empty()) {
134                         fl_set_input(dialog_->input_style, style.c_str());
135                 }
136
137         } else if (ob == dialog_->browser_styles && ob_value == 2) {
138                 // double clicked in styles browser
139                 string const style = getString(dialog_->browser_styles);
140                 if (style.empty()) {
141                         return ButtonPolicy::SMI_NOOP;
142                 } else {
143                         fl_set_input(dialog_->input_style,
144                                         ChangeExtension(style, "").c_str());
145                 }
146                 // reset the browser so that the following
147                 // single-click callback doesn't do anything
148                 fl_deselect_browser(dialog_->browser_styles);
149
150         } else if (ob == dialog_->button_rescan) {
151                 fl_clear_browser(dialog_->browser_styles);
152                 controller().rescanBibStyles();
153                 vector<string> styles;
154                 controller().getBibStyles(styles);
155                 fl_add_browser_line(dialog_->browser_styles,
156                                     getStringFromVector(styles, "\n").c_str());
157         }
158
159         // with an empty database nothing makes sense ...
160         if (!compare(fl_get_input(dialog_->input_database), "")) {
161                 return ButtonPolicy::SMI_NOOP;
162         }
163
164         return ButtonPolicy::SMI_VALID;
165 }
166
167
168 void FormBibtex::update()
169 {
170         fl_set_input(dialog_->input_database,
171                      controller().params().getContents().c_str());
172
173         string bibtotoc = "bibtotoc";
174         string bibstyle = controller().params().getOptions();
175
176         bool const bibtotoc_exists = prefixIs(bibstyle, bibtotoc);
177         fl_set_button(dialog_->check_bibtotoc, bibtotoc_exists);
178         if (bibtotoc_exists) {
179                 if (contains(bibstyle, ',')) { // bibstyle exists?
180                         bibstyle = split(bibstyle, bibtotoc, ',');
181                 } else {
182                         bibstyle.erase();
183                 }
184         }
185         fl_set_input(dialog_->input_style, bibstyle.c_str());
186
187         vector<string> styles;
188         controller().getBibStyles(styles);
189
190         fl_clear_browser(dialog_->browser_styles);
191         fl_add_browser_line(dialog_->browser_styles,
192                             getStringFromVector(styles, "\n").c_str());
193 }
194
195 namespace {
196
197 string const unique_and_no_extensions(string const & str_in)
198 {
199         vector<string> dbase = getVectorFromString(str_in);
200         for (vector<string>::iterator it = dbase.begin();
201              it != dbase.end(); ++it) {
202                 *it = ChangeExtension(*it, string());
203         }
204         lyx::eliminate_duplicates(dbase);
205         return getStringFromVector(dbase);
206 }
207
208 } // namespace anon
209
210
211 void FormBibtex::apply()
212 {
213         string const db = getString(dialog_->input_database);
214         if (db.empty()) {
215                 // no database -> no bibtex-command and no options!
216                 controller().params().setContents("");
217                 controller().params().setOptions("");
218                 return;
219         }
220
221         controller().params().setContents(unique_and_no_extensions(db));
222
223         // empty is valid!
224         string bibstyle = getString(dialog_->input_style);
225         if (!bibstyle.empty()) {
226                 // save the BibTeX style without any ".bst" extension
227                 bibstyle = ChangeExtension(OnlyFilename(bibstyle), "");
228         }
229
230         bool const addtotoc = fl_get_button(dialog_->check_bibtotoc);
231         string const bibtotoc = addtotoc ? "bibtotoc" : "";
232         if (addtotoc && !bibstyle.empty()) {
233                 // Both bibtotoc and style.
234                 controller().params().setOptions(bibtotoc + ',' + bibstyle);
235
236         } else {
237                 // At least one of addtotoc and bibstyle is empty. No harm to output both!
238                 controller().params().setOptions(bibtotoc + bibstyle);
239         }
240 }