On Wed, Mar 19, 2008 at 07:54:35PM +0100, Pavel Sanda wrote:
> > > > some 30s here. btw Display all is disabled on utf-8. thats bug or
> > > > intention?
> > > 
> > > Intention (because it's currently unusably slow).
> > 
> > What do I have to do to reproduce this "unusably slow" behaviour?
> 
> set utf-8 document encoding and try insert some symbol.

With the attached patch it should be quite a bit faster. 

I am sure I broke the logic somewhere, so feel free to fix & apply
or leave it ;-)

Juergen, maybe you want to have a look, too?

Andre'
Index: GuiSymbols.h
===================================================================
--- GuiSymbols.h        (revision 23858)
+++ GuiSymbols.h        (working copy)
@@ -15,11 +15,7 @@
 #include "DialogView.h"
 #include "ui_SymbolsUi.h"
 
-#include <map>
-#include <set>
 
-class QListWidgetItem;
-
 namespace lyx {
 namespace frontend {
 
@@ -43,31 +39,20 @@
        void on_applyPB_clicked();
        void on_okPB_clicked();
        void on_closePB_clicked();
-       void on_symbolsLW_itemActivated(QListWidgetItem *);
-       void on_symbolsLW_itemClicked(QListWidgetItem * item);
+       void on_symbolsLW_activated(QModelIndex const & index);
+       void on_symbolsLW_clicked(QModelIndex const & index);
        void on_categoryCO_activated(QString const & text);
-       void on_categoryFilterCB_toggled(bool);
        void on_chosenLE_returnPressed();
        void on_chosenLE_textChanged(QString const &);
 
 private:
-       /** update the widgets (symbol browser, category combo)
-        *  \p combo indicates if the combo box has to be refreshed
-        *  as well (which is rather expensive)
-       **/
-       void updateSymbolList(bool update_combo = true);
-       /// get the unicode block associated with \p c
-       QString getBlock(char_type c) const;
-       /// the encoding at cursor position
-       std::string encoding_;
-       /// which blocks do we actually include?
-       typedef std::map<QString, QListWidgetItem *> UsedBlocks;
-       ///
-       UsedBlocks used_blocks;
-       /// list of all symbols
-       typedef std::set<char_type> SymbolsList;
-       ///
-       SymbolsList symbols_;
+       // update the symbol list
+       void updateSymbolList();
+       // update the category combo
+       void updateComboBox();
+       // the model used in the symbol list view
+       class Model;
+       Model * model_;
 };
 
 } // namespace frontend
Index: ui/SymbolsUi.ui
===================================================================
--- ui/SymbolsUi.ui     (revision 23858)
+++ ui/SymbolsUi.ui     (working copy)
@@ -71,18 +71,8 @@
      </property>
     </spacer>
    </item>
-   <item row="0" column="2" >
-    <widget class="QCheckBox" name="categoryFilterCB" >
-     <property name="toolTip" >
-      <string>Select this to display all available characters at once</string>
-     </property>
-     <property name="text" >
-      <string>&amp;Display all</string>
-     </property>
-    </widget>
-   </item>
    <item row="1" column="0" colspan="3" >
-    <widget class="QListWidget" name="symbolsLW" >
+    <widget class="QListView" name="symbolsLW" >
      <property name="sizePolicy" >
       <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
        <horstretch>0</horstretch>
@@ -116,9 +106,6 @@
      <property name="spacing" >
       <number>0</number>
      </property>
-     <property name="currentRow" >
-      <number>-1</number>
-     </property>
     </widget>
    </item>
    <item row="2" column="0" colspan="3" >
Index: GuiSymbols.cpp
===================================================================
--- GuiSymbols.cpp      (revision 23858)
+++ GuiSymbols.cpp      (working copy)
@@ -22,13 +22,17 @@
 #include "Encoding.h"
 #include "FuncRequest.h"
 
+#include "support/debug.h"
 #include "support/gettext.h"
 
