2 * \file GuiSelectionManager.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
9 * Some of the material in this file previously appeared in
10 * GuiCitationDialog.cpp.
12 * Full author contact details are available in file CREDITS.
17 #include "GuiSelectionManager.h"
19 #include "support/debug.h"
23 #include <QPushButton>
24 #include <QAbstractListModel>
30 GuiSelectionManager::GuiSelectionManager(
37 QAbstractListModel * amod,
38 QAbstractListModel * smod)
46 availableModel = amod;
49 selectedLV->setModel(smod);
50 availableLV->setModel(amod);
52 connect(availableLV->selectionModel(),
53 SIGNAL(currentChanged(QModelIndex,QModelIndex)),
54 this, SLOT(availableChanged(QModelIndex, QModelIndex)));
55 connect(selectedLV->selectionModel(),
56 SIGNAL(currentChanged(QModelIndex, QModelIndex)),
57 this, SLOT(selectedChanged(QModelIndex, QModelIndex)));
58 connect(addPB, SIGNAL(clicked()),
59 this, SLOT(addPB_clicked()));
60 connect(deletePB, SIGNAL(clicked()),
61 this, SLOT(deletePB_clicked()));
62 connect(upPB, SIGNAL(clicked()),
63 this, SLOT(upPB_clicked()));
64 connect(downPB, SIGNAL(clicked()),
65 this, SLOT(downPB_clicked()));
66 connect(availableLV, SIGNAL(clicked(QModelIndex)),
67 this, SLOT(availableLV_clicked(QModelIndex)));
68 connect(availableLV, SIGNAL(doubleClicked(QModelIndex)),
69 this, SLOT(availableLV_doubleClicked(QModelIndex)));
70 connect(selectedLV, SIGNAL(clicked(QModelIndex)),
71 this, SLOT(selectedLV_clicked(QModelIndex)));
73 availableLV->installEventFilter(this);
74 selectedLV->installEventFilter(this);
78 void GuiSelectionManager::update()
87 void GuiSelectionManager::updateAddPB()
89 int const arows = availableModel->rowCount();
90 QModelIndexList const availSels =
91 availableLV->selectionModel()->selectedIndexes();
92 addPB->setEnabled(arows > 0 &&
93 !availSels.isEmpty() &&
94 !isSelected(availSels.first()));
98 void GuiSelectionManager::updateDelPB()
100 int const srows = selectedModel->rowCount();
102 deletePB->setEnabled(false);
105 QModelIndexList const selSels =
106 selectedLV->selectionModel()->selectedIndexes();
107 int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
108 deletePB->setEnabled(sel_nr >= 0);
112 void GuiSelectionManager::updateUpPB()
114 int const srows = selectedModel->rowCount();
116 upPB->setEnabled(false);
119 QModelIndexList const selSels =
120 selectedLV->selectionModel()->selectedIndexes();
121 int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
122 upPB->setEnabled(sel_nr > 0);
126 void GuiSelectionManager::updateDownPB()
128 int const srows = selectedModel->rowCount();
130 downPB->setEnabled(false);
133 QModelIndexList const selSels =
134 selectedLV->selectionModel()->selectedIndexes();
135 int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
136 downPB->setEnabled(sel_nr >= 0 && sel_nr < srows - 1);
140 bool GuiSelectionManager::isSelected(const QModelIndex & idx)
142 if (selectedModel->rowCount() == 0)
144 QVariant const & str = availableModel->data(idx, Qt::DisplayRole);
145 QModelIndexList qmil =
146 selectedModel->match(selectedModel->index(0),
147 Qt::DisplayRole, str, 1,
148 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchWrap));
149 return !qmil.empty();
153 void GuiSelectionManager::availableChanged(const QModelIndex & idx, const QModelIndex &)
158 selectedHasFocus_ = false;
163 void GuiSelectionManager::selectedChanged(const QModelIndex & idx, const QModelIndex &)
168 selectedHasFocus_ = true;
173 bool GuiSelectionManager::insertRowToSelected(int i,
174 QMap<int, QVariant> const & itemData)
176 if (i <= -1 || i > selectedModel->rowCount())
178 if (!selectedModel->insertRow(i))
180 return selectedModel->setItemData(selectedModel->index(i), itemData);
184 void GuiSelectionManager::addPB_clicked()
186 QModelIndexList selIdx =
187 availableLV->selectionModel()->selectedIndexes();
188 if (selIdx.isEmpty())
191 QModelIndex const idxToAdd = selIdx.first();
192 QModelIndex const idx = selectedLV->currentIndex();
193 int const srows = selectedModel->rowCount();
195 QMap<int, QVariant> qm = availableModel->itemData(idxToAdd);
196 insertRowToSelected(srows, qm);
198 selectionChanged(); //signal
201 selectedLV->setCurrentIndex(idx);
207 void GuiSelectionManager::deletePB_clicked()
209 QModelIndexList selIdx =
210 selectedLV->selectionModel()->selectedIndexes();
211 if (selIdx.isEmpty())
213 QModelIndex idx = selIdx.first();
214 selectedModel->removeRow(idx.row());
215 selectionChanged(); //signal
217 int nrows = selectedLV->model()->rowCount();
218 if (idx.row() == nrows) //was last item on list
219 idx = idx.sibling(idx.row() - 1, idx.column());
222 selectedLV->setCurrentIndex(idx);
224 selectedLV->setCurrentIndex(selectedLV->model()->index(0, 0));
225 selectedHasFocus_ = (nrows > 0);
230 void GuiSelectionManager::upPB_clicked()
232 QModelIndex idx = selectedLV->currentIndex();
234 int const pos = idx.row();
238 QMap<int, QVariant> qm = selectedModel->itemData(idx);
240 selectedModel->removeRow(pos);
241 insertRowToSelected(pos - 1, qm);
243 selectionChanged(); //signal
245 selectedLV->setCurrentIndex(idx.sibling(idx.row() - 1, idx.column()));
246 selectedHasFocus_ = true;
251 void GuiSelectionManager::downPB_clicked()
253 QModelIndex idx = selectedLV->currentIndex();
255 int const pos = idx.row();
256 if (pos >= selectedModel->rowCount() - 1)
259 QMap<int, QVariant> qm = selectedModel->itemData(idx);
261 selectedModel->removeRow(pos);
262 insertRowToSelected(pos + 1, qm);
264 selectionChanged(); //signal
266 selectedLV->setCurrentIndex(idx.sibling(idx.row() + 1, idx.column()));
267 selectedHasFocus_ = true;
272 // FIXME These slots do not really do what they need to do, since focus
273 // can enter the QListView in other ways. But there are no signals sent
274 // in that case. We need to reimplement focusInEvent() to capture those,
275 // which means subclassing QListView. (rgh)
276 // Or by installing an event listener.. (andre)
277 void GuiSelectionManager::availableLV_clicked(const QModelIndex &)
279 selectedHasFocus_ = false;
284 void GuiSelectionManager::availableLV_doubleClicked(const QModelIndex & idx)
286 if (isSelected(idx) || !addPB->isEnabled())
290 selectedHasFocus_ = false;
292 //updateHook() will be emitted there
296 void GuiSelectionManager::selectedLV_clicked(const QModelIndex &)
298 selectedHasFocus_ = true;
303 bool GuiSelectionManager::eventFilter(QObject * obj, QEvent * event)
305 if (obj == availableLV) {
306 if (event->type() != QEvent::KeyPress)
307 return QObject::eventFilter(obj, event);
308 QKeyEvent * keyEvent = static_cast<QKeyEvent *>(event);
309 int const keyPressed = keyEvent->key();
310 Qt::KeyboardModifiers const keyModifiers = keyEvent->modifiers();
311 // Enter key without modifier will add current item.
312 // Ctrl-Enter will add it and close the dialog.
313 // This is designed to work both with the main enter key
314 // and the one on the numeric keypad.
315 if (keyPressed == Qt::Key_Enter || keyPressed == Qt::Key_Return) {
318 else if (keyModifiers == Qt::ControlModifier ||
319 keyModifiers == Qt::KeypadModifier ||
320 keyModifiers == (Qt::ControlModifier | Qt::KeypadModifier)) {
321 if (addPB->isEnabled()) {
329 } else if (obj == selectedLV) {
330 if (event->type() != QEvent::KeyPress)
331 return QObject::eventFilter(obj, event);
332 QKeyEvent * keyEvent = static_cast<QKeyEvent *>(event);
333 int const keyPressed = keyEvent->key();
334 Qt::KeyboardModifiers const keyModifiers = keyEvent->modifiers();
335 // Delete or backspace key will delete current item
336 // ...with control modifier will clear the list
337 if (keyPressed == Qt::Key_Delete || keyPressed == Qt::Key_Backspace) {
338 if (keyModifiers == Qt::NoModifier && deletePB->isEnabled()) {
341 } else if (keyModifiers == Qt::ControlModifier) {
342 selectedModel->removeRows(0, selectedModel->rowCount());
345 return QObject::eventFilter(obj, event);
347 // Ctrl-Up activates upPB
348 else if (keyPressed == Qt::Key_Up) {
349 if (keyModifiers == Qt::ControlModifier) {
350 if (upPB->isEnabled())
356 // Ctrl-Down activates downPB
357 else if (keyPressed == Qt::Key_Down) {
358 if (keyModifiers == Qt::ControlModifier) {
359 if (downPB->isEnabled())
366 return QObject::eventFilter(obj, event);
369 } // namespace frontend
372 #include "moc_GuiSelectionManager.cpp"