]> git.lyx.org Git - lyx.git/blobdiff - src/frontends/qt4/GuiThesaurus.cpp
* fix spelling in comments to please John.
[lyx.git] / src / frontends / qt4 / GuiThesaurus.cpp
index fd80b5f1f60ce2e9a2876ee1cd0159835b43b62c..6d6269e6f5e34093c865b47d6f87086e9a81cb11 100644 (file)
@@ -4,6 +4,7 @@
  * Licence details can be found in the file COPYING.
  *
  * \author John Levon
+ * \author Jürgen Spitzmüller
  *
  * Full author contact details are available in file CREDITS.
  */
 #include <config.h>
 
 #include "GuiThesaurus.h"
+#include "GuiApplication.h"
 
-#include "ControlThesaurus.h"
 #include "qt_helpers.h"
-#include "debug.h"
 
-#include <QCloseEvent>
+#include "Buffer.h"
+#include "BufferParams.h"
+#include "BufferView.h"
+#include "FuncRequest.h"
+#include "Language.h"
+#include "lyxfind.h"
+
+#include "support/debug.h"
+#include "support/gettext.h"
+#include "support/lstrings.h"
+
+#include <QAbstractItemModel>
 #include <QHeaderView>
 #include <QLineEdit>
 #include <QPushButton>
 #include <QTreeWidget>
 #include <QTreeWidgetItem>
 
-using std::string;
 
