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 "rclconfig.h"
|
||||
#include "mh_html.h"
|
||||
#include "fileudi.h"
|
||||
|
||||
#ifdef RCL_USE_XATTR
|
||||
#include "pxattr.h"
|
||||
#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
|
||||
// (ie message having a given attachment)
|
||||
bool FileInterner::getEnclosing(const string &url, const string &ipath,
|
||||
string &eurl, string &eipath)
|
||||
string &eurl, string &eipath, string& udi)
|
||||
{
|
||||
eurl = url;
|
||||
eipath = ipath;
|
||||
@ -98,6 +100,8 @@ bool FileInterner::getEnclosing(const string &url, const string &ipath,
|
||||
} else {
|
||||
eipath.erase();
|
||||
}
|
||||
make_udi(url_gpath(eurl), eipath, udi);
|
||||
|
||||
LOGDEB(("FileInterner::getEnclosing() after: [%s]\n", eipath.c_str()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ class FileInterner {
|
||||
* with Rcl::Db::addOrUpdate(). The latter is generally the enclosing file.
|
||||
*/
|
||||
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
|
||||
* 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) {
|
||||
QMessageBox::warning(0, "Recoll",
|
||||
tr("No external viewer configured for mime type ")
|
||||
+ doc.mimetype.c_str());
|
||||
tr("No external viewer configured for mime type [")
|
||||
+ doc.mimetype.c_str() + "]");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -91,6 +91,22 @@ ResList::ResList(QWidget* parent, const char* name)
|
||||
|
||||
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()
|
||||
@ -346,18 +362,6 @@ void ResList::resultPageFirst()
|
||||
|
||||
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);
|
||||
#if 0
|
||||
{
|
||||
@ -565,12 +569,14 @@ RCLPOPUP *ResList::createPopupMenu(const QPoint& pos)
|
||||
popup->insertItem(tr("Copy &URL"), this, SLOT(menuCopyURL()));
|
||||
Rcl::Doc doc;
|
||||
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("P&arent document/folder"),
|
||||
this, SLOT(menuSeeParent()));
|
||||
popup->insertItem(tr("Preview P&arent document/folder"),
|
||||
this, SLOT(menuPreviewParent()));
|
||||
popup->insertItem(tr("&Open Parent document/folder"),
|
||||
this, SLOT(menuOpenParent()));
|
||||
return popup;
|
||||
}
|
||||
|
||||
@ -583,20 +589,37 @@ void ResList::menuSaveToFile()
|
||||
emit docSaveToFileClicked(m_popDoc);
|
||||
}
|
||||
|
||||
void ResList::menuSeeParent()
|
||||
void ResList::menuPreviewParent()
|
||||
{
|
||||
Rcl::Doc doc;
|
||||
if (!getDoc(m_popDoc, doc))
|
||||
if (!getDoc(m_popDoc, doc) || m_baseDocSource.isNull())
|
||||
return;
|
||||
Rcl::Doc doc1;
|
||||
if (FileInterner::getEnclosing(doc.url, doc.ipath, doc1.url, doc1.ipath)) {
|
||||
emit previewRequested(doc1);
|
||||
Rcl::Doc pdoc;
|
||||
if (m_baseDocSource->getEnclosing(doc, pdoc)) {
|
||||
emit previewRequested(pdoc);
|
||||
} else {
|
||||
// No parent doc: show enclosing folder with app configured for
|
||||
// directories
|
||||
doc1.url = path_getfather(doc.url);
|
||||
doc1.mimetype = "application/x-fsdirectory";
|
||||
emit editRequested(doc1);
|
||||
pdoc.url = path_getfather(doc.url);
|
||||
pdoc.mimetype = "application/x-fsdirectory";
|
||||
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 menuCopyURL();
|
||||
virtual void menuExpand();
|
||||
virtual void menuSeeParent();
|
||||
virtual void menuPreviewParent();
|
||||
virtual void menuOpenParent();
|
||||
virtual void previewExposed(int);
|
||||
virtual void append(const QString &text);
|
||||
// Only used for qt ver >=4 but seems we cant undef it
|
||||
|
||||
@ -104,6 +104,8 @@ class DocSequence {
|
||||
return doc.meta[Rcl::Doc::keyabs];
|
||||
}
|
||||
|
||||
virtual bool getEnclosing(Rcl::Doc&, Rcl::Doc&) {return false;}
|
||||
|
||||
/** Get estimated total count in results */
|
||||
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 "rcldb.h"
|
||||
#include "debuglog.h"
|
||||
#include "internfile.h"
|
||||
|
||||
DocSequenceDb::DocSequenceDb(RefCntr<Rcl::Query> q, const string &t,
|
||||
RefCntr<Rcl::SearchData> sdata)
|
||||
@ -78,6 +79,15 @@ string DocSequenceDb::getAbstract(Rcl::Doc &doc)
|
||||
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)
|
||||
{
|
||||
return m_q->expand(doc);
|
||||
|
||||
@ -36,6 +36,7 @@ class DocSequenceDb : public DocSequence {
|
||||
vector<vector<string> >& groups,
|
||||
vector<int>& gslks);
|
||||
virtual string getAbstract(Rcl::Doc &doc);
|
||||
virtual bool getEnclosing(Rcl::Doc& doc, Rcl::Doc& pdoc);
|
||||
virtual string getDescription();
|
||||
virtual list<string> expand(Rcl::Doc &doc);
|
||||
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 "rcldb.h"
|
||||
#include "fileudi.h"
|
||||
#include "internfile.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
if (m_hlist.empty())
|
||||
|
||||
@ -35,6 +35,7 @@ class DocSequenceHistory : public DocSequence {
|
||||
virtual ~DocSequenceHistory() {}
|
||||
|
||||
virtual bool getDoc(int num, Rcl::Doc &doc, string *sh = 0);
|
||||
virtual bool getEnclosing(Rcl::Doc& doc, Rcl::Doc& pdoc);
|
||||
virtual int getResCnt();
|
||||
virtual string getDescription() {return m_description;}
|
||||
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
|
||||
// path and the internal path (ie: email number inside
|
||||
// folder/attachment number/etc.) As the size of Xapian terms is
|
||||
// limited, the path is truncated to a maximum length, and completed
|
||||
// by a hash of the remainder. So the unique id looks like:
|
||||
// /some/truncated/paHASHVALUE|ipath
|
||||
// limited, the Id path is truncated to a maximum length, and completed
|
||||
// by a hash of the remainder (including the ipath)
|
||||
|
||||
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] != '/')
|
||||
s += '/';
|
||||
}
|
||||
|
||||
std::string path_cat(const std::string &s1, const std::string &s2) {
|
||||
std::string res = s1;
|
||||
string path_cat(const string &s1, const string &s2) {
|
||||
string res = s1;
|
||||
path_catslash(res);
|
||||
res += s2;
|
||||
return res;
|
||||
@ -274,7 +274,7 @@ extern string path_tildexpand(const string &s)
|
||||
return o;
|
||||
}
|
||||
|
||||
extern std::string path_absolute(const std::string &is)
|
||||
extern string path_absolute(const string &is)
|
||||
{
|
||||
if (is.length() == 0)
|
||||
return is;
|
||||
@ -290,7 +290,7 @@ extern std::string path_absolute(const std::string &is)
|
||||
}
|
||||
|
||||
#include <smallut.h>
|
||||
extern std::string path_canon(const std::string &is)
|
||||
extern string path_canon(const string &is)
|
||||
{
|
||||
if (is.length() == 0)
|
||||
return is;
|
||||
@ -330,8 +330,8 @@ extern std::string path_canon(const std::string &is)
|
||||
|
||||
#include <glob.h>
|
||||
#include <sys/stat.h>
|
||||
list<std::string> path_dirglob(const std::string &dir,
|
||||
const std::string pattern)
|
||||
list<string> path_dirglob(const string &dir,
|
||||
const string pattern)
|
||||
{
|
||||
list<string> res;
|
||||
glob_t mglob;
|
||||
@ -356,7 +356,7 @@ bool path_isdir(const string& path)
|
||||
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);
|
||||
const char *cp = url.c_str();
|
||||
@ -392,6 +392,26 @@ std::string url_encode(const std::string url, string::size_type offs)
|
||||
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
|
||||
// into either utf-8 if transcoding succeeds, or url-encoded
|
||||
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,
|
||||
const string pattern);
|
||||
/// Encode according to rfc 1738
|
||||
extern string url_encode(const string url,
|
||||
extern string url_encode(const string& url,
|
||||
string::size_type offs = 0);
|
||||
/// Transcode to utf-8 if possible or url encoding, for display.
|
||||
extern bool printableUrl(const string &fcharset,
|
||||
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
|
||||
extern bool path_isdir(const string& path);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user