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"
22 GuiSelectionManager::GuiSelectionManager(
29 QStringListModel * amod,
30 QStringListModel * smod)
38 availableModel = amod;
41 selectedLV->setModel(smod);
42 availableLV->setModel(amod);
44 connect(availableLV->selectionModel(),
45 SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
46 this, SLOT(availableChanged(const QModelIndex &, const QModelIndex &)));
47 connect(selectedLV->selectionModel(),
48 SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
49 this, SLOT(selectedChanged(const QModelIndex &, const QModelIndex &)));
50 connect(addPB, SIGNAL(clicked()),
51 this, SLOT(addPB_clicked()));
52 connect(deletePB, SIGNAL(clicked()),
53 this, SLOT(deletePB_clicked()));
54 connect(upPB, SIGNAL(clicked()),
55 this, SLOT(upPB_clicked()));
56 connect(downPB, SIGNAL(clicked()),
57 this, SLOT(downPB_clicked()));
58 connect(availableLV, SIGNAL(clicked(const QModelIndex &)),
59 this, SLOT(availableLV_clicked(const QModelIndex &)));
60 connect(availableLV, SIGNAL(doubleClicked(const QModelIndex &)),
61 this, SLOT(availableLV_doubleClicked(const QModelIndex &)));
62 connect(selectedLV, SIGNAL(clicked(const QModelIndex &)),
63 this, SLOT(selectedLV_clicked(const QModelIndex &)));
65 availableLV->installEventFilter(this);
66 selectedLV->installEventFilter(this);
70 void GuiSelectionManager::update()
79 void GuiSelectionManager::updateAddPB()
81 int const arows = availableLV->model()->rowCount();
82 QModelIndexList const availSels =
83 availableLV->selectionModel()->selectedIndexes();
84 addPB->setEnabled(arows > 0 &&
85 !availSels.isEmpty() &&
86 !isSelected(availSels.first()));
90 void GuiSelectionManager::updateDelPB()
92 int const srows = selectedLV->model()->rowCount();
94 deletePB->setEnabled(false);
97 QModelIndexList const selSels =
98 selectedLV->selectionModel()->selectedIndexes();
99 int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
100 deletePB->setEnabled(sel_nr >= 0);
104 void GuiSelectionManager::updateUpPB()
106 int const srows = selectedLV->model()->rowCount();
108 upPB->setEnabled(false);
111 QModelIndexList const selSels =
112 selectedLV->selectionModel()->selectedIndexes();
113 int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
114 upPB->setEnabled(sel_nr > 0);
118 void GuiSelectionManager::updateDownPB()
120 int const srows = selectedLV->model()->rowCount();
122 downPB->setEnabled(false);
125 QModelIndexList const selSels =
126 selectedLV->selectionModel()->selectedIndexes();
127 int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
128 downPB->setEnabled(sel_nr >= 0 && sel_nr < srows - 1);
131 bool GuiSelectionManager::isSelected(const QModelIndex & idx)
133 QString const str = idx.data().toString();
134 return selectedModel->stringList().contains(str);
138 void GuiSelectionManager::availableChanged(const QModelIndex & idx, const QModelIndex &)
143 selectedHasFocus_ = false;
148 void GuiSelectionManager::selectedChanged(const QModelIndex & idx, const QModelIndex &)
153 selectedHasFocus_ = true;
158 static QModelIndex getSelectedIndex(QListView * lv)
160 QModelIndex retval = QModelIndex();
161 QModelIndexList selIdx =
162 lv->selectionModel()->selectedIndexes();
164 retval = selIdx.first();
169 void GuiSelectionManager::addPB_clicked()
171 QModelIndex const idxToAdd = getSelectedIndex(availableLV);
172 if (!idxToAdd.isValid())
174 QModelIndex idx = selectedLV->currentIndex();
176 QStringList keys = selectedModel->stringList();
177 keys.append(idxToAdd.data().toString());
178 selectedModel->setStringList(keys);
179 selectionChanged(); //signal
182 selectedLV->setCurrentIndex(idx);
187 void GuiSelectionManager::deletePB_clicked()
189 QModelIndex idx = getSelectedIndex(selectedLV);
193 QStringList keys = selectedModel->stringList();
194 keys.removeAt(idx.row());
195 selectedModel->setStringList(keys);
196 selectionChanged(); //signal
198 int nrows = selectedLV->model()->rowCount();
199 if (idx.row() == nrows) //was last item on list
200 idx = idx.sibling(idx.row() - 1, idx.column());
203 selectedLV->setCurrentIndex(idx);
205 selectedLV->setCurrentIndex(selectedLV->model()->index(0,0));
206 selectedHasFocus_ = (nrows > 0);
211 void GuiSelectionManager::upPB_clicked()
213 QModelIndex idx = selectedLV->currentIndex();
215 int const pos = idx.row();
216 QStringList keys = selectedModel->stringList();
217 keys.swap(pos, pos - 1);
218 selectedModel->setStringList(keys);
219 selectionChanged(); //signal
221 selectedLV->setCurrentIndex(idx.sibling(idx.row() - 1, idx.column()));
222 selectedHasFocus_ = true;
227 void GuiSelectionManager::downPB_clicked()
229 QModelIndex idx = selectedLV->currentIndex();
231 int const pos = idx.row();
232 QStringList keys = selectedModel->stringList();
233 keys.swap(pos, pos + 1);
234 selectedModel->setStringList(keys);
235 selectionChanged(); //signal
237 selectedLV->setCurrentIndex(idx.sibling(idx.row() + 1, idx.column()));
238 selectedHasFocus_ = true;
243 //FIXME These slots do not really do what they need to do, since focus
244 //can enter the QListView in other ways. But there are no signals sent
245 //in that case. We need to reimplement focusInEvent() to capture those,
246 //which means subclassing QListView. (rgh)
247 void GuiSelectionManager::availableLV_clicked(const QModelIndex &)
249 selectedHasFocus_ = false;
254 void GuiSelectionManager::availableLV_doubleClicked(const QModelIndex & idx)
256 if (isSelected(idx) || !addPB->isEnabled())
260 selectedHasFocus_ = false;
262 //updateHook() will be emitted there
266 void GuiSelectionManager::selectedLV_clicked(const QModelIndex &)
268 selectedHasFocus_ = true;
273 bool GuiSelectionManager::eventFilter(QObject * obj, QEvent * event)
275 if (obj == availableLV) {
276 if (event->type() != QEvent::KeyPress)
277 return QObject::eventFilter(obj, event);
278 QKeyEvent * keyEvent = static_cast<QKeyEvent *>(event);
279 int const keyPressed = keyEvent->key();
280 Qt::KeyboardModifiers const keyModifiers = keyEvent->modifiers();
281 //Enter key without modifier will add current item.
282 //Ctrl-Enter will add it and close the dialog.
283 //This is designed to work both with the main enter key
284 //and the one on the numeric keypad.
285 if ((keyPressed == Qt::Key_Enter || keyPressed == Qt::Key_Return) &&
286 //We want one or both of Control and Keypad, and nothing else
287 //(KeypadModifier is what you get if you use the Enter key on the
290 (keyModifiers == Qt::ControlModifier) ||
291 (keyModifiers == Qt::KeypadModifier) ||
292 (keyModifiers == (Qt::ControlModifier | Qt::KeypadModifier))
295 if (addPB->isEnabled()) {
302 } else if (obj == selectedLV) {
303 //Delete or backspace key will delete current item
304 //...with control modifier will clear the list
305 if (event->type() != QEvent::KeyPress)
306 return QObject::eventFilter(obj, event);
307 QKeyEvent * keyEvent = static_cast<QKeyEvent *>(event);
308 int const keyPressed = keyEvent->key();
309 Qt::KeyboardModifiers const keyModifiers = keyEvent->modifiers();
310 if (keyPressed == Qt::Key_Delete || keyPressed == Qt::Key_Backspace) {
311 if (keyModifiers == Qt::NoModifier && deletePB->isEnabled())
313 else if (keyModifiers == Qt::ControlModifier) {
314 QStringList list = selectedModel->stringList();
316 selectedModel->setStringList(list);
319 //ignore it otherwise
320 return QObject::eventFilter(obj, event);
325 return QObject::eventFilter(obj, event);
328 } // namespace frontend
331 #include "GuiSelectionManager_moc.cpp"