lyx_mirror/src/frontends/qt4/GuiSelectionManager.cpp
Richard Heck 6f0703e707 Repair behavior of citation dialog after all the recent changes in src/frontends/. Previously, there had been a virtual initialiseParams() method in QCitation which overrode the corresponding method in ControlCitation. But now there is no "local" controller, and so intialiseParams() overrode nothing and so never got called.
I've also made some minor changes here to GuiSelectionManager, changing updateView(), which is now used as a commonly overridden method of GuiDialog, back to update(). The method does not serve the same purpose here.

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@20281 a592a061-630c-0410-9148-cb99ea01b6c8
2007-09-15 01:53:26 +00:00

290 lines
7.6 KiB
C++

/**
* \file GuiSelectionManager.cpp
* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
* \author Richard Heck
* \author Et Alia
*
* Some of the material in this file previously appeared in
* GuiCitationDialog.cpp.
*
* Full author contact details are available in file CREDITS.
*/
#include <config.h>
#include "GuiSelectionManager.h"
namespace lyx {
namespace frontend {
GuiSelectionManager::GuiSelectionManager(
QListView * avail,
QListView * sel,
QPushButton * add,
QPushButton * del,
QPushButton * up,
QPushButton * down,
QStringListModel * amod,
QStringListModel * smod)
{
availableLV = avail;
selectedLV = sel;
addPB = add;
deletePB = del;
upPB = up;
downPB = down;
availableModel = amod;
selectedModel = smod;
selectedLV->setModel(smod);
availableLV->setModel(amod);
connect(availableLV->selectionModel(),
SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(availableChanged(const QModelIndex &, const QModelIndex &)));
connect(selectedLV->selectionModel(),
SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)),
this, SLOT(selectedChanged(const QModelIndex &, const QModelIndex &)));
connect(addPB, SIGNAL(clicked()),
this, SLOT(addPB_clicked()));
connect(deletePB, SIGNAL(clicked()),
this, SLOT(deletePB_clicked()));
connect(upPB, SIGNAL(clicked()),
this, SLOT(upPB_clicked()));
connect(downPB, SIGNAL(clicked()),
this, SLOT(downPB_clicked()));
connect(availableLV, SIGNAL(clicked(const QModelIndex &)),
this, SLOT(availableLV_clicked(const QModelIndex &)));
connect(availableLV, SIGNAL(doubleClicked(const QModelIndex &)),
this, SLOT(availableLV_doubleClicked(const QModelIndex &)));
connect(selectedLV, SIGNAL(clicked(const QModelIndex &)),
this, SLOT(selectedLV_clicked(const QModelIndex &)));
availableLV->installEventFilter(this);
selectedLV->installEventFilter(this);
}
void GuiSelectionManager::update()
{
int const arows = availableLV->model()->rowCount();
QModelIndexList const availSels =
availableLV->selectionModel()->selectedIndexes();
addPB->setEnabled(arows > 0 &&
!availSels.isEmpty() &&
!isSelected(availSels.first()));
int const srows = selectedLV->model()->rowCount();
QModelIndexList const selSels =
selectedLV->selectionModel()->selectedIndexes();
int const sel_nr = selSels.empty() ? -1 : selSels.first().row();
deletePB->setEnabled(sel_nr >= 0);
upPB->setEnabled(sel_nr > 0);
downPB->setEnabled(sel_nr >= 0 && sel_nr < srows - 1);
}
bool GuiSelectionManager::isSelected(const QModelIndex & idx)
{
QString const str = idx.data().toString();
return selectedModel->stringList().contains(str);
}
void GuiSelectionManager::availableChanged(const QModelIndex & idx, const QModelIndex &)
{
if (!idx.isValid())
return;
selectedHasFocus_ = false;
updateHook();
}
void GuiSelectionManager::selectedChanged(const QModelIndex & idx, const QModelIndex &)
{
if (!idx.isValid())
return;
selectedHasFocus_ = true;
updateHook();
}
static QModelIndex getSelectedIndex(QListView * lv)
{
QModelIndex retval = QModelIndex();
QModelIndexList selIdx =
lv->selectionModel()->selectedIndexes();
if (!selIdx.empty())
retval = selIdx.first();
return retval;
}
void GuiSelectionManager::addPB_clicked()
{
QModelIndex const idxToAdd = getSelectedIndex(availableLV);
if (!idxToAdd.isValid())
return;
QModelIndex idx = selectedLV->currentIndex();
QStringList keys = selectedModel->stringList();
keys.append(idxToAdd.data().toString());
selectedModel->setStringList(keys);
selectionChanged(); //signal
if (idx.isValid())
selectedLV->setCurrentIndex(idx);
updateHook();
}
void GuiSelectionManager::deletePB_clicked()
{
QModelIndex idx = getSelectedIndex(selectedLV);
if (!idx.isValid())
return;
QStringList keys = selectedModel->stringList();
keys.removeAt(idx.row());
selectedModel->setStringList(keys);
selectionChanged(); //signal
int nrows = selectedLV->model()->rowCount();
if (idx.row() == nrows) //was last item on list
idx = idx.sibling(idx.row() - 1, idx.column());
if (nrows > 1)
selectedLV->setCurrentIndex(idx);
else if (nrows == 1)
selectedLV->setCurrentIndex(selectedLV->model()->index(0,0));
selectedHasFocus_ = (nrows > 0);
updateHook();
}
void GuiSelectionManager::upPB_clicked()
{
QModelIndex idx = selectedLV->currentIndex();
int const pos = idx.row();
QStringList keys = selectedModel->stringList();
keys.swap(pos, pos - 1);
selectedModel->setStringList(keys);
selectionChanged(); //signal
selectedLV->setCurrentIndex(idx.sibling(idx.row() - 1, idx.column()));
selectedHasFocus_ = true;
updateHook();
}
void GuiSelectionManager::downPB_clicked()
{
QModelIndex idx = selectedLV->currentIndex();
int const pos = idx.row();
QStringList keys = selectedModel->stringList();
keys.swap(pos, pos + 1);
selectedModel->setStringList(keys);
selectionChanged(); //signal
selectedLV->setCurrentIndex(idx.sibling(idx.row() + 1, idx.column()));
selectedHasFocus_ = true;
updateHook();
}
//FIXME These slots do not really do what they need to do, since focus
//can enter the QListView in other ways. But there are no signals sent
//in that case. We need to reimplement focusInEvent() to capture those,
//which means subclassing QListView. (rgh)
void GuiSelectionManager::availableLV_clicked(const QModelIndex &)
{
selectedHasFocus_ = false;
updateHook();
}
void GuiSelectionManager::availableLV_doubleClicked(const QModelIndex & idx)
{
if (isSelected(idx))
return;
if (idx.isValid())
selectedHasFocus_ = false;
addPB_clicked();
//updateHook() will be emitted there
}
void GuiSelectionManager::selectedLV_clicked(const QModelIndex &)
{
selectedHasFocus_ = true;
updateHook();
}
bool GuiSelectionManager::eventFilter(QObject * obj, QEvent * event)
{
if (obj == availableLV) {
if (event->type() != QEvent::KeyPress)
return QObject::eventFilter(obj, event);
QKeyEvent * keyEvent = static_cast<QKeyEvent *>(event);
int const keyPressed = keyEvent->key();
Qt::KeyboardModifiers const keyModifiers = keyEvent->modifiers();
//Enter key without modifier will add current item.
//Ctrl-Enter will add it and close the dialog.
//This is designed to work both with the main enter key
//and the one on the numeric keypad.
if ((keyPressed == Qt::Key_Enter || keyPressed == Qt::Key_Return) &&
//We want one or both of Control and Keypad, and nothing else
//(KeypadModifier is what you get if you use the Enter key on the
//numeric keypad.)
(!keyModifiers ||
(keyModifiers == Qt::ControlModifier) ||
(keyModifiers == Qt::KeypadModifier) ||
(keyModifiers == (Qt::ControlModifier | Qt::KeypadModifier))
)
) {
if (addPB->isEnabled()) {
addPB_clicked();
okHook(); //signal
}
event->accept();
return true;
}
} else if (obj == selectedLV) {
//Delete or backspace key will delete current item
//...with control modifier will clear the list
if (event->type() != QEvent::KeyPress)
return QObject::eventFilter(obj, event);
QKeyEvent * keyEvent = static_cast<QKeyEvent *>(event);
int const keyPressed = keyEvent->key();
Qt::KeyboardModifiers const keyModifiers = keyEvent->modifiers();
if (keyPressed == Qt::Key_Delete || keyPressed == Qt::Key_Backspace) {
if (keyModifiers == Qt::NoModifier && deletePB->isEnabled())
deletePB_clicked();
else if (keyModifiers == Qt::ControlModifier) {
QStringList list = selectedModel->stringList();
list.clear();
selectedModel->setStringList(list);
updateHook();
} else
//ignore it otherwise
return QObject::eventFilter(obj, event);
event->accept();
return true;
}
}
return QObject::eventFilter(obj, event);
}
} // namespace frontend
} // namespace lyx
#include "GuiSelectionManager_moc.cpp"