Add delete and copy url ops to the webcache editor

This commit is contained in:
Jean-Francois Dockes 2016-04-13 18:27:08 +02:00
parent 241586a3a7
commit 759d8eca9f
5 changed files with 171 additions and 15 deletions

View File

@ -29,6 +29,11 @@
#endif
#include <QDebug>
#include <QSettings>
#include <QCloseEvent>
#include <QShortcut>
#include <QMenu>
#include <QClipboard>
#include "recoll.h"
#include "webcache.h"
@ -58,10 +63,17 @@ public:
WebcacheModel::WebcacheModel(QObject *parent)
: QAbstractTableModel(parent), m(new WebcacheModelInternal())
{
qDebug() << "WebcacheModel::WebcacheModel()";
//qDebug() << "WebcacheModel::WebcacheModel()";
reload();
}
void WebcacheModel::reload()
{
m->cache =
STD_SHARED_PTR<BeagleQueueCache>(new BeagleQueueCache(theconfig));
m->all.clear();
m->disp.clear();
if (m->cache) {
bool eof;
m->cache->cc()->rewind(eof);
@ -80,6 +92,21 @@ WebcacheModel::WebcacheModel(QObject *parent)
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
@ -181,15 +208,120 @@ void WebcacheModel::setSearchFilter(const QString& _txt)
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)
: QDialog(parent)
{
qDebug() << "WebcacheEdit::WebcacheEdit()";
//qDebug() << "WebcacheEdit::WebcacheEdit()";
setupUi(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&)),
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();
}

View File

@ -27,6 +27,7 @@
#include <QAbstractTableModel>
class WebcacheModelInternal;
class QCloseEvent;
class WebcacheModel : public QAbstractTableModel {
Q_OBJECT;
@ -41,9 +42,13 @@ public:
int role = Qt::DisplayRole) const;
virtual QVariant data(const QModelIndex& index,
int role = Qt::DisplayRole ) const;
bool deleteIdx(unsigned int idx);
std::string getURL(unsigned int idx);
void reload();
public slots:
void setSearchFilter(const QString&);
private:
WebcacheModelInternal *m;
};
@ -53,6 +58,13 @@ class WebcacheEdit : public QDialog, public Ui::Webcache {
public:
WebcacheEdit(QWidget *parent);
public slots:
void saveColState();
void createPopupMenu(const QPoint&);
void deleteSelected();
void copyURL();
protected:
void closeEvent(QCloseEvent *);
private:
WebcacheModel *m_model;
};

View File

@ -32,7 +32,7 @@
</layout>
</item>
<item>
<widget class="QTableView" name="webcacheTV">
<widget class="QTableView" name="tableview">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>

View File

@ -441,7 +441,8 @@ public:
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) {
m_reason << "writeEntryHeader: not open ";
return false;
@ -459,6 +460,17 @@ public:
m_reason << "CirCache::weh: write failed. errno " << errno;
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;
}
@ -928,7 +940,7 @@ bool CirCache::get(const string& udi, string& dic, string *data, int instance)
return bret;
}
bool CirCache::erase(const string& udi)
bool CirCache::erase(const string& udi, bool reallyclear)
{
if (m_d == 0) {
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++) {
LOGDEB(("CirCache::erase: reading at %lu\n", (unsigned long)*it));
LOGDEB2(("CirCache::erase: reading at %lu\n", (unsigned long)*it));
EntryHeaderData d;
string fudi;
if (!m_d->readHUdi(*it, d, fudi)) {
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)) {
EntryHeaderData nd;
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) {
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"));
return false;
}
@ -1050,8 +1062,8 @@ bool CirCache::put(const string& udi, const ConfSimple *iconf,
uLong len = compressBound(static_cast<uLong>(data.size()));
char *bf = compbuf.setsize(len);
if (bf != 0 &&
compress((Bytef*)bf, &len, (Bytef*)data.c_str(), static_cast<uLong>(data.size()))
== Z_OK) {
compress((Bytef*)bf, &len, (Bytef*)data.c_str(),
static_cast<uLong>(data.size())) == Z_OK) {
if (float(len) < 0.9 * float(data.size())) {
// bf is local but it's our static buffer address
datap = bf;

View File

@ -73,7 +73,7 @@ public:
virtual bool put(const std::string& udi, const ConfSimple *dicp,
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.
*