allow indexing individual files. Fix pb with preview and charsets (local defcharset ignored)

This commit is contained in:
dockes 2005-12-14 11:00:48 +00:00
parent 315f8cdb33
commit be485e8059
9 changed files with 329 additions and 159 deletions

View File

@ -1,10 +1,10 @@
#ifndef lint
static char rcsid[] = "@(#$Id: indexer.cpp,v 1.19 2005-11-30 09:46:25 dockes Exp $ (C) 2004 J.F.Dockes";
static char rcsid[] = "@(#$Id: indexer.cpp,v 1.20 2005-12-14 11:00:48 dockes Exp $ (C) 2004 J.F.Dockes";
#endif
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <strings.h>
#include <iostream>
@ -33,63 +33,24 @@ using namespace std;
#define deleteZ(X) {delete X;X = 0;}
#endif
/// A class to index a list of top directories into one database.
///
/// Inherits FsTreeWalkerCB so that its processone() method is
/// called by the file-system tree walk code for each file and
/// directory, and keeps all state used while indexing a
/// directory tree.
class DbIndexer : public FsTreeWalkerCB {
FsTreeWalker walker;
RclConfig *config;
string dbdir;
list<string> *topdirs;
Rcl::Db db;
string tmpdir;
public:
/// Constructor does nothing but store parameters
DbIndexer(RclConfig *cnf, const string &dbd, list<string> *top)
: config(cnf), dbdir(dbd), topdirs(top) {}
virtual ~DbIndexer() {
// Maybe clean up temporary directory
if (tmpdir.length()) {
wipedir(tmpdir);
if (rmdir(tmpdir.c_str()) < 0) {
LOGERR(("DbIndexer::~DbIndexer: cant clear temp dir %s\n",
tmpdir.c_str()));
}
DbIndexer::~DbIndexer() {
// Maybe clean up temporary directory
if (tmpdir.length()) {
wipedir(tmpdir);
if (rmdir(tmpdir.c_str()) < 0) {
LOGERR(("DbIndexer::~DbIndexer: cannot clear temp dir %s\n",
tmpdir.c_str()));
}
}
/// Start indexing.
bool index(bool resetbefore);
/// Tree walker callback method
FsTreeWalker::Status
processone(const std::string &, const struct stat *, FsTreeWalker::CbFlag);
};
db.close();
}
/// Top level file system tree index method for updating a given database.
///
/// We create the temporary directory, open the database, then call a
/// file system walk for each top-level directory.
/// When walking is done, we create the stem databases and close the
/// main db.
bool DbIndexer::index(bool resetbefore)
bool DbIndexer::indexDb(bool resetbefore, list<string> *topdirs)
{
string tdir;
if (!init(resetbefore))
return false;
if (!maketmpdir(tmpdir)) {
LOGERR(("DbIndexer: cant create temp directory\n"));
return false;
}
if (!db.open(dbdir, resetbefore ? Rcl::Db::DbTrunc : Rcl::Db::DbUpd)) {
LOGERR(("DbIndexer::index: error opening database in %s\n",
dbdir.c_str()));
return false;
}
for (list<string>::const_iterator it = topdirs->begin();
it != topdirs->end(); it++) {
LOGDEB(("DbIndexer::index: Indexing %s into %s\n", it->c_str(),
@ -118,7 +79,6 @@ bool DbIndexer::index(bool resetbefore)
if (walker.walk(*it, *this) != FsTreeWalker::FtwOk) {
LOGERR(("DbIndexer::index: error while indexing %s\n",
it->c_str()));
db.close();
return false;
}
}
@ -138,6 +98,7 @@ bool DbIndexer::index(bool resetbefore)
}
}
// The close would be done in our destructor, but we want status here
if (!db.close()) {
LOGERR(("DbIndexer::index: error closing database in %s\n",
dbdir.c_str()));
@ -146,6 +107,52 @@ bool DbIndexer::index(bool resetbefore)
return true;
}
bool DbIndexer::init(bool resetbefore)
{
if (!maketmpdir(tmpdir)) {
LOGERR(("DbIndexer: cannot create temporary directory\n"));
return false;
}
if (!db.open(dbdir, resetbefore ? Rcl::Db::DbTrunc : Rcl::Db::DbUpd)) {
LOGERR(("DbIndexer: error opening database in %s\n", dbdir.c_str()));
return false;
}
return true;
}
bool DbIndexer::indexFiles(const list<string> &filenames)
{
if (!init())
return false;
list<string>::const_iterator it;
for (it = filenames.begin(); it != filenames.end();it++) {
config->setKeyDir(path_getfather(*it));
struct stat stb;
if (stat(it->c_str(), &stb) != 0) {
LOGERR(("DbIndexer::indexFiles: stat(%s): %s", it->c_str(),
strerror(errno)));
continue;
}
if (!S_ISREG(stb.st_mode)) {
LOGERR(("DbIndexer::indexFiles: %s: not a regular file\n",
it->c_str()));
continue;
}
if (processone(*it, &stb, FsTreeWalker::FtwRegular) !=
FsTreeWalker::FtwOk) {
LOGERR(("DbIndexer::indexFiles: Database error\n"));
return false;
}
}
// The close would be done in our destructor, but we want status here
if (!db.close()) {
LOGERR(("DbIndexer::indexfiles: error closing database in %s\n",
dbdir.c_str()));
return false;
}
return true;
}
/// This method gets called for every file and directory found by the
/// tree walker.
@ -257,6 +264,7 @@ bool ConfIndexer::index(bool resetbefore)
}
config->setKeyDir("");
// The dbmap now has dbdir as key and directory lists as values.
// Index each directory group in turn
for (dbit = dbmap.begin(); dbit != dbmap.end(); dbit++) {
//cout << dbit->first << " -> ";
@ -265,8 +273,8 @@ bool ConfIndexer::index(bool resetbefore)
// cout << *dit << " ";
//}
//cout << endl;
dbindexer = new DbIndexer(config, dbit->first, &dbit->second);
if (!dbindexer->index(resetbefore)) {
dbindexer = new DbIndexer(config, dbit->first);
if (!dbindexer->indexDb(resetbefore, &dbit->second)) {
deleteZ(dbindexer);
return false;
}

View File

@ -1,32 +1,84 @@
#ifndef _INDEXER_H_INCLUDED_
#define _INDEXER_H_INCLUDED_
/* @(#$Id: indexer.h,v 1.7 2005-11-30 09:46:25 dockes Exp $ (C) 2004 J.F.Dockes */
/* @(#$Id: indexer.h,v 1.8 2005-12-14 11:00:48 dockes Exp $ (C) 2004 J.F.Dockes */
#include <string>
#include <list>
#include "rclconfig.h"
#include "fstreewalk.h"
#include "rcldb.h"
/**
* An internal class to process all directories indexed into the same database.
*/
/* Forward decl for lower level indexing object */
class DbIndexer;
/**
* The file system indexing object. Processes the configuration, then invokes
* file system walking to populate/update the database(s).
*
* Multiple top-level directories can be listed in the
* configuration. Each can be indexed to a different
* database. Directories are first grouped by database, then an
* internal class (DbIndexer) is used to process each group.
*/
The top level indexing object. Processes the configuration, then invokes
file system walking to populate/update the database(s).
Multiple top-level directories can be listed in the
configuration. Each can be indexed to a different
database. Directories are first grouped by database, then an
internal class (DbIndexer) is used to process each group.
*/
class ConfIndexer {
RclConfig *config;
DbIndexer *dbindexer; // Object to process directories for a given db
public:
enum runStatus {IndexerOk, IndexerError};
ConfIndexer(RclConfig *cnf) : config(cnf), dbindexer(0) {}
virtual ~ConfIndexer();
/** Worker function: doe the actual indexing */
bool index(bool resetbefore = false);
virtual ~ConfIndexer();
/** Worker function: doe the actual indexing */
bool index(bool resetbefore = false);
private:
RclConfig *config;
DbIndexer *dbindexer; // Object to process directories for a given db
};
/** Index things into one database
Tree indexing: we inherits FsTreeWalkerCB so that, the processone()
method is called by the file-system tree walk code for each file and
directory. We keep all state needed while indexing, and finally call
the methods to purge the db of stale entries and create the stemming
databases.
Single file(s) indexing: no database purging or stem db updating.
*/
class DbIndexer : public FsTreeWalkerCB {
public:
/** Constructor does nothing but store parameters */
DbIndexer(RclConfig *cnf, const std::string &dbd)
: config(cnf), dbdir(dbd) {
}
virtual ~DbIndexer();
/** Top level file system tree index method for updating a
given database.
The list is supposed to have all the filename space for the
db, and we shall purge entries for non-existing files at the
end. We create the temporary directory, open the database,
then call a file system walk for each top-level directory.
When walking is done, we create the stem databases and close
the main db.
*/
bool indexDb(bool resetbefore, std::list<std::string> *topdirs);
/** Index a list of files. No db cleaning or stemdb updating */
bool indexFiles(const std::list<std::string> &files);
/** Tree walker callback method */
FsTreeWalker::Status
processone(const std::string &, const struct stat *,
FsTreeWalker::CbFlag);
private:
FsTreeWalker walker;
RclConfig *config;
std::string dbdir;
Rcl::Db db;
std::string tmpdir;
bool init(bool rst = false);
};
#endif /* _INDEXER_H_INCLUDED_ */

View File

@ -1,20 +1,53 @@
#ifndef lint
static char rcsid[] = "@(#$Id: recollindex.cpp,v 1.12 2005-11-30 09:46:25 dockes Exp $ (C) 2004 J.F.Dockes";
static char rcsid[] = "@(#$Id: recollindex.cpp,v 1.13 2005-12-14 11:00:48 dockes Exp $ (C) 2004 J.F.Dockes";
#endif
#include <stdio.h>
#include <signal.h>
#include <sys/stat.h>
#include <iostream>
#include <list>
#include <string>
using namespace std;
#include "debuglog.h"
#include "rclinit.h"
#include "indexer.h"
#include "smallut.h"
#include "pathut.h"
ConfIndexer *indexer;
ConfIndexer *confindexer;
DbIndexer *dbindexer;
bool indexfiles(RclConfig *config, const list<string> &filenames)
{
if (filenames.empty())
return true;
// Note that we do not bother to check for multiple databases,
// which are currently a fiction anyway.
config->setKeyDir(path_getfather(*filenames.begin()));
string dbdir;
if (!config->getConfParam("dbdir", dbdir)) {
LOGERR(("indexfiles: no database directory in "
"configuration for %s\n", filenames.begin()->c_str()));
return false;
}
dbdir = path_tildexpand(dbdir);
dbindexer = new DbIndexer(config, dbdir);
return dbindexer->indexFiles(filenames);
}
static void cleanup()
{
delete indexer;
indexer = 0;
delete confindexer;
confindexer = 0;
delete dbindexer;
dbindexer = 0;
}
static void sigcleanup(int sig)
@ -29,12 +62,16 @@ static int op_flags;
#define OPT_MOINS 0x1
#define OPT_z 0x2
#define OPT_h 0x4
#define OPT_i 0x8
static const char usage [] =
" recollindex [-hz]\n"
" recollindex [-hz] \n"
" recollindex -i <filename [filename ...]>\n"
"Options:\n"
" -h : print this message\n"
" -z : reset database before starting indexation\n\n"
" -i <filename [filename ...]> : index individual files. No db purge or stem\n"
" database updates in this case\n"
;
static void
@ -59,22 +96,43 @@ int main(int argc, const char **argv)
switch (*(*argv)++) {
case 'z': op_flags |= OPT_z; break;
case 'h': op_flags |= OPT_h; break;
case 'i': op_flags |= OPT_i; break;
default: Usage(); break;
}
b1: argc--; argv++;
}
if (op_flags & OPT_h)
Usage();
if ((op_flags & OPT_z) && (op_flags & OPT_i))
Usage();
string reason;
RclConfig *config = recollinit(cleanup, sigcleanup, reason);
if (config == 0 || !config->ok()) {
string str = "Configuration problem: ";
str += reason;
fprintf(stderr, "%s\n", str.c_str());
cerr << "Configuration problem: " << reason << endl;
exit(1);
}
indexer = new ConfIndexer(config);
exit(!indexer->index((op_flags & OPT_z) != 0));
if (op_flags & OPT_i) {
list<string> filenames;
if (argc == 0) {
// Read from stdin
char line[1024];
while (fgets(line, 1023, stdin)) {
string sl(line);
trimstring(sl, "\n\r");
filenames.push_back(sl);
}
} else {
while (argc--) {
filenames.push_back(*argv++);
}
}
exit(!indexfiles(config, filenames));
} else {
confindexer = new ConfIndexer(config);
bool rezero(op_flags & OPT_z);
exit(!confindexer->index(rezero));
}
}

View File

@ -112,9 +112,7 @@ MimeHandlerHtml::mkDoc(RclConfig *conf, const string &,
charset.c_str(),result.doccharset.c_str()));
if (!result.doccharset.empty() &&
!samecharset(result.doccharset, result.ocharset)) {
LOGDEB(("textHtmlToDoc: charset '%s' doc charset '%s',"
"reparse\n", charset.c_str(),
result.doccharset.c_str()));
LOGDEB(("textHtmlToDoc: reparse for charsets\n"));
charset = result.doccharset;
} else {
LOGERR(("textHtmlToDoc:: error: non charset exception\n"));

View File

@ -1,5 +1,5 @@
#ifndef lint
static char rcsid[] = "@(#$Id: mh_text.cpp,v 1.2 2005-11-24 07:16:15 dockes Exp $ (C) 2005 J.F.Dockes";
static char rcsid[] = "@(#$Id: mh_text.cpp,v 1.3 2005-12-14 11:00:48 dockes Exp $ (C) 2005 J.F.Dockes";
#endif
#include <iostream>
@ -30,12 +30,14 @@ MimeHandler::Status MimeHandlerText::mkDoc(RclConfig *conf, const string &fn,
charset = csguess(otext, conf->getDefCharset());
} else
charset = conf->getDefCharset();
string utf8;
LOGDEB1(("textPlainToDoc: transcod from %s to %s\n", charset, "UTF-8"));
LOGDEB1(("MimeHandlerText::mkDoc: transcod from %s to utf-8\n",
charset.c_str()));
string utf8;
if (!transcode(otext, utf8, charset, "UTF-8")) {
cerr << "textPlainToDoc: transcode failed: charset '" << charset
<< "' to UTF-8: "<< utf8 << endl;
LOGERR(("MimeHandlerText::mkDoc: transcode to utf-8 failed "
"for charset [%s]\n", charset.c_str()));
otext.erase();
return MimeHandler::MHError;
}

View File

@ -399,6 +399,8 @@ void Preview::loadFileInCurrentTab(string fn, size_t sz, const Rcl::Doc &idoc)
// Load and convert file
Rcl::Doc fdoc;
// Need to setup config to retrieve possibly local parameters
rclconfig->setKeyDir(path_getfather(fn));
int status = 1;
LoadThread lthr(&status, &fdoc, fn, doc.ipath, &doc.mimetype);
lthr.start();
@ -419,6 +421,8 @@ void Preview::loadFileInCurrentTab(string fn, size_t sz, const Rcl::Doc &idoc)
doc.mimetype.c_str());
return;
}
// Reset config just in case.
rclconfig->setKeyDir("");
// Highlight search terms:
progress.setLabelText(tr("Creating preview text"));

