Add delete and copy url ops to the webcache editor
This commit is contained in:
parent
241586a3a7
commit
759d8eca9f
@ -29,6 +29,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QCloseEvent>
|
||||||
|
#include <QShortcut>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QClipboard>
|
||||||
|
|
||||||
#include "recoll.h"
|
#include "recoll.h"
|
||||||
#include "webcache.h"
|
#include "webcache.h"
|
||||||
@ -58,9 +63,16 @@ public:
|
|||||||
WebcacheModel::WebcacheModel(QObject *parent)
|
WebcacheModel::WebcacheModel(QObject *parent)
|
||||||
: QAbstractTableModel(parent), m(new WebcacheModelInternal())
|
: QAbstractTableModel(parent), m(new WebcacheModelInternal())
|
||||||
{
|
{
|
||||||
qDebug() << "WebcacheModel::WebcacheModel()";
|
//qDebug() << "WebcacheModel::WebcacheModel()";
|
||||||
|
reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebcacheModel::reload()
|
||||||
|
{
|
||||||
m->cache =
|
m->cache =
|
||||||
STD_SHARED_PTR<BeagleQueueCache>(new BeagleQueueCache(theconfig));
|
STD_SHARED_PTR<BeagleQueueCache>(new BeagleQueueCache(theconfig));
|
||||||
|
m->all.clear();
|
||||||
|
m->disp.clear();
|
||||||
|
|
||||||
if (m->cache) {
|
if (m->cache) {
|
||||||
bool eof;
|
bool eof;
|
||||||
@ -80,6 +92,21 @@ WebcacheModel::WebcacheModel(QObject *parent)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
emit dataChanged(createIndex(0,0,0), createIndex(1, m->all.size(),0));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebcacheModel::deleteIdx(unsigned int idx)
|
||||||
|
{
|
||||||
|
if (idx > m->disp.size() || !m->cache)
|
||||||
|
return false;
|
||||||
|
return m->cache->cc()->erase(m->disp[idx].udi, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
string WebcacheModel::getURL(unsigned int idx)
|
||||||
|
{
|
||||||
|
if (idx > m->disp.size() || !m->cache)
|
||||||
|
return string();
|
||||||
|
return m->disp[idx].url;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WebcacheModel::rowCount(const QModelIndex&) const
|
int WebcacheModel::rowCount(const QModelIndex&) const
|
||||||
@ -181,15 +208,120 @@ void WebcacheModel::setSearchFilter(const QString& _txt)
|
|||||||
emit dataChanged(createIndex(0,0,0), createIndex(1, m->all.size(),0));
|
emit dataChanged(createIndex(0,0,0), createIndex(1, m->all.size(),0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const int ROWHEIGHTPAD = 2;
|
||||||
|
static const char *cwnm = "/Recoll/prefs/webcachecolw";
|
||||||
|
static const char *wwnm = "/Recoll/prefs/webcachew";
|
||||||
|
static const char *whnm = "/Recoll/prefs/webcacheh";
|
||||||
|
static const QKeySequence closeKS(Qt::ControlModifier+Qt::Key_W);
|
||||||
|
|
||||||
WebcacheEdit::WebcacheEdit(QWidget *parent)
|
WebcacheEdit::WebcacheEdit(QWidget *parent)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
{
|
{
|
||||||
qDebug() << "WebcacheEdit::WebcacheEdit()";
|
//qDebug() << "WebcacheEdit::WebcacheEdit()";
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
m_model = new WebcacheModel(this);
|
m_model = new WebcacheModel(this);
|
||||||
webcacheTV->setModel(m_model);
|
tableview->setModel(m_model);
|
||||||
|
tableview->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
tableview->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||||
|
tableview->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
tableview->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
|
|
||||||
|
QSettings settings;
|
||||||
|
QStringList wl;
|
||||||
|
wl = settings.value(cwnm).toStringList();
|
||||||
|
QHeaderView *header = tableview->horizontalHeader();
|
||||||
|
if (header) {
|
||||||
|
if (int(wl.size()) == header->count()) {
|
||||||
|
for (int i = 0; i < header->count(); i++) {
|
||||||
|
header->resizeSection(i, wl[i].toInt());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connect(header, SIGNAL(sectionResized(int,int,int)),
|
||||||
|
this, SLOT(saveColState()));
|
||||||
|
|
||||||
|
header = tableview->verticalHeader();
|
||||||
|
if (header) {
|
||||||
|
header->setDefaultSectionSize(QApplication::fontMetrics().height() +
|
||||||
|
ROWHEIGHTPAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
int width = settings.value(wwnm, 0).toInt();
|
||||||
|
int height = settings.value(whnm, 0).toInt();
|
||||||
|
if (width && height) {
|
||||||
|
resize(QSize(width, height));
|
||||||
|
}
|
||||||
|
|
||||||
connect(searchLE, SIGNAL(textEdited(const QString&)),
|
connect(searchLE, SIGNAL(textEdited(const QString&)),
|
||||||
m_model, SLOT(setSearchFilter(const QString&)));
|
m_model, SLOT(setSearchFilter(const QString&)));
|
||||||
|
connect(new QShortcut(closeKS, this), SIGNAL (activated()),
|
||||||
|
this, SLOT (close()));
|
||||||
|
connect(tableview, SIGNAL(customContextMenuRequested(const QPoint&)),
|
||||||
|
this, SLOT(createPopupMenu(const QPoint&)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebcacheEdit::createPopupMenu(const QPoint& pos)
|
||||||
|
{
|
||||||
|
int selsz = tableview->selectionModel()->selectedRows().size();
|
||||||
|
if (selsz <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QMenu *popup = new QMenu(this);
|
||||||
|
if (selsz == 1) {
|
||||||
|
popup->addAction(tr("Copy URL"), this, SLOT(copyURL()));
|
||||||
|
}
|
||||||
|
popup->addAction(tr("Delete selection"), this, SLOT(deleteSelected()));
|
||||||
|
|
||||||
|
popup->popup(tableview->mapToGlobal(pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebcacheEdit::deleteSelected()
|
||||||
|
{
|
||||||
|
QModelIndexList selection = tableview->selectionModel()->selectedRows();
|
||||||
|
for (int i = 0; i < selection.size(); i++) {
|
||||||
|
m_model->deleteIdx(selection[i].row());
|
||||||
|
}
|
||||||
|
m_model->reload();
|
||||||
|
m_model->setSearchFilter(searchLE->text());
|
||||||
|
tableview->clearSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebcacheEdit::copyURL()
|
||||||
|
{
|
||||||
|
QModelIndexList selection = tableview->selectionModel()->selectedRows();
|
||||||
|
if (selection.size() != 1)
|
||||||
|
return;
|
||||||
|
string url = m_model->getURL(selection[0].row());
|
||||||
|
if (!url.empty()) {
|
||||||
|
url = url_encode(url, 7);
|
||||||
|
QApplication::clipboard()->setText(url.c_str(),
|
||||||
|
QClipboard::Selection);
|
||||||
|
QApplication::clipboard()->setText(url.c_str(),
|
||||||
|
QClipboard::Clipboard);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebcacheEdit::saveColState()
|
||||||
|
{
|
||||||
|
//qDebug() << "void WebcacheEdit::saveColState()";
|
||||||
|
QHeaderView *header = tableview->horizontalHeader();
|
||||||
|
QStringList newwidths;
|
||||||
|
for (int vi = 0; vi < header->count(); vi++) {
|
||||||
|
int li = header->logicalIndex(vi);
|
||||||
|
newwidths.push_back(lltodecstr(header->sectionSize(li)).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
QSettings settings;
|
||||||
|
settings.setValue(cwnm, newwidths);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebcacheEdit::closeEvent(QCloseEvent *event)
|
||||||
|
{
|
||||||
|
if (!isFullScreen()) {
|
||||||
|
QSettings settings;
|
||||||
|
settings.setValue(wwnm, width());
|
||||||
|
settings.setValue(whnm, height());
|
||||||
|
}
|
||||||
|
event->accept();
|
||||||
|
}
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
#include <QAbstractTableModel>
|
#include <QAbstractTableModel>
|
||||||
|
|
||||||
class WebcacheModelInternal;
|
class WebcacheModelInternal;
|
||||||
|
class QCloseEvent;
|
||||||
|
|
||||||
class WebcacheModel : public QAbstractTableModel {
|
class WebcacheModel : public QAbstractTableModel {
|
||||||
Q_OBJECT;
|
Q_OBJECT;
|
||||||
@ -41,6 +42,10 @@ public:
|
|||||||
int role = Qt::DisplayRole) const;
|
int role = Qt::DisplayRole) const;
|
||||||
virtual QVariant data(const QModelIndex& index,
|
virtual QVariant data(const QModelIndex& index,
|
||||||
int role = Qt::DisplayRole ) const;
|
int role = Qt::DisplayRole ) const;
|
||||||
|
bool deleteIdx(unsigned int idx);
|
||||||
|
std::string getURL(unsigned int idx);
|
||||||
|
void reload();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setSearchFilter(const QString&);
|
void setSearchFilter(const QString&);
|
||||||
|
|
||||||
@ -53,6 +58,13 @@ class WebcacheEdit : public QDialog, public Ui::Webcache {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
WebcacheEdit(QWidget *parent);
|
WebcacheEdit(QWidget *parent);
|
||||||
|
public slots:
|
||||||
|
void saveColState();
|
||||||
|
void createPopupMenu(const QPoint&);
|
||||||
|
void deleteSelected();
|
||||||
|
void copyURL();
|
||||||
|
protected:
|
||||||
|
void closeEvent(QCloseEvent *);
|
||||||
private:
|
private:
|
||||||
WebcacheModel *m_model;
|
WebcacheModel *m_model;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTableView" name="webcacheTV">
|
<widget class="QTableView" name="tableview">
|
||||||
<property name="editTriggers">
|
<property name="editTriggers">
|
||||||
<set>QAbstractItemView::NoEditTriggers</set>
|
<set>QAbstractItemView::NoEditTriggers</set>
|
||||||
</property>
|
</property>
|
||||||
|
|||||||
@ -441,7 +441,8 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool writeEntryHeader(off_t offset, const EntryHeaderData& d) {
|
bool writeEntryHeader(off_t offset, const EntryHeaderData& d,
|
||||||
|
bool eraseData = false) {
|
||||||
if (m_fd < 0) {
|
if (m_fd < 0) {
|
||||||
m_reason << "writeEntryHeader: not open ";
|
m_reason << "writeEntryHeader: not open ";
|
||||||
return false;
|
return false;
|
||||||
@ -459,6 +460,17 @@ public:
|
|||||||
m_reason << "CirCache::weh: write failed. errno " << errno;
|
m_reason << "CirCache::weh: write failed. errno " << errno;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (eraseData == true) {
|
||||||
|
if (d.dicsize || d.datasize) {
|
||||||
|
m_reason << "CirCache::weh: erase requested but not empty";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
string buf(d.padsize, ' ');
|
||||||
|
if (write(m_fd, buf.c_str(), d.padsize) != d.padsize) {
|
||||||
|
m_reason << "CirCache::weh: write failed. errno " << errno;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -928,7 +940,7 @@ bool CirCache::get(const string& udi, string& dic, string *data, int instance)
|
|||||||
return bret;
|
return bret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CirCache::erase(const string& udi)
|
bool CirCache::erase(const string& udi, bool reallyclear)
|
||||||
{
|
{
|
||||||
if (m_d == 0) {
|
if (m_d == 0) {
|
||||||
LOGERR(("CirCache::erase: null data\n"));
|
LOGERR(("CirCache::erase: null data\n"));
|
||||||
@ -960,21 +972,21 @@ bool CirCache::erase(const string& udi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (vector<off_t>::iterator it = ofss.begin(); it != ofss.end(); it++) {
|
for (vector<off_t>::iterator it = ofss.begin(); it != ofss.end(); it++) {
|
||||||
LOGDEB(("CirCache::erase: reading at %lu\n", (unsigned long)*it));
|
LOGDEB2(("CirCache::erase: reading at %lu\n", (unsigned long)*it));
|
||||||
EntryHeaderData d;
|
EntryHeaderData d;
|
||||||
string fudi;
|
string fudi;
|
||||||
if (!m_d->readHUdi(*it, d, fudi)) {
|
if (!m_d->readHUdi(*it, d, fudi)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LOGDEB(("CirCache::erase: found fudi [%s]\n", fudi.c_str()));
|
LOGDEB2(("CirCache::erase: found fudi [%s]\n", fudi.c_str()));
|
||||||
if (!fudi.compare(udi)) {
|
if (!fudi.compare(udi)) {
|
||||||
EntryHeaderData nd;
|
EntryHeaderData nd;
|
||||||
nd.padsize = d.dicsize + d.datasize + d.padsize;
|
nd.padsize = d.dicsize + d.datasize + d.padsize;
|
||||||
LOGDEB(("CirCache::erase: rewriting at %lu\n", (unsigned long)*it));
|
LOGDEB2(("CirCache::erase: rewrite at %lu\n", (unsigned long)*it));
|
||||||
if (*it == m_d->m_nheadoffs) {
|
if (*it == m_d->m_nheadoffs) {
|
||||||
m_d->m_npadsize = nd.padsize;
|
m_d->m_npadsize = nd.padsize;
|
||||||
}
|
}
|
||||||
if (!m_d->writeEntryHeader(*it, nd)) {
|
if (!m_d->writeEntryHeader(*it, nd, reallyclear)) {
|
||||||
LOGERR(("CirCache::erase: write header failed\n"));
|
LOGERR(("CirCache::erase: write header failed\n"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1050,8 +1062,8 @@ bool CirCache::put(const string& udi, const ConfSimple *iconf,
|
|||||||
uLong len = compressBound(static_cast<uLong>(data.size()));
|
uLong len = compressBound(static_cast<uLong>(data.size()));
|
||||||
char *bf = compbuf.setsize(len);
|
char *bf = compbuf.setsize(len);
|
||||||
if (bf != 0 &&
|
if (bf != 0 &&
|
||||||
compress((Bytef*)bf, &len, (Bytef*)data.c_str(), static_cast<uLong>(data.size()))
|
compress((Bytef*)bf, &len, (Bytef*)data.c_str(),
|
||||||
== Z_OK) {
|
static_cast<uLong>(data.size())) == Z_OK) {
|
||||||
if (float(len) < 0.9 * float(data.size())) {
|
if (float(len) < 0.9 * float(data.size())) {
|
||||||
// bf is local but it's our static buffer address
|
// bf is local but it's our static buffer address
|
||||||
datap = bf;
|
datap = bf;
|
||||||
|
|||||||
@ -73,7 +73,7 @@ public:
|
|||||||
virtual bool put(const std::string& udi, const ConfSimple *dicp,
|
virtual bool put(const std::string& udi, const ConfSimple *dicp,
|
||||||
const std::string& data, unsigned int flags = 0);
|
const std::string& data, unsigned int flags = 0);
|
||||||
|
|
||||||
virtual bool erase(const std::string& udi);
|
virtual bool erase(const std::string& udi, bool reallyclear = false);
|
||||||
|
|
||||||
/** Walk the archive.
|
/** Walk the archive.
|
||||||
*
|
*
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user