add option to have clickable links inside the preview windows

This commit is contained in:
Jean-Francois Dockes 2018-04-16 10:47:52 +02:00
parent 2be261e00b
commit 2176d81e60
10 changed files with 166 additions and 148 deletions

View File

@ -2834,17 +2834,23 @@
version instead. </para> version instead. </para>
</listitem> </listitem>
<listitem><para><guilabel>Plain text to HTML line style</guilabel>: <listitem><para><guilabel>Activate links in
when displaying plain text inside the preview window, &RCL; preview</guilabel> if set, Recoll will turn HTTP links found
tries to preserve some of the original text line breaks and inside plain text into proper HTML anchors, and clicking a
indentation. It can either use PRE HTML tags, which will link inside a preview window will start the default browser
well preserve the indentation but will force horizontal on the link target.</para> </listitem>
scrolling for long lines, or use BR tags to break at the
original line breaks, which will let the editor introduce <listitem><para><guilabel>Plain text to HTML line
other line breaks according to the window width, but will style</guilabel>: when displaying plain text inside the
lose some of the original indentation. The third option has preview window, &RCL; tries to preserve some of the original
been available in recent releases and is probably now the best text line breaks and indentation. It can either use PRE HTML
one: use PRE tags with line wrapping.</para> tags, which will well preserve the indentation but will force
horizontal scrolling for long lines, or use BR tags to break
at the original line breaks, which will let the editor
introduce other line breaks according to the window width,
but will lose some of the original indentation. The third
option has been available in recent releases and is probably
now the best one: use PRE tags with line wrapping.</para>
</listitem> </listitem>
<listitem><para><guilabel>Choose editor <listitem><para><guilabel>Choose editor

View File

@ -88,6 +88,8 @@ void rwSettings(bool writing)
SETTING_RW(prefs.startWithAdvSearchOpen, SETTING_RW(prefs.startWithAdvSearchOpen,
"/Recoll/prefs/startWithAdvSearchOpen", Bool, false); "/Recoll/prefs/startWithAdvSearchOpen", Bool, false);
SETTING_RW(prefs.previewHtml, "/Recoll/prefs/previewHtml", Bool, true); SETTING_RW(prefs.previewHtml, "/Recoll/prefs/previewHtml", Bool, true);
SETTING_RW(prefs.previewActiveLinks,
"/Recoll/prefs/previewActiveLinks", Bool, false);
QString advSearchClauses; QString advSearchClauses;
const int maxclauselistsize = 20; const int maxclauselistsize = 20;

View File

