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.
16 #include "GuiSelectionManager.h"
18 #include "support/debug.h"
26 GuiSelectionManager::GuiSelectionManager(
33 QAbstractListModel * amod,
34 QAbstractListModel * smod)
42 availableModel = amod;
45 selectedLV->setModel(smod);
46 availableLV->setModel(amod);
48 connect(availableLV->selectionModel(),
49 SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
50 this, SLOT(availableChanged(const QModelIndex &, const QModelIndex &)));
51 connect(selectedLV->selectionModel(),
52 SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
53 this, SLOT(selectedChanged(const QModelIndex &, const QModelIndex &)));
54 connect(addPB, SIGNAL(clicked()),
55 this, SLOT(addPB_clicked()));
56 connect(deletePB, SIGNAL(clicked()),
57 this, SLOT(deletePB_clicked()));
58 connect(upPB, SIGNAL(clicked()),
59 this, SLOT(upPB_clicked()));
60 connect(downPB, SIGNAL(clicked()),
61 this, SLOT(downPB_clicked()));
62 connect(availableLV, SIGNAL(clicked(const QModelIndex &)),
63 this, SLOT(availableLV_clicked(const QModelIndex &)));
64 connect(availableLV, SIGNAL(doubleClicked(const QModelIndex &)),
65 this, SLOT(availableLV_doubleClicked(const QModelIndex &)));
66 connect(selectedLV, SIGNAL(clicked(const QModelIndex &)),
67 this, SLOT(selectedLV_clicked(const QModelIndex &)));
69 availableLV->installEventFilter(this);
70 selectedLV->installEventFilter(this);
74 void GuiSelectionManager::update()
83 void GuiSelectionManager::updateAddPB()
85 int const arows = availableModel->rowCount();
86 QModelIndexList const availSels =
87 availableLV->selectionModel()->selectedIndexes();
88 addPB->setEnabled(arows > 0 &&
89 !availSels.isEmpty() &&
90 !isSelected(availSels.first()));
94 void GuiSelectionManager::updateDelPB()
96 int const srows = selectedModel->rowCount();
98 deletePB->setEnabled(false);
101 QModelIndexList const selSels =
102 selectedLV->selectionModel()->selectedIndexes();
103 int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
104 deletePB->setEnabled(sel_nr >= 0);
108 void GuiSelectionManager::updateUpPB()
110 int const srows = selectedModel->rowCount();
112 upPB->setEnabled(false);
115 QModelIndexList const selSels =
116 selectedLV->selectionModel()->selectedIndexes();
117 int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
118 upPB->setEnabled(sel_nr > 0);
122 void GuiSelectionManager::updateDownPB()
124 int const srows = selectedModel->rowCount();
126 downPB->setEnabled(false);
129 QModelIndexList const selSels =
130 selectedLV->selectionModel()->selectedIndexes();
131 int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
132 downPB->setEnabled(sel_nr >= 0 && sel_nr < srows - 1);
136 bool GuiSelectionManager::isSelected(const QModelIndex & idx)
138 if (selectedModel->rowCount() == 0)
140 QVariant const & str = availableModel->data(idx, Qt::DisplayRole);
141 QModelIndexList qmil =
142 selectedModel->match(selectedModel->index(0),
143 Qt::DisplayRole, str,
144 Qt::MatchExactly | Qt::MatchWrap);
145 return !qmil.empty();
149 void GuiSelectionManager::availableChanged(const QModelIndex & idx, const QModelIndex &)
154 selectedHasFocus_ = false;
159 void GuiSelectionManager::selectedChanged(const QModelIndex & idx, const QModelIndex &)
164 selectedHasFocus_ = true;
170 QModelIndex getSelectedIndex(QListView * lv)
172 QModelIndex retval = QModelIndex();
173 QModelIndexList selIdx =
174 lv->selectionModel()->selectedIndexes();
176 retval = selIdx.first();
182 bool GuiSelectionManager::insertRowToSelected(int i,
183 QMap<int, QVariant> const & itemData)
185 if (i <= -1 || i > selectedModel->rowCount())
187 if (!selectedModel->insertRow(i))
189 return selectedModel->setItemData(selectedModel->index(i), itemData);
193 void GuiSelectionManager::addPB_clicked()
195 QModelIndex const idxToAdd = getSelectedIndex(availableLV);
196 if (!idxToAdd.isValid())
198 QModelIndex const idx = selectedLV->currentIndex();
199 int const srows = selectedModel->rowCount();
201 QMap<int, QVariant> qm = availableModel->itemData(idxToAdd);
202 insertRowToSelected(srows, qm);
204 selectionChanged(); //signal
207 selectedLV->setCurrentIndex(idx);
213 void GuiSelectionManager::deletePB_clicked()
215 QModelIndex idx = getSelectedIndex(selectedLV);
219 selectedModel->removeRow(idx.row());
220 selectionChanged(); //signal
222 int nrows = selectedLV->model()->rowCount();
223 if (idx.row() == nrows) //was last item on list
224 idx = idx.sibling(idx.row() - 1, idx.column());
227 selectedLV->setCurrentIndex(idx);
229 selectedLV->setCurrentIndex(selectedLV->model()->index(0,0));
230 selectedHasFocus_ = (nrows > 0);
235 void GuiSelectionManager::upPB_clicked()
237 QModelIndex idx = selectedLV->currentIndex();
239 int const pos = idx.row();
243 QMap<int, QVariant> qm = selectedModel->itemData(idx);
245 selectedModel->removeRow(pos);
246 insertRowToSelected(pos - 1, qm);
248 selectionChanged(); //signal
250 selectedLV->setCurrentIndex(idx.sibling(idx.row() - 1, idx.column()));
251 selectedHasFocus_ = true;
256 void GuiSelectionManager::downPB_clicked()
258 QModelIndex idx = selectedLV->currentIndex();
260 int const pos = idx.row();
261 if (pos >= selectedModel->rowCount() - 1)
264 QMap<int, QVariant> qm = selectedModel->itemData(idx);
266 selectedModel->removeRow(pos);
267 insertRowToSelected(pos + 1, qm);
269 selectionChanged(); //signal
271 selectedLV->setCurrentIndex(idx.sibling(idx.row() + 1, idx.column()));
272 selectedHasFocus_ = true;
277 //FIXME These slots do not really do what they need to do, since focus
278 //can enter the QListView in other ways. But there are no signals sent
279 //in that case. We need to reimplement focusInEvent() to capture those,
280 //which means subclassing QListView. (rgh)
281 void GuiSelectionManager::availableLV_clicked(const QModelIndex &)
283 selectedHasFocus_ = false;
288 void GuiSelectionManager::availableLV_doubleClicked(const QModelIndex & idx)
290 if (isSelected(idx) || !addPB->isEnabled())
294 selectedHasFocus_ = false;
296 //updateHook() will be emitted there
300 void GuiSelectionManager::selectedLV_clicked(const QModelIndex &)
302 selectedHasFocus_ = true;
307 bool GuiSelectionManager::eventFilter(QObject * obj, QEvent * event)
309 if (obj == availableLV) {
310 if (event->type() != QEvent::KeyPress)
311 return QObject::eventFilter(obj, event);
312 QKeyEvent * keyEvent = static_cast<QKeyEvent *>(event);
313 int const keyPressed = keyEvent->key();
314 Qt::KeyboardModifiers const keyModifiers = keyEvent->modifiers();
315 //Enter key without modifier will add current item.
316 //Ctrl-Enter will add it and close the dialog.
317 //This is designed to work both with the main enter key
318 //and the one on the numeric keypad.
319 if ((keyPressed == Qt::Key_Enter || keyPressed == Qt::Key_Return) &&
320 //We want one or both of Control and Keypad, and nothing else
321 //(KeypadModifier is what you get if you use the Enter key on the
324 (keyModifiers == Qt::ControlModifier) ||
325 (keyModifiers == Qt::KeypadModifier) ||
326 (keyModifiers == (Qt::ControlModifier | Qt::KeypadModifier))
329 if (addPB->isEnabled()) {
336 } else if (obj == selectedLV) {
337 //Delete or backspace key will delete current item
338 //...with control modifier will clear the list
339 if (event->type() != QEvent::KeyPress)
340 return QObject::eventFilter(obj, event);
341 QKeyEvent * keyEvent = static_cast<QKeyEvent *>(event);
342 int const keyPressed = keyEvent->key();
343 Qt::KeyboardModifiers const keyModifiers = keyEvent->modifiers();
344 if (keyPressed == Qt::Key_Delete || keyPressed == Qt::Key_Backspace) {
345 if (keyModifiers == Qt::NoModifier && deletePB->isEnabled())
347 else if (keyModifiers == Qt::ControlModifier) {
348 selectedModel->removeRows(0, selectedModel->rowCount());
351 //ignore it otherwise
352 return QObject::eventFilter(obj, event);
357 return QObject::eventFilter(obj, event);
360 } // namespace frontend
363 #include "GuiSelectionManager_moc.cpp"