+#include <QAbstractItemModel>
+#include <QModelIndex>
 #include <QChar>
 #include <QPixmap>
-#include <QListWidgetItem>
 #include <QString>
 
+#include <set>
+
 using namespace std;
 
 namespace lyx {
@@ -146,11 +150,117 @@
 const int no_blocks = sizeof(unicode_blocks) / sizeof(UnicodeBlocks);
 
 
+bool isIgnored(char_type c)
+{
+#if QT_VERSION >= 0x040300
+       QChar::Category const cat = QChar::category(uint(c));
+#else
+       QChar const qc = uint(c);
+       QChar::Category const cat = qc.category();
+#endif
+       // we do not want control or space characters
+       return cat == QChar::Other_Control || cat == QChar::Separator_Space;
+}
+
+/// get the unicode block associated with \p c
+QString getBlock(char_type c)
+{
+       int i = 1; // Skip "All Symbols"
+       while (c > unicode_blocks[i].end && i < no_blocks)
+               ++i;
+       if (!unicode_blocks[i].name.isEmpty())
+               return unicode_blocks[i].name;
+       return QString();
+}
+
+
 } // namespace anon
 
 
+/////////////////////////////////////////////////////////////////////
+//
+// GuiSymbols::Model
+//
+///////////////////////////////////////////////////////////////////////
+
+class GuiSymbols::Model : public QAbstractItemModel
+{
+public:
+       Model(GuiSymbols * parent)
+               : QAbstractItemModel(parent), parent_(parent),
+                       range_start_(0), range_end_(0x7f)
+       {}
+
+       QModelIndex index(int row, int column, QModelIndex const &) const
+       {
+               return createIndex(row, column);
+       }
+
+       QModelIndex parent(QModelIndex const &) const
+       {
+               return QModelIndex();
+       }
+
+       int rowCount(QModelIndex const &) const
+       {
+               return range_end_ - range_start_;
+       }
+
+       int columnCount(QModelIndex const &) const
+       {
+               return 1;
+       }
+
+       QVariant data(QModelIndex const & index, int role) const
+       {
+               static QString const strCharacter = qt_("Character: ");
+               static QString const strCodePoint = qt_("Code Point: ");
+
+               static char codeName[10];
+
+               char_type c = range_start_ + index.row(); 
+
+               if (role == Qt::TextAlignmentRole)
+                       return QVariant(Qt::AlignCenter);
+
+               if (role == Qt::DisplayRole)
+                       return isIgnored(c) ? QString::number(c) : toqstr(c);
+
+               if (role == Qt::ToolTipRole) {
+                       if (isIgnored(c))
+                               return QString(); 
+                       sprintf(codeName, "0x%04x", c);
+                       return strCharacter + toqstr(c) + '\n'
+                               + strCodePoint + QLatin1String(codeName);
+               }
+
+               //LYXERR0("role: " << role << " row: " << index.row());
+               return QVariant();
+       }
+
+       void reset(char_type start, char_type end)
+       {
+               range_start_ = start;   
+               range_end_  = end;      
+               QAbstractItemModel::reset();
+       }
+
+private:
+       GuiSymbols * parent_;
+       char_type range_start_;
+       char_type range_end_;
+};
+
+
+
+/////////////////////////////////////////////////////////////////////
+//
+// GuiSymbols
+//
+///////////////////////////////////////////////////////////////////////
+
 GuiSymbols::GuiSymbols(GuiView & lv)