View File

@ -22,7 +22,7 @@
</property>
<property name="minimumSize">
<size>
<width>466</width>
<width>362</width>
<height>190</height>
</size>
</property>
@ -62,6 +62,9 @@
<property name="accel">
<string>Ctrl+S</string>
</property>
<property name="toolTip" stdset="0">
<string>Erase search entry</string>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
@ -73,6 +76,9 @@
<property name="text">
<string>Search</string>
</property>
<property name="toolTip" stdset="0">
<string>Start query</string>
</property>
</widget>
<widget class="QCheckBox">
<property name="name">
@ -84,6 +90,12 @@
<property name="accel">
<string>Alt+A</string>
</property>
<property name="toolTip" stdset="0">
<string>Do documents have to contain all terms in query?</string>
</property>
<property name="whatsThis" stdset="0">
<string>If this is set, each returned document will contain all the terms in the query. Else documents will be ordered by relevance, but may not contain all the terms.</string>
</property>
</widget>
<widget class="QLineEdit">
<property name="name">
@ -109,6 +121,9 @@
<property name="frameShadow">
<enum>Sunken</enum>
</property>
<property name="toolTip" stdset="0">
<string>Enter search terms here</string>
</property>
</widget>
</hbox>
</widget>
@ -181,6 +196,14 @@
<action name="prevPageAction"/>
<action name="nextPageAction"/>
</toolbar>
<toolbar dock="2">
<property name="name">
<cstring>HelpToolbar</cstring>
</property>
<property name="label">
<string>Toolbar_2</string>
</property>
</toolbar>
</toolbars>
<actions>
<action>
@ -224,10 +247,13 @@
<iconset>history</iconset>
</property>
<property name="text">
<string>Doc History</string>
<string>Document &amp;History</string>
</property>
<property name="menuText">
<string>Doc &amp;History</string>
<string>Document &amp;History</string>
</property>
<property name="toolTip">
<string>Document History</string>
</property>
</action>
<action>
@ -241,7 +267,10 @@
<string>Advanced Search</string>
</property>
<property name="menuText">
<string>Advanced Search</string>
<string>&amp;Advanced Search</string>
</property>
<property name="toolTip">
<string>Advanced/complex Search</string>
</property>
</action>
<action>
@ -252,9 +281,12 @@
<iconset>sortparms</iconset>
</property>
<property name="text">
<string>Sort parameters</string>
<string>&amp;Sort parameters</string>
</property>
<property name="menuText">
<string>&amp;Sort parameters</string>
</property>
<property name="toolTip">
<string>Sort parameters</string>
</property>
</action>
@ -262,7 +294,7 @@
<property name="name">
<cstring>nextPageAction</cstring>
</property>
<property name="enabled">
<property name="enabled">
<bool>false</bool>
</property>
<property name="iconSet">
@ -271,12 +303,15 @@
<property name="text">
<string>Next page</string>
</property>
<property name="toolTip">
<string>Next page of results</string>
</property>
</action>
<action>
<property name="name">
<cstring>prevPageAction</cstring>
</property>
<property name="enabled">
<property name="enabled">
<bool>false</bool>
</property>
<property name="iconSet">
@ -285,6 +320,9 @@
<property name="text">
<string>Previous page</string>
</property>
<property name="toolTip">
<string>Previous page of results</string>
</property>
</action>
</actions>
<connections>
@ -383,7 +421,6 @@
</includes>
<variables>
<variable>int reslist_winfirst;</variable>
<variable>int reslist_current;</variable>
<variable>bool reslist_mouseDrag;</variable>
<variable>bool reslist_mouseDown;</variable>
<variable>int reslist_par;</variable>
@ -425,8 +462,9 @@
<function access="private">init()</function>
<function returnType="bool">close( bool )</function>
<function access="private" returnType="bool">eventFilter( QObject * target, QEvent * event )</function>
<function access="private">startPreview( int docnum )</function>
<function access="private" returnType="int">reldocnumfromparnum( int parnum )</function>
<function access="private">startPreview( int docnum )</function>
<function access="private">startNativeViewer( int docnum )</function>
</functions>
<pixmapinproject/>
<layoutdefaults spacing="6" margin="11"/>

