From 8fc223425b16ae77dede0f2f32709165d21b7c73 Mon Sep 17 00:00:00 2001 From: dockes Date: Thu, 15 Nov 2007 18:05:32 +0000 Subject: [PATCH] finally got anchors to work. qt3 --- src/qtgui/plaintorich.cpp | 25 ++----- src/qtgui/plaintorich.h | 13 +--- src/qtgui/preview_w.cpp | 133 ++++++++++++++++++++++++-------------- src/qtgui/preview_w.h | 91 +++++++++++++++++--------- src/qtgui/recoll.pro.in | 1 - 5 files changed, 156 insertions(+), 107 deletions(-) diff --git a/src/qtgui/plaintorich.cpp b/src/qtgui/plaintorich.cpp index 1473d669..7210ace1 100644 --- a/src/qtgui/plaintorich.cpp +++ b/src/qtgui/plaintorich.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: plaintorich.cpp,v 1.29 2007-10-18 10:39:41 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: plaintorich.cpp,v 1.30 2007-11-15 18:05:32 dockes Exp $ (C) 2005 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -309,24 +309,9 @@ string termAnchorName(int i) return string(acname); } -#ifdef QT_SCROLL_TO_ANCHOR_BUG -// qtextedit scrolltoanchor(), which we would like to use to walk the -// search hit positions does not work well. So we mark the positions with -// a special string which we then use with the find() function for positionning -// We used to use some weird utf8 char for this, but this was displayed -// inconsistently depending of system, font, etc. We now use a good ole ctl -// char which doesnt' seem to cause any trouble. Wanted to use ^L, but can't -// be searched, so ^G -const char *firstTermBeacon = "\007"; -#endif - static string termBeacon(int i) { - return string("" -#ifdef QT_SCROLL_TO_ANCHOR_BUG - + firstTermBeacon -#endif - + ""; + return string(""; } @@ -342,7 +327,7 @@ static string termBeacon(int i) // caller will use the editor's find() function to position on it bool plaintorich(const string& in, list& out, const HiliteData& hdata, - bool noHeader, bool needBeacons, int chunksize) + bool noHeader, int *lastAnchor, int chunksize) { Chrono chron; const vector& terms(hdata.terms); @@ -416,7 +401,7 @@ bool plaintorich(const string& in, list& out, if (tPosIt != tboffsend) { int ibyteidx = chariter.getBpos(); if (ibyteidx == tPosIt->first) { - if (needBeacons) + if (lastAnchor) *sit += termBeacon(anchoridx++); *sit += ""; } else if (ibyteidx == tPosIt->second) { @@ -461,6 +446,8 @@ bool plaintorich(const string& in, list& out, chariter.appendchartostring(*sit); } } + if (lastAnchor) + *lastAnchor = anchoridx - 1; #if 0 { FILE *fp = fopen("/tmp/debugplaintorich", "a"); diff --git a/src/qtgui/plaintorich.h b/src/qtgui/plaintorich.h index 62e19261..895aa0ee 100644 --- a/src/qtgui/plaintorich.h +++ b/src/qtgui/plaintorich.h @@ -16,7 +16,7 @@ */ #ifndef _PLAINTORICH_H_INCLUDED_ #define _PLAINTORICH_H_INCLUDED_ -/* @(#$Id: plaintorich.h,v 1.15 2007-10-18 10:39:41 dockes Exp $ (C) 2004 J.F.Dockes */ +/* @(#$Id: plaintorich.h,v 1.16 2007-11-15 18:05:32 dockes Exp $ (C) 2004 J.F.Dockes */ #include #include @@ -43,22 +43,15 @@ struct HiliteData { * @param hdata terms and groups to be highlighted. These are * lowercase and unaccented. * @param noHeader if true don't output header (...) - * @param needBeacons Need to navigate highlighted terms, mark them. + * @param needBeacons Need to navigate highlighted terms, mark them,return last */ extern bool plaintorich(const string &in, list<string> &out, const HiliteData& hdata, bool noHeader, - bool needBeacons, + int *needBeacons, int chunksize = 50000 ); extern string termAnchorName(int i); -#define QT_SCROLL_TO_ANCHOR_BUG -#ifdef QT_SCROLL_TO_ANCHOR_BUG -// For some reason, can't get scrollToAnchor() to work. We use a special -// string as a beacon for the match area. -extern const char *firstTermBeacon; -#endif - #endif /* _PLAINTORICH_H_INCLUDED_ */ diff --git a/src/qtgui/preview_w.cpp b/src/qtgui/preview_w.cpp index 4bc6c3f1..b80d651a 100644 --- a/src/qtgui/preview_w.cpp +++ b/src/qtgui/preview_w.cpp @@ -1,5 +1,5 @@ #ifndef lint -static char rcsid[] = "@(#$Id: preview_w.cpp,v 1.28 2007-10-18 10:39:41 dockes Exp $ (C) 2005 J.F.Dockes"; +static char rcsid[] = "@(#$Id: preview_w.cpp,v 1.29 2007-11-15 18:05:32 dockes Exp $ (C) 2005 J.F.Dockes"; #endif /* * This program is free software; you can redistribute it and/or modify @@ -69,6 +69,62 @@ using std::pair; void Preview::init() { + setName("Preview"); + setSizePolicy( QSizePolicy((QSizePolicy::SizeType)5, + (QSizePolicy::SizeType)5, 0, 0, + sizePolicy().hasHeightForWidth())); + QVBoxLayout* previewLayout = + new QVBoxLayout( this, 4, 6, "previewLayout"); + + pvTab = new QTabWidget(this, "pvTab"); + + // Create the first tab. Should be possible to use addEditorTab + // but this causes a pb with the sizeing + QWidget *unnamed = new QWidget(pvTab, "unnamed"); + QVBoxLayout *unnamedLayout = + new QVBoxLayout(unnamed, 0, 6, "unnamedLayout"); + QTextEditFixed *pvEdit = new QTextEditFixed(unnamed, "pvEdit"); + pvEdit->setFocusPolicy(QTextEdit::WheelFocus); + pvEdit->setReadOnly(TRUE); + pvEdit->setUndoRedoEnabled(FALSE); + unnamedLayout->addWidget(pvEdit); + pvTab->insertTab(unnamed, QString::fromLatin1("")); + m_tabData.push_back(TabData(pvTab->currentPage())); + + previewLayout->addWidget(pvTab); + + // Create the buttons and entry field + QHBoxLayout *layout3 = new QHBoxLayout(0, 0, 6, "layout3"); + searchLabel = new QLabel(this, "searchLabel"); + layout3->addWidget(searchLabel); + searchTextLine = new QLineEdit(this, "searchTextLine"); + layout3->addWidget(searchTextLine); + nextButton = new QPushButton(this, "nextButton"); + nextButton->setEnabled(TRUE); + layout3->addWidget(nextButton); + prevButton = new QPushButton(this, "prevButton"); + prevButton->setEnabled(TRUE); + layout3->addWidget(prevButton); + clearPB = new QPushButton(this, "clearPB"); + clearPB->setEnabled(FALSE); + layout3->addWidget(clearPB); + matchCheck = new QCheckBox(this, "matchCheck"); + layout3->addWidget(matchCheck); + + previewLayout->addLayout(layout3); + + resize(QSize(640, 480).expandedTo(minimumSizeHint())); + clearWState(WState_Polished); + + // buddies + searchLabel->setBuddy(searchTextLine); + + searchLabel->setText(tr("&Search for:")); + nextButton->setText(tr("&Next")); + prevButton->setText(tr("&Previous")); + clearPB->setText(tr("Clear")); + matchCheck->setText(tr("Match &Case")); + #if 0 // Couldn't get a small button really in the corner. stays on the left of // the button area and looks ugly @@ -93,7 +149,6 @@ void Preview::init() m_dynSearchActive = false; m_canBeep = true; - m_tabData.push_back(TabData(pvTab->currentPage())); m_currentW = 0; if (prefs.pvwidth > 100) { resize(prefs.pvwidth, prefs.pvheight); @@ -102,6 +157,7 @@ void Preview::init() currentChanged(pvTab->currentPage()); m_justCreated = true; m_haveAnchors = false; + m_curAnchor = 1; } void Preview::closeEvent(QCloseEvent *e) @@ -161,9 +217,9 @@ bool Preview::eventFilter(QObject *target, QEvent *event) return QApplication::sendEvent(searchTextLine, event); } else { QWidget *tw = pvTab->currentPage(); - QTextEdit *e = 0; + QTextEditFixed *e = 0; if (tw) - e = (QTextEdit *)tw->child("pvEdit"); + e = (QTextEditFixed *)tw->child("pvEdit"); LOGDEB1(("Widget: %p, edit %p, target %p\n", tw, e, target)); if (e && target == e) { if (keyEvent->key() == Qt::Key_Slash) { @@ -201,17 +257,16 @@ void Preview::searchTextLine_textChanged(const QString & text) } #if (QT_VERSION >= 0x040000) -#define QTextEdit Q3TextEdit #define QProgressDialog Q3ProgressDialog #define QStyleSheetItem Q3StyleSheetItem #endif -QTextEdit *Preview::getCurrentEditor() +QTextEditFixed *Preview::getCurrentEditor() { QWidget *tw = pvTab->currentPage(); - QTextEdit *edit = 0; + QTextEditFixed *edit = 0; if (tw) { - edit = (QTextEdit*)tw->child("pvEdit"); + edit = (QTextEditFixed*)tw->child("pvEdit"); } return edit; } @@ -229,7 +284,7 @@ void Preview::doSearch(const QString &_text, bool next, bool reverse, QString text = _text; bool matchCase = matchCheck->isChecked(); - QTextEdit *edit = getCurrentEditor(); + QTextEditFixed *edit = getCurrentEditor(); if (edit == 0) { // ?? return; @@ -238,12 +293,13 @@ void Preview::doSearch(const QString &_text, bool next, bool reverse, if (text.isEmpty()) { if (m_haveAnchors == false) return; -#ifdef QT_SCROLL_TO_ANCHOR_BUG - text = QString::fromUtf8(firstTermBeacon); - matchCase = false; -#else -#error "Cycling without beacons needs coding" -#endif + if (m_curAnchor == m_lastAnchor) + m_curAnchor = 1; + else + m_curAnchor++; + QString aname = + QString::fromUtf8(termAnchorName(m_curAnchor).c_str()); + edit->moveToAnchor(aname); } // If next is false, the user added characters to the current @@ -339,7 +395,7 @@ void Preview::selecChanged() LOGDEB1(("Selection changed\n")); if (!m_currentW) return; - QTextEdit *edit = (QTextEdit *)m_currentW->child("pvEdit"); + QTextEditFixed *edit = (QTextEditFixed*)m_currentW->child("pvEdit"); if (edit == 0) { LOGERR(("Editor child not found\n")); return; @@ -365,7 +421,7 @@ void Preview::textDoubleClicked(int, int) LOGDEB2(("Preview::textDoubleClicked\n")); if (!m_currentW) return; - QTextEdit *edit = (QTextEdit *)m_currentW->child("pvEdit"); + QTextEditFixed *edit = (QTextEditFixed *)m_currentW->child("pvEdit"); if (edit == 0) { LOGERR(("Editor child not found\n")); return; @@ -399,11 +455,11 @@ void Preview::closeCurrentTab() } } -QTextEdit *Preview::addEditorTab() +QTextEditFixed *Preview::addEditorTab() { QWidget *anon = new QWidget((QWidget *)pvTab); QVBoxLayout *anonLayout = new QVBoxLayout(anon, 1, 1, "anonLayout"); - QTextEdit *editor = new QTextEdit(anon, "pvEdit"); + QTextEditFixed *editor = new QTextEditFixed(anon, "pvEdit"); editor->setReadOnly(TRUE); editor->setUndoRedoEnabled(FALSE ); anonLayout->addWidget(editor); @@ -585,9 +641,11 @@ class ToRichThread : public QThread { const HiliteData &hdata; list<string> &out; int loglevel; + int *lastanchor; public: - ToRichThread(string &i, const HiliteData& hd, list<string> &o) - : in(i), hdata(hd), out(o) + ToRichThread(string &i, const HiliteData& hd, list<string> &o, + int *lsta) + : in(i), hdata(hd), out(o), lastanchor(lsta) { loglevel = DebugLog::getdbl()->getlevel(); } @@ -595,7 +653,7 @@ class ToRichThread : public QThread { { DebugLog::getdbl()->setloglevel(loglevel); try { - plaintorich(in, out, hdata, false, true); + plaintorich(in, out, hdata, false, lastanchor); } catch (CancelExcept) { } } @@ -712,7 +770,7 @@ bool Preview::loadFileInCurrentTab(string fn, size_t sz, const Rcl::Doc &idoc, progress.setLabelText(tr("Creating preview text")); qApp->processEvents(); list<string> richlst; - ToRichThread rthr(fdoc.text, m_hData, richlst); + ToRichThread rthr(fdoc.text, m_hData, richlst, &m_lastAnchor); rthr.start(); for (;;prog++) { @@ -760,7 +818,7 @@ bool Preview::loadFileInCurrentTab(string fn, size_t sz, const Rcl::Doc &idoc, } // Load into editor - QTextEdit *editor = getCurrentEditor(); + QTextEditFixed *editor = getCurrentEditor(); editor->setText(""); if (highlightTerms) { QStyleSheetItem *item = @@ -777,8 +835,6 @@ bool Preview::loadFileInCurrentTab(string fn, size_t sz, const Rcl::Doc &idoc, it != qrichlst.end(); it++, prog++, instep++) { progress.setProgress(prog , prog <= nsteps-1 ? nsteps : prog+1); qApp->processEvents(); - if (it->find(QString::fromUtf8(firstTermBeacon)) != -1) - m_haveAnchors = true; editor->append(*it); @@ -795,9 +851,9 @@ bool Preview::loadFileInCurrentTab(string fn, size_t sz, const Rcl::Doc &idoc, } } - progress.close(); + m_haveAnchors = m_lastAnchor != 0; if (searchTextLine->text().length() != 0) { // If there is a current search string, perform the search m_canBeep = true; @@ -806,26 +862,9 @@ bool Preview::loadFileInCurrentTab(string fn, size_t sz, const Rcl::Doc &idoc, // Position to the first query term if (m_haveAnchors) { QString aname = QString::fromUtf8(termAnchorName(1).c_str()); - LOGDEB2(("Call scrolltoanchor(%s)\n", (const char *)aname.utf8())); - editor->scrollToAnchor(aname); - -#if (QT_VERSION < 0x040000) - // The q3textedit version of te::find() is slow to the point of - // being unusable (plus it does not always work). So we - // don't position to the first term automatically, the - // user can still use the search function in the preview - // window to do it -#ifdef QT_SCROLL_TO_ANCHOR_BUG - bool ocanbeep = m_canBeep; - m_canBeep = false; - QString empty; - // Calling doSearch() with an empty string will look for - // the first occurrence of a search term` - // doSearch(_text, next, reverse, wordOnly) - doSearch(empty, true, false, false); - m_canBeep = ocanbeep; -#endif -#endif // (QT_VERSION < 0x040000) + LOGDEB2(("Call movetoanchor(%s)\n", (const char *)aname.utf8())); + editor->moveToAnchor(aname); + m_curAnchor = 1; } } diff --git a/src/qtgui/preview_w.h b/src/qtgui/preview_w.h index d26d0a38..584588c7 100644 --- a/src/qtgui/preview_w.h +++ b/src/qtgui/preview_w.h @@ -1,6 +1,6 @@ #ifndef _PREVIEW_W_H_INCLUDED_ #define _PREVIEW_W_H_INCLUDED_ -/* @(#$Id: preview_w.h,v 1.15 2007-07-20 14:43:21 dockes Exp $ (C) 2006 J.F.Dockes */ +/* @(#$Id: preview_w.h,v 1.16 2007-11-15 18:05:32 dockes Exp $ (C) 2006 J.F.Dockes */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,15 +22,54 @@ #include <qwidget.h> #include "rcldb.h" -#if (QT_VERSION < 0x040000) -#include "preview.h" -#else -#include "ui_preview.h" -#define QTextEdit Q3TextEdit -#endif #include "refcntr.h" #include "plaintorich.h" +class QTabWidget; +class QLabel; +class QLineEdit; +class QPushButton; +class QCheckBox; +class QTextEditFixed; + +#include <qtextedit.h> +#include <private/qrichtext_p.h> +class QTextEditFixed : public QTextEdit { + Q_OBJECT +public: + QTextEditFixed( QWidget* parent=0, const char* name=0 ) + : QTextEdit(parent, name) + {} + void moveToAnchor(const QString& name) + { + if (name.isEmpty()) + return; + sync(); + QTextCursor l_cursor(document()); + QTextParagraph* last = document()->lastParagraph(); + for (;;) { + QTextStringChar* c = l_cursor.paragraph()->at(l_cursor.index()); + if(c->isAnchor()) { + QString a = c->anchorName(); + fprintf(stderr, "QTextEdit::scrollToAnchor: anchor nm [%s]\n", + (const char *)a.ascii()); + if ( a == name || + (a.contains( '#' ) && + QStringList::split('#', a).contains(name))) { + + *(textCursor()) = l_cursor; + ensureCursorVisible(); + break; + } + } + if (l_cursor.paragraph() == last && l_cursor.atParagEnd()) + break; + l_cursor.gotoNextLetter(); + } + } +}; + + // We keep a list of data associated to each tab class TabData { public: @@ -44,36 +83,18 @@ class TabData { {} }; -class QTextEdit; +class Preview : public QWidget { -//MOC_SKIP_BEGIN -#if QT_VERSION < 0x040000 -class DummyPreviewBase : public PreviewBase -{ - public: DummyPreviewBase(QWidget* parent = 0) : PreviewBase(parent) {} -}; -#else -class DummyPreviewBase : public QWidget, public Ui::PreviewBase -{ -public: DummyPreviewBase(QWidget* parent):QWidget(parent){setupUi(this);} -}; -#endif -//MOC_SKIP_END - -class Preview : public DummyPreviewBase -{ Q_OBJECT public: + Preview(int sid, // Search Id const HiliteData& hdata) // Search terms etc. for highlighting - : DummyPreviewBase(0) + : QWidget(0), m_searchId(sid), m_hData(hdata) { init(); - m_searchId = sid; - m_hData = hdata; } - ~Preview(){} virtual void closeEvent(QCloseEvent *e ); @@ -114,12 +135,22 @@ private: HiliteData m_hData; bool m_justCreated; // First tab create is different bool m_haveAnchors; // Search terms are marked in text + int m_lastAnchor; // Number of last anchor. Then rewind to 1 + int m_curAnchor; + + QTabWidget* pvTab; + QLabel* searchLabel; + QLineEdit* searchTextLine; + QPushButton* nextButton; + QPushButton* prevButton; + QPushButton* clearPB; + QCheckBox* matchCheck; void init(); virtual void setCurTabProps(const string& fn, const Rcl::Doc& doc, int docnum); - virtual QTextEdit *getCurrentEditor(); - virtual QTextEdit *addEditorTab(); + virtual QTextEditFixed *getCurrentEditor(); + virtual QTextEditFixed *addEditorTab(); virtual bool loadFileInCurrentTab(string fn, size_t sz, const Rcl::Doc& idoc, int dnm); TabData *tabDataForCurrent(); // Return auxiliary data pointer for cur tab diff --git a/src/qtgui/recoll.pro.in b/src/qtgui/recoll.pro.in index 11901517..244e7a33 100644 --- a/src/qtgui/recoll.pro.in +++ b/src/qtgui/recoll.pro.in @@ -39,7 +39,6 @@ SOURCES += \ FORMS = \ advsearch.ui \ spell.ui \ - preview.ui \ rclmain.ui \ sort.ui \ ssearchb.ui \