-       : DialogView(lv, "symbols", qt_("Symbols")), encoding_("ascii")
+       : DialogView(lv, "symbols", qt_("Symbols")), model_(new Model(this))
 {
        setupUi(this);
 
@@ -159,30 +269,20 @@
        symbolsLW->setViewMode(QListView::IconMode);
        symbolsLW->setUniformItemSizes(true);
        // increase the display size of the symbols a bit
-       QFont font= symbolsLW->font();
-       int size = font.pointSize() + 3;
-       font.setPointSize(size);
+       QFont font = symbolsLW->font();
+       font.setPointSize(font.pointSize() + 3);
        symbolsLW->setFont(font);
+       symbolsLW->setModel(model_);
+
+       updateComboBox();
+       updateSymbolList();
 }
 
 
 void GuiSymbols::updateView()
 {
        chosenLE->clear();
-
-       string new_encoding = bufferview()->cursor().getEncoding()->name();
-       if (buffer().params().inputenc != "auto" &&
-           buffer().params().inputenc != "default")
-               new_encoding = buffer().params().encoding().name();
-       if (new_encoding == encoding_)
-               // everything up to date
-               return;
-       if (!new_encoding.empty())
-               encoding_ = new_encoding;
-       bool const utf8 = toqstr(encoding_).startsWith("utf8");
-       if (utf8)
-               categoryFilterCB->setChecked(false);
-       categoryFilterCB->setEnabled(!utf8);
+       updateComboBox();
        updateSymbolList();
 }
 
@@ -214,7 +314,7 @@
 }
 
 
-void GuiSymbols::on_symbolsLW_itemActivated(QListWidgetItem *)
+void GuiSymbols::on_symbolsLW_activated(QModelIndex const &)
 {
        on_okPB_clicked();
 }
@@ -234,128 +334,84 @@
 }
 
 
-void GuiSymbols::on_symbolsLW_itemClicked(QListWidgetItem * item)
+void GuiSymbols::on_symbolsLW_clicked(QModelIndex const & index)
 {
-       QString const text = item->text();
+       QString const text = model_->data(index, Qt::DisplayRole).toString();
        if (text.isEmpty())
                return;
        if (chosenLE->isEnabled())
                chosenLE->insert(text);
+/*
        if (categoryFilterCB->isChecked()) {
                QString const category = getBlock(text.data()->unicode());
                categoryCO->setCurrentIndex(categoryCO->findText(category));
        }
+*/
 }
 
 
-void GuiSymbols::on_categoryCO_activated(QString const & text)
+void GuiSymbols::on_categoryCO_activated(QString const &)
 {
-       if (!categoryFilterCB->isChecked())
-               updateSymbolList(false);
-       else if (used_blocks.find(text) != used_blocks.end())
-               symbolsLW->scrollToItem(used_blocks[text],
-                       QAbstractItemView::PositionAtTop);
+       updateSymbolList();
 }
 
 
-void GuiSymbols::on_categoryFilterCB_toggled(bool on)
+void GuiSymbols::updateComboBox()
 {
-       updateSymbolList(on);
-       if (on) {
-               QString const category = categoryCO->currentText();
-               if (used_blocks.find(category) != used_blocks.end())
-                       symbolsLW->scrollToItem(used_blocks[category],
-                               QAbstractItemView::PositionAtTop);
-       }
-}
+       // get encoding at cursor position
+       std::string encoding = bufferview()->cursor().getEncoding()->name();
+       if (buffer().params().inputenc != "auto" &&
+           buffer().params().inputenc != "default")
+               encoding = buffer().params().encoding().name();
+       LYXERR0("ENCODING: " << encoding);
 
+       typedef std::set<char_type> SymbolsList;
+       SymbolsList symbols_ = 
encodings.getFromLyXName(encoding)->getSymbolsList();
+       LYXERR0("SYMBOLS size: " << symbols_.size());
 
