]> git.lyx.org Git - lyx.git/blob - src/frontends/qt4/GuiRef.cpp
proper fix for bug 4936.
[lyx.git] / src / frontends / qt4 / GuiRef.cpp
1 /**
2  * \file GuiRef.cpp
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author John Levon
7  * \author Jürgen Spitzmüller
8  *
9  * Full author contact details are available in file CREDITS.
10  */
11
12 #include <config.h>
13
14 #include "GuiRef.h"
15
16 #include "Buffer.h"
17 #include "BufferList.h"
18 #include "FuncRequest.h"
19
20 #include "qt_helpers.h"
21
22 #include "insets/InsetRef.h"
23
24 #include "support/FileName.h"
25 #include "support/filetools.h" // makeAbsPath, makeDisplayPath
26
27 #include <QLineEdit>
28 #include <QCheckBox>
29 #include <QListWidget>
30 #include <QListWidgetItem>
31 #include <QPushButton>
32 #include <QToolTip>
33 #include <QCloseEvent>
34
35 using namespace std;
36 using namespace lyx::support;
37
38 namespace lyx {
39 namespace frontend {
40
41 GuiRef::GuiRef(GuiView & lv)
42         : GuiDialog(lv, "ref", qt_("Cross-reference")),
43           params_(insetCode("ref"))
44 {
45         setupUi(this);
46
47         sort_ = false;
48         at_ref_ = false;
49
50         //FIXME: when/if we support the xr package for cross-reference
51         //between independant files. Those can be re-enabled.
52         refsL->setEnabled(false);
53         refsL->hide();
54         bufferCO->setEnabled(false);
55         bufferCO->hide();
56
57         connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
58         connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
59         connect(closePB, SIGNAL(clicked()), this, SLOT(slotClose()));
60         connect(closePB, SIGNAL(clicked()), this, SLOT(reset_dialog()));
61         connect(this, SIGNAL(rejected()), this, SLOT(reset_dialog()));
62
63         connect(typeCO, SIGNAL(activated(int)),
64                 this, SLOT(changed_adaptor()));
65         connect(referenceED, SIGNAL(textChanged(QString)),
66                 this, SLOT(changed_adaptor()));
67         connect(nameED, SIGNAL(textChanged(QString)),
68                 this, SLOT(changed_adaptor()));
69         connect(refsLW, SIGNAL(itemClicked(QListWidgetItem *)),
70                 this, SLOT(refHighlighted(QListWidgetItem *)));
71         connect(refsLW, SIGNAL(itemSelectionChanged()),
72                 this, SLOT(selectionChanged()));
73         connect(refsLW, SIGNAL(itemActivated(QListWidgetItem *)),
74                 this, SLOT(refSelected(QListWidgetItem *)));
75         connect(sortCB, SIGNAL(clicked(bool)),
76                 this, SLOT(sortToggled(bool)));
77         connect(gotoPB, SIGNAL(clicked()),
78                 this, SLOT(gotoClicked()));
79         connect(updatePB, SIGNAL(clicked()),
80                 this, SLOT(updateClicked()));
81         connect(bufferCO, SIGNAL(activated(int)),
82                 this, SLOT(updateClicked()));
83
84         setFocusProxy(refsLW);
85
86         bc().setPolicy(ButtonPolicy::NoRepeatedApplyReadOnlyPolicy);
87         bc().setOK(okPB);
88         bc().setApply(applyPB);
89         bc().setCancel(closePB);
90         bc().addReadOnly(refsLW);
91         bc().addReadOnly(sortCB);
92         bc().addReadOnly(nameED);
93         bc().addReadOnly(referenceED);
94         bc().addReadOnly(typeCO);
95         bc().addReadOnly(bufferCO);
96
97         restored_buffer_ = -1;
98 }
99
100
101 void GuiRef::changed_adaptor()
102 {
103         changed();
104 }
105
106
107 void GuiRef::gotoClicked()
108 {
109         gotoRef();
110 }
111
112
113 void GuiRef::selectionChanged()
114 {
115         if (isBufferReadonly())
116                 return;
117
118         QList<QListWidgetItem *> selections = refsLW->selectedItems();
119         if (selections.isEmpty())
120                 return;
121         QListWidgetItem * sel = selections.first();
122         refHighlighted(sel);
123         return;
124 }
125
126
127 void GuiRef::refHighlighted(QListWidgetItem * sel)
128 {
129         if (isBufferReadonly())
130                 return;
131
132 /*      int const cur_item = refsLW->currentRow();
133         bool const cur_item_selected = cur_item >= 0 ?
134                 refsLB->isSelected(cur_item) : false;*/
135         bool const cur_item_selected = refsLW->isItemSelected(sel);
136
137         if (cur_item_selected)
138                 referenceED->setText(sel->text());
139
140         if (at_ref_)
141                 gotoRef();
142         gotoPB->setEnabled(true);
143         if (typeAllowed())
144                 typeCO->setEnabled(true);
145         if (nameAllowed())
146                 nameED->setEnabled(true);
147 }
148
149
150 void GuiRef::refSelected(QListWidgetItem * sel)
151 {
152         if (isBufferReadonly())
153                 return;
154
155 /*      int const cur_item = refsLW->currentRow();
156         bool const cur_item_selected = cur_item >= 0 ?
157                 refsLB->isSelected(cur_item) : false;*/
158         bool const cur_item_selected = refsLW->isItemSelected(sel);
159
160         if (cur_item_selected)
161                 referenceED->setText(sel->text());
162         // <enter> or double click, inserts ref and closes dialog
163         slotOK();
164 }
165
166
167 void GuiRef::sortToggled(bool on)
168 {
169         sort_ = on;
170         redoRefs();
171 }
172
173
174 void GuiRef::updateClicked()
175 {
176         updateRefs();
177 }
178
179
180 void GuiRef::reset_dialog()
181 {
182         at_ref_ = false;
183         setGotoRef();
184 }
185
186
187 void GuiRef::closeEvent(QCloseEvent * e)
188 {
189         slotClose();
190         reset_dialog();
191         e->accept();
192 }
193
194
195 void GuiRef::updateContents()
196 {
197         int orig_type = typeCO->currentIndex();
198
199         referenceED->setText(toqstr(params_["reference"]));
200
201         nameED->setText(toqstr(params_["name"]));
202         nameED->setReadOnly(!nameAllowed() && !isBufferReadonly());
203
204         // restore type settings for new insets
205         if (params_["reference"].empty())
206                 typeCO->setCurrentIndex(orig_type);
207         else
208                 typeCO->setCurrentIndex(InsetRef::getType(params_.getCmdName()));
209         typeCO->setEnabled(typeAllowed() && !isBufferReadonly());
210         if (!typeAllowed())
211                 typeCO->setCurrentIndex(0);
212
213         sortCB->setChecked(sort_);
214
215         // insert buffer list
216         bufferCO->clear();
217         vector<string> buffers = theBufferList().getFileNames();
218         for (vector<string>::iterator it = buffers.begin();
219              it != buffers.end(); ++it) {
220                 bufferCO->addItem(toqstr(makeDisplayPath(*it)));
221         }
222
223         // restore the buffer combo setting for new insets
224         if (params_["reference"].empty() && restored_buffer_ != -1
225             && restored_buffer_ < bufferCO->count()) 
226                 bufferCO->setCurrentIndex(restored_buffer_);
227         else {
228                 int num = theBufferList().bufferNum(buffer().absFileName());
229                 bufferCO->setCurrentIndex(num);
230         }
231
232         updateRefs();
233         bc().setValid(false);
234 }
235
236
237 void GuiRef::applyView()
238 {
239         last_reference_ = referenceED->text();
240
241         params_.setCmdName(InsetRef::getName(typeCO->currentIndex()));
242         params_["reference"] = qstring_to_ucs4(last_reference_);
243         params_["name"] = qstring_to_ucs4(nameED->text());
244
245         restored_buffer_ = bufferCO->currentIndex();
246 }
247
248
249 bool GuiRef::nameAllowed()
250 {
251         KernelDocType const doc_type = docType();
252         return doc_type != LATEX && doc_type != LITERATE;
253 }
254
255
256 bool GuiRef::typeAllowed()
257 {
258         return docType() != DOCBOOK;
259 }
260
261
262 void GuiRef::setGoBack()
263 {
264         gotoPB->setText(qt_("&Go Back"));
265         gotoPB->setToolTip("");
266         gotoPB->setToolTip(qt_("Jump back"));
267 }
268
269
270 void GuiRef::setGotoRef()
271 {
272         gotoPB->setText(qt_("&Go to Label"));
273         gotoPB->setToolTip("");
274         gotoPB->setToolTip(qt_("Jump to label"));
275 }
276
277
278 void GuiRef::gotoRef()
279 {
280         string ref = fromqstr(referenceED->text());
281
282         if (at_ref_) {
283                 // go back
284                 setGotoRef();
285                 gotoBookmark();
286         } else {
287                 // go to the ref
288                 setGoBack();
289                 gotoRef(ref);
290         }
291         at_ref_ = !at_ref_;
292 }
293
294
295 void GuiRef::redoRefs()
296 {
297         // Prevent these widgets from emitting any signals whilst
298         // we modify their state.
299         refsLW->blockSignals(true);
300         referenceED->blockSignals(true);
301         refsLW->setUpdatesEnabled(false);
302
303         refsLW->clear();
304
305         // need this because Qt will send a highlight() here for
306         // the first item inserted
307         QString const oldSelection(referenceED->text());
308
309         for (vector<docstring>::const_iterator iter = refs_.begin();
310                 iter != refs_.end(); ++iter) {
311                 refsLW->addItem(toqstr(*iter));
312         }
313
314         if (sort_)
315                 refsLW->sortItems();
316
317         referenceED->setText(oldSelection);
318
319         // restore the last selection or, for new insets, highlight
320         // the previous selection
321         if (!oldSelection.isEmpty() || !last_reference_.isEmpty()) {
322                 bool const newInset = oldSelection.isEmpty();
323                 QString textToFind = newInset ? last_reference_ : oldSelection;
324                 last_reference_.clear();
325                 for (int i = 0; i != refsLW->count(); ++i) {
326                         QListWidgetItem * item = refsLW->item(i);
327                         if (textToFind == item->text()) {
328                                 refsLW->setCurrentItem(item);
329                                 refsLW->setItemSelected(item, !newInset);
330                                 //Make sure selected item is visible
331                                 refsLW->scrollToItem(item);
332                                 last_reference_ = textToFind;
333                                 break;
334                         }
335                 }
336         }
337         refsLW->setUpdatesEnabled(true);
338         refsLW->update();
339
340         // Re-activate the emission of signals by these widgets.
341         refsLW->blockSignals(false);
342         referenceED->blockSignals(false);
343 }
344
345
346 void GuiRef::updateRefs()
347 {
348         refs_.clear();
349         string const name = theBufferList().getFileNames()[bufferCO->currentIndex()];
350         Buffer const * buf = theBufferList().getBuffer(
351                 support::makeAbsPath(name).absFilename());
352         buf->getLabelList(refs_);
353         sortCB->setEnabled(!refs_.empty());
354         refsLW->setEnabled(!refs_.empty());
355         gotoPB->setEnabled(!refs_.empty());
356         redoRefs();
357 }
358
359
360 bool GuiRef::isValid()
361 {
362         return !referenceED->text().isEmpty();
363 }
364
365
366 void GuiRef::gotoRef(string const & ref)
367 {
368         dispatch(FuncRequest(LFUN_BOOKMARK_SAVE, "0"));
369         dispatch(FuncRequest(LFUN_LABEL_GOTO, ref));
370 }
371
372
373 void GuiRef::gotoBookmark()
374 {
375         dispatch(FuncRequest(LFUN_BOOKMARK_GOTO, "0"));
376 }
377
378
379 bool GuiRef::initialiseParams(std::string const & data)
380 {
381         InsetCommand::string2params("ref", data, params_);
382         return true;
383 }
384
385
386 void GuiRef::dispatchParams()
387 {
388         std::string const lfun = InsetCommand::params2string("ref", params_);
389         dispatch(FuncRequest(getLfun(), lfun));
390 }
391
392
393
394 Dialog * createGuiRef(GuiView & lv) { return new GuiRef(lv); }
395
396
397 } // namespace frontend
398 } // namespace lyx
399
400 #include "GuiRef_moc.cpp"