+using namespace lyx::support;
+using namespace std;
 
 namespace lyx {
 namespace frontend {
 
-GuiThesaurusDialog::GuiThesaurusDialog(LyXView & lv)
-       : GuiDialog(lv, "thesaurus")
+GuiThesaurus::GuiThesaurus(GuiView & lv)
+       : GuiDialog(lv, "thesaurus", qt_("Thesaurus"))
 {
        setupUi(this);
-       setViewTitle(_("Thesaurus"));
-       setController(new ControlThesaurus(*this));
 
        meaningsTV->setColumnCount(1);
        meaningsTV->header()->hide();
@@ -43,19 +53,31 @@ GuiThesaurusDialog::GuiThesaurusDialog(LyXView & lv)
                this, SLOT(slotClose()));
        connect(replaceED, SIGNAL(returnPressed()),
                this, SLOT(replaceClicked()));
-       connect(replaceED, SIGNAL(textChanged(const QString &)),
-               this, SLOT(change_adaptor() ) );
-       connect(entryED, SIGNAL(returnPressed()),
+       connect(replaceED, SIGNAL(textChanged(QString)),
+               this, SLOT(change_adaptor()));
+       connect(entryCO, SIGNAL(editTextChanged(const QString &)),
+               this, SLOT(entryChanged()));
+       connect(entryCO, SIGNAL(activated(int)),
+               this, SLOT(entryChanged()));
+       connect(lookupPB, SIGNAL(clicked()),
                this, SLOT(entryChanged()));
        connect(replacePB, SIGNAL(clicked()),
                this, SLOT(replaceClicked()));
+       connect(languageCO, SIGNAL(activated(int)),
+               this, SLOT(entryChanged()));
        connect(meaningsTV, SIGNAL(itemClicked(QTreeWidgetItem *, int)),
                this, SLOT(itemClicked(QTreeWidgetItem *, int)));
        connect(meaningsTV, SIGNAL(itemSelectionChanged()),
                this, SLOT(selectionChanged()));
-       connect(meaningsTV, SIGNAL(itemActivated(QTreeWidgetItem *, int)),
+       connect(meaningsTV, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)),
                this, SLOT(selectionClicked(QTreeWidgetItem *, int)));
 
+       // language
+       QAbstractItemModel * language_model = guiApp->languageModel();
+       // FIXME: it would be nice if sorting was enabled/disabled via a checkbox.
+       language_model->sort(0);
+       languageCO->setModel(language_model);
+
        bc().setCancel(closePB);
        bc().setApply(replacePB);
        bc().addReadOnly(replaceED);
@@ -64,73 +86,110 @@ GuiThesaurusDialog::GuiThesaurusDialog(LyXView & lv)
 }
 
 
-ControlThesaurus & GuiThesaurusDialog::controller() const
-{
-       return static_cast<ControlThesaurus &>(GuiDialog::controller());
-}
-
-void GuiThesaurusDialog::change_adaptor()
+void GuiThesaurus::change_adaptor()
 {
        changed();
 }
 
 
-void GuiThesaurusDialog::closeEvent(QCloseEvent * e)
-{
-       slotClose();
-       e->accept();
-}
-
-
-void GuiThesaurusDialog::entryChanged()
+void GuiThesaurus::entryChanged()
 {
        updateLists();
 }
 
 
-void GuiThesaurusDialog::selectionChanged()
+void GuiThesaurus::selectionChanged()
 {
        int const col = meaningsTV->currentColumn();
-       if (col<0 || readOnly())
+       if (col < 0 || isBufferReadonly())
                return;
 
-       replaceED->setText(meaningsTV->currentItem()->text(col));
+       QString item = meaningsTV->currentItem()->text(col);
+       // cut out the classification in brackets:
+       // "hominid (generic term)" -> "hominid"
+       QRegExp re("^([^\\(\\)]+)\\b\\(?.*\\)?.*$");
+       // This is for items with classifications at the beginning:
+       // "(noun) man" -> "man"; "(noun) male (generic term)" -> "male"
+       QRegExp rex("^(\\(.+\\))\\s*([^\\(\\)]+)\\s*\\(?.*\\)?.*$");
+       int pos = re.indexIn(item);
+       if (pos > -1)
+               item = re.cap(1).trimmed();
+       pos = rex.indexIn(item);
+       if (pos > -1)
+               item = rex.cap(2).trimmed();
+       replaceED->setText(item);
        replacePB->setEnabled(true);
        changed();
 }
 
 
-void GuiThesaurusDialog::itemClicked(QTreeWidgetItem * /*item*/, int /*col*/)
+void GuiThesaurus::itemClicked(QTreeWidgetItem * /*item*/, int /*col*/)
 {
        selectionChanged();
 }
 
 
-void GuiThesaurusDialog::selectionClicked(QTreeWidgetItem * item, int col)
+void GuiThesaurus::selectionClicked(QTreeWidgetItem * item, int col)
 {
-       entryED->setText(item->text(col));
+       QString str = item->text(col);
+       // cut out the classification in brackets:
+       // "hominid (generic term)" -> "hominid"
+       QRegExp re("^([^\\(\\)]+)\\b\\(?.*\\)?.*$");
+       // This is for items with classifications at the beginning:
+       // "(noun) man" -> "man"; "(noun) male (generic term)" -> "male"
+       QRegExp rex("^(\\(.+\\))\\s*([^\\(\\)]+)\\s*\\(?.*\\)?.*$");
+       int pos = re.indexIn(str);
+       if (pos > -1)
+               str = re.cap(1).trimmed();
+       pos = rex.indexIn(str);
+       if (pos > -1)
+               str = rex.cap(2).trimmed();
+       entryCO->insertItem(0, str);
+       entryCO->setCurrentIndex(0);
+
        selectionChanged();
        updateLists();
 }
 
 
-void GuiThesaurusDialog::updateLists()
+void GuiThesaurus::updateLists()
 {
        meaningsTV->clear();
        meaningsTV->setUpdatesEnabled(false);
 
-       Thesaurus::Meanings meanings = controller().getMeanings(qstring_to_ucs4(entryED->text()));
+       QString const lang = languageCO->itemData(
+               languageCO->currentIndex()).toString();
+       docstring const lang_code =
+               from_ascii(lyx::languages.getLanguage(fromqstr(lang))->code());
+
+       Thesaurus::Meanings meanings =
+               getMeanings(qstring_to_ucs4(entryCO->currentText()), lang_code);
 
        for (Thesaurus::Meanings::const_iterator cit = meanings.begin();
                cit != meanings.end(); ++cit) {
                QTreeWidgetItem * i = new QTreeWidgetItem(meaningsTV);
                i->setText(0, toqstr(cit->first));
                meaningsTV->expandItem(i);
-               for (std::vector<docstring>::const_iterator cit2 = cit->second.begin();
+               for (vector<docstring>::const_iterator cit2 = cit->second.begin();
                        cit2 != cit->second.end(); ++cit2) {
                                QTreeWidgetItem * i2 = new QTreeWidgetItem(i);
                                i2->setText(0, toqstr(*cit2));
                        }
+               meaningsTV->setEnabled(true);
+               lookupPB->setEnabled(true);
+               replaceED->setEnabled(true);
+               replacePB->setEnabled(true);
+       }
+
+       if (meanings.empty()) {
+               if (!thesaurus.thesaurusAvailable(lang_code)) {
+                       QTreeWidgetItem * i = new QTreeWidgetItem(meaningsTV);
+                       i->setText(0, qt_("No thesaurus available for this language!"));
+                       meaningsTV->setEnabled(false);
+                       lookupPB->setEnabled(false);
+                       replaceED->setEnabled(false);
+                       replacePB->setEnabled(false);
+               }
        }
 
        meaningsTV->setUpdatesEnabled(true);
@@ -138,21 +197,79 @@ void GuiThesaurusDialog::updateLists()
 }
 
 
-void GuiThesaurusDialog::update_contents()
+void GuiThesaurus::updateContents()
 {
-       entryED->setText(toqstr(controller().text()));
+       entryCO->clear();
+       entryCO->addItem(toqstr(text_));
+       entryCO->setCurrentIndex(0);
        replaceED->setText("");
+       int const pos = languageCO->findData(toqstr(lang_));
+       if (pos != -1)
+               languageCO->setCurrentIndex(pos);
        updateLists();
 }
 
 
-void GuiThesaurusDialog::replaceClicked()
+void GuiThesaurus::replaceClicked()
 {
-       controller().replace(qstring_to_ucs4(replaceED->text()));
+       replace(qstring_to_ucs4(replaceED->text()));
 }
 
+
+bool GuiThesaurus::initialiseParams(string const & data)
+{
+       string arg;
+       string const lang = rsplit(data, arg, ' ');
+       if (prefixIs(lang, "lang=")) {
+               lang_ = from_utf8(split(lang, '='));
+               text_ = from_utf8(arg);
+       } else {
+               text_ = from_utf8(data);
+               if (bufferview())
+                       lang_ = from_ascii(
+                               bufferview()->buffer().params().language->lang());
+       }
+       return true;
+}
+
+
+void GuiThesaurus::clearParams()
+{
+       text_.erase();
+       lang_.erase();
+}
+
+
+void GuiThesaurus::replace(docstring const & newstr)
+{
+       /* FIXME: this is not suitable ! We need to have a "lock"
+        * on a particular charpos in a paragraph that is broken on
+        * deletion/change !
+        */
+       docstring const data =
+               replace2string(newstr, text_,
+                                    true,  // case sensitive
+                                    true,  // match word
+                                    false, // all words
+                                    true); // forward
+       dispatch(FuncRequest(LFUN_WORD_REPLACE, data));
+}
+
+
+Thesaurus::Meanings const & GuiThesaurus::getMeanings(docstring const & str,
+       docstring const & lang)
+{
+       if (str != laststr_)
+               meanings_ = thesaurus.lookup(str, lang);
+       return meanings_;
+}
+
+
+Dialog * createGuiThesaurus(GuiView & lv) { return new GuiThesaurus(lv); }
+
+
 } // namespace frontend
 } // namespace lyx
 
 
-#include "GuiThesaurus_moc.cpp"
+#include "moc_GuiThesaurus.cpp"