diff --git a/src/python/samples/recollgui/qrecoll.py b/src/python/samples/recollgui/qrecoll.py
new file mode 100755
index 00000000..d7f7e4ac
--- /dev/null
+++ b/src/python/samples/recollgui/qrecoll.py
@@ -0,0 +1,208 @@
+#!/usr/bin/env python
+
+import sys
+import datetime
+try:
+ from recoll import recoll
+ from recoll import rclextract
+ hasextract = True
+except:
+ import recoll
+ hasextract = False
+
+import queryarea
+from getopt import getopt
+
+from PyQt4 import QtCore, QtGui
+
+class RecollQuery(QtCore.QAbstractTableModel):
+ def __init__(self):
+ QtCore.QAbstractTableModel.__init__(self)
+ self.totres = -1
+ self.query = None
+ self.docs = []
+ self.pagelen = 10
+ self.attrs = ("filename", "title", "mtime", "url", "ipath")
+ def rowCount(self, parent):
+ ret = len(self.docs)
+ #print "RecollQuery.rowCount(): ", ret
+ return ret
+ def columnCount(self, parent):
+ #print "RecollQuery.columnCount()"
+ if parent.isValid():
+ return 0
+ else:
+ return len(self.attrs)
+ def setquery(self, db, q):
+ """Parse and execute query on open db"""
+ print "RecollQuery.setquery():"
+ # Get query object
+ self.query = db.query()
+ # Parse/run input query string
+ self.totres = self.query.execute(q)
+ self.docs = []
+ self.fetchMore(None)
+ def getdoc(self, index):
+ if index.row() < len(self.docs):
+ return self.docs[index.row()]
+ else:
+ return None
+ def headerData(self, idx, orient, role):
+ if orient == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
+ return self.attrs[idx]
+ return None
+ def data(self, index, role):
+ #print "RecollQuery.data: row %d, role: " % (index.row(),), role
+ if not index.isValid():
+ return QtCore.QVariant()
+
+ if index.row() >= len(self.docs):
+ return QtCore.QVariant()
+
+ if role == QtCore.Qt.DisplayRole:
+ #print "RecollQuery.data: row %d, col %d role: " % \
+ # (index.row(), index.column()), role
+ attr = self.attrs[index.column()]
+ value = getattr(self.docs[index.row()], attr)
+ if attr == "mtime":
+ dte = datetime.datetime.fromtimestamp(int(value))
+ value = str(dte)
+ return value
+ else:
+ return QtCore.QVariant()
+ def canFetchMore(self, parent):
+ #print "RecollQuery.canFetchMore:"
+ if len(self.docs) < self.totres:
+ return True
+ else:
+ return False
+ def fetchMore(self, parent):
+ #print "RecollQuery.fetchMore:"
+ self.beginInsertRows(QtCore.QModelIndex(), len(self.docs), \
+ len(self.docs) + self.pagelen)
+ count = 0
+ while self.query.next >= 0 and self.query.next < self.totres \
+ and count < self.pagelen:
+ #print "Got: ", title.encode("utf-8")
+ self.docs.append(self.query.fetchone())
+ count += 1
+ self.endInsertRows()
+
+class HlMeths:
+ def __init__(self, groups):
+ self.groups = groups
+ def startMatch(self, idx):
+ ugroup = " ".join(self.groups[idx][1])
+ return ''
+ def endMatch(self):
+ return ''
+
+def extract(doc):
+ extractor = rclextract.Extractor(doc)
+ newdoc = extractor.textextract(doc.ipath)
+ return newdoc
+
+def extractofile(doc, outfilename=""):
+ extractor = rclextract.Extractor(doc)
+ outfilename = extractor.idoctofile(doc.ipath, doc.mimetype, \
+ ofilename=outfilename)
+ return outfilename
+
+class RclGui_Main(QtGui.QWidget):
+ def __init__(self, db, parent=None):
+ QtGui.QWidget.__init__(self, parent)
+ self.ui = queryarea.Ui_queryArea()
+ self.ui.setupUi(self)
+ self.db = db
+ self.qmodel = RecollQuery()
+ self.connect(self.ui.exitPB, QtCore.SIGNAL("clicked()"),
+ self.onexit)
+ def on_searchEntry_returnPressed(self):
+ self.startQuery()
+ def on_resTable_clicked(self, index):
+ doc = self.qmodel.getdoc(index)
+ query = self.qmodel.query;
+ groups = self.qmodel.query.getgroups()
+ meths = HlMeths(groups)
+ if doc is not None:
+ ipath = doc.get('ipath')
+ print "ipath[", ipath, "]"
+ if index.column() == 1:
+ newdoc = extract(doc)
+ print "newdoc.mimetype:", newdoc.mimetype
+ if newdoc.mimetype == 'text/html':
+ ishtml = True
+ else:
+ ishtml = False
+ text = query.highlight(newdoc.text,
+ methods=meths,
+ ishtml=ishtml,
+ eolbr=True)
+ print text
+
+ text = '' + text + ''
+ self.ui.resDetail.setText(text)
+ elif index.column() == 3 and ipath:
+ fn = QtGui.QFileDialog.getSaveFileName(self)
+ if fn:
+ docitems = doc.items()
+ fn = extractofile(doc, str(fn.toLocal8Bit()))
+ print "Saved as", fn
+ else:
+ print >> sys.stderr, "Canceled"
+ else:
+ abs = query.makedocabstract(doc, methods=meths)
+ self.ui.resDetail.setText(abs)
+
+ def startQuery(self):
+ self.qmodel.setquery(self.db, self.ui.searchEntry.text())
+ self.ui.resTable.setModel(self.qmodel)
+ def onexit(self):
+ sys.exit(0)
+
+def Usage():
+ print >> sys.stderr, '''Usage: qt.py [ [ ...]]'''
+ sys.exit(1)
+
+def main(args):
+
+ app = QtGui.QApplication(args)
+
+ confdir=""
+ extra_dbs = []
+ # Snippet params
+ maxchars = 300
+ contextwords = 6
+
+ # Process options: [-c confdir] [-i extra_db [-i extra_db] ...]
+ options, args = getopt(args[1:], "c:i:")
+ for opt,val in options:
+ if opt == "-c":
+ confdir = val
+ elif opt == "-i":
+ extra_dbs.append(val)
+ else:
+ print >> sys.stderr, "Bad opt: ", opt
+ Usage()
+
+ # The query should be in the remaining arg(s)
+ q = None
+ if len(args) > 0:
+ q = ""
+ for word in args:
+ q += word + " "
+
+ db = recoll.connect(confdir=confdir, extra_dbs=extra_dbs)
+ db.setAbstractParams(maxchars=maxchars, contextwords=contextwords)
+
+ topwindow = RclGui_Main(db)
+ topwindow.show()
+ if q is not None:
+ topwindow.ui.searchEntry.setText(q)
+ topwindow.startQuery()
+
+ sys.exit(app.exec_())
+
+
+if __name__=="__main__":
+ main(sys.argv)
diff --git a/src/python/samples/recollgui/queryarea.ui b/src/python/samples/recollgui/queryarea.ui
new file mode 100644
index 00000000..4e966ac8
--- /dev/null
+++ b/src/python/samples/recollgui/queryarea.ui
@@ -0,0 +1,64 @@
+
+
+ queryArea
+
+
+
+ 0
+ 0
+ 614
+ 759
+
+
+
+ Recoll query
+
+
+ -
+
+
-
+
+
+ Exit
+
+
+
+ -
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+
+ 0
+ 4
+
+
+
+ QAbstractItemView::NoEditTriggers
+
+
+ false
+
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+
+
+
+