diff --git a/src/internfile/internfile.cpp b/src/internfile/internfile.cpp index b44d045f..ba30ca5d 100644 --- a/src/internfile/internfile.cpp +++ b/src/internfile/internfile.cpp @@ -547,6 +547,50 @@ void FileInterner::getMissingDescription(FIMissingStore *st, string& out) } } +void FileInterner::getMissingFromDescription(FIMissingStore *st, const string& in) +{ + if (st == 0) + return; + + // The "missing" file is text. Each line defines a missing filter + // and the list of mime types actually encountered that needed it (see method + // getMissingDescription()) + + vector lines; + stringToTokens(in, lines, "\n"); + + for (vector::const_iterator it = lines.begin(); + it != lines.end(); it++) { + // Lines from the file are like: + // + // filter name string (mime1 mime2) + // + // We can't be too sure that there will never be a parenthesis + // inside the filter string as this comes from the filter + // itself. The list part is safer, so we start from the end. + const string& line = *it; + string::size_type lastopen = line.find_last_of("("); + if (lastopen == string::npos) + continue; + string::size_type lastclose = line.find_last_of(")"); + if (lastclose == string::npos || lastclose <= lastopen + 1) + continue; + string smtypes = line.substr(lastopen+1, lastclose - lastopen - 1); + vector mtypes; + stringToTokens(smtypes, mtypes); + string filter = line.substr(0, lastopen); + trimstring(filter); + if (filter.empty()) + continue; + + st->m_missingExternal.insert(filter); + for (vector::const_iterator itt = mtypes.begin(); + itt != mtypes.end(); itt++) { + st->m_typesForMissing[filter].insert(*itt); + } + } +} + // Helper for extracting a value from a map. static inline bool getKeyValue(const map& docdata, const string& key, string& value) diff --git a/src/internfile/internfile.h b/src/internfile/internfile.h index 8acd235b..13e07046 100644 --- a/src/internfile/internfile.h +++ b/src/internfile/internfile.h @@ -193,6 +193,8 @@ class FileInterner { const string& getReason() const {return m_reason;} static void getMissingExternal(FIMissingStore *st, string& missing); static void getMissingDescription(FIMissingStore *st, string& desc); + // Parse "missing" file contents into memory struct + static void getMissingFromDescription(FIMissingStore *st, const string& desc); bool ok() {return m_ok;} private: diff --git a/src/qtgui/listdialog.h b/src/qtgui/listdialog.h new file mode 100644 index 00000000..d3ff3d69 --- /dev/null +++ b/src/qtgui/listdialog.h @@ -0,0 +1,32 @@ +/* + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#ifndef LISTDIALOG_H +#define LISTDIALOG_H +#include "ui_listdialog.h" + +class ListDialog : public QDialog, public Ui::ListDialog { + Q_OBJECT + public: + ListDialog(QWidget * parent = 0) + : QDialog(parent) + { + setupUi(this); + } +}; + + +#endif // LISTDIALOG_H diff --git a/src/qtgui/listdialog.ui b/src/qtgui/listdialog.ui new file mode 100644 index 00000000..c9839b78 --- /dev/null +++ b/src/qtgui/listdialog.ui @@ -0,0 +1,79 @@ + + + ListDialog + + + + 0 + 0 + 400 + 300 + + + + Dialog + + + + + + GroupBox + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Ok + + + true + + + + + + + + + buttonBox + accepted() + ListDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + ListDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qtgui/rclmain.ui b/src/qtgui/rclmain.ui index e2f19c26..f3c8255d 100644 --- a/src/qtgui/rclmain.ui +++ b/src/qtgui/rclmain.ui @@ -138,7 +138,9 @@ + + @@ -169,6 +171,7 @@ + @@ -221,6 +224,14 @@ showMissingHelpers_Action + + + &Show indexed types + + + showActiveTypes_Action + + &About Recoll diff --git a/src/qtgui/rclmain_w.cpp b/src/qtgui/rclmain_w.cpp index 6e4bc88b..f22a4eb2 100644 --- a/src/qtgui/rclmain_w.cpp +++ b/src/qtgui/rclmain_w.cpp @@ -68,6 +68,7 @@ using std::pair; #include "docseqhist.h" #include "confguiindex.h" #include "restable.h" +#include "listdialog.h" using namespace confgui; @@ -225,6 +226,8 @@ void RclMain::init() this, SLOT(showAboutDialog())); connect(showMissingHelpers_Action, SIGNAL(activated()), this, SLOT(showMissingHelpers())); + connect(showActiveTypes_Action, SIGNAL(activated()), + this, SLOT(showActiveTypes())); connect(userManualAction, SIGNAL(activated()), this, SLOT(startManual())); connect(toolsDoc_HistoryAction, SIGNAL(activated()), @@ -749,6 +752,86 @@ void RclMain::showMissingHelpers() QMessageBox::information(this, tr("Missing helper programs"), msg); } +void RclMain::showActiveTypes() +{ + if (rcldb == 0) { + QMessageBox::warning(0, tr("Error"), + tr("Index not open"), + QMessageBox::Ok, + QMessageBox::NoButton); + return; + } + + // Get list of all mime types in index. For this, we use a + // wildcard field search on mtype + Rcl::TermMatchResult matches; + string prefix; + if (!rcldb->termMatch(Rcl::Db::ET_WILD, "", "*", matches, -1, "mtype", + &prefix)) { + QMessageBox::warning(0, tr("Error"), + tr("Index query error"), + QMessageBox::Ok, + QMessageBox::NoButton); + return; + } + + // Build the set of mtypes, stripping the prefix + set mtypesfromdb; + for (list::const_iterator it = matches.entries.begin(); + it != matches.entries.end(); it++) { + mtypesfromdb.insert(it->term.substr(prefix.size())); + } + + // All types listed in mimeconf: + list mtypesfromconfig = theconfig->getAllMimeTypes(); + + // Intersect file system types with config types (those not in the + // config can be indexed by name, not by content) + set mtypesfromdbconf; + for (list::const_iterator it = mtypesfromconfig.begin(); + it != mtypesfromconfig.end(); it++) { + if (mtypesfromdb.find(*it) != mtypesfromdb.end()) + mtypesfromdbconf.insert(*it); + } + + // Substract the types for missing helpers (the docs are indexed by name only): + string miss = theconfig->getMissingHelperDesc(); + if (!miss.empty()) { + FIMissingStore st; + FileInterner::getMissingFromDescription(&st, miss); + map >::const_iterator it; + for (it = st.m_typesForMissing.begin(); + it != st.m_typesForMissing.end(); it++) { + set::const_iterator it1; + for (it1 = it->second.begin(); + it1 != it->second.end(); it1++) { + set::iterator it2 = mtypesfromdbconf.find(*it1); + if (it2 != mtypesfromdbconf.end()) + mtypesfromdbconf.erase(it2); + } + } + } + ListDialog dialog; + dialog.setWindowTitle(tr("Indexed Mime Types")); + + // Turn the result into a string and display + dialog.groupBox->setTitle(tr("Content has been indexed for these mime types:")); + + // We replace the list with an editor so that the user can copy/paste + delete dialog.listWidget; + QTextEdit *editor = new QTextEdit(dialog.groupBox); + editor->setReadOnly(TRUE); + dialog.horizontalLayout->addWidget(editor); + + for (set::const_iterator it = mtypesfromdbconf.begin(); + it != mtypesfromdbconf.end(); it++) { + editor->append(QString::fromAscii(it->c_str())); + } + editor->moveCursor(QTextCursor::Start); + editor->ensureCursorVisible(); + dialog.exec(); +} + // If a preview (toplevel) window gets closed by the user, we need to // clean up because there is no way to reopen it. And check the case // where the current one is closed diff --git a/src/qtgui/rclmain_w.h b/src/qtgui/rclmain_w.h index 2bda5644..2c1a6d0c 100644 --- a/src/qtgui/rclmain_w.h +++ b/src/qtgui/rclmain_w.h @@ -69,6 +69,7 @@ public slots: virtual void showSpellDialog(); virtual void showAboutDialog(); virtual void showMissingHelpers(); + virtual void showActiveTypes(); virtual void startManual(); virtual void startManual(const string&); virtual void showDocHistory(); diff --git a/src/qtgui/recoll.pro.in b/src/qtgui/recoll.pro.in index f2881732..69fe9221 100644 --- a/src/qtgui/recoll.pro.in +++ b/src/qtgui/recoll.pro.in @@ -7,6 +7,7 @@ HEADERS += \ advsearch_w.h \ confgui/confgui.h \ confgui/confguiindex.h \ + listdialog.h \ preview_w.h \ rclhelp.h \ rclmain_w.h \ @@ -41,6 +42,7 @@ SOURCES += \ FORMS = \ advsearch.ui \ + listdialog.ui \ rclmain.ui \ restable.ui \ spell.ui \ diff --git a/src/rcldb/searchdata.cpp b/src/rcldb/searchdata.cpp index 774a2854..a3127907 100644 --- a/src/rcldb/searchdata.cpp +++ b/src/rcldb/searchdata.cpp @@ -139,6 +139,11 @@ date_range_filter(int y1, int m1, int d1, int y2, int m2, int d2) } // Expand categories and mime type wild card exps +// Actually, using getAllMimeTypes() here is a bit problematic because +// there maybe other types in the index, not indexed by content, but +// which could be searched by file name. It would probably be +// preferable to do a termMatch() on field "mtype", which would +// retrieve all values from the index. bool SearchData::expandFileTypes(RclConfig *cfg, vector& tps) { if (!cfg) {