GUI: add popup menu option to copy simple file name. fix typo keytcfn->keyctfn. Change utf8check() parms for easier usage
This commit is contained in:
parent
fbec7a6adb
commit
8da0bf28cc
@ -800,7 +800,7 @@ FsIndexer::processonefile(RclConfig *config,
|
|||||||
doc.meta[Rcl::Doc::keyfn] = utf8fn;
|
doc.meta[Rcl::Doc::keyfn] = utf8fn;
|
||||||
}
|
}
|
||||||
// Set container file name for all docs, top or subdoc
|
// Set container file name for all docs, top or subdoc
|
||||||
doc.meta[Rcl::Doc::keytcfn] = utf8fn;
|
doc.meta[Rcl::Doc::keyctfn] = utf8fn;
|
||||||
|
|
||||||
doc.pcbytes = lltodecstr(stp->pst_size);
|
doc.pcbytes = lltodecstr(stp->pst_size);
|
||||||
// Document signature for up to date checks. All subdocs inherit the
|
// Document signature for up to date checks. All subdocs inherit the
|
||||||
@ -900,8 +900,7 @@ FsIndexer::processonefile(RclConfig *config,
|
|||||||
fileDoc.onlyxattr = true;
|
fileDoc.onlyxattr = true;
|
||||||
} else {
|
} else {
|
||||||
fileDoc.fmtime = ascdate;
|
fileDoc.fmtime = ascdate;
|
||||||
fileDoc.meta[Rcl::Doc::keyfn] =
|
fileDoc.meta[Rcl::Doc::keyfn] = fileDoc.meta[Rcl::Doc::keyctfn] = utf8fn;
|
||||||
fileDoc.meta[Rcl::Doc::keytcfn] = utf8fn;
|
|
||||||
fileDoc.haschildren = true;
|
fileDoc.haschildren = true;
|
||||||
fileDoc.mimetype = mimetype;
|
fileDoc.mimetype = mimetype;
|
||||||
fileDoc.url = path_pathtofileurl(fn);
|
fileDoc.url = path_pathtofileurl(fn);
|
||||||
|
|||||||
@ -121,7 +121,7 @@ bool RecollFilter::txtdcode(const string& who)
|
|||||||
// utf-8. We check if the text is actually utf-8. This is worth
|
// utf-8. We check if the text is actually utf-8. This is worth
|
||||||
// it, else the conversion from 8-bit is going to succeed if the
|
// it, else the conversion from 8-bit is going to succeed if the
|
||||||
// text is already utf-8, and produce bogus data.
|
// text is already utf-8, and produce bogus data.
|
||||||
if (utf8check(itext, otext) >= 0) {
|
if (utf8check(itext) >= 0) {
|
||||||
m_metaData[cstr_dj_keycharset] = cstr_utf8;
|
m_metaData[cstr_dj_keycharset] = cstr_utf8;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1270,6 +1270,13 @@ void ResList::menuCopyFN()
|
|||||||
ResultPopup::copyFN(doc);
|
ResultPopup::copyFN(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResList::menuCopyPath()
|
||||||
|
{
|
||||||
|
Rcl::Doc doc;
|
||||||
|
if (getDoc(m_popDoc, doc))
|
||||||
|
ResultPopup::copyPath(doc);
|
||||||
|
}
|
||||||
|
|
||||||
void ResList::menuCopyText()
|
void ResList::menuCopyText()
|
||||||
{
|
{
|
||||||
Rcl::Doc doc;
|
Rcl::Doc doc;
|
||||||
|
|||||||
@ -81,6 +81,7 @@ public slots:
|
|||||||
virtual void menuEdit();
|
virtual void menuEdit();
|
||||||
virtual void menuOpenWith(QAction *);
|
virtual void menuOpenWith(QAction *);
|
||||||
virtual void menuCopyFN();
|
virtual void menuCopyFN();
|
||||||
|
virtual void menuCopyPath();
|
||||||
virtual void menuCopyURL();
|
virtual void menuCopyURL();
|
||||||
virtual void menuCopyText();
|
virtual void menuCopyText();
|
||||||
virtual void menuExpand();
|
virtual void menuExpand();
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
#include "respopup.h"
|
#include "respopup.h"
|
||||||
#include "appformime.h"
|
#include "appformime.h"
|
||||||
#include "rclmain_w.h"
|
#include "rclmain_w.h"
|
||||||
|
#include "utf8iter.h"
|
||||||
|
|
||||||
namespace ResultPopup {
|
namespace ResultPopup {
|
||||||
|
|
||||||
@ -95,9 +96,10 @@ QMenu *create(QWidget *me, int opts, std::shared_ptr<DocSequence> source,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (doc.isFsFile()) {
|
if (doc.isFsFile()) {
|
||||||
popup->addAction(QWidget::tr("Copy &File Path"), me, SLOT(menuCopyFN()));
|
popup->addAction(QWidget::tr("Copy &File Path"), me, SLOT(menuCopyPath()));
|
||||||
}
|
}
|
||||||
popup->addAction(QWidget::tr("Copy &URL"), me, SLOT(menuCopyURL()));
|
popup->addAction(QWidget::tr("Copy &URL"), me, SLOT(menuCopyURL()));
|
||||||
|
popup->addAction(QWidget::tr("Copy File Name"), me, SLOT(menuCopyFN()));
|
||||||
popup->addAction(QWidget::tr("Copy Text"), me, SLOT(menuCopyText()));
|
popup->addAction(QWidget::tr("Copy Text"), me, SLOT(menuCopyText()));
|
||||||
|
|
||||||
if ((opts&showSaveOne) && !(isFsTop))
|
if ((opts&showSaveOne) && !(isFsTop))
|
||||||
@ -158,24 +160,52 @@ Rcl::Doc getFolder(Rcl::Doc& doc)
|
|||||||
return pdoc;
|
return pdoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const std::string twoslash{"//"};
|
||||||
|
void copyPath(const Rcl::Doc &doc)
|
||||||
|
{
|
||||||
|
auto pos = doc.url.find(twoslash);
|
||||||
|
std::string path;
|
||||||
|
if (pos == std::string::npos) {
|
||||||
|
path = doc.url; // ??
|
||||||
|
} else {
|
||||||
|
path = doc.url.substr(pos+2);
|
||||||
|
}
|
||||||
|
// Problem: setText expects a QString. Passing a (const char*) as
|
||||||
|
// we used to do causes an implicit conversion from latin1. File
|
||||||
|
// are binary and the right approach would be no conversion, but
|
||||||
|
// it's probably better (less worse...) to make a "best effort"
|
||||||
|
// tentative and try to convert from the locale's charset than
|
||||||
|
// accept the default conversion. This is unlikely to yield a
|
||||||
|
// usable path for binary paths in non-utf8 locales though.
|
||||||
|
QString qpath = path2qs(path);
|
||||||
|
QApplication::clipboard()->setText(qpath, QClipboard::Selection);
|
||||||
|
QApplication::clipboard()->setText(qpath, QClipboard::Clipboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is typically used to add the file name to the query string, so
|
||||||
|
// we want the values as search terms here, not the binary from the
|
||||||
|
// url.
|
||||||
void copyFN(const Rcl::Doc &doc)
|
void copyFN(const Rcl::Doc &doc)
|
||||||
{
|
{
|
||||||
// Our urls currently always begin with "file://"
|
std::string fn;
|
||||||
//
|
doc.getmeta(Rcl::Doc::keyfn, &fn);
|
||||||
// Problem: setText expects a QString. Passing a (const char*)
|
QString qpath = u8s2qs(fn);
|
||||||
// as we used to do causes an implicit conversion from
|
QApplication::clipboard()->setText(qpath, QClipboard::Selection);
|
||||||
// latin1. File are binary and the right approach would be no
|
QApplication::clipboard()->setText(qpath, QClipboard::Clipboard);
|
||||||
// conversion, but it's probably better (less worse...) to
|
|
||||||
// make a "best effort" tentative and try to convert from the
|
|
||||||
// locale's charset than accept the default conversion.
|
|
||||||
QString qfn = path2qs(doc.url.c_str()+7);
|
|
||||||
QApplication::clipboard()->setText(qfn, QClipboard::Selection);
|
|
||||||
QApplication::clipboard()->setText(qfn, QClipboard::Clipboard);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void copyURL(const Rcl::Doc &doc)
|
void copyURL(const Rcl::Doc &doc)
|
||||||
{
|
{
|
||||||
QString url = path2qs(doc.url);
|
QString url;
|
||||||
|
#ifdef _WIN32
|
||||||
|
url = u8s2qs(doc.url);
|
||||||
|
#else
|
||||||
|
if (utf8check(doc.url)) {
|
||||||
|
url = u8s2qs(doc.url);
|
||||||
|
} else {
|
||||||
|
url = u8s2qs(url_encode(doc.url));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
QApplication::clipboard()->setText(url, QClipboard::Selection);
|
QApplication::clipboard()->setText(url, QClipboard::Selection);
|
||||||
QApplication::clipboard()->setText(url, QClipboard::Clipboard);
|
QApplication::clipboard()->setText(url, QClipboard::Clipboard);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,7 @@ extern Rcl::Doc getParent(std::shared_ptr<DocSequence> source,
|
|||||||
Rcl::Doc& doc);
|
Rcl::Doc& doc);
|
||||||
extern Rcl::Doc getFolder(Rcl::Doc& doc);
|
extern Rcl::Doc getFolder(Rcl::Doc& doc);
|
||||||
extern void copyFN(const Rcl::Doc &doc);
|
extern void copyFN(const Rcl::Doc &doc);
|
||||||
|
extern void copyPath(const Rcl::Doc &doc);
|
||||||
extern void copyURL(const Rcl::Doc &doc);
|
extern void copyURL(const Rcl::Doc &doc);
|
||||||
extern void copyText(Rcl::Doc &doc, RclMain *rclmain=nullptr);
|
extern void copyText(Rcl::Doc &doc, RclMain *rclmain=nullptr);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1255,6 +1255,12 @@ void ResTable::menuCopyFN()
|
|||||||
ResultPopup::copyFN(m_detaildoc);
|
ResultPopup::copyFN(m_detaildoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResTable::menuCopyPath()
|
||||||
|
{
|
||||||
|
if (m_detaildocnum >= 0)
|
||||||
|
ResultPopup::copyPath(m_detaildoc);
|
||||||
|
}
|
||||||
|
|
||||||
void ResTable::menuCopyURL()
|
void ResTable::menuCopyURL()
|
||||||
{
|
{
|
||||||
if (m_detaildocnum >= 0)
|
if (m_detaildocnum >= 0)
|
||||||
|
|||||||
@ -169,6 +169,7 @@ public slots:
|
|||||||
virtual void menuEditAndQuit();
|
virtual void menuEditAndQuit();
|
||||||
virtual void menuOpenWith(QAction *);
|
virtual void menuOpenWith(QAction *);
|
||||||
virtual void menuCopyFN();
|
virtual void menuCopyFN();
|
||||||
|
virtual void menuCopyPath();
|
||||||
virtual void menuCopyURL();
|
virtual void menuCopyURL();
|
||||||
virtual void menuCopyText();
|
virtual void menuCopyText();
|
||||||
virtual void menuExpand();
|
virtual void menuExpand();
|
||||||
|
|||||||
@ -1845,10 +1845,8 @@ bool Db::addOrUpdate(const string &udi, const string &parent_udi, Doc &doc)
|
|||||||
// purposes.
|
// purposes.
|
||||||
const string *fnp = 0;
|
const string *fnp = 0;
|
||||||
if (!doc.peekmeta(Rcl::Doc::keyfn, &fnp) || fnp->empty()) {
|
if (!doc.peekmeta(Rcl::Doc::keyfn, &fnp) || fnp->empty()) {
|
||||||
if (doc.peekmeta(Rcl::Doc::keytcfn, &fnp) && !fnp->empty()) {
|
if (doc.peekmeta(Rcl::Doc::keyctfn, &fnp) && !fnp->empty()) {
|
||||||
string value =
|
string value = neutchars(truncate_to_word(*fnp, m_idxMetaStoredLen), cstr_nc);
|
||||||
neutchars(truncate_to_word(*fnp,
|
|
||||||
m_idxMetaStoredLen), cstr_nc);
|
|
||||||
RECORD_APPEND(record, Rcl::Doc::keyfn, value);
|
RECORD_APPEND(record, Rcl::Doc::keyfn, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,7 @@ const string Doc::keydmt("dmtime");
|
|||||||
const string Doc::keyds("dbytes");
|
const string Doc::keyds("dbytes");
|
||||||
const string Doc::keyfmt("fmtime");
|
const string Doc::keyfmt("fmtime");
|
||||||
const string Doc::keyfn("filename");
|
const string Doc::keyfn("filename");
|
||||||
const string Doc::keytcfn("containerfilename");
|
const string Doc::keyctfn("containerfilename");
|
||||||
const string Doc::keyfs("fbytes");
|
const string Doc::keyfs("fbytes");
|
||||||
const string Doc::keyipt("ipath");
|
const string Doc::keyipt("ipath");
|
||||||
const string Doc::keykw("keywords");
|
const string Doc::keykw("keywords");
|
||||||
|
|||||||
@ -233,7 +233,7 @@ public:
|
|||||||
// given top level container. It is not indexed by default but
|
// given top level container. It is not indexed by default but
|
||||||
// stored in the document record keyfn field if this is still
|
// stored in the document record keyfn field if this is still
|
||||||
// empty when we create it, for display purposes.
|
// empty when we create it, for display purposes.
|
||||||
static const std::string keytcfn;
|
static const std::string keyctfn;
|
||||||
static const std::string keyipt; // ipath
|
static const std::string keyipt; // ipath
|
||||||
static const std::string keytp; // mime type
|
static const std::string keytp; // mime type
|
||||||
static const std::string keyfmt; // file mtime
|
static const std::string keyfmt; // file mtime
|
||||||
|
|||||||
@ -13,6 +13,7 @@ static std::map<std::string, int> options {
|
|||||||
{"path_home", 0},
|
{"path_home", 0},
|
||||||
{"path_tildexpand", 0},
|
{"path_tildexpand", 0},
|
||||||
{"listdir", 0},
|
{"listdir", 0},
|
||||||
|
{"url_encode", 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *thisprog;
|
static const char *thisprog;
|
||||||
@ -55,19 +56,34 @@ int main(int argc, char **argv)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
string s = argv[optind];
|
string s = argv[optind];
|
||||||
argc--;
|
optind++;
|
||||||
if (optind != argc) {
|
if (optind != argc) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
cout << "path_tildexpand(" << s << ") -> [" << path_tildexpand(s) <<
|
cout << "path_tildexpand(" << s << ") -> [" << path_tildexpand(s) << "]\n";
|
||||||
"]\n";
|
} else if (options["url_encode"]) {
|
||||||
|
if (optind >= argc) {
|
||||||
|
cerr << "Usage: trsmallut --url_encode <arg> [offs=0]\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
string s = argv[optind];
|
||||||
|
optind++;
|
||||||
|
int offs = 0;
|
||||||
|
if (optind != argc) {
|
||||||
|
offs = atoi(argv[optind]);
|
||||||
|
optind++;
|
||||||
|
}
|
||||||
|
if (optind != argc) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
cout << "url_encode(" << s << ", " << offs << ") -> [" << url_encode(s, offs) << "]\n";
|
||||||
} else if (options["listdir"]) {
|
} else if (options["listdir"]) {
|
||||||
if (optind >= argc) {
|
if (optind >= argc) {
|
||||||
cerr << "Usage: trsmallut --listdir <arg>\n";
|
cerr << "Usage: trsmallut --listdir <arg>\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
std::string path = argv[optind];
|
std::string path = argv[optind];
|
||||||
argc--;
|
optind++;
|
||||||
if (optind != argc) {
|
if (optind != argc) {
|
||||||
cerr << "Usage: trsmallut --listdir <arg>\n";
|
cerr << "Usage: trsmallut --listdir <arg>\n";
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@ -94,7 +94,7 @@ size_t utf8len(const string& s)
|
|||||||
static const std::string replchar{"\xef\xbf\xbd"};
|
static const std::string replchar{"\xef\xbf\xbd"};
|
||||||
|
|
||||||
// Check utf-8 encoding, replacing errors with the ? char above
|
// Check utf-8 encoding, replacing errors with the ? char above
|
||||||
int utf8check(const std::string& in, std::string& out, bool fixit, int maxrepl)
|
int utf8check(const std::string& in, bool fixit, std::string *out, int maxrepl)
|
||||||
{
|
{
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
Utf8Iter it(in);
|
Utf8Iter it(in);
|
||||||
@ -103,7 +103,7 @@ int utf8check(const std::string& in, std::string& out, bool fixit, int maxrepl)
|
|||||||
if (!fixit) {
|
if (!fixit) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
out += replchar;
|
*out += replchar;
|
||||||
++cnt;
|
++cnt;
|
||||||
for (; cnt < maxrepl; cnt++) {
|
for (; cnt < maxrepl; cnt++) {
|
||||||
it.retryfurther();
|
it.retryfurther();
|
||||||
@ -111,7 +111,7 @@ int utf8check(const std::string& in, std::string& out, bool fixit, int maxrepl)
|
|||||||
return cnt;
|
return cnt;
|
||||||
if (!it.error())
|
if (!it.error())
|
||||||
break;
|
break;
|
||||||
out += replchar;
|
*out += replchar;
|
||||||
}
|
}
|
||||||
if (it.error()) {
|
if (it.error()) {
|
||||||
return -1;
|
return -1;
|
||||||
@ -119,7 +119,7 @@ int utf8check(const std::string& in, std::string& out, bool fixit, int maxrepl)
|
|||||||
}
|
}
|
||||||
// We have reached a good char and eof is false
|
// We have reached a good char and eof is false
|
||||||
if (fixit) {
|
if (fixit) {
|
||||||
it.appendchartostring(out);
|
it.appendchartostring(*out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return cnt;
|
return cnt;
|
||||||
|
|||||||
@ -305,6 +305,6 @@ size_t utf8len(const std::string& s);
|
|||||||
* 0 or positive: replacement count.
|
* 0 or positive: replacement count.
|
||||||
*/
|
*/
|
||||||
int utf8check(
|
int utf8check(
|
||||||
const std::string& in, std::string& out, bool fixit=false, int maxrepl=100);
|
const std::string& in, bool fixit=false, std::string* out = nullptr, int maxrepl=100);
|
||||||
|
|
||||||
#endif /* _UTF8ITER_H_INCLUDED_ */
|
#endif /* _UTF8ITER_H_INCLUDED_ */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user