]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiRef.cpp
On Linux show in crash message box the backtrace
[lyx.git] / src / frontends / qt4 / GuiRef.cpp
index d98a507b371d61ece7744b14900f688276016624..141c67bc13733ac413da9d2c4c0e39eb0f0f94a6 100644 (file)
 
 #include <QLineEdit>
 #include <QCheckBox>
-#include <QListWidget>
-#include <QListWidgetItem>
+#include <QTreeWidget>
+#include <QTreeWidgetItem>
 #include <QPushButton>
 #include <QToolTip>
 #include <QCloseEvent>
+#include <QHeaderView>
 
 using namespace std;
 using namespace lyx::support;
@@ -47,13 +48,8 @@ GuiRef::GuiRef(GuiView & lv)
 
        at_ref_ = false;
 
-       // Enabling is set in updateRefs. Disable for now in case no
-       // call to updateContents follows (e.g. read-only documents).
-       sortCB->setEnabled(false);
-       caseSensitiveCB->setEnabled(false);
-       caseSensitiveCB->setChecked(false);
-       refsLW->setEnabled(false);
-       gotoPB->setEnabled(false);
+       refsTW->setColumnCount(1);
+       refsTW->header()->setVisible(false);
 
        connect(okPB, SIGNAL(clicked()), this, SLOT(slotOK()));
        connect(applyPB, SIGNAL(clicked()), this, SLOT(slotApply()));
@@ -65,18 +61,24 @@ GuiRef::GuiRef(GuiView & lv)
                this, SLOT(changed_adaptor()));
        connect(referenceED, SIGNAL(textChanged(QString)),
                this, SLOT(changed_adaptor()));
+       connect(findLE, SIGNAL(textEdited(QString)), 
+               this, SLOT(filterLabels()));
+       connect(csFindCB, SIGNAL(clicked()), 
+               this, SLOT(filterLabels()));
        connect(nameED, SIGNAL(textChanged(QString)),
                this, SLOT(changed_adaptor()));
-       connect(refsLW, SIGNAL(itemClicked(QListWidgetItem *)),
-               this, SLOT(refHighlighted(QListWidgetItem *)));
-       connect(refsLW, SIGNAL(itemSelectionChanged()),
+       connect(refsTW, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
+               this, SLOT(refHighlighted(QTreeWidgetItem *)));
+       connect(refsTW, SIGNAL(itemSelectionChanged()),
                this, SLOT(selectionChanged()));
-       connect(refsLW, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
-               this, SLOT(refSelected(QListWidgetItem *)));
+       connect(refsTW, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
+               this, SLOT(refSelected(QTreeWidgetItem *)));
        connect(sortCB, SIGNAL(clicked()),
                this, SLOT(sortToggled()));
        connect(caseSensitiveCB, SIGNAL(clicked()),
                this, SLOT(caseSensitiveToggled()));
+       connect(groupCB, SIGNAL(clicked()),
+               this, SLOT(groupToggled()));
        connect(gotoPB, SIGNAL(clicked()),
                this, SLOT(gotoClicked()));
        connect(updatePB, SIGNAL(clicked()),
@@ -88,19 +90,22 @@ GuiRef::GuiRef(GuiView & lv)
        bc().setOK(okPB);
        bc().setApply(applyPB);
        bc().setCancel(closePB);
-       bc().addReadOnly(refsLW);
-       bc().addReadOnly(sortCB);
-       bc().addReadOnly(caseSensitiveCB);
-       bc().addReadOnly(nameED);
-       bc().addReadOnly(referenceED);
        bc().addReadOnly(typeCO);
-       bc().addReadOnly(bufferCO);
 
        restored_buffer_ = -1;
        active_buffer_ = -1;
 }
 
 
+void GuiRef::enableView(bool enable)
+{
+       if (!enable)
+               // In the opposite case, updateContents() will be called anyway.
+               updateContents();
+       GuiDialog::enableView(enable);
+}
+
+
 void GuiRef::changed_adaptor()
 {
        changed();
@@ -118,50 +123,57 @@ void GuiRef::selectionChanged()
        if (isBufferReadonly())
                return;
 
-       QList<QListWidgetItem *> selections = refsLW->selectedItems();
+       QList<QTreeWidgetItem *> selections = refsTW->selectedItems();
        if (selections.isEmpty())
                return;
-       QListWidgetItem * sel = selections.first();
+       QTreeWidgetItem * sel = selections.first();
        refHighlighted(sel);
        return;
 }
 
 
-void GuiRef::refHighlighted(QListWidgetItem * sel)
+void GuiRef::refHighlighted(QTreeWidgetItem * sel)
 {
-       if (isBufferReadonly())
+       if (sel->childCount() > 0) {
+               sel->setExpanded(true);
                return;
+       }
 
-/*     int const cur_item = refsLW->currentRow();
+/*     int const cur_item = refsTW->currentRow();
        bool const cur_item_selected = cur_item >= 0 ?
                refsLB->isSelected(cur_item) : false;*/
-       bool const cur_item_selected = refsLW->isItemSelected(sel);
+       bool const cur_item_selected = refsTW->isItemSelected(sel);
 
        if (cur_item_selected)
-               referenceED->setText(sel->text());
+               referenceED->setText(sel->text(0));
 
        if (at_ref_)
                gotoRef();
        gotoPB->setEnabled(true);
-       if (typeAllowed())
+       if (typeAllowed() && !isBufferReadonly())
                typeCO->setEnabled(true);
-       if (nameAllowed())
-               nameED->setEnabled(true);
+       nameED->setHidden(!nameAllowed());
+       nameL->setHidden(!nameAllowed());
 }
 
 
-void GuiRef::refSelected(QListWidgetItem * sel)
+void GuiRef::refSelected(QTreeWidgetItem * sel)
 {
        if (isBufferReadonly())
                return;
 
-/*     int const cur_item = refsLW->currentRow();
+       if (sel->childCount()) {
+               sel->setExpanded(false);
+               return;
+       }
+
+/*     int const cur_item = refsTW->currentRow();
        bool const cur_item_selected = cur_item >= 0 ?
                refsLB->isSelected(cur_item) : false;*/
-       bool const cur_item_selected = refsLW->isItemSelected(sel);
+       bool const cur_item_selected = refsTW->isItemSelected(sel);
 
        if (cur_item_selected)
-               referenceED->setText(sel->text());
+               referenceED->setText(sel->text(0));
        // <enter> or double click, inserts ref and closes dialog
        slotOK();
 }
@@ -180,6 +192,12 @@ void GuiRef::caseSensitiveToggled()
 }
 
 
