|
a/src/qtgui/restable.cpp |
|
b/src/qtgui/restable.cpp |
|
... |
|
... |
30 |
#include <QStyledItemDelegate>
|
30 |
#include <QStyledItemDelegate>
|
31 |
#include <QTextDocument>
|
31 |
#include <QTextDocument>
|
32 |
#include <QPainter>
|
32 |
#include <QPainter>
|
33 |
#include <QSplitter>
|
33 |
#include <QSplitter>
|
34 |
#include <QClipboard>
|
34 |
#include <QClipboard>
|
|
|
35 |
#include <QFileDialog>
|
|
|
36 |
#include <QMessageBox>
|
35 |
|
37 |
|
36 |
#include "recoll.h"
|
38 |
#include "recoll.h"
|
37 |
#include "refcntr.h"
|
39 |
#include "refcntr.h"
|
38 |
#include "docseq.h"
|
40 |
#include "docseq.h"
|
39 |
#include "debuglog.h"
|
41 |
#include "debuglog.h"
|
|
... |
|
... |
141 |
|
143 |
|
142 |
//////////////////////////////////////////////////////////////////////////////
|
144 |
//////////////////////////////////////////////////////////////////////////////
|
143 |
//// Data model methods
|
145 |
//// Data model methods
|
144 |
////
|
146 |
////
|
145 |
|
147 |
|
146 |
// Routines used to extract named data from an Rcl::Doc. The basic one just uses the meta map. Others
|
148 |
// Routines used to extract named data from an Rcl::Doc. The basic one
|
147 |
// (ie: the date ones) need to do a little processing
|
149 |
// just uses the meta map. Others (ie: the date ones) need to do a
|
|
|
150 |
// little processing
|
148 |
static string gengetter(const string& fld, const Rcl::Doc& doc)
|
151 |
static string gengetter(const string& fld, const Rcl::Doc& doc)
|
149 |
{
|
152 |
{
|
150 |
map<string, string>::const_iterator it = doc.meta.find(fld);
|
153 |
map<string, string>::const_iterator it = doc.meta.find(fld);
|
151 |
if (it == doc.meta.end()) {
|
154 |
if (it == doc.meta.end()) {
|
152 |
return string();
|
155 |
return string();
|
|
... |
|
... |
358 |
string colname = m_fields[index.column()];
|
361 |
string colname = m_fields[index.column()];
|
359 |
|
362 |
|
360 |
list<string> lr;
|
363 |
list<string> lr;
|
361 |
g_hiliter.plaintorich(m_getters[index.column()](colname, doc), lr, m_hdata);
|
364 |
g_hiliter.plaintorich(m_getters[index.column()](colname, doc), lr, m_hdata);
|
362 |
return QString::fromUtf8(lr.front().c_str());
|
365 |
return QString::fromUtf8(lr.front().c_str());
|
|
|
366 |
}
|
|
|
367 |
|
|
|
368 |
void RecollModel::saveAsCSV(FILE *fp)
|
|
|
369 |
{
|
|
|
370 |
if (m_source.isNull())
|
|
|
371 |
return;
|
|
|
372 |
|
|
|
373 |
int cols = columnCount();
|
|
|
374 |
int rows = rowCount();
|
|
|
375 |
vector<string> tokens;
|
|
|
376 |
|
|
|
377 |
for (int col = 0; col < cols; col++) {
|
|
|
378 |
QString qs = headerData(col, Qt::Horizontal,Qt::DisplayRole).toString();
|
|
|
379 |
tokens.push_back((const char *)qs.toUtf8());
|
|
|
380 |
}
|
|
|
381 |
string csv;
|
|
|
382 |
stringsToCSV(tokens, csv);
|
|
|
383 |
fprintf(fp, "%s\n", csv.c_str());
|
|
|
384 |
tokens.clear();
|
|
|
385 |
|
|
|
386 |
for (int row = 0; row < rows; row++) {
|
|
|
387 |
Rcl::Doc doc;
|
|
|
388 |
if (!m_source->getDoc(row, doc)) {
|
|
|
389 |
continue;
|
|
|
390 |
}
|
|
|
391 |
for (int col = 0; col < cols; col++) {
|
|
|
392 |
tokens.push_back(m_getters[col](m_fields[col], doc));
|
|
|
393 |
}
|
|
|
394 |
stringsToCSV(tokens, csv);
|
|
|
395 |
fprintf(fp, "%s\n", csv.c_str());
|
|
|
396 |
tokens.clear();
|
|
|
397 |
}
|
363 |
}
|
398 |
}
|
364 |
|
399 |
|
365 |
// This gets called when the column headers are clicked
|
400 |
// This gets called when the column headers are clicked
|
366 |
void RecollModel::sort(int column, Qt::SortOrder order)
|
401 |
void RecollModel::sort(int column, Qt::SortOrder order)
|
367 |
{
|
402 |
{
|
|
... |
|
... |
592 |
{
|
627 |
{
|
593 |
LOGDEB(("ResTable::resetSource\n"));
|
628 |
LOGDEB(("ResTable::resetSource\n"));
|
594 |
setDocSource(RefCntr<DocSequence>());
|
629 |
setDocSource(RefCntr<DocSequence>());
|
595 |
}
|
630 |
}
|
596 |
|
631 |
|
|
|
632 |
void ResTable::saveAsCSV()
|
|
|
633 |
{
|
|
|
634 |
LOGDEB(("ResTable::saveAsCSV\n"));
|
|
|
635 |
if (!m_model)
|
|
|
636 |
return;
|
|
|
637 |
QString s =
|
|
|
638 |
QFileDialog::getSaveFileName(this, //parent
|
|
|
639 |
tr("Save table to CSV file"),
|
|
|
640 |
QString::fromLocal8Bit(path_home().c_str())
|
|
|
641 |
);
|
|
|
642 |
const char *tofile = s.toLocal8Bit();
|
|
|
643 |
FILE *fp = fopen(tofile, "w");
|
|
|
644 |
if (fp == 0) {
|
|
|
645 |
QMessageBox::warning(0, "Recoll",
|
|
|
646 |
tr("Can't open/create file: ") + s);
|
|
|
647 |
return;
|
|
|
648 |
}
|
|
|
649 |
m_model->saveAsCSV(fp);
|
|
|
650 |
fclose(fp);
|
|
|
651 |
}
|
|
|
652 |
|
597 |
// This is called when the sort order is changed from another widget
|
653 |
// This is called when the sort order is changed from another widget
|
598 |
void ResTable::onSortDataChanged(DocSeqSortSpec spec)
|
654 |
void ResTable::onSortDataChanged(DocSeqSortSpec spec)
|
599 |
{
|
655 |
{
|
600 |
LOGDEB(("ResTable::onSortDataChanged: [%s] desc %d\n",
|
656 |
LOGDEB(("ResTable::onSortDataChanged: [%s] desc %d\n",
|
601 |
spec.field.c_str(), int(spec.desc)));
|
657 |
spec.field.c_str(), int(spec.desc)));
|
|
... |
|
... |
804 |
QMenu *popup = new QMenu(this);
|
860 |
QMenu *popup = new QMenu(this);
|
805 |
|
861 |
|
806 |
popup->addAction(tr("&Reset sort"), this, SLOT(resetSort()));
|
862 |
popup->addAction(tr("&Reset sort"), this, SLOT(resetSort()));
|
807 |
popup->addSeparator();
|
863 |
popup->addSeparator();
|
808 |
|
864 |
|
|
|
865 |
popup->addAction(tr("&Save as CSV"), this, SLOT(saveAsCSV()));
|
|
|
866 |
popup->addSeparator();
|
|
|
867 |
|
809 |
popup->addAction(tr("&Delete column"), this, SLOT(deleteColumn()));
|
868 |
popup->addAction(tr("&Delete column"), this, SLOT(deleteColumn()));
|
810 |
popup->addSeparator();
|
869 |
popup->addSeparator();
|
811 |
|
870 |
|
812 |
QAction *act;
|
871 |
QAction *act;
|
813 |
for (map<string, string>::const_iterator it = allfields.begin();
|
872 |
for (map<string, string>::const_iterator it = allfields.begin();
|