|
a/src/qtgui/restable.cpp |
|
b/src/qtgui/restable.cpp |
|
... |
|
... |
3 |
#endif
|
3 |
#endif
|
4 |
|
4 |
|
5 |
#include "autoconfig.h"
|
5 |
#include "autoconfig.h"
|
6 |
|
6 |
|
7 |
#include <stdlib.h>
|
7 |
#include <stdlib.h>
|
|
|
8 |
#include <time.h>
|
8 |
|
9 |
|
9 |
#include <Qt>
|
10 |
#include <Qt>
|
|
|
11 |
#include <QShortcut>
|
10 |
#include <QAbstractTableModel>
|
12 |
#include <QAbstractTableModel>
|
|
|
13 |
#include <QSettings>
|
11 |
|
14 |
|
12 |
#include "refcntr.h"
|
15 |
#include "refcntr.h"
|
13 |
#include "docseq.h"
|
16 |
#include "docseq.h"
|
14 |
#include "debuglog.h"
|
17 |
#include "debuglog.h"
|
15 |
#include "restable.h"
|
18 |
#include "restable.h"
|
|
... |
|
... |
63 |
}
|
66 |
}
|
64 |
|
67 |
|
65 |
//////////////////////////////////////////////
|
68 |
//////////////////////////////////////////////
|
66 |
//// Data model methods
|
69 |
//// Data model methods
|
67 |
////
|
70 |
////
|
|
|
71 |
static string gengetter(const string& fld, const Rcl::Doc& doc)
|
|
|
72 |
{
|
|
|
73 |
map<string, string>::const_iterator it = doc.meta.find(fld);
|
|
|
74 |
if (it == doc.meta.end()) {
|
|
|
75 |
return string();
|
|
|
76 |
}
|
|
|
77 |
return it->second;
|
|
|
78 |
}
|
|
|
79 |
|
|
|
80 |
static string dategetter(const string&, const Rcl::Doc& doc)
|
|
|
81 |
{
|
|
|
82 |
char datebuf[100];
|
|
|
83 |
datebuf[0] = 0;
|
|
|
84 |
if (!doc.dmtime.empty() || !doc.fmtime.empty()) {
|
|
|
85 |
time_t mtime = doc.dmtime.empty() ?
|
|
|
86 |
atol(doc.fmtime.c_str()) : atol(doc.dmtime.c_str());
|
|
|
87 |
struct tm *tm = localtime(&mtime);
|
|
|
88 |
strftime(datebuf, 99, "%x", tm);
|
|
|
89 |
}
|
|
|
90 |
return datebuf;
|
|
|
91 |
}
|
|
|
92 |
|
|
|
93 |
static string datetimegetter(const string&, const Rcl::Doc& doc)
|
|
|
94 |
{
|
|
|
95 |
char datebuf[100];
|
|
|
96 |
datebuf[0] = 0;
|
|
|
97 |
if (!doc.dmtime.empty() || !doc.fmtime.empty()) {
|
|
|
98 |
time_t mtime = doc.dmtime.empty() ?
|
|
|
99 |
atol(doc.fmtime.c_str()) : atol(doc.dmtime.c_str());
|
|
|
100 |
struct tm *tm = localtime(&mtime);
|
|
|
101 |
#ifndef sun
|
|
|
102 |
strftime(datebuf, 99, "%Y-%m-%d %H:%M:%S %z", tm);
|
|
|
103 |
#else
|
|
|
104 |
strftime(datebuf, 99, "%c", tm);
|
|
|
105 |
#endif
|
|
|
106 |
}
|
|
|
107 |
return datebuf;
|
|
|
108 |
}
|
|
|
109 |
|
68 |
RecollModel::RecollModel(const QStringList fields, QObject *parent)
|
110 |
RecollModel::RecollModel(const QStringList fields, QObject *parent)
|
69 |
: QAbstractTableModel(parent)
|
111 |
: QAbstractTableModel(parent)
|
70 |
{
|
112 |
{
|
71 |
for (QStringList::const_iterator it = fields.begin();
|
113 |
for (QStringList::const_iterator it = fields.begin();
|
72 |
it != fields.end(); it++)
|
114 |
it != fields.end(); it++) {
|
73 |
m_fields.push_back((const char *)(it->toUtf8()));
|
115 |
m_fields.push_back((const char *)(it->toUtf8()));
|
|
|
116 |
if (!stringlowercmp("date", m_fields[m_fields.size()-1]))
|
|
|
117 |
m_getters.push_back(dategetter);
|
|
|
118 |
else if (!stringlowercmp("datetime", m_fields[m_fields.size()-1]))
|
|
|
119 |
m_getters.push_back(datetimegetter);
|
|
|
120 |
else
|
|
|
121 |
m_getters.push_back(gengetter);
|
|
|
122 |
}
|
74 |
}
|
123 |
}
|
75 |
|
124 |
|
76 |
int RecollModel::rowCount(const QModelIndex&) const
|
125 |
int RecollModel::rowCount(const QModelIndex&) const
|
77 |
{
|
126 |
{
|
78 |
LOGDEB(("RecollModel::rowCount\n"));
|
127 |
LOGDEB2(("RecollModel::rowCount\n"));
|
79 |
if (m_source.isNull())
|
128 |
if (m_source.isNull())
|
80 |
return 0;
|
129 |
return 0;
|
81 |
return m_source->getResCnt();
|
130 |
return m_source->getResCnt();
|
82 |
}
|
131 |
}
|
83 |
|
132 |
|
84 |
int RecollModel::columnCount(const QModelIndex&) const
|
133 |
int RecollModel::columnCount(const QModelIndex&) const
|
85 |
{
|
134 |
{
|
86 |
LOGDEB(("RecollModel::columnCount\n"));
|
135 |
LOGDEB2(("RecollModel::columnCount\n"));
|
87 |
return m_fields.size();
|
136 |
return m_fields.size();
|
88 |
}
|
137 |
}
|
89 |
|
138 |
|
90 |
void RecollModel::setDocSource(RefCntr<DocSequence> nsource)
|
139 |
void RecollModel::setDocSource(RefCntr<DocSequence> nsource)
|
91 |
{
|
140 |
{
|
|
... |
|
... |
104 |
if (m_source.isNull())
|
153 |
if (m_source.isNull())
|
105 |
return false;
|
154 |
return false;
|
106 |
return m_source->getDoc(index, doc);
|
155 |
return m_source->getDoc(index, doc);
|
107 |
}
|
156 |
}
|
108 |
|
157 |
|
109 |
QVariant RecollModel::headerData(int col, Qt::Orientation orientation,
|
158 |
QVariant RecollModel::headerData(int idx, Qt::Orientation orientation,
|
110 |
int role) const
|
159 |
int role) const
|
111 |
{
|
160 |
{
|
112 |
LOGDEB(("RecollModel::headerData: col %d\n", col));
|
161 |
LOGDEB2(("RecollModel::headerData: idx %d\n", idx));
|
|
|
162 |
if (orientation == Qt::Vertical && role == Qt::DisplayRole) {
|
|
|
163 |
return idx;
|
|
|
164 |
}
|
113 |
if (orientation != Qt::Horizontal || role != Qt::DisplayRole ||
|
165 |
if (orientation == Qt::Horizontal && role == Qt::DisplayRole &&
|
114 |
col >= int(m_fields.size())) {
|
166 |
idx < int(m_fields.size())) {
|
115 |
return QVariant();
|
|
|
116 |
}
|
|
|
117 |
return QString::fromUtf8(m_fields[col].c_str());
|
167 |
return QString::fromUtf8(m_fields[idx].c_str());
|
|
|
168 |
}
|
|
|
169 |
return QVariant();
|
118 |
}
|
170 |
}
|
119 |
|
171 |
|
120 |
QVariant RecollModel::data(const QModelIndex& index, int role) const
|
172 |
QVariant RecollModel::data(const QModelIndex& index, int role) const
|
121 |
{
|
173 |
{
|
122 |
LOGDEB(("RecollModel::data: row %d col %d\n", index.row(),
|
174 |
LOGDEB2(("RecollModel::data: row %d col %d\n", index.row(),
|
123 |
index.column()));
|
175 |
index.column()));
|
124 |
if (m_source.isNull() || role != Qt::DisplayRole || !index.isValid() ||
|
176 |
if (m_source.isNull() || role != Qt::DisplayRole || !index.isValid() ||
|
125 |
index.column() >= int(m_fields.size())) {
|
177 |
index.column() >= int(m_fields.size())) {
|
126 |
return QVariant();
|
178 |
return QVariant();
|
127 |
}
|
179 |
}
|
|
|
180 |
|
128 |
Rcl::Doc doc;
|
181 |
Rcl::Doc doc;
|
129 |
if (!m_source->getDoc(index.row(), doc)) {
|
182 |
if (!m_source->getDoc(index.row(), doc)) {
|
130 |
return QVariant();
|
183 |
return QVariant();
|
131 |
}
|
184 |
}
|
132 |
map<string, string>::const_iterator it =
|
|
|
133 |
doc.meta.find(m_fields[index.column()]);
|
|
|
134 |
if (it == doc.meta.end()) {
|
|
|
135 |
return QVariant();
|
|
|
136 |
}
|
|
|
137 |
return QString::fromUtf8(it->second.c_str());
|
|
|
138 |
}
|
|
|
139 |
|
185 |
|
|
|
186 |
// Have to handle the special cases here. Some fields are
|
|
|
187 |
// synthetic and their name is hard-coded. Only date and datetime
|
|
|
188 |
// for now.
|
|
|
189 |
string colname = m_fields[index.column()];
|
|
|
190 |
return QString::fromUtf8(m_getters[index.column()](colname, doc).c_str());
|
|
|
191 |
}
|
|
|
192 |
|
|
|
193 |
// This is called when the column headers are clicked
|
140 |
void RecollModel::sort(int column, Qt::SortOrder order)
|
194 |
void RecollModel::sort(int column, Qt::SortOrder order)
|
141 |
{
|
195 |
{
|
142 |
LOGDEB(("RecollModel::sort(%d, %d)\n", column, int(order)));
|
196 |
LOGDEB(("RecollModel::sort(%d, %d)\n", column, int(order)));
|
143 |
|
197 |
|
|
|
198 |
if (column >= 0 && column < int(m_fields.size())) {
|
|
|
199 |
DocSeqSortSpec spec;
|
|
|
200 |
spec.field = m_fields[column];
|
|
|
201 |
if (!stringlowercmp("date", spec.field) ||
|
|
|
202 |
!stringlowercmp("datetime", spec.field))
|
|
|
203 |
spec.field = "mtime";
|
|
|
204 |
spec.desc = order == Qt::AscendingOrder ? false : true;
|
|
|
205 |
m_source->setSortSpec(spec);
|
|
|
206 |
setDocSource(m_source);
|
|
|
207 |
emit sortDataChanged(spec);
|
|
|
208 |
}
|
144 |
}
|
209 |
}
|
145 |
|
210 |
|
146 |
|
211 |
|
147 |
///////////////////////////
|
212 |
///////////////////////////
|
148 |
// ResTable panel methods
|
213 |
// ResTable panel methods
|
149 |
void ResTable::init()
|
214 |
void ResTable::init()
|
150 |
{
|
215 |
{
|
151 |
if (!(m_model = new RecollModel(prefs.restableFields)))
|
216 |
if (!(m_model = new RecollModel(prefs.restableFields)))
|
152 |
return;
|
217 |
return;
|
153 |
tableView->setModel(m_model);
|
218 |
tableView->setModel(m_model);
|
154 |
m_pager = new ResTablePager(this);
|
219 |
tableView->setMouseTracking(true);
|
|
|
220 |
tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
|
221 |
tableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
155 |
|
222 |
|
156 |
QHeaderView *header = tableView->horizontalHeader();
|
223 |
QHeaderView *header = tableView->horizontalHeader();
|
157 |
if (header) {
|
224 |
if (header) {
|
158 |
if (int(prefs.restableColWidths.size()) == header->count()) {
|
225 |
if (int(prefs.restableColWidths.size()) == header->count()) {
|
159 |
for (int i = 0; i < header->count(); i++) {
|
226 |
for (int i = 0; i < header->count(); i++) {
|
|
... |
|
... |
162 |
}
|
229 |
}
|
163 |
header->setSortIndicatorShown(true);
|
230 |
header->setSortIndicatorShown(true);
|
164 |
header->setSortIndicator(-1, Qt::AscendingOrder);
|
231 |
header->setSortIndicator(-1, Qt::AscendingOrder);
|
165 |
connect(header, SIGNAL(sectionResized(int,int,int)),
|
232 |
connect(header, SIGNAL(sectionResized(int,int,int)),
|
166 |
this, SLOT(saveColWidths()));
|
233 |
this, SLOT(saveColWidths()));
|
167 |
connect(header, SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)),
|
|
|
168 |
this, SLOT(sortByColumn(int, Qt::SortOrder)));
|
|
|
169 |
}
|
234 |
}
|
170 |
}
|
|
|
171 |
|
235 |
|
|
|
236 |
header = tableView->verticalHeader();
|
|
|
237 |
if (header) {
|
|
|
238 |
header->setDefaultSectionSize(22);
|
|
|
239 |
}
|
|
|
240 |
|
|
|
241 |
QKeySequence seq("Esc");
|
|
|
242 |
QShortcut *sc = new QShortcut(seq, this);
|
|
|
243 |
connect(sc, SIGNAL (activated()),
|
|
|
244 |
tableView->selectionModel(), SLOT (clear()));
|
|
|
245 |
connect(tableView->selectionModel(), SIGNAL(currentChanged(const QModelIndex&, const QModelIndex &)),
|
|
|
246 |
this, SLOT(onTableView_currentChanged(const QModelIndex&)));
|
|
|
247 |
|
|
|
248 |
m_pager = new ResTablePager(this);
|
|
|
249 |
QSettings settings;
|
|
|
250 |
splitter->restoreState(settings.value("resTableSplitterSizes").toByteArray());
|
|
|
251 |
}
|
|
|
252 |
|
|
|
253 |
void ResTable::saveSizeState()
|
|
|
254 |
{
|
|
|
255 |
QSettings settings;
|
|
|
256 |
settings.setValue("resTableSplitterSizes", splitter->saveState());
|
|
|
257 |
}
|
|
|
258 |
|
172 |
void ResTable::on_tableView_clicked(const QModelIndex& index)
|
259 |
void ResTable::onTableView_currentChanged(const QModelIndex& index)
|
173 |
{
|
260 |
{
|
174 |
LOGDEB(("ResTable::on_tableView_clicked(%d, %d)\n",
|
261 |
LOGDEB(("ResTable::onTableView_currentChanged(%d, %d)\n",
|
175 |
index.row(), index.column()));
|
262 |
index.row(), index.column()));
|
176 |
|
263 |
|
177 |
if (!m_model || m_model->m_source.isNull())
|
264 |
if (!m_model || m_model->m_source.isNull())
|
178 |
return;
|
265 |
return;
|
179 |
HiliteData hdata;
|
266 |
HiliteData hdata;
|
|
... |
|
... |
184 |
m_detaildocnum = index.row();
|
271 |
m_detaildocnum = index.row();
|
185 |
m_pager->displayDoc(index.row(), doc, hdata);
|
272 |
m_pager->displayDoc(index.row(), doc, hdata);
|
186 |
}
|
273 |
}
|
187 |
}
|
274 |
}
|
188 |
|
275 |
|
|
|
276 |
void ResTable::on_tableView_entered(const QModelIndex& index)
|
|
|
277 |
{
|
|
|
278 |
LOGDEB(("ResTable::on_tableView_entered(%d, %d)\n",
|
|
|
279 |
index.row(), index.column()));
|
|
|
280 |
if (!tableView->selectionModel()->hasSelection())
|
|
|
281 |
onTableView_currentChanged(index);
|
|
|
282 |
}
|
|
|
283 |
|
189 |
void ResTable::setDocSource(RefCntr<DocSequence> nsource)
|
284 |
void ResTable::setDocSource(RefCntr<DocSequence> nsource)
|
190 |
{
|
285 |
{
|
191 |
LOGDEB(("ResTable::setDocSource\n"));
|
286 |
LOGDEB(("ResTable::setDocSource\n"));
|
192 |
if (m_model)
|
287 |
if (m_model)
|
193 |
m_model->setDocSource(nsource);
|
288 |
m_model->setDocSource(nsource);
|
|
... |
|
... |
213 |
for (int i = 0; i < header->count(); i++) {
|
308 |
for (int i = 0; i < header->count(); i++) {
|
214 |
prefs.restableColWidths.push_back(header->sectionSize(i));
|
309 |
prefs.restableColWidths.push_back(header->sectionSize(i));
|
215 |
}
|
310 |
}
|
216 |
}
|
311 |
}
|
217 |
|
312 |
|
218 |
void ResTable::sortByColumn(int column, Qt::SortOrder order)
|
313 |
// This is called when the sort order is changed from another widget
|
|
|
314 |
void ResTable::onSortDataChanged(DocSeqSortSpec)
|
219 |
{
|
315 |
{
|
220 |
LOGDEB(("ResTable::sortByColumn(%d,%d)\n", column, int(order)));
|
316 |
QHeaderView *header = tableView->horizontalHeader();
|
221 |
|
317 |
if (!header)
|
222 |
if (column >= 0 && m_model && column < int(m_model->m_fields.size())) {
|
318 |
return;
|
223 |
DocSeqSortSpec spec;
|
319 |
header->setSortIndicator(-1, Qt::AscendingOrder);
|
224 |
spec.field = m_model->m_fields[column];
|
|
|
225 |
spec.desc = order == Qt::AscendingOrder ? false : true;
|
|
|
226 |
m_model->m_source->setSortSpec(spec);
|
|
|
227 |
readDocSource();
|
|
|
228 |
emit sortDataChanged(spec);
|
|
|
229 |
}
|
|
|
230 |
}
|
320 |
}
|
231 |
|
321 |
|
232 |
void ResTable::readDocSource()
|
322 |
void ResTable::readDocSource()
|
233 |
{
|
323 |
{
|
234 |
m_model->setDocSource(m_model->m_source);
|
324 |
m_model->setDocSource(m_model->m_source);
|