From 50238d55778df9d7647493170bdcad643adf593a Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Fri, 28 Jan 2011 12:28:27 +0100 Subject: [PATCH] restable: highlight match terms --- src/qtgui/restable.cpp | 71 +++++++++++++++++++++++++++++++++++------ src/qtgui/restable.h | 10 ++++-- src/query/plaintorich.h | 6 ++++ src/rcldb/rclquery.cpp | 1 - website/download.html | 2 +- 5 files changed, 75 insertions(+), 15 deletions(-) diff --git a/src/qtgui/restable.cpp b/src/qtgui/restable.cpp index 722500cb..90f32bf9 100644 --- a/src/qtgui/restable.cpp +++ b/src/qtgui/restable.cpp @@ -15,6 +15,9 @@ static char rcsid[] = "@(#$Id: reslist.cpp,v 1.52 2008-12-17 15:12:08 dockes Exp #include #include #include +#include +#include +#include #include "refcntr.h" #include "docseq.h" @@ -27,7 +30,8 @@ static char rcsid[] = "@(#$Id: reslist.cpp,v 1.52 2008-12-17 15:12:08 dockes Exp #include "plaintorich.h" ////////////////////////////////// -// Restable "pager". We use it to display a single doc details in the detail area +// Restable "pager". We use it to display a single doc details in the +// detail area /// class ResTablePager : public ResListPager { public: @@ -42,6 +46,21 @@ private: ResTable *m_parent; }; +////////////////////////// +// Restable hiliter: to highlight search term in the table. This is actually +// the same as reslist's, could be shared. +class PlainToRichQtReslist : public PlainToRich { +public: + virtual ~PlainToRichQtReslist() {} + virtual string startMatch() { + return string(""); + } + virtual string endMatch() {return string("");} +}; +static PlainToRichQtReslist g_hiliter; +///////////////////////////////////// + bool ResTablePager::append(const string& data, int docnum, const Rcl::Doc&) { m_parent->textBrowser->moveCursor(QTextCursor::End, @@ -177,6 +196,8 @@ RecollModel::RecollModel(const QStringList fields, QObject *parent) m_fields.push_back((const char *)(it->toUtf8())); m_getters.push_back(chooseGetter(m_fields[m_fields.size()-1])); } + + g_hiliter.set_inputhtml(false); } int RecollModel::rowCount(const QModelIndex&) const @@ -203,10 +224,13 @@ void RecollModel::readDocSource() void RecollModel::setDocSource(RefCntr nsource) { LOGDEB(("RecollModel::setDocSource\n")); - if (nsource.isNull()) + if (nsource.isNull()) { m_source = RefCntr(); - else + } else { m_source = RefCntr(new DocSource(nsource)); + m_hdata.reset(); + m_source->getTerms(m_hdata.terms, m_hdata.groups, m_hdata.gslks); + } readDocSource(); } @@ -273,11 +297,11 @@ QVariant RecollModel::data(const QModelIndex& index, int role) const return QVariant(); } - // Have to handle the special cases here. Some fields are - // synthetic and their name is hard-coded. Only date and datetime - // for now. string colname = m_fields[index.column()]; - return QString::fromUtf8(m_getters[index.column()](colname, doc).c_str()); + + list lr; + g_hiliter.plaintorich(m_getters[index.column()](colname, doc), lr, m_hdata); + return QString::fromUtf8(lr.front().c_str()); } // This gets called when the column headers are clicked @@ -300,6 +324,34 @@ void RecollModel::sort(int column, Qt::SortOrder order) /////////////////////////// // ResTable panel methods + +// We use a custom delegate to display the cells because the base +// tableview's can't handle rich text to highlight the match terms +class ResTableDelegate: public QStyledItemDelegate { +public: + ResTableDelegate(QObject *parent) : QStyledItemDelegate(parent) {} + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const + { + QVariant value = index.data(Qt::DisplayRole); + if (value.isValid() && !value.isNull()) { + // We might possibly want to optimize by passing the data + // to the base method if the text does not contain any + // term matches. Would need a modif to plaintorich to + // return the match count (easy), and a way to pass an + // indicator from data(), a bit more difficult. Anyway, + // the display seems fast enough as is. + QTextDocument document; + document.setHtml(value.toString()); + painter->save(); + painter->setClipRect(option.rect); + painter->translate(option.rect.topLeft()); + document.drawContents(painter); + painter->restore(); + } + } +}; + void ResTable::init() { if (!(m_model = new RecollModel(prefs.restableFields))) @@ -308,6 +360,7 @@ void ResTable::init() tableView->setMouseTracking(true); tableView->setSelectionBehavior(QAbstractItemView::SelectRows); tableView->setSelectionMode(QAbstractItemView::SingleSelection); + tableView->setItemDelegate(new ResTableDelegate(this)); QHeaderView *header = tableView->horizontalHeader(); if (header) { @@ -407,13 +460,11 @@ void ResTable::onTableView_currentChanged(const QModelIndex& index) if (!m_model || m_model->getDocSource().isNull()) return; - HiliteData hdata; - m_model->getDocSource()->getTerms(hdata.terms, hdata.groups, hdata.gslks); Rcl::Doc doc; if (m_model->getDocSource()->getDoc(index.row(), doc)) { textBrowser->clear(); m_detaildocnum = index.row(); - m_pager->displayDoc(index.row(), doc, hdata); + m_pager->displayDoc(index.row(), doc, m_model->m_hdata); } } diff --git a/src/qtgui/restable.h b/src/qtgui/restable.h index b628e92b..47d4cab4 100644 --- a/src/qtgui/restable.h +++ b/src/qtgui/restable.h @@ -23,6 +23,7 @@ #include "ui_restable.h" #include "refcntr.h" #include "docseq.h" +#include "plaintorich.h" class ResTable; @@ -62,6 +63,8 @@ public: // Ignore sort() call because virtual void setIgnoreSort(bool onoff) {m_ignoreSort = onoff;} + friend class ResTable; + signals: void sortColumnChanged(DocSeqSortSpec); @@ -72,6 +75,7 @@ private: static map o_displayableFields; bool m_ignoreSort; FieldGetter* chooseGetter(const string&); + HiliteData m_hdata; }; class ResTablePager; @@ -114,10 +118,10 @@ signals: friend class ResTablePager; private: void init(); - RecollModel *m_model; - ResTablePager *m_pager; + RecollModel *m_model; + ResTablePager *m_pager; int m_detaildocnum; - int m_popcolumn; + int m_popcolumn; }; diff --git a/src/query/plaintorich.h b/src/query/plaintorich.h index 9354dd1a..040a5c29 100644 --- a/src/query/plaintorich.h +++ b/src/query/plaintorich.h @@ -33,6 +33,12 @@ struct HiliteData { // Group slacks (number of permitted non-matched words). // Parallel vector to the above 'groups' vector gslks; + void reset() + { + terms.clear(); + groups.clear(); + gslks.clear(); + } }; /** diff --git a/src/rcldb/rclquery.cpp b/src/rcldb/rclquery.cpp index 7eac293e..a4440ab4 100644 --- a/src/rcldb/rclquery.cpp +++ b/src/rcldb/rclquery.cpp @@ -362,7 +362,6 @@ bool Query::getDoc(int xapi, Doc &doc) doc.pc = pc; char buf[200]; if (collapsecount>0) { - LOGDEB(("COLLAPSECOUNET %d\n", collapsecount)); sprintf(buf,"%3d%% (%d)", pc, collapsecount+1); } else { sprintf(buf,"%3d%%", pc); diff --git a/website/download.html b/website/download.html index 4aedec92..3f832b67 100644 --- a/website/download.html +++ b/website/download.html @@ -205,7 +205,7 @@ manager to install or update Recoll and Xapian. To avoid messages about signature errors, if not done at the previous step, you may have to explicitely import the - Recoll and Xapian public keys (as root):

+       Recoll and Xapian public keys: 

 gpg --keyserver keyserver.ubuntu.com --recv 9DA85604
 gpg --export --armor 9DA85604 | sudo apt-key add -
 gpg --keyserver keyserver.ubuntu.com --recv A0735AD0