-void GuiSymbols::updateSymbolList(bool update_combo)
-{
-       QString category = categoryCO->currentText();
-       bool const nocategory = category.isEmpty();
-       char_type range_start = 0x0000;
-       char_type range_end = 0x110000;
-       symbolsLW->clear();
-       if (update_combo) {
-               used_blocks.clear();
-               categoryCO->clear();
-       }
-       bool const show_all = categoryFilterCB->isChecked();
+       typedef std::set<QString> UsedBlocks;
+       UsedBlocks used_blocks;
+       used_blocks.insert(unicode_blocks[0].name); // ASCII
 
-       if (symbols_.empty() || update_combo)
-               symbols_ = 
encodings.getFromLyXName(encoding_)->getSymbolsList();
-
-       if (!show_all) {
-               for (int i = 0 ; i < no_blocks; ++i)
-                       if (unicode_blocks[i].name == category) {
-                               range_start = unicode_blocks[i].start;
-                               range_end = unicode_blocks[i].end;
-                               break;
-                       }
-       }
-
-       static char codeName[10];
-       static QString const strCharacter = qt_("Character: ");
-       static QString const strCodePoint = qt_("Code Point: ");
-
        SymbolsList::const_iterator const end = symbols_.end();
        for (SymbolsList::const_iterator it = symbols_.begin(); it != end; 
++it) {
                char_type c = *it;
-               if (!update_combo && !show_all && (c <= range_start || c >= 
range_end))
+               if (isIgnored(c))
                        continue;
-#if QT_VERSION >= 0x040300
-               QChar::Category const cat = QChar::category(uint(c));
-#else
-               QChar const qc = uint(c);
-               QChar::Category const cat = qc.category();
-#endif
-               // we do not want control or space characters
-               if (cat == QChar::Other_Control || cat == 
QChar::Separator_Space)
-                       continue;
-               QListWidgetItem * lwi = new QListWidgetItem(toqstr(c));
-               if (show_all || c >= range_start && c <= range_end) {
-                       sprintf(codeName, "0x%04x", c);
-                       lwi->setTextAlignment(Qt::AlignCenter);
-                       lwi->setToolTip(strCharacter + toqstr(c) + '\n'
-                               + strCodePoint + QLatin1String(codeName));
-                       symbolsLW->addItem(lwi);
-               }
-               if (update_combo) {
-                       QString block = getBlock(c);
-                       if (category.isEmpty())
-                               category = block;
-                       if (used_blocks.find(block) == used_blocks.end())
-                               used_blocks[block] = lwi;
-               }
+               QString block = getBlock(c);
+               used_blocks.insert(block);
        }
 
-       if (update_combo) {
-               // update category combo
-               for (UsedBlocks::iterator it = used_blocks.begin();
-                    it != used_blocks.end(); ++it) {
-                       categoryCO->addItem(it->first);
-               }
+       // update category combo box
+       categoryCO->clear();
+       categoryCO->addItem(qt_("All Symbols"));
+       int startIndex = 1;
+       int i = 0;
+       for (UsedBlocks::iterator it = used_blocks.begin();
+                        it != used_blocks.end(); ++it, ++i) {
+               categoryCO->addItem(*it);
+               if (*it == unicode_blocks[0].name)
+                       startIndex = i;
        }
 
-       int old = categoryCO->findText(category);
-       if (old != -1)
-               categoryCO->setCurrentIndex(old);
-       // update again in case the combo has not yet been filled
-       // on first cycle (at dialog initialization)
-       if (nocategory && !category.isEmpty())
-               updateSymbolList();
+       categoryCO->setCurrentIndex(startIndex);
 }
 
 
-QString GuiSymbols::getBlock(char_type c) const
+void GuiSymbols::updateSymbolList()
 {
-       int i = 0;
-       while (c > unicode_blocks[i].end && i < no_blocks)
-               ++i;
-       if (!unicode_blocks[i].name.isEmpty())
-               return unicode_blocks[i].name;
-       return QString();
+       QString category = categoryCO->currentText();
+       int start = 0x0000;
+       int end = 0x110000;
+
+       for (int i = 0; i < no_blocks; ++i) {
+               if (unicode_blocks[i].name == category) {
+                       start = unicode_blocks[i].start;
+                       end = unicode_blocks[i].end;
+                       break;
+               }
+       }
+       model_->reset(start, end);
 }
 
 

Reply via email to