From f41e3f5aeacb6c51a4894a84cbf62edcfc96ae1e Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Thu, 14 Apr 2016 09:32:53 +0200 Subject: [PATCH] webcache editor: handle interactions with indexer --- src/qtgui/rclm_idx.cpp | 16 +++++-- src/qtgui/rclm_wins.cpp | 41 ++++++++++++++--- src/qtgui/rclmain_w.cpp | 7 ++- src/qtgui/rclmain_w.h | 98 +++++++++++++++++++++++------------------ src/qtgui/webcache.cpp | 42 ++++++++++++++++-- src/qtgui/webcache.h | 9 +++- 6 files changed, 155 insertions(+), 58 deletions(-) diff --git a/src/qtgui/rclm_idx.cpp b/src/qtgui/rclm_idx.cpp index cc236c28..04790d52 100644 --- a/src/qtgui/rclm_idx.cpp +++ b/src/qtgui/rclm_idx.cpp @@ -17,6 +17,7 @@ #include "autoconfig.h" #include +#include "safeunistd.h" #include #include @@ -30,7 +31,7 @@ using namespace std; -void RclMain::idxStatus() +void RclMain::updateIdxStatus() { ConfSimple cs(theconfig->getIdxStatusFile().c_str(), 1); QString msg = tr("Indexing in progress: "); @@ -109,7 +110,7 @@ void RclMain::periodic100() // update/show status even if the status file did not // change (else the status line goes blank during // lengthy operations). - idxStatus(); + updateIdxStatus(); } } // Update the "start/stop indexing" menu entry, can't be done from @@ -124,7 +125,16 @@ void RclMain::periodic100() periodictimer->setInterval(200); } else { Pidfile pidfile(theconfig->getPidfile()); - if (pidfile.open() == 0) { + pid_t pid = pidfile.open(); + if (pid == getpid()) { + // Locked by me + m_indexerState = IXST_NOTRUNNING; + fileToggleIndexingAction->setText(tr("Index locked")); + fileToggleIndexingAction->setEnabled(false); + fileRebuildIndexAction->setEnabled(false); + actionSpecial_Indexing->setEnabled(false); + periodictimer->setInterval(1000); + } else if (pid == 0) { m_indexerState = IXST_NOTRUNNING; fileToggleIndexingAction->setText(tr("Update &Index")); fileToggleIndexingAction->setEnabled(true); diff --git a/src/qtgui/rclm_wins.cpp b/src/qtgui/rclm_wins.cpp index 671275f5..f1b9f422 100644 --- a/src/qtgui/rclm_wins.cpp +++ b/src/qtgui/rclm_wins.cpp @@ -77,16 +77,47 @@ void RclMain::showSpellDialog() void RclMain::showWebcacheDialog() { + switch (indexerState()) { + case RclMain::IXST_UNKNOWN: + QMessageBox::warning(0, "Recoll", tr("Unknown indexer state. " + "Can't access webcache file.")); + return; + case RclMain::IXST_RUNNINGMINE: + case RclMain::IXST_RUNNINGNOTMINE: + QMessageBox::warning(0, "Recoll", tr("Indexer is running. " + "Can't access webcache file.")); + return; + case RclMain::IXST_NOTRUNNING: + break; + } + + if (!m_pidfile) { + m_pidfile = new Pidfile(theconfig->getPidfile()); + if (m_pidfile->open() != 0) { + deleteZ(m_pidfile); + return; + } + if (m_pidfile->write_pid() != 0) { + deleteZ(m_pidfile); + return; + } + } + if (webcache == 0) { - webcache = new WebcacheEdit(0); - connect(new QShortcut(quitKeySeq, webcache), SIGNAL (activated()), + webcache = new WebcacheEdit(this); + webcache->setAttribute(Qt::WA_DeleteOnClose); + connect(new QShortcut(quitKeySeq, webcache), SIGNAL (activated()), this, SLOT (fileExit())); - webcache->show(); - } else { - webcache->close(); + connect(webcache, SIGNAL(destroyed(QObject*)), + this, SLOT(onWebcacheDestroyed(QObject*)) ); webcache->show(); } } +void RclMain::onWebcacheDestroyed(QObject *) +{ + deleteZ(m_pidfile); + webcache = 0; +} void RclMain::showIndexStatistics() { diff --git a/src/qtgui/rclmain_w.cpp b/src/qtgui/rclmain_w.cpp index 56b81363..077ff705 100644 --- a/src/qtgui/rclmain_w.cpp +++ b/src/qtgui/rclmain_w.cpp @@ -303,7 +303,8 @@ void RclMain::init() sc = new QShortcut(seql, this); connect(sc, SIGNAL (activated()), sSearch, SLOT (takeFocus())); - connect(&m_watcher, SIGNAL(fileChanged(QString)), this, SLOT(idxStatus())); + connect(&m_watcher, SIGNAL(fileChanged(QString)), + this, SLOT(updateIdxStatus())); #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)) connect(sSearch, @@ -350,8 +351,12 @@ void RclMain::init() this, SLOT(showAdvSearchDialog())); connect(toolsSpellAction, SIGNAL(triggered()), this, SLOT(showSpellDialog())); +#ifdef _WIN32 + actionWebcache_Editor->setEnabled(false); +#else connect(actionWebcache_Editor, SIGNAL(triggered()), this, SLOT(showWebcacheDialog())); +#endif connect(actionQuery_Fragments, SIGNAL(triggered()), this, SLOT(showFragButs())); connect(actionSpecial_Indexing, SIGNAL(triggered()), diff --git a/src/qtgui/rclmain_w.h b/src/qtgui/rclmain_w.h index d891af50..1df1096b 100644 --- a/src/qtgui/rclmain_w.h +++ b/src/qtgui/rclmain_w.h @@ -47,80 +47,84 @@ class WebcacheEdit; #include "ui_rclmain.h" namespace confgui { - class ConfIndexW; +class ConfIndexW; } using confgui::ConfIndexW; class RclTrayIcon; -class RclMain : public QMainWindow, public Ui::RclMainBase -{ - Q_OBJECT +class RclMain : public QMainWindow, public Ui::RclMainBase { + Q_OBJECT; public: - enum IndexerState {IXST_UNKNOWN, IXST_NOTRUNNING, - IXST_RUNNINGMINE, IXST_RUNNINGNOTMINE}; - RclMain(QWidget * parent = 0) - : QMainWindow(parent), - curPreview(0), - asearchform(0), - uiprefs(0), - indexConfig(0), - indexSched(0), - cronTool(0), - rtiTool(0), - spellform(0), + RclMain(QWidget * parent = 0) + : QMainWindow(parent), + curPreview(0), + asearchform(0), + uiprefs(0), + indexConfig(0), + indexSched(0), + cronTool(0), + rtiTool(0), + spellform(0), fragbuts(0), specidx(0), - periodictimer(0), + periodictimer(0), webcache(0), - restable(0), - displayingTable(0), + restable(0), + displayingTable(0), m_idNoStem(0), m_idAllStem(0), - m_toolsTB(0), m_resTB(0), + m_toolsTB(0), m_resTB(0), m_filtFRM(0), m_filtCMB(0), m_filtBGRP(0), m_filtMN(0), - m_idxproc(0), + m_idxproc(0), m_idxkilled(false), m_catgbutvecidx(0), - m_sortspecnochange(false), - m_indexerState(IXST_UNKNOWN), - m_queryActive(false), - m_firstIndexing(false), - m_searchIsSimple(false) - { - setupUi(this); - init(); + m_sortspecnochange(false), + m_indexerState(IXST_UNKNOWN), + m_queryActive(false), + m_firstIndexing(false), + m_searchIsSimple(false), + m_pidfile(0) { + setupUi(this); + init(); } ~RclMain() {} + QString getQueryDescription(); /** This is only called from main() to set an URL to be displayed (using - recoll as a doc extracter for embedded docs */ - virtual void setUrlToView(const QString& u) {m_urltoview = u;} + recoll as a doc extracter for embedded docs */ + virtual void setUrlToView(const QString& u) { + m_urltoview = u; + } /** Same usage: actually display the current urltoview */ virtual void viewUrl(); - bool lastSearchSimple() - { - return m_searchIsSimple; + bool lastSearchSimple() { + return m_searchIsSimple; } // Takes copies of the args instead of refs. Lazy and safe. void newDupsW(const Rcl::Doc doc, const std::vector dups); -protected: - virtual void showEvent(QShowEvent *); + enum IndexerState {IXST_UNKNOWN, IXST_NOTRUNNING, + IXST_RUNNINGMINE, IXST_RUNNINGNOTMINE}; + IndexerState indexerState() const { + return m_indexerState; + } + + public slots: virtual void fileExit(); - virtual void idxStatus(); virtual void periodic100(); virtual void toggleIndexing(); virtual void rebuildIndex(); virtual void specialIndex(); - virtual void startSearch(STD_SHARED_PTR sdata, bool issimple); + virtual void startSearch(STD_SHARED_PTR sdata, + bool issimple); virtual void previewClosed(Preview *w); virtual void showAdvSearchDialog(); virtual void showSpellDialog(); @@ -153,8 +157,8 @@ public slots: virtual void showSnippets(Rcl::Doc); virtual void startPreview(int docnum, Rcl::Doc doc, int keymods); virtual void startPreview(Rcl::Doc); - virtual void startNativeViewer(Rcl::Doc, int pagenum = -1, - QString term=QString()); + virtual void startNativeViewer(Rcl::Doc, int pagenum = -1, + QString term = QString()); virtual void openWith(Rcl::Doc, string); virtual void saveDocToFile(Rcl::Doc); virtual void previewNextInTab(Preview *, int sid, int docnum); @@ -181,6 +185,9 @@ public slots: virtual void setFilterCtlStyle(int stl); virtual void showTrayMessage(const QString& text); +private slots: + virtual void updateIdxStatus(); + virtual void onWebcacheDestroyed(QObject *); signals: void docSourceChanged(STD_SHARED_PTR); void stemLangChanged(const QString& lang); @@ -189,7 +196,9 @@ signals: void searchReset(); protected: - virtual void closeEvent( QCloseEvent * ); + virtual void closeEvent(QCloseEvent *); + virtual void showEvent(QShowEvent *); + private: Preview *curPreview; @@ -236,10 +245,13 @@ private: RclTrayIcon *m_trayicon; + // We sometimes take the indexer lock (e.g.: when editing the webcache) + Pidfile *m_pidfile; + virtual void init(); virtual void setupResTB(bool combo); - virtual void previewPrevOrNextInTab(Preview *, int sid, int docnum, - bool next); + virtual void previewPrevOrNextInTab(Preview *, int sid, int docnum, + bool next); virtual void execViewer(const map& subs, bool enterHistory, const string& execpath, const vector& lcmd, const string& cmd, Rcl::Doc doc); diff --git a/src/qtgui/webcache.cpp b/src/qtgui/webcache.cpp index 5542881d..ceac8275 100644 --- a/src/qtgui/webcache.cpp +++ b/src/qtgui/webcache.cpp @@ -34,12 +34,15 @@ #include #include #include +#include +#include #include "recoll.h" #include "webcache.h" #include "beaglequeuecache.h" #include "circache.h" #include "conftree.h" +#include "rclmain_w.h" using namespace std; @@ -66,6 +69,10 @@ WebcacheModel::WebcacheModel(QObject *parent) //qDebug() << "WebcacheModel::WebcacheModel()"; reload(); } +WebcacheModel::~WebcacheModel() +{ + delete m; +} void WebcacheModel::reload() { @@ -214,8 +221,8 @@ 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) +WebcacheEdit::WebcacheEdit(RclMain *parent) + : QDialog(parent), m_recoll(parent), m_modified(false) { //qDebug() << "WebcacheEdit::WebcacheEdit()"; setupUi(this); @@ -271,7 +278,26 @@ void WebcacheEdit::createPopupMenu(const QPoint& pos) if (selsz == 1) { popup->addAction(tr("Copy URL"), this, SLOT(copyURL())); } - popup->addAction(tr("Delete selection"), this, SLOT(deleteSelected())); + if (m_recoll) { + RclMain::IndexerState ixstate = m_recoll->indexerState(); + switch (ixstate) { + case RclMain::IXST_UNKNOWN: + QMessageBox::warning(0, "Recoll", + tr("Unknown indexer state. " + "Can't edit webcache file.")); + break; + case RclMain::IXST_RUNNINGMINE: + case RclMain::IXST_RUNNINGNOTMINE: + QMessageBox::warning(0, "Recoll", + tr("Indexer is running. " + "Can't edit webcache file.")); + break; + case RclMain::IXST_NOTRUNNING: + popup->addAction(tr("Delete selection"), + this, SLOT(deleteSelected())); + break; + } + } popup->popup(tableview->mapToGlobal(pos)); } @@ -280,7 +306,9 @@ void WebcacheEdit::deleteSelected() { QModelIndexList selection = tableview->selectionModel()->selectedRows(); for (int i = 0; i < selection.size(); i++) { - m_model->deleteIdx(selection[i].row()); + if (m_model->deleteIdx(selection[i].row())) { + m_modified = true; + } } m_model->reload(); m_model->setSearchFilter(searchLE->text()); @@ -318,6 +346,12 @@ void WebcacheEdit::saveColState() void WebcacheEdit::closeEvent(QCloseEvent *event) { + if (m_modified) { + QMessageBox::information(0, "Recoll", + tr("Webcache was modified, you will need " + "to run the indexer after closing this " + "window.")); + } if (!isFullScreen()) { QSettings settings; settings.setValue(wwnm, width()); diff --git a/src/qtgui/webcache.h b/src/qtgui/webcache.h index b89dca3a..f428f503 100644 --- a/src/qtgui/webcache.h +++ b/src/qtgui/webcache.h @@ -34,6 +34,7 @@ class WebcacheModel : public QAbstractTableModel { public: WebcacheModel(QObject *parent = 0); + ~WebcacheModel(); // Reimplemented methods virtual int rowCount (const QModelIndex& = QModelIndex()) const; @@ -44,20 +45,22 @@ public: int role = Qt::DisplayRole ) const; bool deleteIdx(unsigned int idx); std::string getURL(unsigned int idx); - void reload(); public slots: void setSearchFilter(const QString&); + void reload(); private: WebcacheModelInternal *m; }; +class RclMain; + class WebcacheEdit : public QDialog, public Ui::Webcache { Q_OBJECT; public: - WebcacheEdit(QWidget *parent); + WebcacheEdit(RclMain *parent); public slots: void saveColState(); void createPopupMenu(const QPoint&); @@ -67,6 +70,8 @@ protected: void closeEvent(QCloseEvent *); private: WebcacheModel *m_model; + RclMain *m_recoll; + bool m_modified; };