From 5d29d7504e81baa2f6c01560a75adf7c19d29838 Mon Sep 17 00:00:00 2001 From: dockes Date: Sun, 28 Sep 2008 14:20:50 +0000 Subject: [PATCH] 1st impl of catg filtering in reslist --- src/qtgui/guiutils.cpp | 4 +-- src/qtgui/guiutils.h | 4 +-- src/qtgui/rclmain.ui | 49 +++++++++++++++++++++++++++++-- src/qtgui/rclmain_w.cpp | 64 ++++++++++++++++++++++++++++++++++------- src/qtgui/rclmain_w.h | 2 ++ src/qtgui/reslist.cpp | 48 +++++++++++++++++-------------- src/qtgui/reslist.h | 18 ++++++------ src/qtgui/sort_w.cpp | 10 +++---- src/query/filtseq.h | 4 ++- src/query/sortseq.cpp | 20 ++++++------- src/query/sortseq.h | 10 ++++--- src/sampleconf/mimeconf | 3 +- 12 files changed, 169 insertions(+), 67 deletions(-) diff --git a/src/qtgui/guiutils.cpp b/src/qtgui/guiutils.cpp index 9856a0a6..01b3800b 100644 --- a/src/qtgui/guiutils.cpp +++ b/src/qtgui/guiutils.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: guiutils.cpp,v 1.37 2008-07-01 08:26:08 dockes Exp $ (C) 2005 Jean-Francois Dockes"; +static char rcsid[] = "@(#$Id: guiutils.cpp,v 1.38 2008-09-28 14:20:50 dockes Exp $ (C) 2005 Jean-Francois Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -207,7 +207,7 @@ void rwSettings(bool writing) SETTING_RW(prefs.syntAbsCtx, "/Recoll/prefs/query/syntAbsCtx", Num, 4); - SETTING_RW(prefs.sortWidth, "/Recoll/prefs/query/sortWidth", + SETTING_RW(prefs.sortDepth, "/Recoll/prefs/query/sortDepth", Num, 100); SETTING_RW(prefs.sortSpec, "/Recoll/prefs/query/sortSpec", Num, 0); diff --git a/src/qtgui/guiutils.h b/src/qtgui/guiutils.h index 908962cf..618bc982 100644 --- a/src/qtgui/guiutils.h +++ b/src/qtgui/guiutils.h @@ -17,7 +17,7 @@ #ifndef _GUIUTILS_H_INCLUDED_ #define _GUIUTILS_H_INCLUDED_ /* - * @(#$Id: guiutils.h,v 1.27 2008-07-01 08:26:08 dockes Exp $ (C) 2005 Jean-Francois Dockes + * @(#$Id: guiutils.h,v 1.28 2008-09-28 14:20:50 dockes Exp $ (C) 2005 Jean-Francois Dockes * jean-francois.dockes@wanadoo.fr * * This program is free software; you can redistribute it and/or modify @@ -101,7 +101,7 @@ class PrefsPack { int syntAbsCtx; // Sort specs (sort_w.cpp knows how to deal with the values - int sortWidth; + int sortDepth; int sortSpec; // Remembered term match mode diff --git a/src/qtgui/rclmain.ui b/src/qtgui/rclmain.ui index 92e47b6d..9a734c7f 100644 --- a/src/qtgui/rclmain.ui +++ b/src/qtgui/rclmain.ui @@ -35,16 +35,35 @@ - unnamed + layout4 unnamed + + 2 + + + 2 + sSearch + + + 7 + 0 + 0 + 0 + + + + + + catgBGRP + 5 @@ -53,6 +72,26 @@ 0 + + GroupBoxPanel + + + Sunken + + + + + + 0 + + + + allRDB + + + All + + @@ -90,10 +129,10 @@ - + - + @@ -320,4 +359,8 @@ + + ssearch_w.h + reslist.h + diff --git a/src/qtgui/rclmain_w.cpp b/src/qtgui/rclmain_w.cpp index 3e21aa3f..e5ad55ff 100644 --- a/src/qtgui/rclmain_w.cpp +++ b/src/qtgui/rclmain_w.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: rclmain_w.cpp,v 1.52 2008-09-28 07:40:56 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: rclmain_w.cpp,v 1.53 2008-09-28 14:20:50 dockes Exp $ (C) 2005 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -95,6 +95,12 @@ static QIconSet createIconSet(const QString &name) void RclMain::init() { + // This is just to get the common catg strings into the message file + static const char* catg_strings[] = { + QT_TR_NOOP("All"), QT_TR_NOOP("media"), QT_TR_NOOP("message"), + QT_TR_NOOP("other"), QT_TR_NOOP("presentation"), + QT_TR_NOOP("spreadsheet"), QT_TR_NOOP("text") + }; curPreview = 0; asearchform = 0; @@ -146,6 +152,22 @@ void RclMain::init() } preferencesMenu->setItemChecked(curid, true); + // Document categories buttons + catgBGRP->setColumnLayout(1, Qt::Vertical); + list cats; + rclconfig->getMimeCategories(cats); + // Text for button 0 is not used. Next statement just avoids unused + // variable compiler warning for catg_strings + m_catgbutvec.push_back(catg_strings[0]); + for (list::const_iterator it = cats.begin(); + it != cats.end(); it++) { + QRadioButton *but = new QRadioButton(catgBGRP); + QString catgnm = QString::fromUtf8(it->c_str(), it->length()); + m_catgbutvec.push_back(*it); + but->setText(tr(catgnm)); + } + catgBGRP->setButton(0); + // Connections connect(sSearch, SIGNAL(startSearch(RefCntr)), this, SLOT(startSearch(RefCntr))); @@ -203,7 +225,7 @@ void RclMain::init() connect(indexConfigAction, SIGNAL(activated()), this, SLOT(showIndexConfig())); connect(queryPrefsAction, SIGNAL(activated()), this, SLOT(showUIPrefs())); connect(extIdxAction, SIGNAL(activated()), this, SLOT(showExtIdxDialog())); - + connect(catgBGRP, SIGNAL(clicked(int)), this, SLOT(catgFilter(int))); #if (QT_VERSION < 0x040000) nextPageAction->setIconSet(createIconSet("nextpage.png")); @@ -229,7 +251,7 @@ void RclMain::init() if (prefs.keepSort && prefs.sortActive) { SortForm sf(0); connect(&sf, SIGNAL(sortDataChanged(DocSeqSortSpec)), - resList, SLOT(sortDataChanged(DocSeqSortSpec))); + resList, SLOT(setSortParams(DocSeqSortSpec))); // Have to call setdata again after sig connected... sf.setData(); } @@ -486,7 +508,7 @@ void RclMain::showSortDialog() if (sortform == 0) { sortform = new SortForm(0); connect(sortform, SIGNAL(sortDataChanged(DocSeqSortSpec)), - resList, SLOT(sortDataChanged(DocSeqSortSpec))); + resList, SLOT(setSortParams(DocSeqSortSpec))); connect(sortform, SIGNAL(applySortData()), resList, SLOT(setDocSource())); sortform->show(); @@ -605,7 +627,7 @@ void RclMain::startPreview(int docnum, int mod) if (curPreview == 0) { HiliteData hdata; resList->getTerms(hdata.terms, hdata.groups, hdata.gslks); - curPreview = new Preview(resList->searchId(), hdata); + curPreview = new Preview(resList->listId(), hdata); if (curPreview == 0) { QMessageBox::warning(0, tr("Warning"), tr("Can't create preview window"), @@ -675,13 +697,13 @@ void RclMain::previewPrevInTab(Preview * w, int sid, int docnum) // Combined next/prev from result list in current preview tab void RclMain::previewPrevOrNextInTab(Preview * w, int sid, int docnum, bool nxt) { - LOGDEB(("RclMain::previewNextInTab sid %d docnum %d, searchId %d\n", - sid, docnum, resList->searchId())); + LOGDEB(("RclMain::previewNextInTab sid %d docnum %d, listId %d\n", + sid, docnum, resList->listId())); if (w == 0) // ?? return; - if (sid != resList->searchId()) { + if (sid != resList->listId()) { QMessageBox::warning(0, "Recoll", tr("This search is not active any more")); return; @@ -720,8 +742,8 @@ void RclMain::previewPrevOrNextInTab(Preview * w, int sid, int docnum, bool nxt) void RclMain::previewExposed(Preview *, int sid, int docnum) { LOGDEB2(("RclMain::previewExposed: sid %d docnum %d, m_sid %d\n", - sid, docnum, resList->searchId())); - if (sid != resList->searchId()) { + sid, docnum, resList->listId())); + if (sid != resList->listId()) { return; } resList->previewExposed(docnum); @@ -974,3 +996,25 @@ void RclMain::enablePrevPage(bool yesno) prevPageAction->setEnabled(yesno); firstPageAction->setEnabled(yesno); } + +// User pressed a category button: set filter params in reslist +void RclMain::catgFilter(int id) +{ + LOGDEB(("RclMain::catgFilter: id %d\n")); + if (id < 0 || id >= int(m_catgbutvec.size())) + return; + + DocSeqFiltSpec spec; + + if (id != 0) { + string catg = m_catgbutvec[id]; + list tps; + rclconfig->getMimeCatTypes(catg, tps); + for (list::const_iterator it = tps.begin(); + it != tps.end(); it++) + spec.orCrit(DocSeqFiltSpec::DSFS_MIMETYPE, *it); + } + + resList->setFilterParams(spec); + resList->setDocSource(); +} diff --git a/src/qtgui/rclmain_w.h b/src/qtgui/rclmain_w.h index 65239460..1c7ec6a9 100644 --- a/src/qtgui/rclmain_w.h +++ b/src/qtgui/rclmain_w.h @@ -105,6 +105,7 @@ public slots: virtual void setStemLang(int id); // Prefs menu about to show, set the checked lang entry virtual void adjustPrefsMenu(); + virtual void catgFilter(int); signals: void stemLangChanged(const QString& lang); @@ -122,6 +123,7 @@ private: vector m_tempfiles; map m_stemLangToId; + vector m_catgbutvec; int m_idNoStem; int m_idAllStem; bool m_idxStatusAck; // Did we act on last status? diff --git a/src/qtgui/reslist.cpp b/src/qtgui/reslist.cpp index 0255ff25..bfb08b74 100644 --- a/src/qtgui/reslist.cpp +++ b/src/qtgui/reslist.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: reslist.cpp,v 1.44 2008-09-28 07:40:56 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: reslist.cpp,v 1.45 2008-09-28 14:20:50 dockes Exp $ (C) 2005 J.F.Dockes"; #endif #include @@ -81,14 +81,14 @@ ResList::ResList(QWidget* parent, const char* name) m_winfirst = -1; m_curPvDoc = -1; m_lstClckMod = 0; - m_searchId = 0; + m_listId = 0; } ResList::~ResList() { } -int ResList::newSearchId() +int ResList::newListId() { static int id; return ++id; @@ -98,41 +98,47 @@ extern "C" int XFlush(void *); void ResList::setDocSource(RefCntr ndocsource) { - resetList(); - m_searchId = newSearchId(); m_baseDocSource = ndocsource; - if (m_sortspecs.sortwidth > 0) { - m_docSource = RefCntr(new DocSeqSorted(ndocsource, - m_sortspecs, - string(tr("Query results (sorted)").utf8()))); - } else { - m_docSource = m_baseDocSource; - } - resultPageNext(); + setDocSource(); } // Reapply parameters. Sort params probably changed void ResList::setDocSource() { + if (m_baseDocSource.isNull()) + return; resetList(); - m_searchId = newSearchId(); - RefCntr docsource; - if (m_sortspecs.sortwidth > 0) { - m_docSource = RefCntr(new DocSeqSorted(m_baseDocSource, + m_listId = newListId(); + m_docSource = m_baseDocSource; + + // Filtering must be done before sorting, (which usually + // truncates the original list) + if (m_filtspecs.isNotNull()) { + m_docSource = + RefCntr(new DocSeqFiltered(m_docSource, + m_filtspecs, "")); + } + + if (m_sortspecs.isNotNull()) { + m_docSource = RefCntr(new DocSeqSorted(m_docSource, m_sortspecs, string(tr("Query results (sorted)").utf8()))); - } else { - m_docSource = m_baseDocSource; } resultPageNext(); } -void ResList::sortDataChanged(DocSeqSortSpec spec) +void ResList::setSortParams(const DocSeqSortSpec& spec) { - LOGDEB(("RclMain::sortDataChanged\n")); + LOGDEB(("ResList::setSortParams\n")); m_sortspecs = spec; } +void ResList::setFilterParams(const DocSeqFiltSpec& spec) +{ + LOGDEB(("ResList::setFilterParams\n")); + m_filtspecs = spec; +} + void ResList::resetList() { m_winfirst = -1; diff --git a/src/qtgui/reslist.h b/src/qtgui/reslist.h index c0a89941..35264470 100644 --- a/src/qtgui/reslist.h +++ b/src/qtgui/reslist.h @@ -1,6 +1,6 @@ #ifndef _RESLIST_H_INCLUDED_ #define _RESLIST_H_INCLUDED_ -/* @(#$Id: reslist.h,v 1.14 2008-09-28 07:40:56 dockes Exp $ (C) 2005 J.F.Dockes */ +/* @(#$Id: reslist.h,v 1.15 2008-09-28 14:20:50 dockes Exp $ (C) 2005 J.F.Dockes */ #include @@ -22,6 +22,7 @@ class Q3PopupMenu; #include "docseq.h" #include "sortseq.h" +#include "filtseq.h" #include "refcntr.h" #include "rcldoc.h" @@ -46,11 +47,10 @@ class ResList : public QTEXTBROWSER bool getTerms(vector& terms, vector >& groups, vector& gslks); list expand(Rcl::Doc& doc); - int searchId() const {return m_searchId;} + int listId() const {return m_listId;} public slots: - // Erase list and forget current search - virtual void resetList(); + virtual void resetList(); // Erase current list virtual void doubleClicked(int, int); virtual void resPageUpOrBack(); // Page up pressed virtual void resPageDownOrNext(); // Page down pressed @@ -68,7 +68,8 @@ class ResList : public QTEXTBROWSER // Only used for qt ver >=4 but seems we cant undef it virtual void selecChanged(); virtual void setDocSource(); - virtual void sortDataChanged(DocSeqSortSpec spec); + virtual void setSortParams(const DocSeqSortSpec &spec); + virtual void setFilterParams(const DocSeqFiltSpec &spec); signals: void nextPageAvailable(bool); @@ -96,8 +97,9 @@ class ResList : public QTEXTBROWSER RefCntr m_baseDocSource; // Possibly filtered/sorted docsource (the one displayed) RefCntr m_docSource; - // Current sort parameters + // Current sort and filtering parameters DocSeqSortSpec m_sortspecs; + DocSeqFiltSpec m_filtspecs; // Docs for current page std::vector m_curDocs; // First docnum (in m_docSource sequence) for current page @@ -109,7 +111,7 @@ class ResList : public QTEXTBROWSER int m_curPvDoc;// Docnum for current preview int m_lstClckMod; // Last click modifier. list m_selDocs; - int m_searchId; + int m_listId; virtual int docnumfromparnum(int); virtual int parnumfromdocnum(int); @@ -119,7 +121,7 @@ class ResList : public QTEXTBROWSER emit linkClicked(s, m_lstClckMod); }; virtual RCLPOPUP *createPopupMenu(const QPoint& pos); - static int newSearchId(); + static int newListId(); }; diff --git a/src/qtgui/sort_w.cpp b/src/qtgui/sort_w.cpp index 90451a7e..06e64620 100644 --- a/src/qtgui/sort_w.cpp +++ b/src/qtgui/sort_w.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: sort_w.cpp,v 1.6 2007-06-19 16:19:24 dockes Exp $ (C) 2006 J.F.Dockes"; +static char rcsid[] = "@(#$Id: sort_w.cpp,v 1.7 2008-09-28 14:20:50 dockes Exp $ (C) 2006 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -45,7 +45,7 @@ void SortForm::init() #endif // Initialize values from prefs: - mcntSB->setValue(prefs.sortWidth); + mcntSB->setValue(prefs.sortDepth); unsigned int spec = (unsigned int)prefs.sortSpec; // Restore active/inactive state from prefs, only if requested @@ -105,7 +105,7 @@ void SortForm::setData() prefs.sortActive = sortCB->isChecked(); if (!sortCB->isChecked()) { - spec.sortwidth = 0; + spec.sortdepth = 0; } else { bool desc = descCB1->isChecked(); switch (fldCMB1->currentItem()) { @@ -126,10 +126,10 @@ void SortForm::setData() spec.addCrit(DocSeqSortSpec::RCLFLD_MIMETYPE, desc?true:false); break; } - spec.sortwidth = mcntSB->value(); + spec.sortdepth = mcntSB->value(); // Save data to prefs; - prefs.sortWidth = spec.sortwidth; + prefs.sortDepth = spec.sortdepth; unsigned int spec = 0, v, d; v = fldCMB1->currentItem() & 0x7; d = descCB1->isChecked() ? 8 : 0; diff --git a/src/query/filtseq.h b/src/query/filtseq.h index 4b3e83ec..dc20a980 100644 --- a/src/query/filtseq.h +++ b/src/query/filtseq.h @@ -16,7 +16,7 @@ */ #ifndef _FILTSEQ_H_INCLUDED_ #define _FILTSEQ_H_INCLUDED_ -/* @(#$Id: filtseq.h,v 1.1 2008-09-28 07:40:56 dockes Exp $ (C) 2004 J.F.Dockes */ +/* @(#$Id: filtseq.h,v 1.2 2008-09-28 14:20:50 dockes Exp $ (C) 2004 J.F.Dockes */ #include #include @@ -34,6 +34,8 @@ class DocSeqFiltSpec { } std::vector crits; std::vector values; + void reset() {crits.clear(); values.clear();} + bool isNotNull() {return crits.size() != 0;} }; /** diff --git a/src/query/sortseq.cpp b/src/query/sortseq.cpp index e2c87a70..c1594054 100644 --- a/src/query/sortseq.cpp +++ b/src/query/sortseq.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: sortseq.cpp,v 1.11 2007-01-19 15:22:50 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: sortseq.cpp,v 1.12 2008-09-28 14:20:50 dockes Exp $ (C) 2005 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -87,10 +87,10 @@ DocSeqSorted::DocSeqSorted(RefCntr iseq, DocSeqSortSpec &sortspec, : DocSequence(t), m_seq(iseq) { m_spec = sortspec; - LOGDEB(("DocSeqSorted:: count %d\n", m_spec.sortwidth)); - m_docs.resize(m_spec.sortwidth); + LOGDEB(("DocSeqSorted:: count %d\n", m_spec.sortdepth)); + m_docs.resize(m_spec.sortdepth); int i; - for (i = 0; i < m_spec.sortwidth; i++) { + for (i = 0; i < m_spec.sortdepth; i++) { int percent; if (!iseq->getDoc(i, m_docs[i], &percent)) { LOGERR(("DocSeqSorted: getDoc failed for doc %d\n", i)); @@ -98,11 +98,11 @@ DocSeqSorted::DocSeqSorted(RefCntr iseq, DocSeqSortSpec &sortspec, } m_docs[i].pc = percent; } - m_spec.sortwidth = i; - LOGDEB(("DocSeqSorted:: m_count %d\n", m_spec.sortwidth)); - m_docs.resize(m_spec.sortwidth); - m_docsp.resize(m_spec.sortwidth); - for (i = 0; i < m_spec.sortwidth; i++) + m_spec.sortdepth = i; + LOGDEB(("DocSeqSorted:: m_count %d\n", m_spec.sortdepth)); + m_docs.resize(m_spec.sortdepth); + m_docsp.resize(m_spec.sortdepth); + for (i = 0; i < m_spec.sortdepth; i++) m_docsp[i] = &m_docs[i]; CompareDocs cmp(sortspec); @@ -113,7 +113,7 @@ bool DocSeqSorted::getDoc(int num, Rcl::Doc &doc, int *percent, string *) { LOGDEB1(("DocSeqSorted: fetching %d\n", num)); - if (num >= m_spec.sortwidth) + if (num >= m_spec.sortdepth) return false; if (percent) *percent = (*m_docsp[num]).pc; diff --git a/src/query/sortseq.h b/src/query/sortseq.h index 7f53dd60..7f781a70 100644 --- a/src/query/sortseq.h +++ b/src/query/sortseq.h @@ -16,7 +16,7 @@ */ #ifndef _SORTSEQ_H_INCLUDED_ #define _SORTSEQ_H_INCLUDED_ -/* @(#$Id: sortseq.h,v 1.10 2007-01-19 15:22:50 dockes Exp $ (C) 2004 J.F.Dockes */ +/* @(#$Id: sortseq.h,v 1.11 2008-09-28 14:20:50 dockes Exp $ (C) 2004 J.F.Dockes */ #include #include @@ -26,13 +26,15 @@ class DocSeqSortSpec { public: - DocSeqSortSpec() : sortwidth(0) {} - int sortwidth; // We only re-sort the first sortwidth most relevant docs + DocSeqSortSpec() : sortdepth(0) {} enum Field {RCLFLD_URL, RCLFLD_IPATH, RCLFLD_MIMETYPE, RCLFLD_MTIME}; void addCrit(Field fld, bool desc = false) { crits.push_back(fld); dirs.push_back(desc); } + bool isNotNull() {return sortdepth > 0;} + + int sortdepth; // We only re-sort the first sortdepth most relevant docs std::vector crits; std::vector dirs; }; @@ -47,7 +49,7 @@ class DocSeqSorted : public DocSequence { const std::string &t); virtual ~DocSeqSorted() {} virtual bool getDoc(int num, Rcl::Doc &doc, int *percent, string *sh = 0); - virtual int getResCnt() {return m_spec.sortwidth;} + virtual int getResCnt() {return m_spec.sortdepth;} virtual string getAbstract(Rcl::Doc& doc) { return m_seq->getAbstract(doc); } diff --git a/src/sampleconf/mimeconf b/src/sampleconf/mimeconf index 7d7fa791..7bf40bc4 100644 --- a/src/sampleconf/mimeconf +++ b/src/sampleconf/mimeconf @@ -1,4 +1,4 @@ -# @(#$Id: mimeconf,v 1.43 2008-09-15 08:03:37 dockes Exp $ (C) 2004 J.F.Dockes +# @(#$Id: mimeconf,v 1.44 2008-09-28 14:20:50 dockes Exp $ (C) 2004 J.F.Dockes # Recoll : associations of mime types to processing filters. # There are different sections for decompression, 'interning' for indexing @@ -159,6 +159,7 @@ text = \ text/html \ text/plain \ text/rtf \ + text/x-c \ text/x-html-sidux-man \ text/x-man \ text/x-python