+void GuiRef::groupToggled()
+{
+       redoRefs();
+}
+
+
 void GuiRef::updateClicked()
 {
        updateRefs();
@@ -214,10 +232,13 @@ void GuiRef::updateContents()
 {
        int orig_type = typeCO->currentIndex();
 
-       referenceED->setText(toqstr(params_["reference"]));
+       referenceED->clear();
+       nameED->clear();
 
+       referenceED->setText(toqstr(params_["reference"]));
        nameED->setText(toqstr(params_["name"]));
-       nameED->setReadOnly(!nameAllowed() && !isBufferReadonly());
+       nameED->setHidden(!nameAllowed());
+       nameL->setHidden(!nameAllowed());
 
        // restore type settings for new insets
        if (params_["reference"].empty())
@@ -233,7 +254,7 @@ void GuiRef::updateContents()
        FileNameList const & buffers = theBufferList().fileNames();
        for (FileNameList::const_iterator it = buffers.begin();
             it != buffers.end(); ++it) {
-               bufferCO->addItem(toqstr(makeDisplayPath(it->absFilename())));
+               bufferCO->addItem(toqstr(makeDisplayPath(it->absFileName())));
        }
 
        int const thebuffer = theBufferList().bufferNum(buffer().fileName());
@@ -321,20 +342,42 @@ void GuiRef::redoRefs()
 {
        // Prevent these widgets from emitting any signals whilst
        // we modify their state.
-       refsLW->blockSignals(true);
+       refsTW->blockSignals(true);
        referenceED->blockSignals(true);
-       refsLW->setUpdatesEnabled(false);
+       refsTW->setUpdatesEnabled(false);
 
-       refsLW->clear();
+       refsTW->clear();
 
        // need this because Qt will send a highlight() here for
        // the first item inserted
        QString const oldSelection(referenceED->text());
 
        QStringList refsStrings;
+       QStringList refsCategories;
        vector<docstring>::const_iterator iter;
-       for (iter = refs_.begin(); iter != refs_.end(); ++iter)
-               refsStrings.append(toqstr(*iter));
+       bool noprefix = false;
+       for (iter = refs_.begin(); iter != refs_.end(); ++iter) {
+               QString const lab = toqstr(*iter);
+               refsStrings.append(lab);
+               if (groupCB->isChecked()) {
+                       if (lab.contains(":")) {
+                               QString const pref = lab.split(':')[0];
+                               if (!refsCategories.contains(pref)) {
+                                       if (!pref.isEmpty())
+                                               refsCategories.append(pref);
+                                       else
+                                               noprefix = true;
+                               }
+                       }
+                       else
+                               noprefix = true;
+               }
+       }
+       // sort categories case-intensively
+       qSort(refsCategories.begin(), refsCategories.end(),
+             caseInsensitiveLessThan /*defined above*/);
+       if (noprefix)
+               refsCategories.insert(0, qt_("<No prefix>"));
 
        if (sortCB->isEnabled() && sortCB->isChecked()) {
                if(caseSensitiveCB->isEnabled() && caseSensitiveCB->isChecked())
@@ -343,8 +386,36 @@ void GuiRef::redoRefs()
                        qSort(refsStrings.begin(), refsStrings.end(),
                              caseInsensitiveLessThan /*defined above*/);
        }
-
-       refsLW->addItems(refsStrings);
+       
+       if (groupCB->isChecked()) {
+               QList<QTreeWidgetItem *> refsCats;
+               for (int i = 0; i < refsCategories.size(); ++i) {
+                       QString const cat = refsCategories.at(i);
+                       QTreeWidgetItem * item = new QTreeWidgetItem(refsTW);
+                       item->setText(0, cat);
+                       for (int i = 0; i < refsStrings.size(); ++i) {
+                               QString const ref = refsStrings.at(i);
+                               if ((ref.startsWith(cat + QString(":")))
+                                   || (cat == qt_("<No prefix>")
+                                      && (!ref.mid(1).contains(":") || ref.left(1).contains(":")))) {
+                                               QTreeWidgetItem * child =
+                                                       new QTreeWidgetItem(item);
+                                               child->setText(0, ref);
+                                               item->addChild(child);
+                               }
+                       }
+                       refsCats.append(item);
+               }
+               refsTW->addTopLevelItems(refsCats);
+       } else {
+               QList<QTreeWidgetItem *> refsItems;
+               for (int i = 0; i < refsStrings.size(); ++i) {
+                       QTreeWidgetItem * item = new QTreeWidgetItem(refsTW);
+                       item->setText(0, refsStrings.at(i));
+                       refsItems.append(item);
+               }
+               refsTW->addTopLevelItems(refsItems);
+       }
 
        referenceED->setText(oldSelection);
 
@@ -354,23 +425,27 @@ void GuiRef::redoRefs()
                bool const newInset = oldSelection.isEmpty();
                QString textToFind = newInset ? last_reference_ : oldSelection;
                last_reference_.clear();
-               for (int i = 0; i != refsLW->count(); ++i) {
-                       QListWidgetItem * item = refsLW->item(i);
-                       if (textToFind == item->text()) {
-                               refsLW->setCurrentItem(item);
-                               refsLW->setItemSelected(item, !newInset);
+               QTreeWidgetItemIterator it(refsTW);
+               while (*it) {
+                       if ((*it)->text(0) == textToFind) {
+                               refsTW->setCurrentItem(*it);
+                               refsTW->setItemSelected(*it, !newInset);
                                //Make sure selected item is visible
-                               refsLW->scrollToItem(item);
+                               refsTW->scrollToItem(*it);
                                last_reference_ = textToFind;
                                break;
                        }
+                       ++it;
                }
        }
-       refsLW->setUpdatesEnabled(true);
-       refsLW->update();
+       refsTW->setUpdatesEnabled(true);
+       refsTW->update();
+
+       // redo filter
+       filterLabels();
 
        // Re-activate the emission of signals by these widgets.
-       refsLW->blockSignals(false);
+       refsTW->blockSignals(false);
        referenceED->blockSignals(false);
 }
 
@@ -383,12 +458,13 @@ void GuiRef::updateRefs()
                FileName const & name = theBufferList().fileNames()[the_buffer];
                Buffer const * buf = theBufferList().getBuffer(name);
                buf->getLabelList(refs_);
-       }       
+       }
        sortCB->setEnabled(!refs_.empty());
        caseSensitiveCB->setEnabled(sortCB->isEnabled() && sortCB->isChecked());
-       refsLW->setEnabled(!refs_.empty());
-       // refsLW should only be the focus proxy when it is enabled
-       setFocusProxy(refs_.empty() ? 0 : refsLW);
+       refsTW->setEnabled(!refs_.empty());
+       groupCB->setEnabled(!refs_.empty());
+       // refsTW should only be the focus proxy when it is enabled
+       setFocusProxy(refs_.empty() ? 0 : refsTW);
        gotoPB->setEnabled(!refs_.empty());
        redoRefs();
 }
@@ -413,16 +489,31 @@ void GuiRef::gotoBookmark()
 }
 
 
+void GuiRef::filterLabels()
+{
+       Qt::CaseSensitivity cs = csFindCB->isChecked() ?
+               Qt::CaseSensitive : Qt::CaseInsensitive;
+       QTreeWidgetItemIterator it(refsTW);
+       while (*it) {
+               (*it)->setHidden(
+                       (*it)->childCount() == 0
+                       && !(*it)->text(0).contains(findLE->text(), cs)
+               );
+               ++it;
+       }
+}
+
+
 bool GuiRef::initialiseParams(std::string const & data)
 {
-       InsetCommand::string2params("ref", data, params_);
+       InsetCommand::string2params(data, params_);
        return true;
 }
 
 
 void GuiRef::dispatchParams()
 {
-       std::string const lfun = InsetCommand::params2string("ref", params_);
+       std::string const lfun = InsetCommand::params2string(params_);
        dispatch(FuncRequest(getLfun(), lfun));
 }