Only create the snippets menu entry if doc has pages. Add code for a snippets window link inside the result list

This commit is contained in:
Jean-Francois Dockes 2012-10-02 10:56:23 +02:00
parent 71d23639bb
commit 133d3b2a10
7 changed files with 117 additions and 29 deletions

View File

@ -2022,6 +2022,10 @@ fvwm
</listitem>
<listitem><formalpara><title>%D</title><para>Date</para></formalpara>
</listitem>
<listitem><formalpara><title>%E</title><para>Precooked Snippets
link (will only appear for documents indexed with page
numbers)</para></formalpara>
</listitem>
<listitem><formalpara><title>%I</title><para>Icon 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
</sect2>
<sect2 id="rcl.program.filters.pages">
<title>Page numbers</title>
<para>The indexer will interpret <literal>^L</literal> 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
<literal>pdftotext</literal>).</para>
</sect2>
</sect1>
<sect1 id="rcl.program.fields">
@ -4514,27 +4529,42 @@ x-my-tag = mailmytag
<itemizedlist>
<listitem>
<formalpara><title>%D</title><para>Document date</para></formalpara>
</listitem> <listitem><formalpara><title>%f</title><para>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).</para></formalpara>
<formalpara><title>%D</title>
<para>Document date</para></formalpara>
</listitem>
<listitem><formalpara><title>%f</title>
<para>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).</para></formalpara>
</listitem>
<listitem><formalpara><title>%F</title><para>Original file name.
Same as %f except if a temporary file is used.</para></formalpara>
<listitem><formalpara><title>%F</title>
<para>Original file name. Same as %f except if a temporary
file is used.</para></formalpara>
</listitem>
<listitem><formalpara><title>%i</title><para>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.</para></formalpara>
<listitem><formalpara><title>%i</title>
<para>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.</para></formalpara>
</listitem>
<listitem><formalpara><title>%M</title><para>Mime
type</para></formalpara>
<listitem><formalpara><title>%M</title>
<para>Mime type</para></formalpara>
</listitem>
<listitem><formalpara><title>%U, %u</title><para>Url.
</para></formalpara>
<listitem><formalpara><title>%p</title>
<para>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.</para></formalpara>
</listitem>
<listitem><formalpara><title>%U, %u</title>
<para>Url.</para></formalpara>
</listitem>
</itemizedlist>

View File

@ -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()

View File

@ -145,6 +145,7 @@ class ResList : public RESLIST_PARENTCLASS
bool scrollIsAtTop();
bool scrollIsAtBottom();
void setupArrows();
void newSnippetsW(const Rcl::Doc &doc);
};

View File

@ -232,6 +232,11 @@ void ResListPager::displayDoc(RclConfig *config, int i, Rcl::Doc& doc,
linksbuf << "<a href=\"E" << docnumforlinks << "\">"
<< trans("Open") << "</a>";
}
ostringstream snipsbuf;
if (doc.haspages) {
snipsbuf << "<a href=\"A" << docnumforlinks << "\">"
<< trans("Snippets") << "</a>&nbsp;&nbsp;";
}
// Build the result list paragraph:
@ -245,6 +250,7 @@ void ResListPager::displayDoc(RclConfig *config, int i, Rcl::Doc& doc,
map<string, string> 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);
}

View File

@ -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&)

View File

@ -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
{

View File

@ -325,6 +325,7 @@ bool Query::makeDocAbstract(Doc &doc, vector<string>& abstract)
it != vpabs.end(); it++) {
string chunk;
if (it->first > 0) {
doc.haspages = true;
ostringstream ss;
ss << it->first;
chunk += string(" [p ") + ss.str() + "] ";