From 133d3b2a10f9fa810bc43b1e17d69a2f10d2a49d Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Tue, 2 Oct 2012 10:56:23 +0200 Subject: [PATCH] Only create the snippets menu entry if doc has pages. Add code for a snippets window link inside the result list --- src/doc/user/usermanual.sgml | 64 ++++++++++++++++++++++++++---------- src/qtgui/reslist.cpp | 47 ++++++++++++++++++++------ src/qtgui/reslist.h | 1 + src/query/reslistpager.cpp | 18 +++++++++- src/query/reslistpager.h | 2 ++ src/rcldb/rcldoc.h | 13 +++++++- src/rcldb/rclquery.cpp | 1 + 7 files changed, 117 insertions(+), 29 deletions(-) diff --git a/src/doc/user/usermanual.sgml b/src/doc/user/usermanual.sgml index 0a6e3131..e81ac2eb 100644 --- a/src/doc/user/usermanual.sgml +++ b/src/doc/user/usermanual.sgml @@ -2022,6 +2022,10 @@ fvwm %DDate + %EPrecooked Snippets + link (will only appear for documents indexed with page + numbers) + %IIcon image name. This is normally determined from the mime type. The associations are defined inside the @@ -2907,6 +2911,17 @@ application/x-chm = execm rclchm + + Page numbers + + The indexer will interpret ^L characters + in the filter output as indicating page breaks, and will record + them. At query time, this allows starting a viewer on the right + page for a hit or a snippet. Currently, only the PDF filter + generates page breaks (thanks to + pdftotext). + + @@ -4514,27 +4529,42 @@ x-my-tag = mailmytag - %DDocument date - %fFile - name. This may be the name of a temporary file if it was - necessary to create one (ie: to extract a subdocument from a - container). + %D + Document date + + + %f + File name. This may be the name of a temporary file if + it was necessary to create one (ie: to extract a subdocument + from a container). - %FOriginal file name. - Same as %f except if a temporary file is used. + + %F + Original file name. Same as %f except if a temporary + file is used. - %iInternal path, for - subdocuments of containers. The format depends on the container - type. If this appears in the command line, &RCL; will not create - a temporary file to extract the subdocument, expecting the called - application (possibly a script) to be able to handle - it. + + %i + Internal path, for subdocuments of containers. The + format depends on the container type. If this appears in the + command line, &RCL; will not create a temporary file to + extract the subdocument, expecting the called application + (possibly a script) to be able to handle it. - %MMime - type + + %M + Mime type - %U, %uUrl. - + + %p + Page index. Only significant for a subset of document + types, currently only PDF files. Can be used to start the + editor at the right page for a match or + snippet. + + + %U, %u + Url. diff --git a/src/qtgui/reslist.cpp b/src/qtgui/reslist.cpp index 0e84e23d..7953492f 100644 --- a/src/qtgui/reslist.cpp +++ b/src/qtgui/reslist.cpp @@ -510,7 +510,7 @@ bool ResList::getDoc(int docnum, Rcl::Doc &doc) // Is docnum in current page ? Then all Ok if (docnum >= winfirst && docnum <= winlast) { - return m_source->getDoc(docnum, doc); + return m_pager->getDoc(docnum, doc); } // Else we accept to page down or up but not further @@ -522,7 +522,7 @@ bool ResList::getDoc(int docnum, Rcl::Doc &doc) winfirst = pageFirstDocNum(); winlast = m_pager->pageLastDocNum(); if (docnum >= winfirst && docnum <= winlast) { - return m_source->getDoc(docnum, doc); + return m_pager->getDoc(docnum, doc); } return false; } @@ -801,6 +801,16 @@ void ResList::mouseDoubleClickEvent(QMouseEvent *event) #endif } +void ResList::newSnippetsW(const Rcl::Doc& doc) +{ + SnippetsW *sp = new SnippetsW(doc, m_source); + if (m_parent) { + connect(sp, SIGNAL(startNativeViewer(Rcl::Doc, int)), + m_parent, SLOT(startNativeViewer(Rcl::Doc, int))); + } + sp->show(); +} + void ResList::linkWasClicked(const QUrl &url) { string ascurl = (const char *)url.toString().toAscii();; @@ -808,9 +818,27 @@ void ResList::linkWasClicked(const QUrl &url) int what = ascurl[0]; switch (what) { + // Open abstract/snippets window + case 'A': + { + if (m_source.isNull()) + return; + int i = atoi(ascurl.c_str()+1) - 1; + Rcl::Doc doc; + if (!getDoc(i, doc)) { + LOGERR(("ResList::linkWasClicked: can't get doc for %d\n", i)); + return; + } + newSnippetsW(doc); + } + break; + + // Show query details case 'H': emit headerClicked(); break; + + // Preview and edit case 'P': case 'E': { @@ -826,12 +854,16 @@ void ResList::linkWasClicked(const QUrl &url) emit docEditClicked(doc); } break; + + // Next/prev page case 'n': resultPageNext(); break; case 'p': resultPageBack(); break; + + // Spelling: replacement suggestion clicked case 'S': { QString s = url.toString(); @@ -845,6 +877,7 @@ void ResList::linkWasClicked(const QUrl &url) } } break; + default: LOGERR(("ResList::linkWasClicked: bad link [%s]\n", ascurl.c_str())); break;// ?? @@ -897,7 +930,7 @@ void ResList::createPopupMenu(const QPoint& pos) this, SLOT(menuPreviewParent())); popup->addAction(tr("&Open Parent document/folder"), this, SLOT(menuOpenParent())); - if (m_source->snippetsCapable()) + if (havedoc && doc.haspages && m_source->snippetsCapable()) popup->addAction(tr("Open &Snippets window"), this, SLOT(menuOpenSnippets())); popup->popup(mapToGlobal(pos)); @@ -956,13 +989,7 @@ void ResList::menuOpenSnippets() Rcl::Doc doc; if (!getDoc(m_popDoc, doc) || m_source.isNull()) return; - SnippetsW *sp = new SnippetsW(doc, m_source); - if (m_parent) { - connect(sp, SIGNAL(startNativeViewer(Rcl::Doc, int)), - m_parent, SLOT(startNativeViewer(Rcl::Doc, int))); - } - - sp->show(); + newSnippetsW(doc); } void ResList::menuEdit() diff --git a/src/qtgui/reslist.h b/src/qtgui/reslist.h index 8c47cb8f..241b852a 100644 --- a/src/qtgui/reslist.h +++ b/src/qtgui/reslist.h @@ -145,6 +145,7 @@ class ResList : public RESLIST_PARENTCLASS bool scrollIsAtTop(); bool scrollIsAtBottom(); void setupArrows(); + void newSnippetsW(const Rcl::Doc &doc); }; diff --git a/src/query/reslistpager.cpp b/src/query/reslistpager.cpp index d7c7b1d0..973be313 100644 --- a/src/query/reslistpager.cpp +++ b/src/query/reslistpager.cpp @@ -232,6 +232,11 @@ void ResListPager::displayDoc(RclConfig *config, int i, Rcl::Doc& doc, linksbuf << "" << trans("Open") << ""; } + ostringstream snipsbuf; + if (doc.haspages) { + snipsbuf << "" + << trans("Snippets") << "  "; + } // Build the result list paragraph: @@ -245,6 +250,7 @@ void ResListPager::displayDoc(RclConfig *config, int i, Rcl::Doc& doc, map subs; subs["A"] = !richabst.empty() ? richabst : ""; subs["D"] = datebuf; + subs["E"] = snipsbuf.rdbuf()->str(); subs["I"] = iconurl; subs["i"] = doc.ipath; subs["K"] = !doc.meta[Rcl::Doc::keykw].empty() ? @@ -279,6 +285,16 @@ void ResListPager::displayDoc(RclConfig *config, int i, Rcl::Doc& doc, append(chunk.rdbuf()->str(), i, doc); } +bool ResListPager::getDoc(int num, Rcl::Doc& doc) +{ + if (m_winfirst < 0 || m_respage.size() == 0) + return false; + if (num < m_winfirst || num >= m_winfirst + int(m_respage.size())) + return false; + doc = m_respage[num-m_winfirst].doc; + return true; +} + void ResListPager::displayPage(RclConfig *config) { LOGDEB(("ResListPager::displayPage\n")); @@ -384,7 +400,7 @@ void ResListPager::displayPage(RclConfig *config) // Emit data for result entry paragraph. Do it in chunks that make sense // html-wise, else our client may get confused for (int i = 0; i < (int)m_respage.size(); i++) { - Rcl::Doc &doc(m_respage[i].doc); + Rcl::Doc& doc(m_respage[i].doc); string& sh(m_respage[i].subHeader); displayDoc(config, i, doc, hdata, sh); } diff --git a/src/query/reslistpager.h b/src/query/reslistpager.h index 14fcaa2f..6e5e1f09 100644 --- a/src/query/reslistpager.h +++ b/src/query/reslistpager.h @@ -90,6 +90,8 @@ public: string queryDescription() {return m_docSource.isNull() ? "" : m_docSource->getDescription();} + bool getDoc(int num, Rcl::Doc &doc); + // Things that need to be reimplemented in the subclass: virtual bool append(const string& data); virtual bool append(const string& data, int, const Rcl::Doc&) diff --git a/src/rcldb/rcldoc.h b/src/rcldb/rcldoc.h index 44a1b64d..2b26d41e 100644 --- a/src/rcldb/rcldoc.h +++ b/src/rcldb/rcldoc.h @@ -112,10 +112,17 @@ class Doc { // and indexed string text; + ///////////////////////////////////////////////// + // Misc stuff + int pc; // relevancy percentage, used by sortseq, convenience unsigned long xdocid; // Opaque: rcldb doc identifier. + // Page breaks were stored during indexing. + bool haspages; + /////////////////////////////////////////////////////////////////// + void erase() { url.erase(); ipath.erase(); @@ -133,8 +140,12 @@ class Doc { text.erase(); pc = 0; xdocid = 0; + haspages = false; + } + Doc() + : syntabs(false), pc(0), xdocid(0), haspages(false) + { } - /** Get value for named field. If value pointer is 0, just test existence */ bool getmeta(const string& nm, string *value = 0) const { diff --git a/src/rcldb/rclquery.cpp b/src/rcldb/rclquery.cpp index 56105424..a49529a2 100644 --- a/src/rcldb/rclquery.cpp +++ b/src/rcldb/rclquery.cpp @@ -325,6 +325,7 @@ bool Query::makeDocAbstract(Doc &doc, vector& abstract) it != vpabs.end(); it++) { string chunk; if (it->first > 0) { + doc.haspages = true; ostringstream ss; ss << it->first; chunk += string(" [p ") + ss.str() + "] ";