diff --git a/src/qtgui/advsearch_w.cpp b/src/qtgui/advsearch_w.cpp index c5b97f18..f2599e94 100644 --- a/src/qtgui/advsearch_w.cpp +++ b/src/qtgui/advsearch_w.cpp @@ -65,8 +65,6 @@ void AdvSearch::init() HelpClient::installMap((const char *)objectName().toUtf8(), "RCL.SEARCH.COMPLEX"); - this->installEventFilter(this); - // signals and slots connections connect(delFiltypPB, SIGNAL(clicked()), this, SLOT(delFiltypPB_clicked())); connect(searchPB, SIGNAL(clicked()), this, SLOT(runSearch())); @@ -146,20 +144,6 @@ void AdvSearch::init() cat_rtranslations[tr("other")] = QString::fromUtf8("other"); } -bool AdvSearch::eventFilter(QObject *, QEvent *event) -{ - // LOGDEB(("AdvSearch::eventFilter. Type %d\n", (int)event->type())); - if (event->type() == QEvent::KeyPress || - event->type() == QEvent::ShortcutOverride) { - QKeyEvent *ke = static_cast(event); - if (ke->key() == Qt::Key_Q && (ke->modifiers() & Qt::ControlModifier)) { - recollNeedsExit = 1; - return true; - } - } - return false; -} - void AdvSearch::saveCnf() { // Save my state diff --git a/src/qtgui/advsearch_w.h b/src/qtgui/advsearch_w.h index bc07d68f..9415313e 100644 --- a/src/qtgui/advsearch_w.h +++ b/src/qtgui/advsearch_w.h @@ -42,7 +42,6 @@ public: init(); } ~AdvSearch(){} - virtual bool eventFilter(QObject *target, QEvent *event); public slots: virtual void delFiltypPB_clicked(); diff --git a/src/qtgui/guiutils.cpp b/src/qtgui/guiutils.cpp index cacb5762..9cece549 100644 --- a/src/qtgui/guiutils.cpp +++ b/src/qtgui/guiutils.cpp @@ -208,6 +208,7 @@ void rwSettings(bool writing) if (prefs.restableFields.empty()) { prefs.restableFields.push_back("filename"); prefs.restableFields.push_back("title"); + prefs.restableFields.push_back("date"); prefs.restableFields.push_back("url"); } } diff --git a/src/qtgui/main.cpp b/src/qtgui/main.cpp index f7c6b159..be0155cf 100644 --- a/src/qtgui/main.cpp +++ b/src/qtgui/main.cpp @@ -169,7 +169,9 @@ int main(int argc, char **argv) QApplication app(argc, argv); - // fprintf(stderr, "Application created\n"); + QCoreApplication::setOrganizationName("Recoll.org"); + QCoreApplication::setApplicationName("recoll"); + string a_config; string question; diff --git a/src/qtgui/preview_w.cpp b/src/qtgui/preview_w.cpp index 444581be..23640011 100644 --- a/src/qtgui/preview_w.cpp +++ b/src/qtgui/preview_w.cpp @@ -239,11 +239,7 @@ bool Preview::eventFilter(QObject *target, QEvent *event) PreviewTextEdit *edit = currentEditor(); QKeyEvent *keyEvent = (QKeyEvent *)event; - if (keyEvent->key() == Qt::Key_Q && - (keyEvent->modifiers() & Qt::ControlModifier)) { - recollNeedsExit = 1; - return true; - } else if (keyEvent->key() == Qt::Key_Escape) { + if (keyEvent->key() == Qt::Key_Escape) { close(); return true; } else if (keyEvent->key() == Qt::Key_Down && diff --git a/src/qtgui/rclmain_w.cpp b/src/qtgui/rclmain_w.cpp index c215d253..671126fd 100644 --- a/src/qtgui/rclmain_w.cpp +++ b/src/qtgui/rclmain_w.cpp @@ -80,6 +80,7 @@ using namespace confgui; extern "C" int XFlush(void *); QString g_stringAllStem, g_stringNoStem; +static const QKeySequence quitKeySeq("Ctrl+q"); void RclMain::init() { @@ -200,17 +201,18 @@ void RclMain::init() // A shortcut to get the focus back to the search entry. QKeySequence seq("Ctrl+Shift+s"); QShortcut *sc = new QShortcut(seq, this); - connect(sc, SIGNAL (activated()), this, SLOT (focusToSearch())); + connect(sSearch, SIGNAL(startSearch(RefCntr)), this, SLOT(startSearch(RefCntr))); + connect(sSearch, SIGNAL(clearSearch()), + this, SLOT(resetSearch())); + connect(preferencesMenu, SIGNAL(triggered(QAction*)), this, SLOT(setStemLang(QAction*))); connect(preferencesMenu, SIGNAL(aboutToShow()), this, SLOT(adjustPrefsMenu())); - connect(sSearch, SIGNAL(clearSearch()), - this, SLOT(resetSearch())); connect(fileExitAction, SIGNAL(activated() ), this, SLOT(fileExit() ) ); connect(fileToggleIndexingAction, SIGNAL(activated()), @@ -243,14 +245,20 @@ void RclMain::init() connect(periodictimer, SIGNAL(timeout()), this, SLOT(periodic100())); + sc = new QShortcut(quitKeySeq, restable); + connect(sc, SIGNAL (activated()), + this, SLOT (fileExit())); connect(this, SIGNAL(docSourceChanged(RefCntr)), restable, SLOT(setDocSource(RefCntr))); connect(this, SIGNAL(searchReset()), restable, SLOT(resetSource())); - connect(restable, SIGNAL(sortDataChanged(DocSeqSortSpec)), - this, SLOT(onResTableSortBy(DocSeqSortSpec))); connect(this, SIGNAL(applyFiltSortData()), restable, SLOT(readDocSource())); + connect(this, SIGNAL(sortDataChanged(DocSeqSortSpec)), + restable, SLOT(onSortDataChanged(DocSeqSortSpec))); + + connect(restable->getModel(), SIGNAL(sortDataChanged(DocSeqSortSpec)), + this, SLOT(onResTableSortBy(DocSeqSortSpec))); connect(this, SIGNAL(docSourceChanged(RefCntr)), reslist, SLOT(setDocSource(RefCntr))); @@ -289,6 +297,8 @@ void RclMain::init() this, SLOT(startPreview(int, Rcl::Doc, int))); connect(reslist, SIGNAL(previewRequested(Rcl::Doc)), this, SLOT(startPreview(Rcl::Doc))); + connect(reslist, SIGNAL(headerClicked()), + this, SLOT(showQueryDetails())); // Start timer on a slow period (used for checking ^C). Will be // speeded up during indexing @@ -440,6 +450,8 @@ void RclMain::fileExit() prefs.mainwidth = width(); prefs.mainheight = height(); } + restable->saveSizeState(); + prefs.ssearchTyp = sSearch->searchTypCMB->currentIndex(); if (asearchform) delete asearchform; @@ -551,6 +563,7 @@ void RclMain::startSearch(RefCntr sdata) LOGDEB(("RclMain::startSearch. Indexing %s\n", idxthread_getStatus() == IDXTS_NULL?"on":"off")); emit searchReset(); + m_source = RefCntr(); // The db may have been closed at the end of indexing string reason; @@ -583,8 +596,8 @@ void RclMain::startSearch(RefCntr sdata) string(tr("Query results").toUtf8()), sdata); src->setAbstractParams(prefs.queryBuildAbstract, prefs.queryReplaceAbstract); - - emit docSourceChanged(RefCntr(src)); + m_source = RefCntr(src); + emit docSourceChanged(m_source); emit sortDataChanged(m_sortspec); emit filtDataChanged(m_filtspec); emit applyFiltSortData(); @@ -601,6 +614,9 @@ void RclMain::showAdvSearchDialog() { if (asearchform == 0) { asearchform = new AdvSearch(0); + connect(new QShortcut(quitKeySeq, asearchform), SIGNAL (activated()), + this, SLOT (fileExit())); + connect(asearchform, SIGNAL(startSearch(RefCntr)), this, SLOT(startSearch(RefCntr))); asearchform->show(); @@ -615,6 +631,8 @@ void RclMain::showSpellDialog() { if (spellform == 0) { spellform = new SpellW(0); + connect(new QShortcut(quitKeySeq, spellform), SIGNAL (activated()), + this, SLOT (fileExit())); connect(spellform, SIGNAL(wordSelect(QString)), sSearch, SLOT(addTerm(QString))); spellform->show(); @@ -631,7 +649,8 @@ void RclMain::showIndexConfig() LOGDEB(("showIndexConfig()\n")); if (indexConfig == 0) { indexConfig = new ConfIndexW(0, rclconfig); - LOGDEB(("showIndexConfig(): confindexW created\n")); + connect(new QShortcut(quitKeySeq, indexConfig), SIGNAL (activated()), + this, SLOT (fileExit())); } else { // Close and reopen, in hope that makes us visible... indexConfig->close(); @@ -643,6 +662,8 @@ void RclMain::showUIPrefs() { if (uiprefs == 0) { uiprefs = new UIPrefsDialog(0); + connect(new QShortcut(quitKeySeq, uiprefs), SIGNAL (activated()), + this, SLOT (fileExit())); connect(uiprefs, SIGNAL(uiprefsDone()), this, SLOT(setUIPrefs())); connect(this, SIGNAL(stemLangChanged(const QString&)), uiprefs, SLOT(setStemLang(const QString&))); @@ -657,6 +678,8 @@ void RclMain::showExtIdxDialog() { if (uiprefs == 0) { uiprefs = new UIPrefsDialog(0); + connect(new QShortcut(quitKeySeq, uiprefs), SIGNAL (activated()), + this, SLOT (fileExit())); connect(uiprefs, SIGNAL(uiprefsDone()), this, SLOT(setUIPrefs())); } else { // Close and reopen, in hope that makes us visible... @@ -673,6 +696,7 @@ void RclMain::showAboutDialog() string("
http://www.xapian.org"); QMessageBox::information(this, tr("About Recoll"), vstring.c_str()); } + void RclMain::showMissingHelpers() { string miss = rclconfig->getMissingHelperDesc(); @@ -719,6 +743,7 @@ void RclMain::startPreview(int docnum, Rcl::Doc doc, int mod) HiliteData hdata; reslist->getTerms(hdata.terms, hdata.groups, hdata.gslks); curPreview = new Preview(reslist->listId(), hdata); + if (curPreview == 0) { QMessageBox::warning(0, tr("Warning"), tr("Can't create preview window"), @@ -726,6 +751,8 @@ void RclMain::startPreview(int docnum, Rcl::Doc doc, int mod) QMessageBox::NoButton); return; } + connect(new QShortcut(quitKeySeq, curPreview), SIGNAL (activated()), + this, SLOT (fileExit())); connect(curPreview, SIGNAL(previewClosed(Preview *)), this, SLOT(previewClosed(Preview *))); connect(curPreview, SIGNAL(wordSelect(QString)), @@ -736,7 +763,7 @@ void RclMain::startPreview(int docnum, Rcl::Doc doc, int mod) this, SLOT(previewPrevInTab(Preview *, int, int))); connect(curPreview, SIGNAL(previewExposed(Preview *, int, int)), this, SLOT(previewExposed(Preview *, int, int))); - curPreview->setWindowTitle(reslist->getDescription()); + curPreview->setWindowTitle(getQueryDescription()); curPreview->show(); } curPreview->makeDocCurrent(doc, docnum); @@ -759,6 +786,8 @@ void RclMain::startPreview(Rcl::Doc doc) QMessageBox::NoButton); return; } + connect(new QShortcut(quitKeySeq, preview), SIGNAL (activated()), + this, SLOT (fileExit())); connect(preview, SIGNAL(wordSelect(QString)), sSearch, SLOT(addTerm(QString))); preview->show(); @@ -796,7 +825,7 @@ void RclMain::previewPrevOrNextInTab(Preview * w, int sid, int docnum, bool nxt) docnum++; else docnum--; - if (docnum < 0 || docnum >= reslist->getResCnt()) { + if (docnum < 0 || m_source.isNull() || docnum >= m_source->getResCnt()) { QApplication::beep(); return; } @@ -825,6 +854,9 @@ void RclMain::previewExposed(Preview *, int sid, int docnum) void RclMain::onSortCtlChanged() { + if (m_sortspecnochange) + return; + LOGDEB(("RclMain::onCtlDataChanged()\n")); m_sortspec.reset(); if (actionSortByDateAsc->isChecked()) { @@ -845,9 +877,13 @@ void RclMain::onSortCtlChanged() emit applyFiltSortData(); } -void RclMain::onResTableSortBy(DocSeqSortSpec) +void RclMain::onResTableSortBy(DocSeqSortSpec spec) { -// TOBEDONE: do something about the up down arrows ! + m_sortspecnochange = true; + actionSortByDateDesc->setChecked(false); + actionSortByDateAsc->setChecked(false); + m_sortspecnochange = false; + m_sortspec = spec; emit applyFiltSortData(); } @@ -1177,7 +1213,7 @@ void RclMain::showDocHistory() { LOGDEB(("RclMain::showDocHistory\n")); emit searchReset(); - + m_source = RefCntr(); curPreview = 0; string reason; @@ -1196,7 +1232,8 @@ void RclMain::showDocHistory() new DocSequenceHistory(rcldb, g_dynconf, string(tr("Document history").toUtf8())); src->setDescription((const char *)tr("History data").toUtf8()); - reslist->setDocSource(RefCntr(src)); + m_source = RefCntr(src); + emit docSourceChanged(m_source); emit sortDataChanged(m_sortspec); emit filtDataChanged(m_filtspec); emit applyFiltSortData(); @@ -1239,6 +1276,23 @@ void RclMain::enablePrevPage(bool yesno) firstPageAction->setEnabled(yesno); } +QString RclMain::getQueryDescription() +{ + if (m_source.isNull()) + return ""; + return QString::fromUtf8(m_source->getDescription().c_str()); +} + +/** Show detailed expansion of a query */ +void RclMain::showQueryDetails() +{ + if (m_source.isNull()) + return; + string oq = breakIntoLines(m_source->getDescription(), 100, 50); + QString desc = tr("Query details") + ": " + QString::fromUtf8(oq.c_str()); + QMessageBox::information(this, tr("Query details"), desc); +} + // User pressed a category button: set filter params in reslist void RclMain::catgFilter(int id) { diff --git a/src/qtgui/rclmain_w.h b/src/qtgui/rclmain_w.h index 1e3bbdd8..ebac3c36 100644 --- a/src/qtgui/rclmain_w.h +++ b/src/qtgui/rclmain_w.h @@ -48,13 +48,14 @@ class RclMain : public QMainWindow, public Ui::RclMainBase public: RclMain(QWidget * parent = 0) - : QMainWindow(parent) + : QMainWindow(parent), m_sortspecnochange(false) { setupUi(this); init(); } ~RclMain() {} virtual bool eventFilter(QObject *target, QEvent *event); + QString getQueryDescription(); public slots: virtual bool close(); @@ -96,8 +97,9 @@ public slots: virtual void focusToSearch(); virtual void on_actionSortByDateAsc_toggled(bool on); virtual void on_actionSortByDateDesc_toggled(bool on); - virtual void resultCount(int); virtual void onResTableSortBy(DocSeqSortSpec); + virtual void resultCount(int); + virtual void showQueryDetails(); signals: void docSourceChanged(RefCntr); @@ -127,8 +129,10 @@ private: QAction * m_idAllStem; bool m_idxStatusAck; // Did we act on last status? DocSeqFiltSpec m_filtspec; + bool m_sortspecnochange; DocSeqSortSpec m_sortspec; - + RefCntr m_source; + virtual void init(); virtual void previewPrevOrNextInTab(Preview *, int sid, int docnum, bool next); diff --git a/src/qtgui/reslist.cpp b/src/qtgui/reslist.cpp index cc477871..9e2f7cbc 100644 --- a/src/qtgui/reslist.cpp +++ b/src/qtgui/reslist.cpp @@ -91,13 +91,12 @@ bool QtGuiResListPager::append(const string& data) } bool QtGuiResListPager::append(const string& data, int docnum, - const Rcl::Doc& doc) + const Rcl::Doc&) { LOGDEB2(("QtGuiReslistPager::appendDoc: blockCount %d, %s\n", m_parent->document()->blockCount(), data.c_str())); logdata(data.c_str()); int blkcnt0 = m_parent->document()->blockCount(); - m_parent->m_curDocs.push_back(doc); m_parent->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor); m_parent->textCursor().insertBlock(); m_parent->insertHtml(QString::fromUtf8(data.c_str())); @@ -223,7 +222,6 @@ ResList::ResList(QWidget* parent, const char* name) connect(this, SIGNAL(highlighted(const QString &)), this, SLOT(highlighted(const QString &))); #endif - connect(this, SIGNAL(headerClicked()), this, SLOT(showQueryDetails())); setContextMenuPolicy(Qt::CustomContextMenu); connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(createPopupMenu(const QPoint&))); @@ -286,7 +284,7 @@ void ResList::readDocSource() m_pager->setPageSize(prefs.respagesize); m_pager->setDocSource(m_source); resultPageNext(); - emit hasResults(getResCnt()); + emit hasResults(m_source->getResCnt()); } void ResList::setSortParams(DocSeqSortSpec spec) @@ -409,37 +407,33 @@ bool ResList::getDoc(int docnum, Rcl::Doc &doc) { LOGDEB(("ResList::getDoc: docnum %d winfirst %d\n", docnum, m_pager->pageNumber() * prefs.respagesize)); - if (docnum < 0) + int winfirst = m_pager->pageFirstDocNum(); + int winlast = m_pager->pageLastDocNum(); + if (docnum < 0 || winfirst < 0 || winlast < 0) return false; - if (m_pager->pageNumber() < 0) - return false; - int winfirst = m_pager->pageNumber() * prefs.respagesize; + // Is docnum in current page ? Then all Ok - if (docnum >= winfirst && docnum < winfirst + int(m_curDocs.size())) { - doc = m_curDocs[docnum - winfirst]; - return true; + if (docnum >= winfirst && docnum <= winlast) { + return m_source->getDoc(docnum, doc); } // Else we accept to page down or up but not further if (docnum < winfirst && docnum >= winfirst - prefs.respagesize) { resultPageBack(); - } else if (docnum < winfirst + int(m_curDocs.size()) + prefs.respagesize) { + } else if (docnum < winlast + 1 + prefs.respagesize) { resultPageNext(); } - winfirst = m_pager->pageNumber() * prefs.respagesize; - if (docnum >= winfirst && docnum < winfirst + int(m_curDocs.size())) { - doc = m_curDocs[docnum - winfirst]; - return true; + winfirst = m_pager->pageFirstDocNum(); + winlast = m_pager->pageLastDocNum(); + if (docnum >= winfirst && docnum <= winlast) { + return m_source->getDoc(docnum, doc); } return false; } void ResList::keyPressEvent(QKeyEvent * e) { - if (e->key() == Qt::Key_Q && (e->modifiers() & Qt::ControlModifier)) { - recollNeedsExit = 1; - return; - } else if (e->key() == Qt::Key_PageUp || e->key() == Qt::Key_Backspace) { + if (e->key() == Qt::Key_PageUp || e->key() == Qt::Key_Backspace) { resPageUpOrBack(); return; } else if (e->key() == Qt::Key_PageDown || e->key() == Qt::Key_Space) { @@ -461,14 +455,6 @@ void ResList::mouseReleaseEvent(QMouseEvent *e) QTextBrowser::mouseReleaseEvent(e); } -// Return total result list count -int ResList::getResCnt() -{ - if (m_source.isNull()) - return -1; - return m_source->getResCnt(); -} - void ResList::highlighted(const QString& ) { // This is supposedly called when a link is preactivated (hover or tab @@ -530,7 +516,6 @@ void ResList::resultPageNext() void ResList::displayPage() { - m_curDocs.clear(); m_pageParaToReldocnums.clear(); clear(); m_pager->displayPage(); @@ -587,7 +572,6 @@ void ResList::previewExposed(int docnum) } } - // Double click in res list: add selection to simple search void ResList::mouseDoubleClickEvent(QMouseEvent *event) { @@ -668,6 +652,7 @@ void ResList::menuPreview() if (getDoc(m_popDoc, doc)) emit docPreviewClicked(m_popDoc, doc, 0); } + void ResList::menuSaveToFile() { Rcl::Doc doc; @@ -715,6 +700,7 @@ void ResList::menuEdit() if (getDoc(m_popDoc, doc)) emit docEditClicked(doc); } + void ResList::menuCopyFN() { LOGDEB(("menuCopyFN\n")); @@ -734,6 +720,7 @@ void ResList::menuCopyFN() QApplication::clipboard()->setText(qfn, QClipboard::Clipboard); } } + void ResList::menuCopyURL() { Rcl::Doc doc; @@ -752,16 +739,3 @@ void ResList::menuExpand() if (getDoc(m_popDoc, doc)) emit docExpand(doc); } - -QString ResList::getDescription() -{ - return QString::fromUtf8(m_source->getDescription().c_str()); -} - -/** Show detailed expansion of a query */ -void ResList::showQueryDetails() -{ - string oq = breakIntoLines(m_source->getDescription(), 100, 50); - QString desc = tr("Query details") + ": " + QString::fromUtf8(oq.c_str()); - QMessageBox::information(this, tr("Query details"), desc); -} diff --git a/src/qtgui/reslist.h b/src/qtgui/reslist.h index b4de0e72..2f4d5be6 100644 --- a/src/qtgui/reslist.h +++ b/src/qtgui/reslist.h @@ -44,12 +44,9 @@ class ResList : public QTextBrowser // Return document for given docnum. We act as an intermediary to // the docseq here. This has also the side-effect of making the - // entry current (visible and highlighted), and only work if the + // entry current (visible and highlighted), and only works if the // num is inside the current page or its immediate neighbours. bool getDoc(int docnum, Rcl::Doc &); - - QString getDescription(); // Printable actual query performed on db - int getResCnt(); // Return total result list size bool displayingHistory(); bool getTerms(vector& terms, vector >& groups, vector& gslks); @@ -103,16 +100,15 @@ class ResList : public QTextBrowser protected slots: virtual void languageChange(); virtual void linkWasClicked(const QUrl &); - virtual void showQueryDetails(); private: QtGuiResListPager *m_pager; RefCntr m_source; - std::vector m_curDocs; // Docs for current page // Translate from textedit paragraph number to relative // docnum. Built while we insert text into the qtextedit std::map m_pageParaToReldocnums; + int m_popDoc; // Docnum for the popup menu. int m_curPvDoc;// Docnum for current preview int m_lstClckMod; // Last click modifier. diff --git a/src/qtgui/restable.cpp b/src/qtgui/restable.cpp index 56b76633..c99d37ad 100644 --- a/src/qtgui/restable.cpp +++ b/src/qtgui/restable.cpp @@ -5,9 +5,12 @@ static char rcsid[] = "@(#$Id: reslist.cpp,v 1.52 2008-12-17 15:12:08 dockes Exp #include "autoconfig.h" #include +#include #include +#include #include +#include #include "refcntr.h" #include "docseq.h" @@ -65,17 +68,63 @@ string ResTablePager::iconPath(const string& mtype) ////////////////////////////////////////////// //// Data model methods //// +static string gengetter(const string& fld, const Rcl::Doc& doc) +{ + map::const_iterator it = doc.meta.find(fld); + if (it == doc.meta.end()) { + return string(); + } + return it->second; +} + +static string dategetter(const string&, const Rcl::Doc& doc) +{ + char datebuf[100]; + datebuf[0] = 0; + if (!doc.dmtime.empty() || !doc.fmtime.empty()) { + time_t mtime = doc.dmtime.empty() ? + atol(doc.fmtime.c_str()) : atol(doc.dmtime.c_str()); + struct tm *tm = localtime(&mtime); + strftime(datebuf, 99, "%x", tm); + } + return datebuf; +} + +static string datetimegetter(const string&, const Rcl::Doc& doc) +{ + char datebuf[100]; + datebuf[0] = 0; + if (!doc.dmtime.empty() || !doc.fmtime.empty()) { + time_t mtime = doc.dmtime.empty() ? + atol(doc.fmtime.c_str()) : atol(doc.dmtime.c_str()); + struct tm *tm = localtime(&mtime); +#ifndef sun + strftime(datebuf, 99, "%Y-%m-%d %H:%M:%S %z", tm); +#else + strftime(datebuf, 99, "%c", tm); +#endif + } + return datebuf; +} + RecollModel::RecollModel(const QStringList fields, QObject *parent) : QAbstractTableModel(parent) { for (QStringList::const_iterator it = fields.begin(); - it != fields.end(); it++) + it != fields.end(); it++) { m_fields.push_back((const char *)(it->toUtf8())); + if (!stringlowercmp("date", m_fields[m_fields.size()-1])) + m_getters.push_back(dategetter); + else if (!stringlowercmp("datetime", m_fields[m_fields.size()-1])) + m_getters.push_back(datetimegetter); + else + m_getters.push_back(gengetter); + } } int RecollModel::rowCount(const QModelIndex&) const { - LOGDEB(("RecollModel::rowCount\n")); + LOGDEB2(("RecollModel::rowCount\n")); if (m_source.isNull()) return 0; return m_source->getResCnt(); @@ -83,7 +132,7 @@ int RecollModel::rowCount(const QModelIndex&) const int RecollModel::columnCount(const QModelIndex&) const { - LOGDEB(("RecollModel::columnCount\n")); + LOGDEB2(("RecollModel::columnCount\n")); return m_fields.size(); } @@ -106,41 +155,57 @@ bool RecollModel::getdoc(int index, Rcl::Doc &doc) return m_source->getDoc(index, doc); } -QVariant RecollModel::headerData(int col, Qt::Orientation orientation, - int role) const +QVariant RecollModel::headerData(int idx, Qt::Orientation orientation, + int role) const { - LOGDEB(("RecollModel::headerData: col %d\n", col)); - if (orientation != Qt::Horizontal || role != Qt::DisplayRole || - col >= int(m_fields.size())) { - return QVariant(); + LOGDEB2(("RecollModel::headerData: idx %d\n", idx)); + if (orientation == Qt::Vertical && role == Qt::DisplayRole) { + return idx; } - return QString::fromUtf8(m_fields[col].c_str()); + if (orientation == Qt::Horizontal && role == Qt::DisplayRole && + idx < int(m_fields.size())) { + return QString::fromUtf8(m_fields[idx].c_str()); + } + return QVariant(); } QVariant RecollModel::data(const QModelIndex& index, int role) const { - LOGDEB(("RecollModel::data: row %d col %d\n", index.row(), + LOGDEB2(("RecollModel::data: row %d col %d\n", index.row(), index.column())); if (m_source.isNull() || role != Qt::DisplayRole || !index.isValid() || index.column() >= int(m_fields.size())) { return QVariant(); } + Rcl::Doc doc; if (!m_source->getDoc(index.row(), doc)) { return QVariant(); } - map::const_iterator it = - doc.meta.find(m_fields[index.column()]); - if (it == doc.meta.end()) { - return QVariant(); - } - return QString::fromUtf8(it->second.c_str()); + + // Have to handle the special cases here. Some fields are + // synthetic and their name is hard-coded. Only date and datetime + // for now. + string colname = m_fields[index.column()]; + return QString::fromUtf8(m_getters[index.column()](colname, doc).c_str()); } +// This is called when the column headers are clicked void RecollModel::sort(int column, Qt::SortOrder order) { LOGDEB(("RecollModel::sort(%d, %d)\n", column, int(order))); + if (column >= 0 && column < int(m_fields.size())) { + DocSeqSortSpec spec; + spec.field = m_fields[column]; + if (!stringlowercmp("date", spec.field) || + !stringlowercmp("datetime", spec.field)) + spec.field = "mtime"; + spec.desc = order == Qt::AscendingOrder ? false : true; + m_source->setSortSpec(spec); + setDocSource(m_source); + emit sortDataChanged(spec); + } } @@ -151,7 +216,9 @@ void ResTable::init() if (!(m_model = new RecollModel(prefs.restableFields))) return; tableView->setModel(m_model); - m_pager = new ResTablePager(this); + tableView->setMouseTracking(true); + tableView->setSelectionBehavior(QAbstractItemView::SelectRows); + tableView->setSelectionMode(QAbstractItemView::SingleSelection); QHeaderView *header = tableView->horizontalHeader(); if (header) { @@ -164,14 +231,34 @@ void ResTable::init() header->setSortIndicator(-1, Qt::AscendingOrder); connect(header, SIGNAL(sectionResized(int,int,int)), this, SLOT(saveColWidths())); - connect(header, SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), - this, SLOT(sortByColumn(int, Qt::SortOrder))); } + + header = tableView->verticalHeader(); + if (header) { + header->setDefaultSectionSize(22); + } + + QKeySequence seq("Esc"); + QShortcut *sc = new QShortcut(seq, this); + connect(sc, SIGNAL (activated()), + tableView->selectionModel(), SLOT (clear())); + connect(tableView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex &)), + this, SLOT(onTableView_currentChanged(const QModelIndex&))); + + m_pager = new ResTablePager(this); + QSettings settings; + splitter->restoreState(settings.value("resTableSplitterSizes").toByteArray()); } -void ResTable::on_tableView_clicked(const QModelIndex& index) +void ResTable::saveSizeState() { - LOGDEB(("ResTable::on_tableView_clicked(%d, %d)\n", + QSettings settings; + settings.setValue("resTableSplitterSizes", splitter->saveState()); +} + +void ResTable::onTableView_currentChanged(const QModelIndex& index) +{ + LOGDEB(("ResTable::onTableView_currentChanged(%d, %d)\n", index.row(), index.column())); if (!m_model || m_model->m_source.isNull()) @@ -186,6 +273,14 @@ void ResTable::on_tableView_clicked(const QModelIndex& index) } } +void ResTable::on_tableView_entered(const QModelIndex& index) +{ + LOGDEB(("ResTable::on_tableView_entered(%d, %d)\n", + index.row(), index.column())); + if (!tableView->selectionModel()->hasSelection()) + onTableView_currentChanged(index); +} + void ResTable::setDocSource(RefCntr nsource) { LOGDEB(("ResTable::setDocSource\n")); @@ -215,18 +310,13 @@ void ResTable::saveColWidths() } } -void ResTable::sortByColumn(int column, Qt::SortOrder order) +// This is called when the sort order is changed from another widget +void ResTable::onSortDataChanged(DocSeqSortSpec) { - LOGDEB(("ResTable::sortByColumn(%d,%d)\n", column, int(order))); - - if (column >= 0 && m_model && column < int(m_model->m_fields.size())) { - DocSeqSortSpec spec; - spec.field = m_model->m_fields[column]; - spec.desc = order == Qt::AscendingOrder ? false : true; - m_model->m_source->setSortSpec(spec); - readDocSource(); - emit sortDataChanged(spec); - } + QHeaderView *header = tableView->horizontalHeader(); + if (!header) + return; + header->setSortIndicator(-1, Qt::AscendingOrder); } void ResTable::readDocSource() diff --git a/src/qtgui/restable.h b/src/qtgui/restable.h index 521e7f32..1c329abf 100644 --- a/src/qtgui/restable.h +++ b/src/qtgui/restable.h @@ -26,6 +26,8 @@ class ResTable; +typedef string (FieldGetter)(const string& fldname, const Rcl::Doc& doc); + class RecollModel : public QAbstractTableModel { Q_OBJECT @@ -45,9 +47,14 @@ public: virtual bool getdoc(int index, Rcl::Doc &doc); friend class ResTable; + +signals: + void sortDataChanged(DocSeqSortSpec); + private: mutable RefCntr m_source; vector m_fields; + vector m_getters; }; class ResTablePager; @@ -66,18 +73,17 @@ public: } virtual ~ResTable() {} + virtual RecollModel *getModel() {return m_model;} + virtual void saveSizeState(); public slots: - virtual void on_tableView_clicked(const QModelIndex&); + virtual void onTableView_currentChanged(const QModelIndex&); + virtual void on_tableView_entered(const QModelIndex& index); virtual void saveColWidths(); - virtual void sortByColumn(int column, Qt::SortOrder order); - virtual void setDocSource(RefCntr nsource); virtual void resetSource(); virtual void readDocSource(); - -signals: - void sortDataChanged(DocSeqSortSpec); + virtual void onSortDataChanged(DocSeqSortSpec); friend class ResTablePager; private: diff --git a/src/qtgui/restable.ui b/src/qtgui/restable.ui index 140a6663..d91394ae 100644 --- a/src/qtgui/restable.ui +++ b/src/qtgui/restable.ui @@ -26,15 +26,24 @@ 0 - 10 + 2 QAbstractItemView::NoEditTriggers + + false + + + true + true + + false + false @@ -49,7 +58,7 @@ 0 - 1 + 0 diff --git a/src/query/docseqdb.cpp b/src/query/docseqdb.cpp index c5c46c98..563fb310 100644 --- a/src/query/docseqdb.cpp +++ b/src/query/docseqdb.cpp @@ -120,11 +120,12 @@ bool DocSequenceDb::setFiltSpec(const DocSeqFiltSpec &fs) return m_q->setQuery(m_fsdata); } -bool DocSequenceDb::setSortSpec(const DocSeqSortSpec &sortspec) +bool DocSequenceDb::setSortSpec(const DocSeqSortSpec &spec) { - LOGDEB(("DocSequenceDb::setSortSpec\n")); - if (sortspec.isNotNull()) { - m_q->setSortBy(sortspec.field, !sortspec.desc); + LOGDEB(("DocSequenceDb::setSortSpec: fld [%s] %s\n", + spec.field.c_str(), spec.desc ? "desc" : "asc")); + if (spec.isNotNull()) { + m_q->setSortBy(spec.field, !spec.desc); } else { m_q->setSortBy(string(), true); } diff --git a/src/query/reslistpager.h b/src/query/reslistpager.h index c274587e..d43303ea 100644 --- a/src/query/reslistpager.h +++ b/src/query/reslistpager.h @@ -41,6 +41,14 @@ public: return -1; return m_winfirst / m_pagesize; } + int pageFirstDocNum() { + return m_winfirst; + } + int pageLastDocNum() { + if (m_winfirst < 0 || m_respage.size() == 0) + return -1; + return m_winfirst + m_respage.size() - 1; + } virtual int pageSize() const {return m_pagesize;} void pageNext(); bool hasNext() {return m_hasNext;} diff --git a/src/rcldb/rcldb.cpp b/src/rcldb/rcldb.cpp index 4668cb9d..13df4ed0 100644 --- a/src/rcldb/rcldb.cpp +++ b/src/rcldb/rcldb.cpp @@ -142,7 +142,7 @@ static const string keycap("caption"); bool Db::Native::dbDataToRclDoc(Xapian::docid docid, std::string &data, Doc &doc, int percent) { - LOGDEB0(("Db::dbDataToRclDoc: data:\n %s\n", data.c_str())); + LOGDEB2(("Db::dbDataToRclDoc: data:\n%s\n", data.c_str())); ConfSimple parms(data); if (!parms.ok()) return false; @@ -225,7 +225,7 @@ static void listList(const string& what, const list&l) string Db::Native::makeAbstract(Xapian::docid docid, Query *query) { Chrono chron; - LOGDEB(("makeAbstract:%d: maxlen %d wWidth %d\n", chron.ms(), + LOGDEB0(("makeAbstract:%d: maxlen %d wWidth %d\n", chron.ms(), m_rcldb->m_synthAbsLen, m_rcldb->m_synthAbsWordCtxLen)); list terms; @@ -433,7 +433,7 @@ string Db::Native::makeAbstract(Xapian::docid docid, Query *query) if ('A' <= (*term).at(0) && (*term).at(0) <= 'Z') continue; if (cutoff-- < 0) { - LOGDEB(("makeAbstract: max term count cutoff\n")); + LOGDEB0(("makeAbstract: max term count cutoff\n")); break; } @@ -441,7 +441,7 @@ string Db::Native::makeAbstract(Xapian::docid docid, Query *query) for (pos = xrdb.positionlist_begin(docid, *term); pos != xrdb.positionlist_end(docid, *term); pos++) { if (cutoff-- < 0) { - LOGDEB(("makeAbstract: max term count cutoff\n")); + LOGDEB0(("makeAbstract: max term count cutoff\n")); break; } map::iterator vit; @@ -504,7 +504,7 @@ string Db::Native::makeAbstract(Xapian::docid docid, Query *query) if (!abstract.compare("... ")) abstract.clear(); - LOGDEB(("makeAbtract: done in %d mS\n", chron.millis())); + LOGDEB0(("makeAbtract: done in %d mS\n", chron.millis())); return abstract; }