@ -90,6 +90,7 @@ class PrefsPack {
bool startWithAdvSearchOpen; bool startWithAdvSearchOpen;
// Try to display html if it exists in the internfile stack. // Try to display html if it exists in the internfile stack.
bool previewHtml; bool previewHtml;
bool previewActiveLinks;
// Use <pre> tag to display highlighted text/plain inside html (else // Use <pre> tag to display highlighted text/plain inside html (else
// we use <br> at end of lines, which lets textedit wrap lines). // we use <br> at end of lines, which lets textedit wrap lines).
enum PlainPre {PP_BR, PP_PRE, PP_PREWRAP}; enum PlainPre {PP_BR, PP_PRE, PP_PREWRAP};

View File

@ -59,6 +59,7 @@
#include "rclhelp.h" #include "rclhelp.h"
#include "preview_load.h" #include "preview_load.h"
#include "preview_plaintorich.h" #include "preview_plaintorich.h"
#include "rclmain_w.h"
static const QKeySequence closeKS(Qt::Key_Escape); static const QKeySequence closeKS(Qt::Key_Escape);
static const QKeySequence nextDocInTabKS(Qt::ShiftModifier+Qt::Key_Down); static const QKeySequence nextDocInTabKS(Qt::ShiftModifier+Qt::Key_Down);
@ -163,14 +164,10 @@ void Preview::init()
connect(new QShortcut(printTabKS, this), SIGNAL (activated()), connect(new QShortcut(printTabKS, this), SIGNAL (activated()),
this, SIGNAL (printCurrentPreviewRequest())); this, SIGNAL (printCurrentPreviewRequest()));
m_dynSearchActive = false;
m_canBeep = true;
if (prefs.pvwidth > 100) { if (prefs.pvwidth > 100) {
resize(prefs.pvwidth, prefs.pvheight); resize(prefs.pvwidth, prefs.pvheight);
} }
m_loading = false;
currentChanged(pvTab->currentIndex()); currentChanged(pvTab->currentIndex());
m_justCreated = true;
} }
void Preview::emitShowNext() void Preview::emitShowNext()
@ -195,7 +192,7 @@ void Preview::emitShowPrev()
void Preview::closeEvent(QCloseEvent *e) void Preview::closeEvent(QCloseEvent *e)
{ {
LOGDEB("Preview::closeEvent. m_loading " << (m_loading) << "\n" ); LOGDEB("Preview::closeEvent. m_loading " << m_loading << "\n");
if (m_loading) { if (m_loading) {
CancelCheck::instance().setCancel(); CancelCheck::instance().setCancel();
e->ignore(); e->ignore();
@ -226,10 +223,12 @@ bool Preview::eventFilter(QObject *target, QEvent *event)
{ {
if (event->type() != QEvent::KeyPress) { if (event->type() != QEvent::KeyPress) {
#if 0 #if 0
LOGDEB("Preview::eventFilter(): " << (eventTypeToStr(event->type())) << "\n" ); LOGDEB("Preview::eventFilter(): " << eventTypeToStr(event->type()) <<
"\n");
if (event->type() == QEvent::MouseButtonRelease) { if (event->type() == QEvent::MouseButtonRelease) {
QMouseEvent *mev = (QMouseEvent *)event; QMouseEvent *mev = (QMouseEvent *)event;
LOGDEB("Mouse: GlobalY " << (mev->globalY()) << " y " << (mev->y()) << "\n" ); LOGDEB("Mouse: GlobalY " << mev->globalY() << " y " << mev->y() <<
"\n");
} }
#endif #endif
return false; return false;
@ -240,7 +239,7 @@ bool Preview::eventFilter(QObject *target, QEvent *event)
if (m_dynSearchActive) { if (m_dynSearchActive) {
if (keyEvent->key() == Qt::Key_F3) { if (keyEvent->key() == Qt::Key_F3) {
LOGDEB2("Preview::eventFilter: got F3\n" ); LOGDEB2("Preview::eventFilter: got F3\n");
doSearch(searchTextCMB->currentText(), true, doSearch(searchTextCMB->currentText(), true,
(keyEvent->modifiers() & Qt::ShiftModifier) != 0); (keyEvent->modifiers() & Qt::ShiftModifier) != 0);
return true; return true;
@ -253,18 +252,18 @@ bool Preview::eventFilter(QObject *target, QEvent *event)
if (keyEvent->key() == Qt::Key_Slash || if (keyEvent->key() == Qt::Key_Slash ||
(keyEvent->key() == Qt::Key_F && (keyEvent->key() == Qt::Key_F &&
(keyEvent->modifiers() & Qt::ControlModifier))) { (keyEvent->modifiers() & Qt::ControlModifier))) {
LOGDEB2("Preview::eventFilter: got / or C-F\n" ); LOGDEB2("Preview::eventFilter: got / or C-F\n");
searchTextCMB->setFocus(); searchTextCMB->setFocus();
m_dynSearchActive = true; m_dynSearchActive = true;
return true; return true;
} else if (keyEvent->key() == Qt::Key_Space) { } else if (keyEvent->key() == Qt::Key_Space) {
LOGDEB2("Preview::eventFilter: got Space\n" ); LOGDEB2("Preview::eventFilter: got Space\n");
int value = edit->verticalScrollBar()->value(); int value = edit->verticalScrollBar()->value();
value += edit->verticalScrollBar()->pageStep(); value += edit->verticalScrollBar()->pageStep();
edit->verticalScrollBar()->setValue(value); edit->verticalScrollBar()->setValue(value);
return true; return true;
} else if (keyEvent->key() == Qt::Key_Backspace) { } else if (keyEvent->key() == Qt::Key_Backspace) {
LOGDEB2("Preview::eventFilter: got Backspace\n" ); LOGDEB2("Preview::eventFilter: got Backspace\n");
int value = edit->verticalScrollBar()->value(); int value = edit->verticalScrollBar()->value();
value -= edit->verticalScrollBar()->pageStep(); value -= edit->verticalScrollBar()->pageStep();
edit->verticalScrollBar()->setValue(value); edit->verticalScrollBar()->setValue(value);
@ -278,7 +277,7 @@ bool Preview::eventFilter(QObject *target, QEvent *event)
void Preview::searchTextChanged(const QString & text) void Preview::searchTextChanged(const QString & text)
{ {
LOGDEB1("Search line text changed. text: '" << ((const char *)text.toUtf8()) << "'\n" ); LOGDEB1("Search line text changed. text: '" << qs2utf8s(text) << "'\n");
m_searchTextFromIndex = -1; m_searchTextFromIndex = -1;
if (text.isEmpty()) { if (text.isEmpty()) {
m_dynSearchActive = false; m_dynSearchActive = false;
@ -292,13 +291,13 @@ void Preview::searchTextChanged(const QString & text)
void Preview::searchTextFromIndex(int idx) void Preview::searchTextFromIndex(int idx)
{ {
LOGDEB1("search line from index " << (idx) << "\n" ); LOGDEB1("search line from index " << idx << "\n");
m_searchTextFromIndex = idx; m_searchTextFromIndex = idx;
} }
PreviewTextEdit *Preview::currentEditor() PreviewTextEdit *Preview::currentEditor()
{ {
LOGDEB2("Preview::currentEditor()\n" ); LOGDEB2("Preview::currentEditor()\n");
QWidget *tw = pvTab->currentWidget(); QWidget *tw = pvTab->currentWidget();
PreviewTextEdit *edit = 0; PreviewTextEdit *edit = 0;
if (tw) { if (tw) {
@ -323,7 +322,9 @@ void Preview::emitSaveDocToFile()
void Preview::doSearch(const QString &_text, bool next, bool reverse, void Preview::doSearch(const QString &_text, bool next, bool reverse,
bool wordOnly) bool wordOnly)
{ {
LOGDEB("Preview::doSearch: text [" << ((const char *)_text.toUtf8()) << "] idx " << (m_searchTextFromIndex) << " next " << (int(next)) << " rev " << (int(reverse)) << " word " << (int(wordOnly)) << "\n" ); LOGDEB("Preview::doSearch: text [" << qs2utf8s(_text) << "] idx " <<
m_searchTextFromIndex << " next " << next << " rev " << reverse <<
" word " << wordOnly << "\n");
QString text = _text; QString text = _text;
bool matchCase = matchCheck->isChecked(); bool matchCase = matchCheck->isChecked();
@ -335,7 +336,7 @@ void Preview::doSearch(const QString &_text, bool next, bool reverse,
if (text.isEmpty() || m_searchTextFromIndex != -1) { if (text.isEmpty() || m_searchTextFromIndex != -1) {
if (!edit->m_plaintorich->haveAnchors()) { if (!edit->m_plaintorich->haveAnchors()) {
LOGDEB("NO ANCHORS\n" ); LOGDEB("NO ANCHORS\n");
return; return;
} }
// The combobox indices are equal to the search ugroup indices // The combobox indices are equal to the search ugroup indices
@ -346,7 +347,7 @@ void Preview::doSearch(const QString &_text, bool next, bool reverse,
edit->m_plaintorich->nextAnchorNum(m_searchTextFromIndex); edit->m_plaintorich->nextAnchorNum(m_searchTextFromIndex);
} }
QString aname = edit->m_plaintorich->curAnchorName(); QString aname = edit->m_plaintorich->curAnchorName();
LOGDEB("Calling scrollToAnchor(" << ((const char *)aname.toUtf8()) << ")\n" ); LOGDEB("Calling scrollToAnchor(" << qs2utf8s(aname) << ")\n");
edit->scrollToAnchor(aname); edit->scrollToAnchor(aname);
// Position the cursor approximately at the anchor (top of // Position the cursor approximately at the anchor (top of
// viewport) so that searches start from here // viewport) so that searches start from here
@ -366,7 +367,7 @@ void Preview::doSearch(const QString &_text, bool next, bool reverse,
edit->setTextCursor(cursor); edit->setTextCursor(cursor);
} }
Chrono chron; Chrono chron;
LOGDEB("Preview::doSearch: first find call\n" ); LOGDEB("Preview::doSearch: first find call\n");
QTextDocument::FindFlags flags = 0; QTextDocument::FindFlags flags = 0;
if (reverse) if (reverse)
flags |= QTextDocument::FindBackward; flags |= QTextDocument::FindBackward;
@ -375,19 +376,21 @@ void Preview::doSearch(const QString &_text, bool next, bool reverse,
if (matchCase) if (matchCase)
flags |= QTextDocument::FindCaseSensitively; flags |= QTextDocument::FindCaseSensitively;
bool found = edit->find(text, flags); bool found = edit->find(text, flags);
LOGDEB("Preview::doSearch: first find call return: found " << (found) << " " << (chron.secs()) << " S\n" ); LOGDEB("Preview::doSearch: first find call return: found " << found <<
" " << chron.secs() << " S\n");
// If not found, try to wrap around. // If not found, try to wrap around.
if (!found) { if (!found) {
LOGDEB("Preview::doSearch: wrapping around\n" ); LOGDEB("Preview::doSearch: wrapping around\n");
if (reverse) { if (reverse) {
edit->moveCursor (QTextCursor::End); edit->moveCursor (QTextCursor::End);
} else { } else {
edit->moveCursor (QTextCursor::Start); edit->moveCursor (QTextCursor::Start);
} }
LOGDEB("Preview::doSearch: 2nd find call\n" ); LOGDEB("Preview::doSearch: 2nd find call\n");
chron.restart(); chron.restart();
found = edit->find(text, flags); found = edit->find(text, flags);
LOGDEB("Preview::doSearch: 2nd find call return found " << (found) << " " << (chron.secs()) << " S\n" ); LOGDEB("Preview::doSearch: 2nd find call return found " << found <<
" " << chron.secs() << " S\n");
} }
if (found) { if (found) {
@ -397,37 +400,37 @@ void Preview::doSearch(const QString &_text, bool next, bool reverse,
QApplication::beep(); QApplication::beep();
m_canBeep = false; m_canBeep = false;
} }
LOGDEB("Preview::doSearch: return\n" ); LOGDEB("Preview::doSearch: return\n");
} }
void Preview::nextPressed() void Preview::nextPressed()
{ {
LOGDEB2("Preview::nextPressed\n" ); LOGDEB2("Preview::nextPressed\n");
doSearch(searchTextCMB->currentText(), true, false); doSearch(searchTextCMB->currentText(), true, false);
} }
void Preview::prevPressed() void Preview::prevPressed()
{ {
LOGDEB2("Preview::prevPressed\n" ); LOGDEB2("Preview::prevPressed\n");
doSearch(searchTextCMB->currentText(), true, true); doSearch(searchTextCMB->currentText(), true, true);
} }
// Called when user clicks on tab // Called when user clicks on tab
void Preview::currentChanged(int index) void Preview::currentChanged(int index)
{ {
LOGDEB2("PreviewTextEdit::currentChanged\n" ); LOGDEB2("PreviewTextEdit::currentChanged\n");
QWidget *tw = pvTab->widget(index); QWidget *tw = pvTab->widget(index);
PreviewTextEdit *edit = PreviewTextEdit *edit =
tw->findChild<PreviewTextEdit*>("pvEdit"); tw->findChild<PreviewTextEdit*>("pvEdit");
LOGDEB1("Preview::currentChanged(). Editor: " << (edit) << "\n" ); LOGDEB1("Preview::currentChanged(). Editor: " << edit << "\n");
if (edit == 0) { if (edit == 0) {
LOGERR("Editor child not found\n" ); LOGERR("Editor child not found\n");
return; return;
} }
edit->setFocus(); edit->setFocus();
// Disconnect the print signal and reconnect it to the current editor // Disconnect the print signal and reconnect it to the current editor
LOGDEB("Disconnecting reconnecting print signal\n" ); LOGDEB("Disconnecting reconnecting print signal\n");
disconnect(this, SIGNAL(printCurrentPreviewRequest()), 0, 0); disconnect(this, SIGNAL(printCurrentPreviewRequest()), 0, 0);
connect(this, SIGNAL(printCurrentPreviewRequest()), edit, SLOT(print())); connect(this, SIGNAL(printCurrentPreviewRequest()), edit, SLOT(print()));
edit->installEventFilter(this); edit->installEventFilter(this);
@ -438,7 +441,7 @@ void Preview::currentChanged(int index)
void Preview::closeCurrentTab() void Preview::closeCurrentTab()
{ {
LOGDEB1("Preview::closeCurrentTab: m_loading " << (m_loading) << "\n" ); LOGDEB1("Preview::closeCurrentTab: m_loading " << m_loading << "\n");
if (m_loading) { if (m_loading) {
CancelCheck::instance().setCancel(); CancelCheck::instance().setCancel();
return; return;
@ -455,7 +458,7 @@ void Preview::closeCurrentTab()
PreviewTextEdit *Preview::addEditorTab() PreviewTextEdit *Preview::addEditorTab()
{ {
LOGDEB1("PreviewTextEdit::addEditorTab()\n" ); LOGDEB1("PreviewTextEdit::addEditorTab()\n");
QWidget *anon = new QWidget((QWidget *)pvTab); QWidget *anon = new QWidget((QWidget *)pvTab);
QVBoxLayout *anonLayout = new QVBoxLayout(anon); QVBoxLayout *anonLayout = new QVBoxLayout(anon);
PreviewTextEdit *editor = new PreviewTextEdit(anon, "pvEdit", this); PreviewTextEdit *editor = new PreviewTextEdit(anon, "pvEdit", this);
@ -469,7 +472,7 @@ PreviewTextEdit *Preview::addEditorTab()
void Preview::setCurTabProps(const Rcl::Doc &doc, int docnum) void Preview::setCurTabProps(const Rcl::Doc &doc, int docnum)
{ {
LOGDEB1("Preview::setCurTabProps\n" ); LOGDEB1("Preview::setCurTabProps\n");
QString title; QString title;
string ctitle; string ctitle;
if (doc.getmeta(Rcl::Doc::keytt, &ctitle) && !ctitle.empty()) { if (doc.getmeta(Rcl::Doc::keytt, &ctitle) && !ctitle.empty()) {
@ -491,7 +494,7 @@ void Preview::setCurTabProps(const Rcl::Doc &doc, int docnum)
struct tm *tm = localtime(&mtime); struct tm *tm = localtime(&mtime);
strftime(datebuf, 99, "%Y-%m-%d %H:%M:%S", tm); strftime(datebuf, 99, "%Y-%m-%d %H:%M:%S", tm);
} }
LOGDEB("Doc.url: [" << (doc.url) << "]\n" ); LOGDEB("Doc.url: [" << doc.url << "]\n");
string url; string url;
printableUrl(theconfig->getDefCharset(), doc.url, url); printableUrl(theconfig->getDefCharset(), doc.url, url);
string tiptxt = url + string("\n"); string tiptxt = url + string("\n");
@ -511,10 +514,10 @@ void Preview::setCurTabProps(const Rcl::Doc &doc, int docnum)
bool Preview::makeDocCurrent(const Rcl::Doc& doc, int docnum, bool sametab) bool Preview::makeDocCurrent(const Rcl::Doc& doc, int docnum, bool sametab)
{ {
LOGDEB("Preview::makeDocCurrent: " << (doc.url) << "\n" ); LOGDEB("Preview::makeDocCurrent: " << doc.url << "\n");
if (m_loading) { if (m_loading) {
LOGERR("Already loading\n" ); LOGERR("Already loading\n");
return false; return false;
} }
@ -603,7 +606,7 @@ public:
bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum) bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
{ {
LOGDEB1("Preview::loadDocInCurrentTab()\n" ); LOGDEB1("Preview::loadDocInCurrentTab()\n");
LoadGuard guard(&m_loading); LoadGuard guard(&m_loading);
CancelCheck::instance().setCancel(false); CancelCheck::instance().setCancel(false);
@ -641,7 +644,9 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
progress.show(); progress.show();
} }
LOGDEB("loadDocInCurrentTab: after file load: cancel " << (CancelCheck::instance().cancelState()) << " status " << (lthr.status) << " text length " << (lthr.fdoc.text.length()) << "\n" ); LOGDEB("loadDocInCurrentTab: after file load: cancel " <<
CancelCheck::instance().cancelState() << " status " << lthr.status <<
" text length " << lthr.fdoc.text.length() << "\n");
if (CancelCheck::instance().cancelState()) if (CancelCheck::instance().cancelState())
return false; return false;
@ -703,6 +708,7 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
editor->m_format = Qt::RichText; editor->m_format = Qt::RichText;
bool inputishtml = !lthr.fdoc.mimetype.compare("text/html"); bool inputishtml = !lthr.fdoc.mimetype.compare("text/html");
QStringList qrichlst; QStringList qrichlst;
editor->m_plaintorich->set_activatelinks(prefs.previewActiveLinks);
#if 1 #if 1
if (highlightTerms) { if (highlightTerms) {
@ -710,10 +716,10 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
qApp->processEvents(); qApp->processEvents();
if (inputishtml) { if (inputishtml) {
LOGDEB1("Preview: got html " << (lthr.fdoc.text) << "\n" ); LOGDEB1("Preview: got html " << lthr.fdoc.text << "\n");
editor->m_plaintorich->set_inputhtml(true); editor->m_plaintorich->set_inputhtml(true);
} else { } else {
LOGDEB1("Preview: got plain " << (lthr.fdoc.text) << "\n" ); LOGDEB1("Preview: got plain " << lthr.fdoc.text << "\n");
editor->m_plaintorich->set_inputhtml(false); editor->m_plaintorich->set_inputhtml(false);
} }
@ -744,7 +750,8 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
} }
} }
} else { } else {
LOGDEB("Preview: no hilighting, loading " << (int(lthr.fdoc.text.size())) << " bytes\n" ); LOGDEB("Preview: no hilighting, loading " << lthr.fdoc.text.size() <<
" bytes\n");
// No plaintorich() call. In this case, either the text is // No plaintorich() call. In this case, either the text is
// html and the html quoting is hopefully correct, or it's // html and the html quoting is hopefully correct, or it's
// plain-text and there is no need to escape special // plain-text and there is no need to escape special
@ -794,7 +801,7 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
if (progress.wasCanceled()) { if (progress.wasCanceled()) {
editor->append("<b>Cancelled !</b>"); editor->append("<b>Cancelled !</b>");
LOGDEB("loadDocInCurrentTab: cancelled in editor load\n" ); LOGDEB("loadDocInCurrentTab: cancelled in editor load\n");
break; break;
} }
} }
@ -858,7 +865,7 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
// Position to the first query term // Position to the first query term
if (editor->m_plaintorich->haveAnchors()) { if (editor->m_plaintorich->haveAnchors()) {
QString aname = editor->m_plaintorich->curAnchorName(); QString aname = editor->m_plaintorich->curAnchorName();
LOGDEB2("Call movetoanchor(" << ((const char *)aname.toUtf8()) << ")\n" ); LOGDEB2("Call movetoanchor(" << qs2utf8s(aname) << ")\n");
editor->scrollToAnchor(aname); editor->scrollToAnchor(aname);
// Position the cursor approximately at the anchor (top of // Position the cursor approximately at the anchor (top of
// viewport) so that searches start from here // viewport) so that searches start from here
@ -876,7 +883,7 @@ bool Preview::loadDocInCurrentTab(const Rcl::Doc &idoc, int docnum)
editor->setFocus(); editor->setFocus();
emit(previewExposed(this, m_searchId, docnum)); emit(previewExposed(this, m_searchId, docnum));
LOGDEB("loadDocInCurrentTab: returning true\n" ); LOGDEB("loadDocInCurrentTab: returning true\n");
return true; return true;
} }
@ -889,13 +896,27 @@ PreviewTextEdit::PreviewTextEdit(QWidget* parent, const char* nm, Preview *pv)
setObjectName(nm); setObjectName(nm);
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), connect(this, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(createPopupMenu(const QPoint&))); this, SLOT(createPopupMenu(const QPoint&)));
connect(this, SIGNAL(anchorClicked(const QUrl &)),
this, SLOT(onAnchorClicked(const QUrl&)));
setOpenExternalLinks(false); setOpenExternalLinks(false);
setOpenLinks(false); setOpenLinks(false);
} }
void PreviewTextEdit::onAnchorClicked(const QUrl& url)
{
LOGDEB("PreviewTextEdit::onAnchorClicked: " << qs2utf8s(url.toString())
<< std::endl);
if (prefs.previewActiveLinks && m_preview->m_rclmain) {
Rcl::Doc doc;
doc.url = qs2utf8s(url.toString()).c_str();
doc.mimetype = "text/html";
m_preview->m_rclmain->startNativeViewer(doc);
}
}
void PreviewTextEdit::createPopupMenu(const QPoint& pos) void PreviewTextEdit::createPopupMenu(const QPoint& pos)
{ {
LOGDEB1("PreviewTextEdit::createPopupMenu()\n" ); LOGDEB1("PreviewTextEdit::createPopupMenu()\n");
QMenu *popup = new QMenu(this); QMenu *popup = new QMenu(this);
switch (m_curdsp) { switch (m_curdsp) {
case PTE_DSPTXT: case PTE_DSPTXT:
@ -934,7 +955,7 @@ void PreviewTextEdit::createPopupMenu(const QPoint& pos)
// Display main text // Display main text
void PreviewTextEdit::displayText() void PreviewTextEdit::displayText()
{ {
LOGDEB1("PreviewTextEdit::displayText()\n" ); LOGDEB1("PreviewTextEdit::displayText()\n");
if (m_format == Qt::PlainText) if (m_format == Qt::PlainText)
setPlainText(m_richtxt); setPlainText(m_richtxt);
else else
@ -945,7 +966,7 @@ void PreviewTextEdit::displayText()
// Display field values // Display field values
void PreviewTextEdit::displayFields() void PreviewTextEdit::displayFields()
{ {
LOGDEB1("PreviewTextEdit::displayFields()\n" ); LOGDEB1("PreviewTextEdit::displayFields()\n");
QString txt = "<html><head></head><body>\n"; QString txt = "<html><head></head><body>\n";
txt += "<b>" + QString::fromLocal8Bit(m_url.c_str()); txt += "<b>" + QString::fromLocal8Bit(m_url.c_str());
@ -967,7 +988,7 @@ void PreviewTextEdit::displayFields()
void PreviewTextEdit::displayImage() void PreviewTextEdit::displayImage()
{ {
LOGDEB1("PreviewTextEdit::displayImage()\n" ); LOGDEB1("PreviewTextEdit::displayImage()\n");
if (m_image.isNull()) if (m_image.isNull())
displayText(); displayText();
@ -985,7 +1006,7 @@ void PreviewTextEdit::displayImage()
void PreviewTextEdit::mouseDoubleClickEvent(QMouseEvent *event) void PreviewTextEdit::mouseDoubleClickEvent(QMouseEvent *event)
{ {
LOGDEB2("PreviewTextEdit::mouseDoubleClickEvent\n" ); LOGDEB2("PreviewTextEdit::mouseDoubleClickEvent\n");
QTextEdit::mouseDoubleClickEvent(event); QTextEdit::mouseDoubleClickEvent(event);
if (textCursor().hasSelection() && m_preview) if (textCursor().hasSelection() && m_preview)
m_preview->emitWordSelect(textCursor().selectedText()); m_preview->emitWordSelect(textCursor().selectedText());
@ -993,7 +1014,7 @@ void PreviewTextEdit::mouseDoubleClickEvent(QMouseEvent *event)
void PreviewTextEdit::print() void PreviewTextEdit::print()
{ {
LOGDEB("PreviewTextEdit::print\n" ); LOGDEB("PreviewTextEdit::print\n");
if (!m_preview) if (!m_preview)
return; return;

View File

@ -51,6 +51,8 @@ class QPushButton;
class QCheckBox; class QCheckBox;
class Preview; class Preview;
class PlainToRichQtPreview; class PlainToRichQtPreview;
class QUrl;
class RclMain;
class PreviewTextEdit : public PREVIEW_PARENTCLASS { class PreviewTextEdit : public PREVIEW_PARENTCLASS {
Q_OBJECT; Q_OBJECT;
@ -65,6 +67,7 @@ public slots:
virtual void displayImage(); virtual void displayImage();
virtual void print(); virtual void print();
virtual void createPopupMenu(const QPoint& pos); virtual void createPopupMenu(const QPoint& pos);
void onAnchorClicked(const QUrl& url);
friend class Preview; friend class Preview;
@ -104,20 +107,17 @@ private:
class Preview : public QWidget { class Preview : public QWidget {
Q_OBJECT;
public:
Q_OBJECT Preview(RclMain *m, int sid, // Search Id
public:
Preview(int sid, // Search Id
const HighlightData& hdata) // Search terms etc. for highlighting const HighlightData& hdata) // Search terms etc. for highlighting
: QWidget(0), m_searchId(sid), m_searchTextFromIndex(-1), m_hData(hdata) : QWidget(0), m_rclmain(m), m_searchId(sid), m_hData(hdata) {
{
init(); init();
} }
virtual void closeEvent(QCloseEvent *e ); virtual void closeEvent(QCloseEvent *e);
virtual bool eventFilter(QObject *target, QEvent *event ); virtual bool eventFilter(QObject *target, QEvent *event);
/** /**
* Arrange for the document to be displayed either by exposing the tab * Arrange for the document to be displayed either by exposing the tab
@ -158,27 +158,28 @@ signals:
void saveDocToFile(Rcl::Doc); void saveDocToFile(Rcl::Doc);
private: private:
RclMain *m_rclmain{0};
// Identifier of search in main window. This is used to check that // Identifier of search in main window. This is used to check that
// we make sense when requesting the next document when browsing // we make sense when requesting the next document when browsing
// successive search results in a tab. // successive search results in a tab.
int m_searchId; int m_searchId;
bool m_dynSearchActive; bool m_dynSearchActive{false};
// Index value the search text comes from. -1 if text was edited // Index value the search text comes from. -1 if text was edited
int m_searchTextFromIndex; int m_searchTextFromIndex{-1};
bool m_canBeep; bool m_canBeep{true};
bool m_loading; bool m_loading{false};
HighlightData m_hData; HighlightData m_hData;
bool m_justCreated; // First tab create is different bool m_justCreated{true}; // First tab create is different
QTabWidget* pvTab; QTabWidget* pvTab{0};
QLabel* searchLabel; QLabel* searchLabel{0};
QComboBox *searchTextCMB; QComboBox *searchTextCMB{0};
QPushButton* nextButton; QPushButton* nextButton{0};
QPushButton* prevButton; QPushButton* prevButton{0};
QPushButton* clearPB; QPushButton* clearPB{0};
QCheckBox* matchCheck; QCheckBox* matchCheck{0};
void init(); void init();
virtual void setCurTabProps(const Rcl::Doc& doc, int docnum); virtual void setCurTabProps(const Rcl::Doc& doc, int docnum);

View File

@ -150,7 +150,7 @@ void RclMain::startPreview(int docnum, Rcl::Doc doc, int mod)
if (curPreview == 0) { if (curPreview == 0) {
HighlightData hdata; HighlightData hdata;
m_source->getTerms(hdata); m_source->getTerms(hdata);
curPreview = new Preview(reslist->listId(), hdata); curPreview = new Preview(this, reslist->listId(), hdata);
if (curPreview == 0) { if (curPreview == 0) {
QMessageBox::warning(0, tr("Warning"), QMessageBox::warning(0, tr("Warning"),
@ -188,7 +188,7 @@ void RclMain::startPreview(int docnum, Rcl::Doc doc, int mod)
*/ */
void RclMain::startPreview(Rcl::Doc doc) void RclMain::startPreview(Rcl::Doc doc)
{ {
Preview *preview = new Preview(0, HighlightData()); Preview *preview = new Preview(this, 0, HighlightData());
if (preview == 0) { if (preview == 0) {
QMessageBox::warning(0, tr("Warning"), QMessageBox::warning(0, tr("Warning"),
tr("Can't create preview window"), tr("Can't create preview window"),

View File

@ -479,7 +479,8 @@ void RclMain::startManual(const string& index)
webhelp = path_cat(webhelp, "index.html"); webhelp = path_cat(webhelp, "index.html");
bool has_wh = path_exists(webhelp); bool has_wh = path_exists(webhelp);
LOGDEB("RclMain::startManual: help index is " << (index.empty()?"(null)":index) << "\n" ); LOGDEB("RclMain::startManual: help index is " <<
(index.empty() ? "(null)" : index) << "\n");
bool indexempty = index.empty(); bool indexempty = index.empty();
#ifdef _WIN32 #ifdef _WIN32

View File

@ -61,34 +61,7 @@ class RclMain : public QMainWindow, public Ui::RclMainBase {
public: public:
RclMain(QWidget * parent = 0) RclMain(QWidget * parent = 0)
: QMainWindow(parent), : QMainWindow(parent) {
curPreview(0),
asearchform(0),
uiprefs(0),
indexConfig(0),
indexSched(0),
cronTool(0),
rtiTool(0),
spellform(0),
fragbuts(0),
specidx(0),
periodictimer(0),
webcache(0),
restable(0),
displayingTable(0),
m_idNoStem(0),
m_idAllStem(0),
m_toolsTB(0), m_resTB(0),
m_filtFRM(0), m_filtCMB(0), m_filtBGRP(0), m_filtMN(0),
m_idxproc(0),
m_idxkilled(false),
m_catgbutvecidx(0),
m_sortspecnochange(false),
m_indexerState(IXST_UNKNOWN),
m_queryActive(false),
m_firstIndexing(false),
m_searchIsSimple(false),
m_pidfile(0) {
setupUi(this); setupUi(this);
init(); init();
} }
@ -163,7 +136,7 @@ public slots:
virtual void startPreview(int docnum, Rcl::Doc doc, int keymods); virtual void startPreview(int docnum, Rcl::Doc doc, int keymods);
virtual void startPreview(Rcl::Doc); virtual void startPreview(Rcl::Doc);
virtual void startNativeViewer(Rcl::Doc, int pagenum = -1, virtual void startNativeViewer(Rcl::Doc, int pagenum = -1,
QString term = QString()); QString term = QString());
virtual void openWith(Rcl::Doc, string); virtual void openWith(Rcl::Doc, string);
virtual void saveDocToFile(Rcl::Doc); virtual void saveDocToFile(Rcl::Doc);
virtual void previewNextInTab(Preview *, int sid, int docnum); virtual void previewNextInTab(Preview *, int sid, int docnum);
@ -207,53 +180,51 @@ protected:
private: private:
SnippetsW *m_snippets{0}; SnippetsW *m_snippets{0};
Preview *curPreview; Preview *curPreview{0};
AdvSearch *asearchform; AdvSearch *asearchform{0};
UIPrefsDialog *uiprefs; UIPrefsDialog *uiprefs{0};
ConfIndexW *indexConfig; ConfIndexW *indexConfig{0};
IdxSchedW *indexSched; IdxSchedW *indexSched{0};
CronToolW *cronTool; CronToolW *cronTool{0};
RTIToolW *rtiTool; RTIToolW *rtiTool{0};
SpellW *spellform; SpellW *spellform{0};
FragButs *fragbuts; FragButs *fragbuts{0};
SpecIdxW *specidx; SpecIdxW *specidx{0};
QTimer *periodictimer; QTimer *periodictimer{0};
WebcacheEdit *webcache; WebcacheEdit *webcache{0};
ResTable *restable; ResTable *restable{0};
bool displayingTable; bool displayingTable{false};
QAction *m_idNoStem; QAction *m_idNoStem{0};
QAction *m_idAllStem; QAction *m_idAllStem{0};
QToolBar *m_toolsTB; QToolBar *m_toolsTB{0};
QToolBar *m_resTB; QToolBar *m_resTB{0};
QFrame *m_filtFRM; QFrame *m_filtFRM{0};
QComboBox *m_filtCMB; QComboBox *m_filtCMB{0};
QButtonGroup *m_filtBGRP; QButtonGroup *m_filtBGRP{0};
QMenu *m_filtMN; QMenu *m_filtMN{0};
QFileSystemWatcher m_watcher; QFileSystemWatcher m_watcher;
vector<ExecCmd*> m_viewers; vector<ExecCmd*> m_viewers;
ExecCmd *m_idxproc; // Indexing process ExecCmd *m_idxproc{0}; // Indexing process
bool m_idxkilled; // Killed my process bool m_idxkilled{false}; // Killed my process
TempFileInternal *m_idxreasontmp{nullptr}; TempFileInternal *m_idxreasontmp{nullptr};
map<QString, QAction*> m_stemLangToId; map<QString, QAction*> m_stemLangToId;
vector<string> m_catgbutvec; vector<string> m_catgbutvec;
int m_catgbutvecidx; int m_catgbutvecidx{0};
DocSeqFiltSpec m_filtspec; DocSeqFiltSpec m_filtspec;
bool m_sortspecnochange; bool m_sortspecnochange{false};
DocSeqSortSpec m_sortspec; DocSeqSortSpec m_sortspec;
std::shared_ptr<DocSequence> m_source; std::shared_ptr<DocSequence> m_source;
IndexerState m_indexerState; IndexerState m_indexerState{IXST_UNKNOWN};
bool m_queryActive; bool m_queryActive{false};
bool m_firstIndexing; bool m_firstIndexing{false};
bool m_searchIsSimple; // Last search was started from simple // Last search was started from simple
bool m_searchIsSimple{false};
// If set on init, will be displayed either through ext app, or // If set on init, will be displayed either through ext app, or
// preview (if no ext app set) // preview (if no ext app set)
QString m_urltoview; QString m_urltoview;
RclTrayIcon *m_trayicon{0};
RclTrayIcon *m_trayicon;
// We sometimes take the indexer lock (e.g.: when editing the webcache) // We sometimes take the indexer lock (e.g.: when editing the webcache)
Pidfile *m_pidfile; Pidfile *m_pidfile{0};
virtual void init(); virtual void init();
virtual void setupResTB(bool combo); virtual void setupResTB(bool combo);

View File

@ -132,6 +132,19 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="previewActiveLinksCB">
<property name="text">
<string>Activate links in preview.</string>
</property>
<property name="toolTip">
<string>Make links inside the preview window clickable, and start an external browser when they are clicked.</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item> <item>

View File

@ -145,6 +145,7 @@ void UIPrefsDialog::setFromPrefs()
closeToTrayCB->setChecked(prefs.closeToTray); closeToTrayCB->setChecked(prefs.closeToTray);
showTempFileWarningCB->setChecked(prefs.showTempFileWarning == -1); showTempFileWarningCB->setChecked(prefs.showTempFileWarning == -1);
previewHtmlCB->setChecked(prefs.previewHtml); previewHtmlCB->setChecked(prefs.previewHtml);
previewActiveLinksCB->setChecked(prefs.previewActiveLinks);
switch (prefs.previewPlainPre) { switch (prefs.previewPlainPre) {
case PrefsPack::PP_BR: case PrefsPack::PP_BR:
plainBRRB->setChecked(1); plainBRRB->setChecked(1);
@ -330,6 +331,7 @@ void UIPrefsDialog::accept()
prefs.showTempFileWarning = showTempFileWarningCB->isChecked() ? prefs.showTempFileWarning = showTempFileWarningCB->isChecked() ?
-1 : 1024; -1 : 1024;
prefs.previewHtml = previewHtmlCB->isChecked(); prefs.previewHtml = previewHtmlCB->isChecked();
prefs.previewActiveLinks = previewActiveLinksCB->isChecked();
if (plainBRRB->isChecked()) { if (plainBRRB->isChecked()) {
prefs.previewPlainPre = PrefsPack::PP_BR; prefs.previewPlainPre = PrefsPack::PP_BR;