View File

@ -54,7 +54,6 @@ static const int respagesize = 8;
void RecollMain::init()
{
reslist_winfirst = -1;
reslist_current = -1;
reslist_mouseDrag = false;
reslist_mouseDown = false;
reslist_par = -1;
@ -73,6 +72,8 @@ void RecollMain::init()
reslistTE->viewport()->installEventFilter(this);
// reslistTE->viewport()->setFocusPolicy(QWidget::NoFocus);
// Set the focus to the search terms entry:
queryText->setFocus();
}
// We also want to get rid of the advanced search form and previews
@ -279,53 +280,10 @@ void RecollMain::reslistTE_doubleClicked(int par, int)
{
LOGDEB(("RecollMain::reslistTE_doubleClicked: par %d\n", par));
reslist_dblclck = true;
Rcl::Doc doc;
int reldocnum = reldocnumfromparnum(par);
if (!docsource->getDoc(reslist_winfirst + reldocnum, doc, 0, 0))
if (reldocnum < 0)
return;
// Look for appropriate viewer
string cmd = rclconfig->getMimeViewerDef(doc.mimetype);
if (cmd.length() == 0) {
QMessageBox::warning(0, "Recoll",
tr("No external viewer configured for mime type ")
+ doc.mimetype.c_str());
return;
}
string fn = urltolocalpath(doc.url);
// Substitute %u (url) and %f (file name) inside prototype command
string ncmd;
string::const_iterator it1;
for (it1 = cmd.begin(); it1 != cmd.end();it1++) {
if (*it1 == '%') {
if (++it1 == cmd.end()) {
ncmd += '%';
break;
}
if (*it1 == '%')
ncmd += '%';
if (*it1 == 'u')
ncmd += "'" + doc.url + "'";
if (*it1 == 'f')
ncmd += "'" + fn + "'";
} else {
ncmd += *it1;
}
}
ncmd += " &";
QStatusBar *stb = statusBar();
if (stb) {
QString msg = tr("Executing: [") + ncmd.c_str() + "]";
stb->message(msg, 5000);
stb->repaint(false);
XFlush(qt_xdisplay());
}
history->enterDocument(fn, doc.ipath);
system(ncmd.c_str());
startNativeViewer(reslist_winfirst + reldocnum);
}
@ -337,7 +295,7 @@ void RecollMain::reslistTE_clicked(int par, int car)
{
if (reslist_waitingdbl)
return;
LOGDEB(("RecollMain::reslistTE_clckd:winfirst %d par %d char %d drg %d\n",
LOGDEB(("RecollMain::reslistTE_clicked:wfirst %d par %d char %d drg %d\n",
reslist_winfirst, par, car, reslist_mouseDrag));
if (reslist_winfirst == -1 || reslist_mouseDrag)
return;
@ -356,28 +314,32 @@ void RecollMain::reslistTE_clicked(int par, int car)
// requested a native viewer by double-clicking
void RecollMain::reslistTE_delayedclick()
{
LOGDEB(("RecollMain::reslistTE_delayedclick:\n"));
reslist_waitingdbl = false;
if (reslist_dblclck) {
LOGDEB1(("RecollMain::reslistTE_delayedclick: dbleclick\n"));
reslist_dblclck = false;
return;
}
int par = reslist_par;
// Erase everything back to white
{
QColor color("white");
for (int i = 1; i < reslistTE->paragraphs(); i++)
reslistTE->setParagraphBackgroundColor(i, color);
}
// Color the new active paragraph
QColor color("lightblue");
reslistTE->setParagraphBackgroundColor(par, color);
// Document number
int reldocnum = reldocnumfromparnum(par);
if (curPreview && reslist_current == reldocnum)
// Bad number or already displayed. Forget it
if (reldocnum < 0)
return;
reslist_current = reldocnum;
startPreview(reslist_winfirst + reldocnum);
}
@ -412,7 +374,6 @@ void RecollMain::startAdvSearch(Rcl::AdvSearchData sdata)
if (stemlang.empty())
getQueryStemming(dostem, stemlang);
reslist_current = -1;
reslist_winfirst = -1;
if (!rcldb->setQuery(sdata, dostem ?
@ -594,8 +555,6 @@ void RecollMain::showResultPage()
pageParaToReldocnums[reslistTE->paragraphs()-1] = i;
}
reslist_current = -1;
if (gotone) {
reslistTE->append("</body></qt>");
reslistTE->setCursorPosition(0,0);
@ -702,8 +661,7 @@ void RecollMain::startPreview(int docnum)
string fn = urltolocalpath(doc.url);
struct stat st;
if (stat(fn.c_str(), &st) < 0) {
QMessageBox::warning(0, "Recoll",
tr("Cannot access document file: ") +
QMessageBox::warning(0, "Recoll", tr("Cannot access document file: ") +
fn.c_str());
return;
}
@ -733,6 +691,59 @@ void RecollMain::startPreview(int docnum)
curPreview->loadFileInCurrentTab(fn, st.st_size, doc);
}
void RecollMain::startNativeViewer(int docnum)
{
Rcl::Doc doc;
if (!docsource->getDoc(docnum, doc, 0, 0)) {
QMessageBox::warning(0, "Recoll",
tr("Cannot retrieve document info"
" from database"));
return;
}
// Look for appropriate viewer
string cmd = rclconfig->getMimeViewerDef(doc.mimetype);
if (cmd.length() == 0) {
QMessageBox::warning(0, "Recoll",
tr("No external viewer configured for mime type ")
+ doc.mimetype.c_str());
return;
}
string fn = urltolocalpath(doc.url);
// Substitute %u (url) and %f (file name) inside prototype command
string ncmd;
string::const_iterator it1;
for (it1 = cmd.begin(); it1 != cmd.end();it1++) {
if (*it1 == '%') {
if (++it1 == cmd.end()) {
ncmd += '%';
break;
}
if (*it1 == '%')
ncmd += '%';
if (*it1 == 'u')
ncmd += "'" + doc.url + "'";
if (*it1 == 'f')
ncmd += "'" + fn + "'";
} else {
ncmd += *it1;
}
}
ncmd += " &";
QStatusBar *stb = statusBar();
if (stb) {
QString msg = tr("Executing: [") + ncmd.c_str() + "]";
stb->message(msg, 5000);
stb->repaint(false);
XFlush(qt_xdisplay());
}
history->enterDocument(fn, doc.ipath);
system(ncmd.c_str());
}
void RecollMain::showAboutDialog()
{
@ -745,7 +756,6 @@ void RecollMain::showAboutDialog()
void RecollMain::showDocHistory()
{
LOGDEB(("RecollMain::showDocHistory\n"));
reslist_current = -1;
reslist_winfirst = -1;
curPreview = 0;

View File

@ -1,5 +1,5 @@
PROGS = trhist qtry qxtry xadump
PROGS = xadump #trhist qtry qxtry
all: $(PROGS)
XADUMP_OBJS= xadump.o $(BIGLIB)