allow opening parent/enclosing doc with native editor in reslist
This commit is contained in:
parent
8ae11e4125
commit
96dba3a3ee
@ -44,6 +44,8 @@ using namespace std;
|
|||||||
#include "wipedir.h"
|
#include "wipedir.h"
|
||||||
#include "rclconfig.h"
|
#include "rclconfig.h"
|
||||||
#include "mh_html.h"
|
#include "mh_html.h"
|
||||||
|
#include "fileudi.h"
|
||||||
|
|
||||||
#ifdef RCL_USE_XATTR
|
#ifdef RCL_USE_XATTR
|
||||||
#include "pxattr.h"
|
#include "pxattr.h"
|
||||||
#endif // RCL_USE_XATTR
|
#endif // RCL_USE_XATTR
|
||||||
@ -85,7 +87,7 @@ void FileInterner::reapXAttrs(const string& path)
|
|||||||
// This is used when the user wants to retrieve a search result doc's parent
|
// This is used when the user wants to retrieve a search result doc's parent
|
||||||
// (ie message having a given attachment)
|
// (ie message having a given attachment)
|
||||||
bool FileInterner::getEnclosing(const string &url, const string &ipath,
|
bool FileInterner::getEnclosing(const string &url, const string &ipath,
|
||||||
string &eurl, string &eipath)
|
string &eurl, string &eipath, string& udi)
|
||||||
{
|
{
|
||||||
eurl = url;
|
eurl = url;
|
||||||
eipath = ipath;
|
eipath = ipath;
|
||||||
@ -98,6 +100,8 @@ bool FileInterner::getEnclosing(const string &url, const string &ipath,
|
|||||||
} else {
|
} else {
|
||||||
eipath.erase();
|
eipath.erase();
|
||||||
}
|
}
|
||||||
|
make_udi(url_gpath(eurl), eipath, udi);
|
||||||
|
|
||||||
LOGDEB(("FileInterner::getEnclosing() after: [%s]\n", eipath.c_str()));
|
LOGDEB(("FileInterner::getEnclosing() after: [%s]\n", eipath.c_str()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,7 +53,7 @@ class FileInterner {
|
|||||||
* with Rcl::Db::addOrUpdate(). The latter is generally the enclosing file.
|
* with Rcl::Db::addOrUpdate(). The latter is generally the enclosing file.
|
||||||
*/
|
*/
|
||||||
static bool getEnclosing(const string &url, const string &ipath,
|
static bool getEnclosing(const string &url, const string &ipath,
|
||||||
string &eurl, string &eipath);
|
string &eurl, string &eipath, string& udi);
|
||||||
/**
|
/**
|
||||||
* Identify and possibly decompress file, create adequate
|
* Identify and possibly decompress file, create adequate
|
||||||
* handler. The mtype parameter is only set when the object is
|
* handler. The mtype parameter is only set when the object is
|
||||||
|
|||||||
@ -929,8 +929,8 @@ void RclMain::startNativeViewer(Rcl::Doc doc)
|
|||||||
|
|
||||||
if (cmd.length() == 0) {
|
if (cmd.length() == 0) {
|
||||||
QMessageBox::warning(0, "Recoll",
|
QMessageBox::warning(0, "Recoll",
|
||||||
tr("No external viewer configured for mime type ")
|
tr("No external viewer configured for mime type [")
|
||||||
+ doc.mimetype.c_str());
|
+ doc.mimetype.c_str() + "]");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -91,6 +91,22 @@ ResList::ResList(QWidget* parent, const char* name)
|
|||||||
|
|
||||||
ResList::~ResList()
|
ResList::~ResList()
|
||||||
{
|
{
|
||||||
|
// These have to exist somewhere for translations to work
|
||||||
|
#ifdef __GNUC__
|
||||||
|
__attribute__((unused))
|
||||||
|
#endif
|
||||||
|
static const char* strings[] = {
|
||||||
|
QT_TR_NOOP("<p><b>No results found</b><br>"),
|
||||||
|
QT_TR_NOOP("Documents <b>%d-%d</b> out of at least <b>%d</b> for "),
|
||||||
|
QT_TR_NOOP("Documents <b>%d-%d</b> for "),
|
||||||
|
QT_TR_NOOP("Previous"),
|
||||||
|
QT_TR_NOOP("Next"),
|
||||||
|
QT_TR_NOOP("Unavailable document"),
|
||||||
|
QT_TR_NOOP("Preview"),
|
||||||
|
QT_TR_NOOP("Open"),
|
||||||
|
QT_TR_NOOP("(show query)"),
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ResList::newListId()
|
int ResList::newListId()
|
||||||
@ -346,18 +362,6 @@ void ResList::resultPageFirst()
|
|||||||
|
|
||||||
void ResList::append(const QString &text)
|
void ResList::append(const QString &text)
|
||||||
{
|
{
|
||||||
// These has to go somewhere for translations to work
|
|
||||||
static const char* strings[] = {
|
|
||||||
QT_TR_NOOP("<p><b>No results found</b><br>"),
|
|
||||||
QT_TR_NOOP("Documents <b>%d-%d</b> out of at least <b>%d</b> for "),
|
|
||||||
QT_TR_NOOP("Documents <b>%d-%d</b> for "),
|
|
||||||
QT_TR_NOOP("Previous"),
|
|
||||||
QT_TR_NOOP("Next"),
|
|
||||||
QT_TR_NOOP("Unavailable document"),
|
|
||||||
QT_TR_NOOP("Preview"),
|
|
||||||
QT_TR_NOOP("Open"),
|
|
||||||
QT_TR_NOOP("(show query)"),
|
|
||||||
};
|
|
||||||
QTEXTBROWSER::append(text);
|
QTEXTBROWSER::append(text);
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
@ -565,12 +569,14 @@ RCLPOPUP *ResList::createPopupMenu(const QPoint& pos)
|
|||||||
popup->insertItem(tr("Copy &URL"), this, SLOT(menuCopyURL()));
|
popup->insertItem(tr("Copy &URL"), this, SLOT(menuCopyURL()));
|
||||||
Rcl::Doc doc;
|
Rcl::Doc doc;
|
||||||
if (getDoc(m_popDoc, doc) && !doc.ipath.empty()) {
|
if (getDoc(m_popDoc, doc) && !doc.ipath.empty()) {
|
||||||
popup->insertItem(tr("Save to File"), this, SLOT(menuSaveToFile()));
|
popup->insertItem(tr("&Write to File"), this, SLOT(menuSaveToFile()));
|
||||||
}
|
}
|
||||||
|
|
||||||
popup->insertItem(tr("Find &similar documents"), this, SLOT(menuExpand()));
|
popup->insertItem(tr("Find &similar documents"), this, SLOT(menuExpand()));
|
||||||
popup->insertItem(tr("P&arent document/folder"),
|
popup->insertItem(tr("Preview P&arent document/folder"),
|
||||||
this, SLOT(menuSeeParent()));
|
this, SLOT(menuPreviewParent()));
|
||||||
|
popup->insertItem(tr("&Open Parent document/folder"),
|
||||||
|
this, SLOT(menuOpenParent()));
|
||||||
return popup;
|
return popup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,20 +589,37 @@ void ResList::menuSaveToFile()
|
|||||||
emit docSaveToFileClicked(m_popDoc);
|
emit docSaveToFileClicked(m_popDoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResList::menuSeeParent()
|
void ResList::menuPreviewParent()
|
||||||
{
|
{
|
||||||
Rcl::Doc doc;
|
Rcl::Doc doc;
|
||||||
if (!getDoc(m_popDoc, doc))
|
if (!getDoc(m_popDoc, doc) || m_baseDocSource.isNull())
|
||||||
return;
|
return;
|
||||||
Rcl::Doc doc1;
|
Rcl::Doc pdoc;
|
||||||
if (FileInterner::getEnclosing(doc.url, doc.ipath, doc1.url, doc1.ipath)) {
|
if (m_baseDocSource->getEnclosing(doc, pdoc)) {
|
||||||
emit previewRequested(doc1);
|
emit previewRequested(pdoc);
|
||||||
} else {
|
} else {
|
||||||
// No parent doc: show enclosing folder with app configured for
|
// No parent doc: show enclosing folder with app configured for
|
||||||
// directories
|
// directories
|
||||||
doc1.url = path_getfather(doc.url);
|
pdoc.url = path_getfather(doc.url);
|
||||||
doc1.mimetype = "application/x-fsdirectory";
|
pdoc.mimetype = "application/x-fsdirectory";
|
||||||
emit editRequested(doc1);
|
emit editRequested(pdoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResList::menuOpenParent()
|
||||||
|
{
|
||||||
|
Rcl::Doc doc;
|
||||||
|
if (!getDoc(m_popDoc, doc) || m_baseDocSource.isNull())
|
||||||
|
return;
|
||||||
|
Rcl::Doc pdoc;
|
||||||
|
if (m_baseDocSource->getEnclosing(doc, pdoc)) {
|
||||||
|
emit editRequested(pdoc);
|
||||||
|
} else {
|
||||||
|
// No parent doc: show enclosing folder with app configured for
|
||||||
|
// directories
|
||||||
|
pdoc.url = path_getfather(doc.url);
|
||||||
|
pdoc.mimetype = "application/x-fsdirectory";
|
||||||
|
emit editRequested(pdoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -95,7 +95,8 @@ class ResList : public QTEXTBROWSER
|
|||||||
virtual void menuCopyFN();
|
virtual void menuCopyFN();
|
||||||
virtual void menuCopyURL();
|
virtual void menuCopyURL();
|
||||||
virtual void menuExpand();
|
virtual void menuExpand();
|
||||||
virtual void menuSeeParent();
|
virtual void menuPreviewParent();
|
||||||
|
virtual void menuOpenParent();
|
||||||
virtual void previewExposed(int);
|
virtual void previewExposed(int);
|
||||||
virtual void append(const QString &text);
|
virtual void append(const QString &text);
|
||||||
// Only used for qt ver >=4 but seems we cant undef it
|
// Only used for qt ver >=4 but seems we cant undef it
|
||||||
|
|||||||
@ -104,6 +104,8 @@ class DocSequence {
|
|||||||
return doc.meta[Rcl::Doc::keyabs];
|
return doc.meta[Rcl::Doc::keyabs];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool getEnclosing(Rcl::Doc&, Rcl::Doc&) {return false;}
|
||||||
|
|
||||||
/** Get estimated total count in results */
|
/** Get estimated total count in results */
|
||||||
virtual int getResCnt() = 0;
|
virtual int getResCnt() = 0;
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,7 @@ static char rcsid[] = "@(#$Id: docseqdb.cpp,v 1.9 2008-11-13 10:57:46 dockes Exp
|
|||||||
#include "docseqdb.h"
|
#include "docseqdb.h"
|
||||||
#include "rcldb.h"
|
#include "rcldb.h"
|
||||||
#include "debuglog.h"
|
#include "debuglog.h"
|
||||||
|
#include "internfile.h"
|
||||||
|
|
||||||
DocSequenceDb::DocSequenceDb(RefCntr<Rcl::Query> q, const string &t,
|
DocSequenceDb::DocSequenceDb(RefCntr<Rcl::Query> q, const string &t,
|
||||||
RefCntr<Rcl::SearchData> sdata)
|
RefCntr<Rcl::SearchData> sdata)
|
||||||
@ -78,6 +79,15 @@ string DocSequenceDb::getAbstract(Rcl::Doc &doc)
|
|||||||
return abstract.empty() ? doc.meta[Rcl::Doc::keyabs] : abstract;
|
return abstract.empty() ? doc.meta[Rcl::Doc::keyabs] : abstract;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DocSequenceDb::getEnclosing(Rcl::Doc& doc, Rcl::Doc& pdoc)
|
||||||
|
{
|
||||||
|
string udi;
|
||||||
|
if (!FileInterner::getEnclosing(doc.url, doc.ipath, pdoc.url, pdoc.ipath,
|
||||||
|
udi))
|
||||||
|
return false;
|
||||||
|
return m_q->whatDb()->getDoc(udi, pdoc);
|
||||||
|
}
|
||||||
|
|
||||||
list<string> DocSequenceDb::expand(Rcl::Doc &doc)
|
list<string> DocSequenceDb::expand(Rcl::Doc &doc)
|
||||||
{
|
{
|
||||||
return m_q->expand(doc);
|
return m_q->expand(doc);
|
||||||
|
|||||||
@ -36,6 +36,7 @@ class DocSequenceDb : public DocSequence {
|
|||||||
vector<vector<string> >& groups,
|
vector<vector<string> >& groups,
|
||||||
vector<int>& gslks);
|
vector<int>& gslks);
|
||||||
virtual string getAbstract(Rcl::Doc &doc);
|
virtual string getAbstract(Rcl::Doc &doc);
|
||||||
|
virtual bool getEnclosing(Rcl::Doc& doc, Rcl::Doc& pdoc);
|
||||||
virtual string getDescription();
|
virtual string getDescription();
|
||||||
virtual list<string> expand(Rcl::Doc &doc);
|
virtual list<string> expand(Rcl::Doc &doc);
|
||||||
virtual bool canFilter() {return true;}
|
virtual bool canFilter() {return true;}
|
||||||
|
|||||||
@ -24,6 +24,7 @@ static char rcsid[] = "@(#$Id: docseqhist.cpp,v 1.4 2008-09-29 08:59:20 dockes E
|
|||||||
#include "docseqhist.h"
|
#include "docseqhist.h"
|
||||||
#include "rcldb.h"
|
#include "rcldb.h"
|
||||||
#include "fileudi.h"
|
#include "fileudi.h"
|
||||||
|
#include "internfile.h"
|
||||||
|
|
||||||
bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, string *sh)
|
bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, string *sh)
|
||||||
{
|
{
|
||||||
@ -66,6 +67,15 @@ bool DocSequenceHistory::getDoc(int num, Rcl::Doc &doc, string *sh)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DocSequenceHistory::getEnclosing(Rcl::Doc& doc, Rcl::Doc& pdoc)
|
||||||
|
{
|
||||||
|
string udi;
|
||||||
|
if (!FileInterner::getEnclosing(doc.url, doc.ipath, pdoc.url, pdoc.ipath,
|
||||||
|
udi))
|
||||||
|
return false;
|
||||||
|
return m_db->getDoc(udi, pdoc);
|
||||||
|
}
|
||||||
|
|
||||||
int DocSequenceHistory::getResCnt()
|
int DocSequenceHistory::getResCnt()
|
||||||
{
|
{
|
||||||
if (m_hlist.empty())
|
if (m_hlist.empty())
|
||||||
|
|||||||
@ -35,6 +35,7 @@ class DocSequenceHistory : public DocSequence {
|
|||||||
virtual ~DocSequenceHistory() {}
|
virtual ~DocSequenceHistory() {}
|
||||||
|
|
||||||
virtual bool getDoc(int num, Rcl::Doc &doc, string *sh = 0);
|
virtual bool getDoc(int num, Rcl::Doc &doc, string *sh = 0);
|
||||||
|
virtual bool getEnclosing(Rcl::Doc& doc, Rcl::Doc& pdoc);
|
||||||
virtual int getResCnt();
|
virtual int getResCnt();
|
||||||
virtual string getDescription() {return m_description;}
|
virtual string getDescription() {return m_description;}
|
||||||
void setDescription(const string& desc) {m_description = desc;}
|
void setDescription(const string& desc) {m_description = desc;}
|
||||||
|
|||||||
@ -24,9 +24,8 @@ using std::string;
|
|||||||
// indexer). Document Ids are built from a concatenation of the file
|
// indexer). Document Ids are built from a concatenation of the file
|
||||||
// path and the internal path (ie: email number inside
|
// path and the internal path (ie: email number inside
|
||||||
// folder/attachment number/etc.) As the size of Xapian terms is
|
// folder/attachment number/etc.) As the size of Xapian terms is
|
||||||
// limited, the path is truncated to a maximum length, and completed
|
// limited, the Id path is truncated to a maximum length, and completed
|
||||||
// by a hash of the remainder. So the unique id looks like:
|
// by a hash of the remainder (including the ipath)
|
||||||
// /some/truncated/paHASHVALUE|ipath
|
|
||||||
|
|
||||||
extern void make_udi(const string& fn, const string& ipath, string &udi);
|
extern void make_udi(const string& fn, const string& ipath, string &udi);
|
||||||
|
|
||||||
|
|||||||
@ -176,13 +176,13 @@ TempFileInternal::~TempFileInternal()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void path_catslash(std::string &s) {
|
void path_catslash(string &s) {
|
||||||
if (s.empty() || s[s.length() - 1] != '/')
|
if (s.empty() || s[s.length() - 1] != '/')
|
||||||
s += '/';
|
s += '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string path_cat(const std::string &s1, const std::string &s2) {
|
string path_cat(const string &s1, const string &s2) {
|
||||||
std::string res = s1;
|
string res = s1;
|
||||||
path_catslash(res);
|
path_catslash(res);
|
||||||
res += s2;
|
res += s2;
|
||||||
return res;
|
return res;
|
||||||
@ -274,7 +274,7 @@ extern string path_tildexpand(const string &s)
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern std::string path_absolute(const std::string &is)
|
extern string path_absolute(const string &is)
|
||||||
{
|
{
|
||||||
if (is.length() == 0)
|
if (is.length() == 0)
|
||||||
return is;
|
return is;
|
||||||
@ -290,7 +290,7 @@ extern std::string path_absolute(const std::string &is)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include <smallut.h>
|
#include <smallut.h>
|
||||||
extern std::string path_canon(const std::string &is)
|
extern string path_canon(const string &is)
|
||||||
{
|
{
|
||||||
if (is.length() == 0)
|
if (is.length() == 0)
|
||||||
return is;
|
return is;
|
||||||
@ -330,8 +330,8 @@ extern std::string path_canon(const std::string &is)
|
|||||||
|
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
list<std::string> path_dirglob(const std::string &dir,
|
list<string> path_dirglob(const string &dir,
|
||||||
const std::string pattern)
|
const string pattern)
|
||||||
{
|
{
|
||||||
list<string> res;
|
list<string> res;
|
||||||
glob_t mglob;
|
glob_t mglob;
|
||||||
@ -356,7 +356,7 @@ bool path_isdir(const string& path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string url_encode(const std::string url, string::size_type offs)
|
string url_encode(const string& url, string::size_type offs)
|
||||||
{
|
{
|
||||||
string out = url.substr(0, offs);
|
string out = url.substr(0, offs);
|
||||||
const char *cp = url.c_str();
|
const char *cp = url.c_str();
|
||||||
@ -392,6 +392,26 @@ std::string url_encode(const std::string url, string::size_type offs)
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string url_gpath(const string& url)
|
||||||
|
{
|
||||||
|
// Remove the access schema part (or whatever it's called)
|
||||||
|
string::size_type colon = url.find_first_of(":");
|
||||||
|
if (colon == string::npos || colon == url.size() - 1)
|
||||||
|
return url;
|
||||||
|
// If there are non-alphanum chars before the ':', then there
|
||||||
|
// probably is no scheme. Whatever...
|
||||||
|
for (string::size_type i = 0; i < colon; i++) {
|
||||||
|
if (!isalnum(url.at(i)))
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In addition we canonize the path to remove empty host parts
|
||||||
|
// (for compatibility with older versions of recoll where file://
|
||||||
|
// was hardcoded, but the local path was used for doc
|
||||||
|
// identification.
|
||||||
|
return path_canon(url.substr(colon+1));
|
||||||
|
}
|
||||||
|
|
||||||
// Printable url: this is used to transcode from the system charset
|
// Printable url: this is used to transcode from the system charset
|
||||||
// into either utf-8 if transcoding succeeds, or url-encoded
|
// into either utf-8 if transcoding succeeds, or url-encoded
|
||||||
bool printableUrl(const string &fcharset, const string &in, string &out)
|
bool printableUrl(const string &fcharset, const string &in, string &out)
|
||||||
|
|||||||
@ -50,11 +50,16 @@ extern string path_canon(const string &s);
|
|||||||
extern list<string> path_dirglob(const string &dir,
|
extern list<string> path_dirglob(const string &dir,
|
||||||
const string pattern);
|
const string pattern);
|
||||||
/// Encode according to rfc 1738
|
/// Encode according to rfc 1738
|
||||||
extern string url_encode(const string url,
|
extern string url_encode(const string& url,
|
||||||
string::size_type offs = 0);
|
string::size_type offs = 0);
|
||||||
|
/// Transcode to utf-8 if possible or url encoding, for display.
|
||||||
extern bool printableUrl(const string &fcharset,
|
extern bool printableUrl(const string &fcharset,
|
||||||
const string &in, string &out);
|
const string &in, string &out);
|
||||||
|
|
||||||
|
/// Return the host+path part of an url. This is not a general
|
||||||
|
/// routine, it does the right thing only in the recoll context
|
||||||
|
extern string url_gpath(const string& url);
|
||||||
|
|
||||||
/// Stat parameter and check if it's a directory
|
/// Stat parameter and check if it's a directory
|
||||||
extern bool path_isdir(const string& path);
|
extern bool path_isdir(const string& path);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user