|
a/src/qtgui/spell_w.cpp |
|
b/src/qtgui/spell_w.cpp |
|
... |
|
... |
14 |
* Free Software Foundation, Inc.,
|
14 |
* Free Software Foundation, Inc.,
|
15 |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
15 |
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16 |
*/
|
16 |
*/
|
17 |
#include "autoconfig.h"
|
17 |
#include "autoconfig.h"
|
18 |
|
18 |
|
|
|
19 |
#include <stdio.h>
|
|
|
20 |
#include <unistd.h>
|
|
|
21 |
|
19 |
#include <algorithm>
|
22 |
#include <algorithm>
|
20 |
|
|
|
21 |
#include <unistd.h>
|
|
|
22 |
|
|
|
23 |
#include <list>
|
23 |
#include <list>
|
|
|
24 |
#include <map>
|
24 |
#include <stdio.h>
|
25 |
#include <string>
|
|
|
26 |
using std::list;
|
|
|
27 |
using std::multimap;
|
|
|
28 |
using std::string;
|
25 |
|
29 |
|
26 |
#include <qmessagebox.h>
|
30 |
#include <qmessagebox.h>
|
27 |
#include <qpushbutton.h>
|
31 |
#include <qpushbutton.h>
|
28 |
#include <qlabel.h>
|
32 |
#include <qlabel.h>
|
29 |
#include <qlineedit.h>
|
33 |
#include <qlineedit.h>
|
|
... |
|
... |
38 |
#include "debuglog.h"
|
42 |
#include "debuglog.h"
|
39 |
#include "recoll.h"
|
43 |
#include "recoll.h"
|
40 |
#include "spell_w.h"
|
44 |
#include "spell_w.h"
|
41 |
#include "guiutils.h"
|
45 |
#include "guiutils.h"
|
42 |
#include "rcldb.h"
|
46 |
#include "rcldb.h"
|
|
|
47 |
#include "searchdata.h"
|
|
|
48 |
#include "rclquery.h"
|
43 |
#include "rclhelp.h"
|
49 |
#include "rclhelp.h"
|
|
|
50 |
#include "wasatorcl.h"
|
|
|
51 |
#include "execmd.h"
|
44 |
|
52 |
|
45 |
#ifdef RCL_USE_ASPELL
|
53 |
#ifdef RCL_USE_ASPELL
|
46 |
#include "rclaspell.h"
|
54 |
#include "rclaspell.h"
|
47 |
#endif
|
55 |
#endif
|
48 |
|
56 |
|
49 |
void SpellW::init()
|
57 |
void SpellW::init()
|
50 |
{
|
58 |
{
|
51 |
// Don't change the order, or fix the rest of the code...
|
59 |
m_c2t.clear();
|
52 |
/*0*/expTypeCMB->addItem(tr("Wildcards"));
|
60 |
expTypeCMB->addItem(tr("Wildcards"));
|
|
|
61 |
m_c2t.push_back(TYPECMB_WILD);
|
53 |
/*1*/expTypeCMB->addItem(tr("Regexp"));
|
62 |
expTypeCMB->addItem(tr("Regexp"));
|
|
|
63 |
m_c2t.push_back(TYPECMB_REG);
|
54 |
/*2*/expTypeCMB->addItem(tr("Stem expansion"));
|
64 |
expTypeCMB->addItem(tr("Stem expansion"));
|
|
|
65 |
m_c2t.push_back(TYPECMB_STEM);
|
55 |
#ifdef RCL_USE_ASPELL
|
66 |
#ifdef RCL_USE_ASPELL
|
56 |
bool noaspell = false;
|
67 |
bool noaspell = false;
|
57 |
theconfig->getConfParam("noaspell", &noaspell);
|
68 |
theconfig->getConfParam("noaspell", &noaspell);
|
58 |
if (!noaspell)
|
69 |
if (!noaspell) {
|
59 |
/*3*/expTypeCMB->addItem(tr("Spelling/Phonetic"));
|
70 |
expTypeCMB->addItem(tr("Spelling/Phonetic"));
|
|
|
71 |
m_c2t.push_back(TYPECMB_ASPELL);
|
|
|
72 |
}
|
60 |
#endif
|
73 |
#endif
|
|
|
74 |
expTypeCMB->addItem(tr("Show index statistics"));
|
|
|
75 |
m_c2t.push_back(TYPECMB_STATS);
|
61 |
|
76 |
|
62 |
int typ = prefs.termMatchType;
|
77 |
int typ = prefs.termMatchType;
|
63 |
if (typ < 0 || typ > expTypeCMB->count())
|
78 |
vector<comboboxchoice>::const_iterator it =
|
64 |
typ = 0;
|
79 |
std::find(m_c2t.begin(), m_c2t.end(), typ);
|
|
|
80 |
if (it == m_c2t.end())
|
|
|
81 |
it = m_c2t.begin();
|
|
|
82 |
int cmbidx = it - m_c2t.begin();
|
|
|
83 |
|
65 |
expTypeCMB->setCurrentIndex(typ);
|
84 |
expTypeCMB->setCurrentIndex(cmbidx);
|
66 |
|
85 |
|
67 |
// Stemming language combobox
|
86 |
// Stemming language combobox
|
68 |
stemLangCMB->clear();
|
87 |
stemLangCMB->clear();
|
69 |
vector<string> langs;
|
88 |
vector<string> langs;
|
70 |
if (!getStemLangs(langs)) {
|
89 |
if (!getStemLangs(langs)) {
|
|
... |
|
... |
74 |
for (vector<string>::const_iterator it = langs.begin();
|
93 |
for (vector<string>::const_iterator it = langs.begin();
|
75 |
it != langs.end(); it++) {
|
94 |
it != langs.end(); it++) {
|
76 |
stemLangCMB->
|
95 |
stemLangCMB->
|
77 |
addItem(QString::fromAscii(it->c_str(), it->length()));
|
96 |
addItem(QString::fromAscii(it->c_str(), it->length()));
|
78 |
}
|
97 |
}
|
79 |
stemLangCMB->setEnabled(expTypeCMB->currentIndex()==2);
|
|
|
80 |
|
98 |
|
81 |
(void)new HelpClient(this);
|
99 |
(void)new HelpClient(this);
|
82 |
HelpClient::installMap((const char *)this->objectName().toUtf8(),
|
100 |
HelpClient::installMap((const char *)this->objectName().toUtf8(),
|
83 |
"RCL.SEARCH.TERMEXPLORER");
|
101 |
"RCL.SEARCH.TERMEXPLORER");
|
84 |
|
102 |
|
|
... |
|
... |
88 |
connect(baseWordLE, SIGNAL(returnPressed()), this, SLOT(doExpand()));
|
106 |
connect(baseWordLE, SIGNAL(returnPressed()), this, SLOT(doExpand()));
|
89 |
connect(expandPB, SIGNAL(clicked()), this, SLOT(doExpand()));
|
107 |
connect(expandPB, SIGNAL(clicked()), this, SLOT(doExpand()));
|
90 |
connect(dismissPB, SIGNAL(clicked()), this, SLOT(close()));
|
108 |
connect(dismissPB, SIGNAL(clicked()), this, SLOT(close()));
|
91 |
connect(expTypeCMB, SIGNAL(activated(int)), this, SLOT(modeSet(int)));
|
109 |
connect(expTypeCMB, SIGNAL(activated(int)), this, SLOT(modeSet(int)));
|
92 |
|
110 |
|
93 |
QStringList labels(tr("Term"));
|
|
|
94 |
labels.push_back(tr("Doc. / Tot."));
|
|
|
95 |
resTW->setHorizontalHeaderLabels(labels);
|
|
|
96 |
resTW->setShowGrid(0);
|
111 |
resTW->setShowGrid(0);
|
97 |
resTW->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
|
112 |
resTW->horizontalHeader()->setResizeMode(0, QHeaderView::Stretch);
|
98 |
resTW->verticalHeader()->setDefaultSectionSize(20);
|
113 |
resTW->verticalHeader()->setDefaultSectionSize(20);
|
99 |
connect(resTW,
|
114 |
connect(resTW,
|
100 |
SIGNAL(cellDoubleClicked(int, int)),
|
115 |
SIGNAL(cellDoubleClicked(int, int)),
|
101 |
this, SLOT(textDoubleClicked(int, int)));
|
116 |
this, SLOT(textDoubleClicked(int, int)));
|
102 |
|
117 |
|
103 |
resTW->setColumnWidth(0, 200);
|
118 |
resTW->setColumnWidth(0, 200);
|
104 |
resTW->setColumnWidth(1, 150);
|
119 |
resTW->setColumnWidth(1, 150);
|
105 |
resTW->installEventFilter(this);
|
120 |
resTW->installEventFilter(this);
|
|
|
121 |
|
|
|
122 |
modeSet(cmbidx);
|
106 |
}
|
123 |
}
|
107 |
|
124 |
|
108 |
static const int maxexpand = 10000;
|
125 |
static const int maxexpand = 10000;
|
109 |
|
126 |
|
110 |
/* Expand term according to current mode */
|
127 |
/* Expand term according to current mode */
|
111 |
void SpellW::doExpand()
|
128 |
void SpellW::doExpand()
|
112 |
{
|
129 |
{
|
|
|
130 |
int idx = expTypeCMB->currentIndex();
|
|
|
131 |
if (idx < 0 || idx >= int(m_c2t.size()))
|
|
|
132 |
idx = 0;
|
|
|
133 |
comboboxchoice mode = m_c2t[idx];
|
|
|
134 |
|
113 |
// Can't clear qt4 table widget: resets column headers too
|
135 |
// Can't clear qt4 table widget: resets column headers too
|
114 |
resTW->setRowCount(0);
|
136 |
resTW->setRowCount(0);
|
115 |
if (baseWordLE->text().isEmpty())
|
137 |
if (baseWordLE->text().isEmpty() && mode != TYPECMB_STATS)
|
116 |
return;
|
138 |
return;
|
117 |
|
139 |
|
118 |
string reason;
|
140 |
string reason;
|
119 |
if (!maybeOpenDb(reason)) {
|
141 |
if (!maybeOpenDb(reason)) {
|
120 |
QMessageBox::critical(0, "Recoll", QString(reason.c_str()));
|
142 |
QMessageBox::critical(0, "Recoll", QString(reason.c_str()));
|
121 |
LOGDEB(("SpellW::doExpand: db error: %s\n", reason.c_str()));
|
143 |
LOGDEB(("SpellW::doExpand: db error: %s\n", reason.c_str()));
|
122 |
return;
|
144 |
return;
|
123 |
}
|
145 |
}
|
124 |
|
146 |
|
|
|
147 |
Rcl::Db::MatchType mt;
|
|
|
148 |
switch(mode) {
|
|
|
149 |
case TYPECMB_WILD: mt = Rcl::Db::ET_WILD; break;
|
|
|
150 |
case TYPECMB_REG: mt = Rcl::Db::ET_REGEXP; break;
|
|
|
151 |
case TYPECMB_STEM: mt = Rcl::Db::ET_STEM; break;
|
|
|
152 |
default: mt = Rcl::Db::ET_WILD;
|
|
|
153 |
}
|
|
|
154 |
|
|
|
155 |
Rcl::TermMatchResult res;
|
125 |
string expr = string((const char *)baseWordLE->text().toUtf8());
|
156 |
string expr = string((const char *)baseWordLE->text().toUtf8());
|
126 |
list<string> suggs;
|
|
|
127 |
|
157 |
|
128 |
prefs.termMatchType = expTypeCMB->currentIndex();
|
158 |
switch (mode) {
|
129 |
|
159 |
case TYPECMB_WILD:
|
130 |
Rcl::Db::MatchType mt = Rcl::Db::ET_WILD;
|
160 |
default:
|
131 |
switch(expTypeCMB->currentIndex()) {
|
161 |
case TYPECMB_REG:
|
132 |
case 0: mt = Rcl::Db::ET_WILD; break;
|
162 |
case TYPECMB_STEM:
|
133 |
case 1:mt = Rcl::Db::ET_REGEXP; break;
|
|
|
134 |
case 2:mt = Rcl::Db::ET_STEM; break;
|
|
|
135 |
}
|
163 |
{
|
136 |
|
|
|
137 |
Rcl::TermMatchResult res;
|
|
|
138 |
switch (expTypeCMB->currentIndex()) {
|
|
|
139 |
case 0:
|
|
|
140 |
case 1:
|
|
|
141 |
case 2:
|
|
|
142 |
{
|
|
|
143 |
string l_stemlang = (const char*)stemLangCMB->currentText().toAscii();
|
164 |
string l_stemlang = qs2utf8s(stemLangCMB->currentText());
|
144 |
|
165 |
|
145 |
if (!rcldb->termMatch(mt, l_stemlang, expr, res, maxexpand)) {
|
166 |
if (!rcldb->termMatch(mt, l_stemlang, expr, res, maxexpand)) {
|
146 |
LOGERR(("SpellW::doExpand:rcldb::termMatch failed\n"));
|
167 |
LOGERR(("SpellW::doExpand:rcldb::termMatch failed\n"));
|
147 |
return;
|
168 |
return;
|
148 |
}
|
169 |
}
|
|
... |
|
... |
150 |
"%3 results")
|
171 |
"%3 results")
|
151 |
.arg(res.dbdoccount).arg(res.dbavgdoclen, 0, 'f', 1)
|
172 |
.arg(res.dbdoccount).arg(res.dbavgdoclen, 0, 'f', 1)
|
152 |
.arg(res.entries.size()));
|
173 |
.arg(res.entries.size()));
|
153 |
}
|
174 |
}
|
154 |
|
175 |
|
155 |
break;
|
176 |
break;
|
156 |
|
177 |
|
157 |
#ifdef RCL_USE_ASPELL
|
178 |
#ifdef RCL_USE_ASPELL
|
158 |
case 3: {
|
179 |
case TYPECMB_ASPELL:
|
|
|
180 |
{
|
159 |
LOGDEB(("SpellW::doExpand: aspelling\n"));
|
181 |
LOGDEB(("SpellW::doExpand: aspelling\n"));
|
160 |
if (!aspell) {
|
182 |
if (!aspell) {
|
161 |
QMessageBox::warning(0, "Recoll",
|
183 |
QMessageBox::warning(0, "Recoll",
|
162 |
tr("Aspell init failed. "
|
184 |
tr("Aspell init failed. "
|
163 |
"Aspell not installed?"));
|
185 |
"Aspell not installed?"));
|
|
... |
|
... |
180 |
res.entries.push_back(Rcl::TermMatchEntry(rclsugg));
|
202 |
res.entries.push_back(Rcl::TermMatchEntry(rclsugg));
|
181 |
}
|
203 |
}
|
182 |
#endif // TESTING_XAPIAN_SPELL
|
204 |
#endif // TESTING_XAPIAN_SPELL
|
183 |
statsLBL->setText(tr("%1 results").arg(res.entries.size()));
|
205 |
statsLBL->setText(tr("%1 results").arg(res.entries.size()));
|
184 |
}
|
206 |
}
|
185 |
#endif
|
207 |
break;
|
|
|
208 |
#endif // RCL_USE_ASPELL
|
|
|
209 |
|
|
|
210 |
case TYPECMB_STATS:
|
|
|
211 |
{
|
|
|
212 |
showStats();
|
|
|
213 |
return;
|
|
|
214 |
}
|
|
|
215 |
break;
|
186 |
}
|
216 |
}
|
187 |
|
217 |
|
188 |
|
218 |
|
189 |
if (res.entries.empty()) {
|
219 |
if (res.entries.empty()) {
|
190 |
resTW->setItem(0, 0, new QTableWidgetItem(tr("No expansion found")));
|
220 |
resTW->setItem(0, 0, new QTableWidgetItem(tr("No expansion found")));
|
|
... |
|
... |
222 |
new QTableWidgetItem(QString::fromAscii(num)));
|
252 |
new QTableWidgetItem(QString::fromAscii(num)));
|
223 |
}
|
253 |
}
|
224 |
}
|
254 |
}
|
225 |
}
|
255 |
}
|
226 |
|
256 |
|
|
|
257 |
void SpellW::showStats()
|
|
|
258 |
{
|
|
|
259 |
statsLBL->setText("");
|
|
|
260 |
int row = 0;
|
|
|
261 |
|
|
|
262 |
Rcl::TermMatchResult res;
|
|
|
263 |
if (!rcldb->termMatch(Rcl::Db::ET_WILD, "", "azbogusaz", res, 1)) {
|
|
|
264 |
LOGERR(("SpellW::doExpand:rcldb::termMatch failed\n"));
|
|
|
265 |
return;
|
|
|
266 |
}
|
|
|
267 |
|
|
|
268 |
resTW->setRowCount(row+1);
|
|
|
269 |
resTW->setItem(row, 0,
|
|
|
270 |
new QTableWidgetItem(tr("Number of documents")));
|
|
|
271 |
resTW->setItem(row++, 1, new QTableWidgetItem(
|
|
|
272 |
QString::number(res.dbdoccount)));
|
|
|
273 |
|
|
|
274 |
resTW->setRowCount(row+1);
|
|
|
275 |
resTW->setItem(row, 0,
|
|
|
276 |
new QTableWidgetItem(tr("Average terms per document")));
|
|
|
277 |
resTW->setItem(row++, 1, new QTableWidgetItem(
|
|
|
278 |
QString::number(res.dbavgdoclen)));
|
|
|
279 |
|
|
|
280 |
resTW->setRowCount(row+1);
|
|
|
281 |
resTW->setItem(row, 0,
|
|
|
282 |
new QTableWidgetItem(tr("Smallest document length")));
|
|
|
283 |
resTW->setItem(row++, 1, new QTableWidgetItem(
|
|
|
284 |
QString::number(res.mindoclen)));
|
|
|
285 |
|
|
|
286 |
resTW->setRowCount(row+1);
|
|
|
287 |
resTW->setItem(row, 0,
|
|
|
288 |
new QTableWidgetItem(tr("Longest document length")));
|
|
|
289 |
resTW->setItem(row++, 1, new QTableWidgetItem(
|
|
|
290 |
QString::number(res.maxdoclen)));
|
|
|
291 |
|
|
|
292 |
if (!thestableconfig)
|
|
|
293 |
return;
|
|
|
294 |
|
|
|
295 |
ExecCmd cmd;
|
|
|
296 |
vector<string> args;
|
|
|
297 |
int status;
|
|
|
298 |
args.push_back("-sk");
|
|
|
299 |
args.push_back(thestableconfig->getDbDir());
|
|
|
300 |
string output;
|
|
|
301 |
status = cmd.doexec("du", args, 0, &output);
|
|
|
302 |
int dbkbytes = 0;
|
|
|
303 |
if (!status) {
|
|
|
304 |
dbkbytes = atoi(output.c_str());
|
|
|
305 |
}
|
|
|
306 |
resTW->setRowCount(row+1);
|
|
|
307 |
resTW->setItem(row, 0,
|
|
|
308 |
new QTableWidgetItem(tr("Database directory size")));
|
|
|
309 |
resTW->setItem(row++, 1, new QTableWidgetItem(
|
|
|
310 |
QString::fromUtf8(
|
|
|
311 |
displayableBytes(dbkbytes*1024).c_str())));
|
|
|
312 |
|
|
|
313 |
vector<string> allmimetypes = thestableconfig->getAllMimeTypes();
|
|
|
314 |
multimap<int, string> mtbycnt;
|
|
|
315 |
for (vector<string>::const_iterator it = allmimetypes.begin();
|
|
|
316 |
it != allmimetypes.end(); it++) {
|
|
|
317 |
string reason;
|
|
|
318 |
string q = string("mime:") + *it;
|
|
|
319 |
Rcl::SearchData *sd =
|
|
|
320 |
wasaStringToRcl(thestableconfig, "", q, reason);
|
|
|
321 |
RefCntr<Rcl::SearchData> rq(sd);
|
|
|
322 |
Rcl::Query query(rcldb);
|
|
|
323 |
if (!query.setQuery(rq)) {
|
|
|
324 |
LOGERR(("Query setup failed: %s",query.getReason().c_str()));
|
|
|
325 |
return;
|
|
|
326 |
}
|
|
|
327 |
int cnt = query.getResCnt();
|
|
|
328 |
mtbycnt.insert(pair<int,string>(cnt,*it));
|
|
|
329 |
}
|
|
|
330 |
resTW->setRowCount(row+1);
|
|
|
331 |
resTW->setItem(row, 0, new QTableWidgetItem(tr("MIME types:")));
|
|
|
332 |
resTW->setItem(row++, 1, new QTableWidgetItem(""));
|
|
|
333 |
|
|
|
334 |
for (multimap<int, string>::const_reverse_iterator it = mtbycnt.rbegin();
|
|
|
335 |
it != mtbycnt.rend(); it++) {
|
|
|
336 |
resTW->setRowCount(row+1);
|
|
|
337 |
resTW->setItem(row, 0, new QTableWidgetItem(
|
|
|
338 |
QString::fromUtf8(it->second.c_str())));
|
|
|
339 |
resTW->setItem(row++, 1, new QTableWidgetItem(
|
|
|
340 |
QString::number(it->first)));
|
|
|
341 |
}
|
|
|
342 |
}
|
|
|
343 |
|
227 |
void SpellW::wordChanged(const QString &text)
|
344 |
void SpellW::wordChanged(const QString &text)
|
228 |
{
|
345 |
{
|
229 |
if (text.isEmpty()) {
|
346 |
if (text.isEmpty()) {
|
230 |
expandPB->setEnabled(false);
|
347 |
expandPB->setEnabled(false);
|
231 |
resTW->setRowCount(0);
|
348 |
resTW->setRowCount(0);
|
|
... |
|
... |
240 |
QTableWidgetItem *item = resTW->item(row, 0);
|
357 |
QTableWidgetItem *item = resTW->item(row, 0);
|
241 |
if (item)
|
358 |
if (item)
|
242 |
emit(wordSelect(item->text()));
|
359 |
emit(wordSelect(item->text()));
|
243 |
}
|
360 |
}
|
244 |
|
361 |
|
245 |
void SpellW::modeSet(int mode)
|
362 |
void SpellW::modeSet(int idx)
|
246 |
{
|
363 |
{
|
247 |
if (mode == 2)
|
364 |
if (idx < 0 || idx > int(m_c2t.size()))
|
|
|
365 |
return;
|
|
|
366 |
comboboxchoice mode = m_c2t[idx];
|
|
|
367 |
resTW->setRowCount(0);
|
|
|
368 |
|
|
|
369 |
if (mode == TYPECMB_STEM)
|
248 |
stemLangCMB->setEnabled(true);
|
370 |
stemLangCMB->setEnabled(true);
|
249 |
else
|
371 |
else
|
250 |
stemLangCMB->setEnabled(false);
|
372 |
stemLangCMB->setEnabled(false);
|
|
|
373 |
if (mode == TYPECMB_STATS)
|
|
|
374 |
baseWordLE->setEnabled(false);
|
|
|
375 |
else
|
|
|
376 |
baseWordLE->setEnabled(true);
|
|
|
377 |
|
|
|
378 |
|
|
|
379 |
if (mode == TYPECMB_STATS) {
|
|
|
380 |
QStringList labels(tr("Item"));
|
|
|
381 |
labels.push_back(tr("Value"));
|
|
|
382 |
resTW->setHorizontalHeaderLabels(labels);
|
|
|
383 |
doExpand();
|
|
|
384 |
} else {
|
|
|
385 |
QStringList labels(tr("Term"));
|
|
|
386 |
labels.push_back(tr("Doc. / Tot."));
|
|
|
387 |
resTW->setHorizontalHeaderLabels(labels);
|
|
|
388 |
prefs.termMatchType = mode;
|
|
|
389 |
}
|
251 |
}
|
390 |
}
|
252 |
|
391 |
|
253 |
void SpellW::copy()
|
392 |
void SpellW::copy()
|
254 |
{
|
393 |
{
|
255 |
QItemSelectionModel * selection = resTW->selectionModel();
|
394 |
QItemSelectionModel * selection = resTW->selectionModel();
|