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 #ifdef ControlModifier
31 #undef ControlModifier
38 GuiSelectionManager::GuiSelectionManager(
39 QAbstractItemView * avail,
45 QAbstractListModel * amod,
46 QAbstractListModel * smod)
54 availableModel = amod;
57 selectedLV->setModel(smod);
58 availableLV->setModel(amod);
60 connect(availableLV->selectionModel(),
61 SIGNAL(currentChanged(QModelIndex,QModelIndex)),
62 this, SLOT(availableChanged(QModelIndex, QModelIndex)));
63 connect(selectedLV->selectionModel(),
64 SIGNAL(currentChanged(QModelIndex, QModelIndex)),
65 this, SLOT(selectedChanged(QModelIndex, QModelIndex)));
66 connect(addPB, SIGNAL(clicked()),
67 this, SLOT(addPB_clicked()));
68 connect(deletePB, SIGNAL(clicked()),
69 this, SLOT(deletePB_clicked()));
70 connect(upPB, SIGNAL(clicked()),
71 this, SLOT(upPB_clicked()));
72 connect(downPB, SIGNAL(clicked()),
73 this, SLOT(downPB_clicked()));
74 connect(availableLV, SIGNAL(clicked(QModelIndex)),
75 this, SLOT(availableLV_clicked(QModelIndex)));
76 connect(availableLV, SIGNAL(doubleClicked(QModelIndex)),
77 this, SLOT(availableLV_doubleClicked(QModelIndex)));
78 connect(selectedLV, SIGNAL(clicked(QModelIndex)),
79 this, SLOT(selectedLV_clicked(QModelIndex)));
81 availableLV->installEventFilter(this);
82 selectedLV->installEventFilter(this);
86 void GuiSelectionManager::update()
95 QModelIndex GuiSelectionManager::getSelectedIndex() const
98 !availableLV->selectionModel()->selectedIndexes().isEmpty();
100 !selectedLV->selectionModel()->selectedIndexes().isEmpty();
102 if (selectedFocused()) {
104 return selectedLV->currentIndex();
106 return availableLV->currentIndex();
108 else { // available has focus
110 return availableLV->currentIndex();
112 return selectedLV->currentIndex();
114 return QModelIndex();
118 void GuiSelectionManager::updateAddPB()
120 int const arows = availableModel->rowCount();
121 QModelIndexList const availSels =
122 availableLV->selectionModel()->selectedIndexes();
123 addPB->setEnabled(arows > 0 &&
124 !availSels.isEmpty() &&
125 !isSelected(availSels.first()));
129 void GuiSelectionManager::updateDelPB()
131 int const srows = selectedModel->rowCount();
133 deletePB->setEnabled(false);
136 QModelIndexList const selSels =
137 selectedLV->selectionModel()->selectedIndexes();
138 int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
139 deletePB->setEnabled(sel_nr >= 0);
143 void GuiSelectionManager::updateUpPB()
145 int const srows = selectedModel->rowCount();
147 upPB->setEnabled(false);
150 QModelIndexList const selSels =
151 selectedLV->selectionModel()->selectedIndexes();
152 int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
153 upPB->setEnabled(sel_nr > 0);
157 void GuiSelectionManager::updateDownPB()
159 int const srows = selectedModel->rowCount();
161 downPB->setEnabled(false);
164 QModelIndexList const selSels =
165 selectedLV->selectionModel()->selectedIndexes();
166 int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
167 downPB->setEnabled(sel_nr >= 0 && sel_nr < srows - 1);
171 bool GuiSelectionManager::isSelected(const QModelIndex & idx)
173 if (selectedModel->rowCount() == 0)
175 QVariant const & str = availableModel->data(idx, Qt::DisplayRole);
176 QModelIndexList qmil =
177 selectedModel->match(selectedModel->index(0),
178 Qt::DisplayRole, str, 1,
179 Qt::MatchFlags(Qt::MatchExactly | Qt::MatchWrap));
180 return !qmil.empty();
184 void GuiSelectionManager::availableChanged(const QModelIndex & idx, const QModelIndex &)
189 selectedHasFocus_ = false;
194 void GuiSelectionManager::selectedChanged(const QModelIndex & idx, const QModelIndex &)
199 selectedHasFocus_ = true;
204 bool GuiSelectionManager::insertRowToSelected(int i,
205 QMap<int, QVariant> const & itemData)
207 if (i <= -1 || i > selectedModel->rowCount())
209 if (!selectedModel->insertRow(i))
211 return selectedModel->setItemData(selectedModel->index(i), itemData);
215 void GuiSelectionManager::addPB_clicked()
217 QModelIndexList selIdx =
218 availableLV->selectionModel()->selectedIndexes();
219 if (selIdx.isEmpty())
222 QModelIndex const idxToAdd = selIdx.first();
223 QModelIndex const idx = selectedLV->currentIndex();
224 int const srows = selectedModel->rowCount();
226 QMap<int, QVariant> qm = availableModel->itemData(idxToAdd);
227 insertRowToSelected(srows, qm);
229 selectionChanged(); //signal
232 selectedLV->setCurrentIndex(idx);
238 void GuiSelectionManager::deletePB_clicked()
240 QModelIndexList selIdx =
241 selectedLV->selectionModel()->selectedIndexes();
242 if (selIdx.isEmpty())
244 QModelIndex idx = selIdx.first();
245 selectedModel->removeRow(idx.row());
246 selectionChanged(); //signal
248 int nrows = selectedLV->model()->rowCount();
249 if (idx.row() == nrows) //was last item on list
250 idx = idx.sibling(idx.row() - 1, idx.column());
253 selectedLV->setCurrentIndex(idx);
255 selectedLV->setCurrentIndex(selectedLV->model()->index(0, 0));
256 selectedHasFocus_ = (nrows > 0);
261 void GuiSelectionManager::upPB_clicked()
263 QModelIndex idx = selectedLV->currentIndex();
265 int const pos = idx.row();
269 QMap<int, QVariant> qm = selectedModel->itemData(idx);
271 selectedModel->removeRow(pos);
272 insertRowToSelected(pos - 1, qm);
274 selectionChanged(); //signal
276 selectedLV->setCurrentIndex(idx.sibling(idx.row() - 1, idx.column()));
277 selectedHasFocus_ = true;
282 void GuiSelectionManager::downPB_clicked()
284 QModelIndex idx = selectedLV->currentIndex();
286 int const pos = idx.row();
287 if (pos >= selectedModel->rowCount() - 1)
290 QMap<int, QVariant> qm = selectedModel->itemData(idx);
292 selectedModel->removeRow(pos);
293 insertRowToSelected(pos + 1, qm);
295 selectionChanged(); //signal
297 selectedLV->setCurrentIndex(idx.sibling(idx.row() + 1, idx.column()));
298 selectedHasFocus_ = true;
303 // FIXME These slots do not really do what they need to do, since focus
304 // can enter the QListView in other ways. But there are no signals sent
305 // in that case. We need to reimplement focusInEvent() to capture those,
306 // which means subclassing QListView. (rgh)
307 // Or by installing an event listener.. (andre)
308 void GuiSelectionManager::availableLV_clicked(const QModelIndex &)
310 selectedHasFocus_ = false;
315 void GuiSelectionManager::availableLV_doubleClicked(const QModelIndex & idx)
317 if (isSelected(idx) || !addPB->isEnabled())
321 selectedHasFocus_ = false;
323 //updateHook() will be emitted there
327 void GuiSelectionManager::selectedLV_clicked(const QModelIndex &)
329 selectedHasFocus_ = true;
334 bool GuiSelectionManager::eventFilter(QObject * obj, QEvent * event)
336 if (obj == availableLV) {
337 if (event->type() != QEvent::KeyPress)
338 return QObject::eventFilter(obj, event);
339 QKeyEvent * keyEvent = static_cast<QKeyEvent *>(event);
340 int const keyPressed = keyEvent->key();
341 Qt::KeyboardModifiers const keyModifiers = keyEvent->modifiers();
342 // Enter key without modifier will add current item.
343 // Ctrl-Enter will add it and close the dialog.
344 // This is designed to work both with the main enter key
345 // and the one on the numeric keypad.
346 if (keyPressed == Qt::Key_Enter || keyPressed == Qt::Key_Return) {
349 else if (keyModifiers == Qt::ControlModifier ||
350 keyModifiers == Qt::KeypadModifier ||
351 keyModifiers == (Qt::ControlModifier | Qt::KeypadModifier)) {
352 if (addPB->isEnabled()) {
360 } else if (obj == selectedLV) {
361 if (event->type() != QEvent::KeyPress)
362 return QObject::eventFilter(obj, event);
363 QKeyEvent * keyEvent = static_cast<QKeyEvent *>(event);
364 int const keyPressed = keyEvent->key();
365 Qt::KeyboardModifiers const keyModifiers = keyEvent->modifiers();
366 // Delete or backspace key will delete current item
367 // ...with control modifier will clear the list
368 if (keyPressed == Qt::Key_Delete || keyPressed == Qt::Key_Backspace) {
369 if (keyModifiers == Qt::NoModifier && deletePB->isEnabled()) {
372 } else if (keyModifiers == Qt::ControlModifier) {
373 selectedModel->removeRows(0, selectedModel->rowCount());
376 return QObject::eventFilter(obj, event);
378 // Ctrl-Up activates upPB
379 else if (keyPressed == Qt::Key_Up) {
380 if (keyModifiers == Qt::ControlModifier) {
381 if (upPB->isEnabled())
387 // Ctrl-Down activates downPB
388 else if (keyPressed == Qt::Key_Down) {
389 if (keyModifiers == Qt::ControlModifier) {
390 if (downPB->isEnabled())
397 return QObject::eventFilter(obj, event);
400 } // namespace frontend
403 #include "moc_GuiSelectionManager.cpp"