From 759d8eca9f779d02aa6b8dd027cc449edf45aa07 Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Wed, 13 Apr 2016 18:27:08 +0200 Subject: [PATCH] Add delete and copy url ops to the webcache editor --- src/qtgui/webcache.cpp | 140 +++++++++++++++++++++++++++++++++++++++-- src/qtgui/webcache.h | 14 ++++- src/qtgui/webcache.ui | 2 +- src/utils/circache.cpp | 28 ++++++--- src/utils/circache.h | 2 +- 5 files changed, 171 insertions(+), 15 deletions(-) diff --git a/src/qtgui/webcache.cpp b/src/qtgui/webcache.cpp index 3a4b787f..5542881d 100644 --- a/src/qtgui/webcache.cpp +++ b/src/qtgui/webcache.cpp @@ -29,6 +29,11 @@ #endif #include +#include +#include +#include +#include +#include #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(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(); +} diff --git a/src/qtgui/webcache.h b/src/qtgui/webcache.h index 5b9196e1..b89dca3a 100644 --- a/src/qtgui/webcache.h +++ b/src/qtgui/webcache.h @@ -27,6 +27,7 @@ #include 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; }; diff --git a/src/qtgui/webcache.ui b/src/qtgui/webcache.ui index f7e9974a..bdd2400a 100644 --- a/src/qtgui/webcache.ui +++ b/src/qtgui/webcache.ui @@ -32,7 +32,7 @@ - + QAbstractItemView::NoEditTriggers diff --git a/src/utils/circache.cpp b/src/utils/circache.cpp index 20e73911..bcd66d6a 100644 --- a/src/utils/circache.cpp +++ b/src/utils/circache.cpp @@ -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::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(data.size())); char *bf = compbuf.setsize(len); if (bf != 0 && - compress((Bytef*)bf, &len, (Bytef*)data.c_str(), static_cast(data.size())) - == Z_OK) { + compress((Bytef*)bf, &len, (Bytef*)data.c_str(), + static_cast(data.size())) == Z_OK) { if (float(len) < 0.9 * float(data.size())) { // bf is local but it's our static buffer address datap = bf; diff --git a/src/utils/circache.h b/src/utils/circache.h index 5f92cbe7..b7562ad5 100644 --- a/src/utils/circache.h +++ b/src/utils/circache.h @@ -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. *