* This file is part of LyX, the document processor.
* Licence details can be found in the file COPYING.
*
- * \author Jürgen Spitzmüller
+ * \author Jürgen Spitzmüller
*
* Full author contact details are available in file CREDITS.
*/
#include "qt_helpers.h"
#include "Buffer.h"
+#include "BufferParams.h"
#include "BufferView.h"
+#include "Cursor.h"
#include "Encoding.h"
+#include "FuncRequest.h"
+#include "support/debug.h"
#include "support/gettext.h"
#include <QChar>
#include <QListWidgetItem>
#include <QString>
+#include <cstdio>
+
using namespace std;
namespace lyx {
{ N_("CJK Compatibility Ideographs Supplement"), 0x2f800, 0x2fa1f },
{ N_("Tags"), 0xe0000, 0xe007f },
{ N_("Variation Selectors Supplement"), 0xe0100, 0xe01ef },
- { N_("Supplementary Private Use Area-A"), 0xf0000, 0xe01ef },
- { N_("Supplementary Private Use Area-B"), 0x100000, 0x10ffff }
+ { N_("Supplementary Private Use Area-A"), 0xf0000, 0xffffd },
+ { N_("Supplementary Private Use Area-B"), 0x100000, 0x10fffd }
};
const int no_blocks = sizeof(unicode_blocks) / sizeof(UnicodeBlocks);
+
+QString getBlock(char_type c)
+{
+ // store an educated guess for the next search
+ static int lastBlock = 0;
+
+ // "clever reset"
+ if (c < 0x7f)
+ lastBlock = 0;
+
+ // off the end already
+ if (lastBlock == no_blocks)
+ return QString();
+
+ // c falls into a covered area, and we can guess which
+ if (c >= unicode_blocks[lastBlock].start
+ && c <= unicode_blocks[lastBlock].end)
+ return qt_(unicode_blocks[lastBlock].name);
+
+ // c falls into an uncovered area, but we can guess which
+ if (c > unicode_blocks[lastBlock].end
+ && c < unicode_blocks[lastBlock + 1].start)
+ return QString();
+
+ // guessing was wrong so far. do a real search.
+ int i = 0;
+ while (c > unicode_blocks[i].end && i < no_blocks)
+ ++i;
+ if (i == no_blocks)
+ return QString();
+ lastBlock = i;
+ //LYXERR0("fail: " << int(c) << ' ' << lastBlock);
+ return qt_(unicode_blocks[lastBlock].name);
+}
+
+
} // namespace anon
+/////////////////////////////////////////////////////////////////////
+//
+// GuiSymbols::Model
+//
+/////////////////////////////////////////////////////////////////////
+
+class GuiSymbols::Model : public QAbstractItemModel
+{
+public:
+ Model(GuiSymbols * parent)
+ : QAbstractItemModel(parent), parent_(parent)
+ {}
+
+ 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 symbols_.count();
+ }
+
+ 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 = symbols_.at(index.row());
+
+ if (role == Qt::TextAlignmentRole)
+ return QVariant(Qt::AlignCenter);
+
+ if (role == Qt::DisplayRole)
+ return toqstr(c);
+
+ if (role == Qt::ToolTipRole) {
+ sprintf(codeName, "0x%04x", c);
+ return strCharacter + toqstr(c) + '\n'
+ + strCodePoint + QLatin1String(codeName);
+ }
+
+ //LYXERR0("role: " << role << " row: " << index.row());
+ return QVariant();
+ }
+
+ void setSymbols(QList<char_type> const & symbols)
+ {
+ symbols_ = symbols;
+ QAbstractItemModel::reset();
+ }
+
+private:
+ friend class GuiSymbols;
+ GuiSymbols * parent_;
+
+ QList<char_type> symbols_;
+};
+
+
+/////////////////////////////////////////////////////////////////////
+//
+// GuiSymbols
+//
+/////////////////////////////////////////////////////////////////////
+
GuiSymbols::GuiSymbols(GuiView & lv)
- : DialogView(lv, "symbols", qt_("Symbols")), encoding_("ascii")
+ : DialogView(lv, "symbols", qt_("Symbols")), encoding_("ascii"),
+ model_(new Model(this))
{
setupUi(this);
int size = font.pointSize() + 3;
font.setPointSize(size);
symbolsLW->setFont(font);
+ symbolsLW->setModel(model_);
}
{
chosenLE->clear();
- string const & new_encoding = bufferview()->cursor().getEncoding()->name();
+ 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);
updateSymbolList();
}
}
-void GuiSymbols::on_symbolsLW_itemActivated(QListWidgetItem *)
+void GuiSymbols::on_symbolsLW_activated(QModelIndex const &)
{
on_okPB_clicked();
}
}
-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);
- QString const category = getBlock(text.data()->unicode());
- categoryCO->setCurrentIndex(categoryCO->findText(category));
+ if (categoryFilterCB->isChecked()) {
+ QString const category = getBlock(text.data()->unicode());
+ categoryCO->setCurrentIndex(categoryCO->findText(category));
+ }
}
void GuiSymbols::on_categoryCO_activated(QString const & text)
{
if (!categoryFilterCB->isChecked())
- updateSymbolList();
- if (used_blocks.find(text) != used_blocks.end())
- symbolsLW->scrollToItem(used_blocks[text],
- QAbstractItemView::PositionAtTop);
+ updateSymbolList(false);
+ else
+ scrollToItem(text);
}
void GuiSymbols::on_categoryFilterCB_toggled(bool on)
{
- updateSymbolList();
- if (on) {
- QString const category = categoryCO->currentText();
- if (used_blocks.find(category) != used_blocks.end())
- symbolsLW->scrollToItem(used_blocks[category],
- QAbstractItemView::PositionAtTop);
- }
+ updateSymbolList(on);
+ if (on)
+ scrollToItem(categoryCO->currentText());
}
-void GuiSymbols::updateSymbolList()
+void GuiSymbols::scrollToItem(QString const & category)
+{
+ if (used_blocks.find(category) == used_blocks.end())
+ return;
+ int row = used_blocks[category];
+ QModelIndex index = symbolsLW->model()->index(row, 0, QModelIndex());
+ symbolsLW->scrollTo(index, QAbstractItemView::PositionAtTop);
+}
+
+
+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();
- used_blocks.clear();
- categoryCO->clear();
+ QList<char_type> s;
+ if (update_combo) {
+ used_blocks.clear();
+ categoryCO->clear();
+ }
bool const show_all = categoryFilterCB->isChecked();
- typedef set<char_type> SymbolsList;
- Encoding enc = *(encodings.getFromLyXName(encoding_));
- SymbolsList symbols = enc.getSymbolsList();
+ if (symbols_.empty() || update_combo)
+ symbols_ = encodings.fromLyXName(encoding_)->symbolsList();
if (!show_all) {
for (int i = 0 ; i < no_blocks; ++i)
- if (unicode_blocks[i].name == fromqstr(category)) {
+ if (qt_(unicode_blocks[i].name) == category) {
range_start = unicode_blocks[i].start;
range_end = unicode_blocks[i].end;
break;
}
}
- SymbolsList::const_iterator const end = symbols.end();
- for (SymbolsList::const_iterator it = symbols.begin(); it != end; ++it) {
+ SymbolsList::const_iterator const end = symbols_.end();
+ int numItem = 0;
+ 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))
+ 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();
+ QChar::Category const cat = QChar(uint(c)).category();
#endif
// we do not want control or space characters
if (cat == QChar::Other_Control || cat == QChar::Separator_Space)
continue;
- QListWidgetItem * lwi = new QListWidgetItem(
- QString::fromUcs4((uint const *) &c, 1));
- if (show_all || c >= range_start && c <= range_end) {
- lwi->setTextAlignment(Qt::AlignCenter);
- symbolsLW->addItem(lwi);
+ ++numItem;
+ if (show_all || (c >= range_start && c <= range_end))
+ s.append(c);
+ if (update_combo) {
+ QString block = getBlock(c);
+ if (category.isEmpty())
+ category = block;
+ if (used_blocks.find(block) == used_blocks.end())
+ used_blocks[block] = numItem;
}
- QString block = getBlock(c);
- if (category.isEmpty())
- category = block;
- if (used_blocks.find(block) == used_blocks.end())
- used_blocks[block] = lwi;
}
+ model_->setSymbols(s);
- // update category combo
- for (UsedBlocks::iterator it = used_blocks.begin(); it != used_blocks.end(); ++it) {
- categoryCO->addItem(it->first);
+ if (update_combo) {
+ // update category combo
+ for (UsedBlocks::iterator it = used_blocks.begin();
+ it != used_blocks.end(); ++it) {
+ categoryCO->addItem(it->first);
+ }
}
+
int old = categoryCO->findText(category);
if (old != -1)
categoryCO->setCurrentIndex(old);
}
-QString const GuiSymbols::getBlock(char_type c) const
-{
- int i = 0;
- while (c > unicode_blocks[i].end && i < no_blocks)
- ++i;
- if (unicode_blocks[i].name)
- return toqstr(unicode_blocks[i].name);
- return QString();
-}
-
-
void GuiSymbols::dispatchParams()
{
dispatch(FuncRequest(getLfun(), fromqstr(chosenLE->text())));
} // namespace frontend
} // namespace lyx
-#include "GuiSymbols_moc.cpp"
+#include "moc_GuiSymbols.cpp"