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