X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Ffrontends%2Fqt4%2FGuiSelectionManager.cpp;h=4d172bc35d890cb52de14e27d6ec9f50f9edcfaf;hb=425d092204118ea6c24c28e85fdf03fcf2bb51a4;hp=130d3f85c484a63bdf03f3108020b73f565c8731;hpb=c9ea6e6eef090b863fb54445010f24443b15eb23;p=lyx.git diff --git a/src/frontends/qt4/GuiSelectionManager.cpp b/src/frontends/qt4/GuiSelectionManager.cpp index 130d3f85c4..4d172bc35d 100644 --- a/src/frontends/qt4/GuiSelectionManager.cpp +++ b/src/frontends/qt4/GuiSelectionManager.cpp @@ -13,271 +13,362 @@ */ #include + #include "GuiSelectionManager.h" +#include "support/debug.h" + +#include +#include +#include +#include + +#ifdef KeyPress +#undef KeyPress +#endif + +#ifdef ControlModifier +#undef ControlModifier +#endif + namespace lyx { namespace frontend { GuiSelectionManager::GuiSelectionManager( - QListView * avail, + QAbstractItemView * avail, QListView * sel, QPushButton * add, QPushButton * del, QPushButton * up, QPushButton * down, - QStringListModel * amod, - QStringListModel * smod) + QAbstractListModel * amod, + QAbstractListModel * 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(QModelIndex,QModelIndex)), + this, SLOT(availableChanged(QModelIndex, QModelIndex))); + connect(selectedLV->selectionModel(), + SIGNAL(currentChanged(QModelIndex, QModelIndex)), + this, SLOT(selectedChanged(QModelIndex, 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(QModelIndex)), + this, SLOT(availableLV_clicked(QModelIndex))); + connect(availableLV, SIGNAL(doubleClicked(QModelIndex)), + this, SLOT(availableLV_doubleClicked(QModelIndex))); + connect(selectedLV, SIGNAL(clicked(QModelIndex)), + this, SLOT(selectedLV_clicked(QModelIndex))); + + availableLV->installEventFilter(this); + selectedLV->installEventFilter(this); +} + + +void GuiSelectionManager::update() { -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); + updateAddPB(); + updateDelPB(); + updateDownPB(); + updateUpPB(); } -void GuiSelectionManager::updateView() +void GuiSelectionManager::updateAddPB() { -int const arows = availableLV->model()->rowCount(); -QModelIndexList const availSels = + int const arows = availableModel->rowCount(); + QModelIndexList const availSels = availableLV->selectionModel()->selectedIndexes(); -addPB->setEnabled(arows > 0 && + addPB->setEnabled(arows > 0 && !availSels.isEmpty() && !isSelected(availSels.first())); +} + -int const srows = selectedLV->model()->rowCount(); -QModelIndexList const selSels = +void GuiSelectionManager::updateDelPB() +{ + int const srows = selectedModel->rowCount(); + if (srows == 0) { + deletePB->setEnabled(false); + return; + } + 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); + int const sel_nr = selSels.empty() ? -1 : selSels.first().row(); + deletePB->setEnabled(sel_nr >= 0); +} + + +void GuiSelectionManager::updateUpPB() +{ + int const srows = selectedModel->rowCount(); + if (srows == 0) { + upPB->setEnabled(false); + return; + } + QModelIndexList const selSels = + selectedLV->selectionModel()->selectedIndexes(); + int const sel_nr = selSels.empty() ? -1 : selSels.first().row(); + upPB->setEnabled(sel_nr > 0); +} + + +void GuiSelectionManager::updateDownPB() +{ + int const srows = selectedModel->rowCount(); + if (srows == 0) { + downPB->setEnabled(false); + return; + } + QModelIndexList const selSels = + selectedLV->selectionModel()->selectedIndexes(); + int const sel_nr = selSels.empty() ? -1 : selSels.first().row(); + 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); + if (selectedModel->rowCount() == 0) + return false; + QVariant const & str = availableModel->data(idx, Qt::DisplayRole); + QModelIndexList qmil = + selectedModel->match(selectedModel->index(0), + Qt::DisplayRole, str, 1, + Qt::MatchFlags(Qt::MatchExactly | Qt::MatchWrap)); + return !qmil.empty(); } void GuiSelectionManager::availableChanged(const QModelIndex & idx, const QModelIndex &) { -if (!idx.isValid()) - return; - -selectedHasFocus_ = false; -updateHook(); + if (!idx.isValid()) + return; + + selectedHasFocus_ = false; + updateHook(); } void GuiSelectionManager::selectedChanged(const QModelIndex & idx, const QModelIndex &) { -if (!idx.isValid()) - return; - -selectedHasFocus_ = true; -updateHook(); + if (!idx.isValid()) + return; + + selectedHasFocus_ = true; + updateHook(); } -static QModelIndex getSelectedIndex(QListView * lv) +bool GuiSelectionManager::insertRowToSelected(int i, + QMap const & itemData) { -QModelIndex retval = QModelIndex(); -QModelIndexList selIdx = - lv->selectionModel()->selectedIndexes(); -if (!selIdx.empty()) - retval = selIdx.first(); -return retval; + if (i <= -1 || i > selectedModel->rowCount()) + return false; + if (!selectedModel->insertRow(i)) + return false; + return selectedModel->setItemData(selectedModel->index(i), itemData); } 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(); + QModelIndexList selIdx = + availableLV->selectionModel()->selectedIndexes(); + if (selIdx.isEmpty()) + return; + + QModelIndex const idxToAdd = selIdx.first(); + QModelIndex const idx = selectedLV->currentIndex(); + int const srows = selectedModel->rowCount(); + + QMap qm = availableModel->itemData(idxToAdd); + insertRowToSelected(srows, qm); + + 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(); + QModelIndexList selIdx = + selectedLV->selectionModel()->selectedIndexes(); + if (selIdx.isEmpty()) + return; + QModelIndex idx = selIdx.first(); + selectedModel->removeRow(idx.row()); + 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(); + QModelIndex idx = selectedLV->currentIndex(); + + int const pos = idx.row(); + if (pos <= 0) + return; + + QMap qm = selectedModel->itemData(idx); -int const pos = idx.row(); -QStringList keys = selectedModel->stringList(); -keys.swap(pos, pos - 1); -selectedModel->setStringList(keys); -selectionChanged(); //signal + selectedModel->removeRow(pos); + insertRowToSelected(pos - 1, qm); -selectedLV->setCurrentIndex(idx.sibling(idx.row() - 1, idx.column())); -selectedHasFocus_ = true; -updateHook(); + selectionChanged(); //signal + + selectedLV->setCurrentIndex(idx.sibling(idx.row() - 1, idx.column())); + selectedHasFocus_ = true; + updateHook(); } void GuiSelectionManager::downPB_clicked() { -QModelIndex idx = selectedLV->currentIndex(); + QModelIndex idx = selectedLV->currentIndex(); + + int const pos = idx.row(); + if (pos >= selectedModel->rowCount() - 1) + return; + + QMap qm = selectedModel->itemData(idx); -int const pos = idx.row(); -QStringList keys = selectedModel->stringList(); -keys.swap(pos, pos + 1); -selectedModel->setStringList(keys); -selectionChanged(); //signal + selectedModel->removeRow(pos); + insertRowToSelected(pos + 1, qm); -selectedLV->setCurrentIndex(idx.sibling(idx.row() + 1, idx.column())); -selectedHasFocus_ = true; -updateHook(); + 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) +// 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) +// Or by installing an event listener.. (andre) void GuiSelectionManager::availableLV_clicked(const QModelIndex &) { -selectedHasFocus_ = false; -updateHook(); + 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 + if (isSelected(idx) || !addPB->isEnabled()) + return; + + if (idx.isValid()) + selectedHasFocus_ = false; + addPB_clicked(); + //updateHook() will be emitted there } void GuiSelectionManager::selectedLV_clicked(const QModelIndex &) { -selectedHasFocus_ = true; -updateHook(); + 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(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()) { + if (obj == availableLV) { + if (event->type() != QEvent::KeyPress) + return QObject::eventFilter(obj, event); + QKeyEvent * keyEvent = static_cast(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) { + if (!keyModifiers) addPB_clicked(); - okHook(); //signal + else if (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(event); int const keyPressed = keyEvent->key(); Qt::KeyboardModifiers const keyModifiers = keyEvent->modifiers(); + // Delete or backspace key will delete current item + // ...with control modifier will clear the list if (keyPressed == Qt::Key_Delete || keyPressed == Qt::Key_Backspace) { - if (keyModifiers == Qt::NoModifier && deletePB->isEnabled()) + if (keyModifiers == Qt::NoModifier && deletePB->isEnabled()) { deletePB_clicked(); - else if (keyModifiers == Qt::ControlModifier) { - QStringList list = selectedModel->stringList(); - list.clear(); - selectedModel->setStringList(list); + updateHook(); + } else if (keyModifiers == Qt::ControlModifier) { + selectedModel->removeRows(0, selectedModel->rowCount()); updateHook(); } else - //ignore it otherwise return QObject::eventFilter(obj, event); + } + // Ctrl-Up activates upPB + else if (keyPressed == Qt::Key_Up) { + if (keyModifiers == Qt::ControlModifier) { + if (upPB->isEnabled()) + upPB_clicked(); event->accept(); return true; + } + } + // Ctrl-Down activates downPB + else if (keyPressed == Qt::Key_Down) { + if (keyModifiers == Qt::ControlModifier) { + if (downPB->isEnabled()) + downPB_clicked(); + event->accept(); + return true; + } } } return QObject::eventFilter(obj, event); @@ -286,4 +377,4 @@ if (obj == availableLV) { } // namespace frontend } // namespace lyx -#include "GuiSelectionManager_moc.cpp" +#include "moc_GuiSelectionManager.cpp"