]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiSelectionManager.cpp
Complete the removal of the embedding stuff. Maybe. It's hard to be sure we got every...
[lyx.git] / src / frontends / qt4 / GuiSelectionManager.cpp
index 130d3f85c484a63bdf03f3108020b73f565c8731..b9e356d5665cb847e0ccf01ea84c91ead6204921 100644 (file)
 
 #include <config.h>
 #include "GuiSelectionManager.h"
+#include "GuiDocument.h"
 
+#include "support/debug.h"
+
+using std::vector;
 
 namespace lyx {
 namespace frontend {
 
+
 GuiSelectionManager::GuiSelectionManager(
        QListView * avail, 
        QListView * sel,
@@ -26,175 +31,234 @@ GuiSelectionManager::GuiSelectionManager(
        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(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()
 {
-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, 
+                                            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<int, QVariant> 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();
+       QModelIndex const idxToAdd = getSelectedIndex(availableLV);
+       if (!idxToAdd.isValid())
+               return;
+       QModelIndex const idx = selectedLV->currentIndex();
+       int const srows = selectedModel->rowCount();
+       
+       QMap<int, QVariant> 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();
+       QModelIndex idx = getSelectedIndex(selectedLV);
+       if (!idx.isValid())
+               return;
+       
+       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();
-QStringList keys = selectedModel->stringList();
-keys.swap(pos, pos - 1);
-selectedModel->setStringList(keys);
-selectionChanged(); //signal
+       int const pos = idx.row();
+       if (pos <= 0)
+               return;
+       
+       QMap<int, QVariant> qm = selectedModel->itemData(idx);
 
-selectedLV->setCurrentIndex(idx.sibling(idx.row() - 1, idx.column()));
-selectedHasFocus_ = true;
-updateHook();
+       selectedModel->removeRow(pos);
+       insertRowToSelected(pos - 1, qm);
+
+       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<int, QVariant> 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();
 }
 
 
@@ -204,59 +268,59 @@ updateHook();
 //which means subclassing QListView. (rgh)
 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<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.
+       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))
-                                        )
-                        ) {
+                                       (!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
@@ -269,9 +333,7 @@ if (obj == availableLV) {
                        if (keyModifiers == Qt::NoModifier && deletePB->isEnabled())
                                deletePB_clicked();
                        else if (keyModifiers == Qt::ControlModifier) {
-                               QStringList list = selectedModel->stringList();
-                               list.clear();
-                               selectedModel->setStringList(list);
+                               selectedModel->removeRows(0, selectedModel->rowCount());
                                updateHook();
                        } else
                                //ignore it otherwise