GUI reslist: fixed webengine image display issue, but failed with reliably getting scroll position for paging (cf QTBUG-105842)
This commit is contained in:
parent
426fee8a86
commit
8bd38a858d
@ -149,7 +149,7 @@ public:
|
|||||||
// Now also set for webkit because, as we set baseURL to file://,
|
// Now also set for webkit because, as we set baseURL to file://,
|
||||||
// the relative links we set in the list will also be prefixed (by
|
// the relative links we set in the list will also be prefixed (by
|
||||||
// the HTML engine)
|
// the HTML engine)
|
||||||
virtual string linkPrefix() override {return "file:///";}
|
virtual string linkPrefix() override {return "file:///recoll-links/";}
|
||||||
virtual string bodyAttrs() override {
|
virtual string bodyAttrs() override {
|
||||||
return "onload=\"addEventListener('contextmenu', saveLoc)\"";
|
return "onload=\"addEventListener('contextmenu', saveLoc)\"";
|
||||||
}
|
}
|
||||||
@ -305,17 +305,21 @@ ResList::ResList(QWidget* parent, const char* name)
|
|||||||
|
|
||||||
#if defined(USING_WEBKIT) || defined(USING_WEBENGINE)
|
#if defined(USING_WEBKIT) || defined(USING_WEBENGINE)
|
||||||
setPage(new RclWebPage(this));
|
setPage(new RclWebPage(this));
|
||||||
|
settings()->setAttribute(QWEBSETTINGS::JavascriptEnabled, true);
|
||||||
#ifdef USING_WEBKIT
|
#ifdef USING_WEBKIT
|
||||||
LOGDEB("Reslist: using Webkit\n");
|
LOGDEB("Reslist: using Webkit\n");
|
||||||
page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
|
page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
|
||||||
// signals and slots connections
|
// signals and slots connections
|
||||||
connect(this, SIGNAL(linkClicked(const QUrl &)),
|
connect(this, SIGNAL(linkClicked(const QUrl &)), this, SLOT(onLinkClicked(const QUrl &)));
|
||||||
this, SLOT(onLinkClicked(const QUrl &)));
|
|
||||||
#else
|
#else
|
||||||
LOGDEB("Reslist: using Webengine\n");
|
LOGDEB("Reslist: using Webengine\n");
|
||||||
connect(page(), SIGNAL(loadFinished(bool)), this, SLOT(runStoredJS(bool)));
|
connect(page(), SIGNAL(loadFinished(bool)), this, SLOT(runStoredJS(bool)));
|
||||||
|
// These appear to get randomly disconnected or never connected.
|
||||||
|
connect(page(), SIGNAL(scrollPositionChanged(const QPointF &)),
|
||||||
|
this, SLOT(onPageScrollPositionChanged(const QPointF &)));
|
||||||
|
connect(page(), SIGNAL(contentsSizeChanged(const QSizeF &)),
|
||||||
|
this, SLOT(onPageContentsSizeChanged(const QSizeF &)));
|
||||||
#endif
|
#endif
|
||||||
settings()->setAttribute(QWEBSETTINGS::JavascriptEnabled, true);
|
|
||||||
#else
|
#else
|
||||||
LOGDEB("Reslist: using QTextBrowser\n");
|
LOGDEB("Reslist: using QTextBrowser\n");
|
||||||
setReadOnly(true);
|
setReadOnly(true);
|
||||||
@ -323,8 +327,7 @@ ResList::ResList(QWidget* parent, const char* name)
|
|||||||
setOpenLinks(false);
|
setOpenLinks(false);
|
||||||
setTabChangesFocus(true);
|
setTabChangesFocus(true);
|
||||||
// signals and slots connections
|
// signals and slots connections
|
||||||
connect(this, SIGNAL(anchorClicked(const QUrl &)),
|
connect(this, SIGNAL(anchorClicked(const QUrl &)), this, SLOT(onLinkClicked(const QUrl &)));
|
||||||
this, SLOT(onLinkClicked(const QUrl &)));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setFont();
|
setFont();
|
||||||
@ -388,6 +391,20 @@ void ResList::setRclMain(RclMain *m, bool ismain)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(USING_WEBKIT) || defined(USING_WEBENGINE)
|
||||||
|
|
||||||
|
void ResList::runJS(const QString& js)
|
||||||
|
{
|
||||||
|
LOGDEB("runJS: " << qs2utf8s(js) << "\n");
|
||||||
|
#if defined(USING_WEBKIT)
|
||||||
|
page()->mainFrame()->evaluateJavaScript(js);
|
||||||
|
#elif defined(USING_WEBENGINE)
|
||||||
|
page()->runJavaScript(js);
|
||||||
|
// page()->runJavaScript(js, [](const QVariant &v) {qDebug() << v.toString();});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(USING_WEBENGINE)
|
||||||
void ResList::runStoredJS(bool res)
|
void ResList::runStoredJS(bool res)
|
||||||
{
|
{
|
||||||
if (m_js.isEmpty()) {
|
if (m_js.isEmpty()) {
|
||||||
@ -403,17 +420,39 @@ void ResList::runStoredJS(bool res)
|
|||||||
m_js.clear();
|
m_js.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResList::runJS(const QString& js)
|
void ResList::onPageScrollPositionChanged(const QPointF &position)
|
||||||
{
|
{
|
||||||
#if defined(USING_WEBKIT)
|
LOGDEB0("ResList::onPageScrollPositionChanged: y : " << position.y() << "\n");
|
||||||
page()->mainFrame()->evaluateJavaScript(js);
|
m_scrollpos = position;
|
||||||
#elif defined(USING_WEBENGINE)
|
|
||||||
page()->runJavaScript(js);
|
|
||||||
#else
|
|
||||||
Q_UNUSED(js);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ResList::onPageContentsSizeChanged(const QSizeF &size)
|
||||||
|
{
|
||||||
|
LOGDEB0("ResList::onPageContentsSizeChanged: y : " << size.height() << "\n");
|
||||||
|
m_contentsize = size;
|
||||||
|
}
|
||||||
|
#endif // WEBENGINE
|
||||||
|
|
||||||
|
static void maybeDump(const QString& text)
|
||||||
|
{
|
||||||
|
std::string dumpfile;
|
||||||
|
if (!theconfig->getConfParam("reslisthtmldumpfile", dumpfile) || dumpfile.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dumpfile = path_tildexpand(dumpfile);
|
||||||
|
if (path_exists(dumpfile)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto fp = fopen(dumpfile.c_str(), "w");
|
||||||
|
if (fp) {
|
||||||
|
auto s = qs2utf8s(text);
|
||||||
|
fwrite(s.c_str(), 1, s.size(), fp);
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // WEBKIT or WEBENGINE
|
||||||
|
|
||||||
void ResList::onUiPrefsChanged()
|
void ResList::onUiPrefsChanged()
|
||||||
{
|
{
|
||||||
setFont();
|
setFont();
|
||||||
@ -454,7 +493,7 @@ void ResList::setDocSource(std::shared_ptr<DocSequence> nsource)
|
|||||||
void ResList::readDocSource()
|
void ResList::readDocSource()
|
||||||
{
|
{
|
||||||
LOGDEB("ResList::readDocSource()\n");
|
LOGDEB("ResList::readDocSource()\n");
|
||||||
resetView();
|
m_curPvDoc = -1;
|
||||||
if (!m_source)
|
if (!m_source)
|
||||||
return;
|
return;
|
||||||
m_listId = newListId();
|
m_listId = newListId();
|
||||||
@ -648,9 +687,9 @@ void ResList::resPageUpOrBack()
|
|||||||
setupArrows();
|
setupArrows();
|
||||||
#elif defined(USING_WEBENGINE)
|
#elif defined(USING_WEBENGINE)
|
||||||
if (scrollIsAtTop()) {
|
if (scrollIsAtTop()) {
|
||||||
// Displaypage first calls resetview() which causes a page load event. We want to run the js
|
// Displaypage used to call resetview() which caused a page load event. We wanted to run the
|
||||||
// on the second event.
|
// js on the second event, with countdown = 1. Not needed any more, but kept around.
|
||||||
m_js_countdown = 1;
|
m_js_countdown = 0;
|
||||||
m_js = "window.scrollBy(0,50000);";
|
m_js = "window.scrollBy(0,50000);";
|
||||||
resultPageBack();
|
resultPageBack();
|
||||||
} else {
|
} else {
|
||||||
@ -677,8 +716,10 @@ void ResList::resPageDownOrNext()
|
|||||||
setupArrows();
|
setupArrows();
|
||||||
#elif defined(USING_WEBENGINE)
|
#elif defined(USING_WEBENGINE)
|
||||||
if (scrollIsAtBottom()) {
|
if (scrollIsAtBottom()) {
|
||||||
|
LOGDEB0("downOrNext: at bottom: call resultPageNext\n");
|
||||||
resultPageNext();
|
resultPageNext();
|
||||||
} else {
|
} else {
|
||||||
|
LOGDEB0("downOrNext: scroll\n");
|
||||||
QString js = QString("window.scrollBy(%1, %2);").arg(0).arg(int(0.9*geometry().height()));
|
QString js = QString("window.scrollBy(%1, %2);").arg(0).arg(int(0.9*geometry().height()));
|
||||||
runJS(js);
|
runJS(js);
|
||||||
}
|
}
|
||||||
@ -693,12 +734,6 @@ void ResList::resPageDownOrNext()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResList::setupArrows()
|
|
||||||
{
|
|
||||||
emit prevPageAvailable(m_pager->hasPrev() || !scrollIsAtTop());
|
|
||||||
emit nextPageAvailable(m_pager->hasNext() || !scrollIsAtBottom());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ResList::scrollIsAtBottom()
|
bool ResList::scrollIsAtBottom()
|
||||||
{
|
{
|
||||||
#if defined(USING_WEBKIT)
|
#if defined(USING_WEBKIT)
|
||||||
@ -715,10 +750,20 @@ bool ResList::scrollIsAtBottom()
|
|||||||
LOGDEB2("scrollIsAtBottom: returning " << ret << "\n");
|
LOGDEB2("scrollIsAtBottom: returning " << ret << "\n");
|
||||||
return ret;
|
return ret;
|
||||||
#elif defined(USING_WEBENGINE)
|
#elif defined(USING_WEBENGINE)
|
||||||
QSize css = page()->contentsSize().toSize();
|
// TLDR: Could not find any way whatsoever to reliably get the page contents size or position
|
||||||
|
// with either signals or direct calls. No obvious way to get this from javascript either. This
|
||||||
|
// used to work, with direct calls and broke down around qt 5.15
|
||||||
|
|
||||||
QSize wss = size();
|
QSize wss = size();
|
||||||
QPoint sp = page()->scrollPosition().toPoint();
|
|
||||||
LOGDEB1("atBottom: contents W " << css.width() << " H " << css.height() <<
|
//QSize css = page()->contentsSize().toSize();
|
||||||
|
QSize css = m_contentsize.toSize();
|
||||||
|
// Does not work with recent (2022) qt releases: always 0
|
||||||
|
//auto spf = page()->scrollPosition();
|
||||||
|
// Found no easy way to block waiting for the js output
|
||||||
|
//runJS("document.body.scrollTop", [](const QVariant &v) {qDebug() << v.toInt();});
|
||||||
|
QPoint sp = m_scrollpos.toPoint();
|
||||||
|
LOGDEB0("atBottom: contents W " << css.width() << " H " << css.height() <<
|
||||||
" widget W " << wss.width() << " Y " << wss.height() <<
|
" widget W " << wss.width() << " Y " << wss.height() <<
|
||||||
" scroll X " << sp.x() << " Y " << sp.y() << "\n");
|
" scroll X " << sp.x() << " Y " << sp.y() << "\n");
|
||||||
// This seems to work but it's mysterious as points and pixels
|
// This seems to work but it's mysterious as points and pixels
|
||||||
@ -729,6 +774,7 @@ bool ResList::scrollIsAtBottom()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool ResList::scrollIsAtTop()
|
bool ResList::scrollIsAtTop()
|
||||||
{
|
{
|
||||||
#if defined(USING_WEBKIT)
|
#if defined(USING_WEBKIT)
|
||||||
@ -745,12 +791,21 @@ bool ResList::scrollIsAtTop()
|
|||||||
LOGDEB2("scrollIsAtTop: returning " << ret << "\n");
|
LOGDEB2("scrollIsAtTop: returning " << ret << "\n");
|
||||||
return ret;
|
return ret;
|
||||||
#elif defined(USING_WEBENGINE)
|
#elif defined(USING_WEBENGINE)
|
||||||
return page()->scrollPosition().toPoint().ry() == 0;
|
//return page()->scrollPosition().toPoint().ry() == 0;
|
||||||
|
return m_scrollpos.y() == 0;
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ResList::setupArrows()
|
||||||
|
{
|
||||||
|
emit prevPageAvailable(m_pager->hasPrev() || !scrollIsAtTop());
|
||||||
|
emit nextPageAvailable(m_pager->hasNext() || !scrollIsAtBottom());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Show previous page of results. We just set the current number back
|
// Show previous page of results. We just set the current number back
|
||||||
// 2 pages and show next page.
|
// 2 pages and show next page.
|
||||||
void ResList::resultPageBack()
|
void ResList::resultPageBack()
|
||||||
@ -807,35 +862,18 @@ void ResList::append(const QString &text)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void maybeDump(const QString& text)
|
|
||||||
{
|
|
||||||
std::string dumpfile;
|
|
||||||
if (!theconfig->getConfParam("reslisthtmldumpfile", dumpfile) || dumpfile.empty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dumpfile = path_tildexpand(dumpfile);
|
|
||||||
if (path_exists(dumpfile)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto fp = fopen(dumpfile.c_str(), "w");
|
|
||||||
if (fp) {
|
|
||||||
auto s = qs2utf8s(text);
|
|
||||||
fwrite(s.c_str(), 1, s.size(), fp);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResList::displayPage()
|
void ResList::displayPage()
|
||||||
{
|
{
|
||||||
resetView();
|
|
||||||
|
|
||||||
#if defined(USING_WEBENGINE) || defined(USING_WEBKIT)
|
#if defined(USING_WEBENGINE) || defined(USING_WEBKIT)
|
||||||
|
const static QUrl baseUrl("file:///");
|
||||||
|
|
||||||
QProgressDialog progress("Generating text snippets...", "", 0, prefs.respagesize, this);
|
QProgressDialog progress("Generating text snippets...", "", 0, prefs.respagesize, this);
|
||||||
m_residx = 0;
|
m_residx = 0;
|
||||||
progress.setWindowModality(Qt::WindowModal);
|
progress.setWindowModality(Qt::WindowModal);
|
||||||
progress.setCancelButton(nullptr);
|
progress.setCancelButton(nullptr);
|
||||||
progress.setMinimumDuration(2000);
|
progress.setMinimumDuration(2000);
|
||||||
m_progress = &progress;
|
m_progress = &progress;
|
||||||
|
m_text = "";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
m_pager->displayPage(theconfig);
|
m_pager->displayPage(theconfig);
|
||||||
@ -847,9 +885,11 @@ void ResList::displayPage()
|
|||||||
m_progress->close();
|
m_progress->close();
|
||||||
m_progress = nullptr;
|
m_progress = nullptr;
|
||||||
}
|
}
|
||||||
const static QUrl baseUrl("file:///");
|
if (m_lasttext == m_text)
|
||||||
|
return;
|
||||||
maybeDump(m_text);
|
maybeDump(m_text);
|
||||||
setHtml(m_text, baseUrl);
|
setHtml(m_text, baseUrl);
|
||||||
|
m_lasttext = m_text;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LOGDEB0("ResList::displayPg: hasNext " << m_pager->hasNext() <<
|
LOGDEB0("ResList::displayPg: hasNext " << m_pager->hasNext() <<
|
||||||
@ -867,7 +907,7 @@ void ResList::previewExposed(int docnum)
|
|||||||
LOGDEB("ResList::previewExposed: doc " << docnum << "\n");
|
LOGDEB("ResList::previewExposed: doc " << docnum << "\n");
|
||||||
|
|
||||||
// Possibly erase old one to white
|
// Possibly erase old one to white
|
||||||
if (m_curPvDoc != -1) {
|
if (m_curPvDoc > -1) {
|
||||||
#if defined(USING_WEBKIT)
|
#if defined(USING_WEBKIT)
|
||||||
QString sel =
|
QString sel =
|
||||||
QString("div[rcldocnum=\"%1\"]").arg(m_curPvDoc - pageFirstDocNum());
|
QString("div[rcldocnum=\"%1\"]").arg(m_curPvDoc - pageFirstDocNum());
|
||||||
@ -901,12 +941,14 @@ void ResList::previewExposed(int docnum)
|
|||||||
m_curPvDoc = -1;
|
m_curPvDoc = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((m_curPvDoc = docnum) < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Set background for active preview's doc entry
|
// Set background for active preview's doc entry
|
||||||
m_curPvDoc = docnum;
|
|
||||||
|
|
||||||
#if defined(USING_WEBKIT)
|
#if defined(USING_WEBKIT)
|
||||||
QString sel =
|
QString sel = QString("div[rcldocnum=\"%1\"]").arg(docnum - pageFirstDocNum());
|
||||||
QString("div[rcldocnum=\"%1\"]").arg(docnum - pageFirstDocNum());
|
|
||||||
LOGDEB2("Searching for element, selector: [" << qs2utf8s(sel) << "]\n");
|
LOGDEB2("Searching for element, selector: [" << qs2utf8s(sel) << "]\n");
|
||||||
QWebElement elt = page()->mainFrame()->findFirstElement(sel);
|
QWebElement elt = page()->mainFrame()->findFirstElement(sel);
|
||||||
if (!elt.isNull()) {
|
if (!elt.isNull()) {
|
||||||
|
|||||||
@ -124,11 +124,15 @@ protected:
|
|||||||
public slots:
|
public slots:
|
||||||
virtual void onLinkClicked(const QUrl &);
|
virtual void onLinkClicked(const QUrl &);
|
||||||
virtual void onPopupJsDone(const QVariant&);
|
virtual void onPopupJsDone(const QVariant&);
|
||||||
void runJS(const QString& js);
|
|
||||||
protected slots:
|
protected slots:
|
||||||
virtual void languageChange();
|
virtual void languageChange();
|
||||||
void runStoredJS(bool);
|
|
||||||
void setupArrows();
|
void setupArrows();
|
||||||
|
#if defined(USING_WEBENGINE)
|
||||||
|
void runStoredJS(bool);
|
||||||
|
void onPageScrollPositionChanged(const QPointF &position);
|
||||||
|
void onPageContentsSizeChanged(const QSizeF &size);
|
||||||
|
#endif // USING_WEBENGINE
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QtGuiResListPager *m_pager{0};
|
QtGuiResListPager *m_pager{0};
|
||||||
@ -144,6 +148,14 @@ private:
|
|||||||
QString m_text;
|
QString m_text;
|
||||||
QProgressDialog *m_progress{nullptr};
|
QProgressDialog *m_progress{nullptr};
|
||||||
int m_residx{0}; // result index in page
|
int m_residx{0}; // result index in page
|
||||||
|
void runJS(const QString& js);
|
||||||
|
#if defined(USING_WEBENGINE)
|
||||||
|
// Webengine local image display appears to break randomly (for some versions and platforms,
|
||||||
|
// circa 2022) when we display the same data multiple times. Detect and avoid.
|
||||||
|
QString m_lasttext;
|
||||||
|
QPointF m_scrollpos{0,0};
|
||||||
|
QSizeF m_contentsize{0,0};
|
||||||
|
#endif // WEBENGINE
|
||||||
#else
|
#else
|
||||||
// Translate from textedit paragraph number to relative
|
// Translate from textedit paragraph number to relative
|
||||||
// docnum. Built while we insert text into the qtextedit
|
// docnum. Built while we insert text into the qtextedit
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user