GUI: result table: when displaying content in the detail area, if the doc is a free-standing image, display it

This commit is contained in:
Jean-Francois Dockes 2021-07-04 17:19:38 +02:00
parent ae8fd0902a
commit e6055681d4
5 changed files with 147 additions and 131 deletions

View File

@ -61,6 +61,7 @@
#include "preview_plaintorich.h"
#include "rclmain_w.h"
#include "scbase.h"
#include "appformime.h"
// Make an attempt at trimming wildcard exprs at both ends of string
static void trimwildcards(string& elt)
@ -945,18 +946,16 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
editor->displayFields();
// If this is an image, display it instead of the text.
if (!idoc.mimetype.compare(0, 6, "image/")) {
if (mimeIsImage(idoc.mimetype)) {
string fn = fileurltolocalpath(idoc.url);
theconfig->setKeyDir(fn.empty() ? "" : path_getfather(fn));
// We want a real file, so if this comes from data or we have
// an ipath, create it.
// We want a real file, so if this comes from data or we have an ipath, create it.
if (fn.empty() || !idoc.ipath.empty()) {
TempFile temp = lthr.tmpimg;
if (temp.ok()) {
LOGDEB1("Preview: load: got temp file from internfile\n");
} else if (!FileInterner::idocToFile(temp, string(),
theconfig, idoc)) {
} else if (!FileInterner::idocToFile(temp, string(), theconfig, idoc)) {
temp = TempFile(); // just in case.
}
if (temp.ok()) {
@ -1137,10 +1136,8 @@ void PreviewTextEdit::displayImage()
m_image.height() > height()) {
m_image = m_image.scaled(width(), height(), Qt::KeepAspectRatio);
}
document()->addResource(QTextDocument::ImageResource, QUrl("image"),
m_image);
QTextCursor cursor = textCursor();
cursor.insertImage("image");
document()->addResource(QTextDocument::ImageResource, QUrl("image"), m_image);
textCursor().insertImage("image");
m_curdsp = PTE_DSPIMG;
}

View File

@ -147,9 +147,8 @@ void ResTableDetailArea::createPopupMenu(const QPoint& pos)
if (m_table && m_table->m_model && m_table->m_detaildocnum >= 0) {
int opts = m_table->m_ismainres ? ResultPopup::showExpand : 0;
opts |= ResultPopup::showSaveOne;
QMenu *popup = ResultPopup::create(m_table, opts,
m_table->m_model->getDocSource(),
m_table->m_detaildoc);
QMenu *popup = ResultPopup::create(
m_table, opts, m_table->m_model->getDocSource(), m_table->m_detaildoc);
popup->popup(mapToGlobal(pos));
}
}
@ -669,8 +668,7 @@ void ResTable::init()
m_detail->setOpenLinks(false);
m_detail->init();
// signals and slots connections
connect(m_detail, SIGNAL(anchorClicked(const QUrl &)),
this, SLOT(linkWasClicked(const QUrl &)));
connect(m_detail, SIGNAL(anchorClicked(const QUrl&)), this, SLOT(linkWasClicked(const QUrl&)));
splitter->addWidget(m_detail);
splitter->setOrientation(Qt::Vertical);
QVariant saved = settings.value(settingskey_splittersizes);
@ -767,21 +765,15 @@ void ResTable::setRclMain(RclMain *m, bool ismain)
tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
if (!m_ismainres) {
// don't set this shortcut when we are a child of main, would
// be duplicate/ambiguous
connect(new QShortcut(quitKeySeq, this), SIGNAL(activated()),
m_rclmain, SLOT (fileExit()));
// Don't set this shortcut when we are a child of main, would be duplicate/ambiguous
connect(new QShortcut(quitKeySeq, this), SIGNAL(activated()), m_rclmain, SLOT (fileExit()));
}
new QShortcut(closeKeySeq, this, SLOT (close()));
connect(this, SIGNAL(previewRequested(Rcl::Doc)),
m_rclmain, SLOT(startPreview(Rcl::Doc)));
connect(this, SIGNAL(editRequested(Rcl::Doc)),
m_rclmain, SLOT(startNativeViewer(Rcl::Doc)));
connect(this, SIGNAL(docSaveToFileClicked(Rcl::Doc)),
m_rclmain, SLOT(saveDocToFile(Rcl::Doc)));
connect(this, SIGNAL(showSnippets(Rcl::Doc)),
m_rclmain, SLOT(showSnippets(Rcl::Doc)));
connect(this, SIGNAL(previewRequested(Rcl::Doc)), m_rclmain, SLOT(startPreview(Rcl::Doc)));
connect(this, SIGNAL(editRequested(Rcl::Doc)), m_rclmain, SLOT(startNativeViewer(Rcl::Doc)));
connect(this, SIGNAL(docSaveToFileClicked(Rcl::Doc)), m_rclmain, SLOT(saveDocToFile(Rcl::Doc)));
connect(this, SIGNAL(showSnippets(Rcl::Doc)), m_rclmain, SLOT(showSnippets(Rcl::Doc)));
}
void ResTable::toggleHeader()
@ -911,39 +903,65 @@ void ResTable::onTableView_currentChanged(const QModelIndex& index)
if (!m_model || !m_model->getDocSource())
return;
Rcl::Doc doc;
if (m_model->getDocSource()->getDoc(index.row(), doc)) {
m_detail->init();
m_detaildocnum = index.row();
m_detaildoc = doc;
bool isShift = (QApplication::keyboardModifiers() & Qt::ShiftModifier);
bool showtext{false};
bool showmeta{false};
if (m_rowchangefromkbd) {
// Ctrl+... jump to row. Show text/meta as for simple click
if (hasselection) {
// When getting here from ctrl+... we get called twice, once with row 0
// and no selection, once with the actual row and selection. Only
// reset fromkbd and set showtext in the second case.
m_rowchangefromkbd = false;
showtext = prefs.resTableTextNoShift;
}
} else {
// Mouse click. Show text or meta depending on shift key. Never show text when hovering
// (no selection).
showtext = hasselection && (isShift ^ prefs.resTableTextNoShift);
}
if (!showtext) {
showmeta = hasselection || !prefs.resTableNoHoverMeta;
}
if (showtext && rcldb->getDocRawText(m_detaildoc)) {
m_detail->setPlainText(u8s2qs(m_detaildoc.text));
} else if (showmeta) {
m_pager->displaySingleDoc(theconfig, m_detaildocnum, m_detaildoc, m_model->m_hdata);
}
emit(detailDocChanged(doc, m_model->getDocSource()));
} else {
if (!m_model->getDocSource()->getDoc(index.row(), doc)) {
m_detaildocnum = -1;
return;
}
m_detail->init();
m_detaildocnum = index.row();
m_detaildoc = doc;
bool isShift = (QApplication::keyboardModifiers() & Qt::ShiftModifier);
bool showcontent{false};
bool showmeta{false};
if (m_rowchangefromkbd) {
// Ctrl+... jump to row. Show text/meta as for simple click
if (hasselection) {
// When getting here from ctrl+... we get called twice, once with row 0
// and no selection, once with the actual row and selection. Only
// reset fromkbd and set showcontent in the second case.
m_rowchangefromkbd = false;
showcontent = prefs.resTableTextNoShift;
}
} else {
// Mouse click. Show text or meta depending on shift key. Never show text when hovering
// (no selection).
showcontent = hasselection && (isShift ^ prefs.resTableTextNoShift);
}
if (!showcontent) {
showmeta = hasselection || !prefs.resTableNoHoverMeta;
}
bool displaydone{false};
if (showcontent) {
// If it's an image, and simply stored in a file, display it. We don't go to the trouble of
// extracting an embedded image here.
if (mimeIsImage(m_detaildoc.mimetype) && m_detaildoc.ipath.empty()) {
auto image = QImage(fileurltolocalpath(m_detaildoc.url).c_str());
if (!image.isNull()) {
m_detail->setPlainText("");
auto w = m_detail->width();
auto h = m_detail->height();
if (image.width() > w || image.height() > h) {
image = image.scaled(w, h, Qt::KeepAspectRatio);
}
m_detail->document()->addResource(QTextDocument::ImageResource,QUrl("image"),image);
m_detail->textCursor().insertImage("image");
displaydone = true;
}
}
if (!displaydone && rcldb->getDocRawText(m_detaildoc)) {
m_detail->setPlainText(u8s2qs(m_detaildoc.text));
displaydone = true;
}
}
if (!displaydone && showmeta) {
m_pager->displaySingleDoc(theconfig, m_detaildocnum, m_detaildoc, m_model->m_hdata);
}
emit(detailDocChanged(doc, m_model->getDocSource()));
}
void ResTable::on_tableView_entered(const QModelIndex& index)
@ -1163,8 +1181,7 @@ void ResTable::onDoubleClick(const QModelIndex& index)
void ResTable::createPopupMenu(const QPoint& pos)
{
LOGDEB("ResTable::createPopupMenu: m_detaildocnum " << m_detaildocnum <<
"\n");
LOGDEB("ResTable::createPopupMenu: m_detaildocnum " << m_detaildocnum << "\n");
if (m_detaildocnum >= 0 && m_model) {
int opts = m_ismainres? ResultPopup::isMain : 0;
@ -1177,8 +1194,7 @@ void ResTable::createPopupMenu(const QPoint& pos)
// docs are necessary subdocs and multisave only works with those.
opts |= ResultPopup::showSaveSel;
}
QMenu *popup = ResultPopup::create(this, opts, m_model->getDocSource(),
m_detaildoc);
QMenu *popup = ResultPopup::create(this, opts, m_model->getDocSource(), m_detaildoc);
popup->popup(mapToGlobal(pos));
}
}
@ -1343,8 +1359,7 @@ void ResTable::menuShowSubDocs()
void ResTable::createHeaderPopupMenu(const QPoint& pos)
{
LOGDEB("ResTable::createHeaderPopupMenu(" << pos.x() << ", " <<
pos.y() << ")\n");
LOGDEB("ResTable::createHeaderPopupMenu(" << pos.x() << ", " << pos.y() << ")\n");
QHeaderView *header = tableView->horizontalHeader();
if (!header || !m_model)
return;
@ -1386,10 +1401,10 @@ void ResTable::deleteColumn()
void ResTable::addColumn()
{
if (!m_model)
return;
QAction *action = (QAction *)sender();
LOGDEB("addColumn: text " << qs2utf8s(action->text()) << ", data " <<
qs2utf8s(action->data().toString()) << "\n");
m_model->addColumn(m_popcolumn, qs2utf8s(action->data().toString()));
if (nullptr == action || nullptr == m_model)
return;
std::string field = qs2utf8s(action->data().toString());
LOGDEB("addColumn: text " << qs2utf8s(action->text()) << ", field " << field << "\n");
m_model->addColumn(m_popcolumn, field);
}

View File

@ -0,0 +1,59 @@
#else // TEST_APPFORMIME
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
#include "appformime.h"
static char *thisprog;
static char usage [] =
" appformime <mime type>\n\n"
;
static void
Usage(void)
{
fprintf(stderr, "%s: usage:\n%s", thisprog, usage);
exit(1);
}
int main(int argc, char **argv)
{
thisprog = argv[0];
argc--; argv++;
if (argc != 1)
Usage();
string mime = *argv++;argc--;
string reason;
vector<DesktopDb::AppDef> appdefs;
DesktopDb *ddb = DesktopDb::getDb();
if (ddb == 0) {
cerr << "Could not create desktop db\n";
exit(1);
}
if (!ddb->appForMime(mime, &appdefs, &reason)) {
cerr << "appForMime failed: " << reason << endl;
exit(1);
}
if (appdefs.empty()) {
cerr << "No application found for [" << mime << "]" << endl;
exit(1);
}
cout << mime << " -> ";
for (vector<DesktopDb::AppDef>::const_iterator it = appdefs.begin();
it != appdefs.end(); it++) {
cout << "[" << it->name << ", " << it->command << "], ";
}
cout << endl;
exit(0);
}

View File

@ -14,7 +14,7 @@
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef TEST_APPFORMIME
#include <conftree.h>
#include <fstreewalk.h>
@ -33,9 +33,7 @@ static DesktopDb *theDb;
class FstCb : public FsTreeWalkerCB {
public:
FstCb(DesktopDb::AppMap *appdefs)
: m_appdefs(appdefs)
{
}
: m_appdefs(appdefs) {}
virtual FsTreeWalker::Status
processone(const string &, const struct PathStat *, FsTreeWalker::CbFlag);
DesktopDb::AppMap *m_appdefs;
@ -173,64 +171,8 @@ const string& DesktopDb::getReason()
return m_reason;
}
#else // TEST_APPFORMIME
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
#include "appformime.h"
static char *thisprog;
static char usage [] =
" appformime <mime type>\n\n"
;
static void
Usage(void)
bool mimeIsImage(const std::string& tp)
{
fprintf(stderr, "%s: usage:\n%s", thisprog, usage);
exit(1);
return !tp.compare(0, 6, "image/") &&
tp.compare("image/vnd.djvu") && tp.compare("image/svg+xml");
}
int main(int argc, char **argv)
{
thisprog = argv[0];
argc--; argv++;
if (argc != 1)
Usage();
string mime = *argv++;argc--;
string reason;
vector<DesktopDb::AppDef> appdefs;
DesktopDb *ddb = DesktopDb::getDb();
if (ddb == 0) {
cerr << "Could not create desktop db\n";
exit(1);
}
if (!ddb->appForMime(mime, &appdefs, &reason)) {
cerr << "appForMime failed: " << reason << endl;
exit(1);
}
if (appdefs.empty()) {
cerr << "No application found for [" << mime << "]" << endl;
exit(1);
}
cout << mime << " -> ";
for (vector<DesktopDb::AppDef>::const_iterator it = appdefs.begin();
it != appdefs.end(); it++) {
cout << "[" << it->name << ", " << it->command << "], ";
}
cout << endl;
exit(0);
}
#endif //TEST_APPFORMIME

View File

@ -88,4 +88,7 @@ private:
};
/** Helper function: is MIME type a simple image ? */
bool mimeIsImage(const std::string& tp);
#endif /* _APPFORMIME_H_INCLUDED_ */