From 07226fa3060f13e52628be25677ea5f842bb9607 Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Wed, 7 Dec 2011 13:41:05 +0100 Subject: [PATCH] GUI tools for setting up indexing schedule, initial implementation done --- src/common/rclconfig.cpp | 26 ++-- src/common/rclconfig.h | 7 +- src/qtgui/crontool.cpp | 4 +- src/qtgui/crontool.h | 6 +- src/qtgui/crontool.ui | 8 +- src/qtgui/firstidx.ui | 6 + src/qtgui/idxsched.h | 4 + src/qtgui/idxsched.ui | 19 ++- src/qtgui/rclmain.ui | 9 ++ src/qtgui/rclmain_w.cpp | 39 +++++- src/qtgui/rclmain_w.h | 6 + src/qtgui/recoll.pro.in | 3 + src/qtgui/rtitool.cpp | 172 ++++++++++++++++++++++++++ src/qtgui/{firstidx.cpp => rtitool.h} | 28 ++++- src/qtgui/rtitool.ui | 123 ++++++++++++++++++ src/recollinstall.in | 1 + src/utils/ecrontab.cpp | 6 +- 17 files changed, 438 insertions(+), 29 deletions(-) create mode 100644 src/qtgui/rtitool.cpp rename src/qtgui/{firstidx.cpp => rtitool.h} (64%) create mode 100644 src/qtgui/rtitool.ui diff --git a/src/common/rclconfig.cpp b/src/common/rclconfig.cpp index 56b67fea..fc0dda6a 100644 --- a/src/common/rclconfig.cpp +++ b/src/common/rclconfig.cpp @@ -100,6 +100,14 @@ void RclConfig::zeroMe() { m_rmtstate.init(this, 0, "indexedmimetypes"); } +bool RclConfig::isDefaultConfig() +{ + string defaultconf = path_cat(path_canon(path_home()), ".recoll/"); + string specifiedconf = path_canon(m_confdir); + path_catslash(specifiedconf); + return !defaultconf.compare(specifiedconf); +} + RclConfig::RclConfig(const string *argcnf) { zeroMe(); @@ -130,18 +138,18 @@ RclConfig::RclConfig(const string *argcnf) m_confdir = cp; } else { autoconfdir = true; - m_confdir = path_home(); - m_confdir += ".recoll/"; + m_confdir = path_cat(path_home(), ".recoll/"); } } - if (!autoconfdir) { - // We want a recoll.conf file to exist in this case to avoid - // creating indexes all over the place - string conffile = path_cat(m_confdir, "recoll.conf"); - if (access(conffile.c_str(), 0) < 0) { - m_reason = "Explicitly specified configuration directory must exist" - " (won't be automatically created)"; + // Note: autoconfdir and isDefaultConfig() are normally the same. We just + // want to avoid the imperfect test in isDefaultConfig() if we actually know + // this is the default conf + if (!autoconfdir && !isDefaultConfig()) { + if (access(m_confdir.c_str(), 0) < 0) { + m_reason = "Explicitly specified configuration " + "directory must exist" + " (won't be automatically created). Use mkdir first"; return; } } diff --git a/src/common/rclconfig.h b/src/common/rclconfig.h index 4c7ca26a..aa8d3196 100644 --- a/src/common/rclconfig.h +++ b/src/common/rclconfig.h @@ -83,8 +83,13 @@ class RclConfig { bool ok() {return m_ok;} const string &getReason() {return m_reason;} - /** Return the directory where this configuration is stored */ + /** Return the directory where this configuration is stored. + * This was possibly silently created by the rclconfig + * constructor it it is the default one (~/.recoll) and it did + * not exist yet. */ string getConfDir() {return m_confdir;} + /** Returns true if this is ~/.recoll */ + bool isDefaultConfig(); /** Get the local value for /usr/local/share/recoll/ */ const string& getDatadir() {return m_datadir;} diff --git a/src/qtgui/crontool.cpp b/src/qtgui/crontool.cpp index 8f66df9f..e2285f4b 100644 --- a/src/qtgui/crontool.cpp +++ b/src/qtgui/crontool.cpp @@ -72,7 +72,7 @@ void CronToolW::changeCron(bool enable) return; string id = idstring(theconfig->getConfDir()); - string cmd("recollindex -m -w 60"); + string cmd("recollindex"); string reason; @@ -88,7 +88,7 @@ void CronToolW::changeCron(bool enable) accept(); } else { QMessageBox::warning(0, "Recoll", - tr("Error installing cron entry. Bad syntax in fields ? ")); + tr("Error installing cron entry. Bad syntax in fields ?")); } } } diff --git a/src/qtgui/crontool.h b/src/qtgui/crontool.h index 8378b809..7495aa8e 100644 --- a/src/qtgui/crontool.h +++ b/src/qtgui/crontool.h @@ -14,8 +14,8 @@ * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#ifndef _CRONTAB_W_H_INCLUDED_ -#define _CRONTAB_W_H_INCLUDED_ +#ifndef _CRONTOOL_W_H_INCLUDED_ +#define _CRONTOOL_W_H_INCLUDED_ #include "ui_crontool.h" @@ -45,4 +45,4 @@ private: }; -#endif /* _CRONTAB_W_H_INCLUDED_ */ +#endif /* _CRONTOOL_W_H_INCLUDED_ */ diff --git a/src/qtgui/crontool.ui b/src/qtgui/crontool.ui index 38bee435..ae30ac74 100644 --- a/src/qtgui/crontool.ui +++ b/src/qtgui/crontool.ui @@ -7,7 +7,7 @@ 0 0 465 - 365 + 367 @@ -18,6 +18,12 @@ + + + 0 + 1 + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> diff --git a/src/qtgui/firstidx.ui b/src/qtgui/firstidx.ui index f9e81d1b..dc7eba6a 100644 --- a/src/qtgui/firstidx.ui +++ b/src/qtgui/firstidx.ui @@ -43,6 +43,9 @@ p, li { white-space: pre-wrap; } false + + false + This will let you adjust the directories you want to index, and other parameters like excluded file paths or names, default character sets, etc. @@ -53,6 +56,9 @@ p, li { white-space: pre-wrap; } Indexing schedule + + false + This will let you chose between batch and real-time indexing, and set up an automatic schedule for batch indexing (using cron). diff --git a/src/qtgui/idxsched.h b/src/qtgui/idxsched.h index 9db8a443..dedf6ba9 100644 --- a/src/qtgui/idxsched.h +++ b/src/qtgui/idxsched.h @@ -18,6 +18,7 @@ #define _IDXSCHED_H_INCLUDED_ #include "ui_idxsched.h" +#include "rclhelp.h" class IdxSchedW : public QDialog, public Ui::IdxSchedW { Q_OBJECT @@ -26,6 +27,9 @@ class IdxSchedW : public QDialog, public Ui::IdxSchedW { : QDialog(parent) { setupUi(this); + (void)new HelpClient(this); + HelpClient::installMap((const char *)this->objectName().toUtf8(), + "RCL.INDEXING"); } }; diff --git a/src/qtgui/idxsched.ui b/src/qtgui/idxsched.ui index 95fb0f86..3df2f3f0 100644 --- a/src/qtgui/idxsched.ui +++ b/src/qtgui/idxsched.ui @@ -7,7 +7,7 @@ 0 0 400 - 300 + 352 @@ -24,8 +24,9 @@ p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Recoll</span> indexing can run permanently, indexing files as they change, or run at discrete intervals. </p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Reading the manual may help you to decide between these approaches. Hopefuly, F1 should get you there.</p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This tool can help you set up a schedule to automate batch indexing runs, or start real time indexing when you log in (or both actually, which may make sense in some situations). </p></body></html> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Reading the manual may help you to decide between these approaches (press F1). </p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">This tool can help you set up a schedule to automate batch indexing runs, or start real time indexing when you log in (or both, which rarely makes sense). </p></body></html> Qt::AutoText @@ -38,7 +39,10 @@ p, li { white-space: pre-wrap; } - Start cron scheduling tool + Cron scheduling + + + false The tool will let you decide at what time indexing should run and will install a crontab entry. @@ -48,10 +52,13 @@ p, li { white-space: pre-wrap; } - Real time indexing start up options + Real time indexing start up + + + false - Decide if real time indexing will be started when you log in + Decide if real time indexing will be started when you log in (only for the default index). diff --git a/src/qtgui/rclmain.ui b/src/qtgui/rclmain.ui index f3c8255d..27643190 100644 --- a/src/qtgui/rclmain.ui +++ b/src/qtgui/rclmain.ui @@ -160,6 +160,7 @@ &Preferences + @@ -375,6 +376,14 @@ indexConfigAction + + + &Indexing schedule + + + indexScheduleAction + + &Query configuration diff --git a/src/qtgui/rclmain_w.cpp b/src/qtgui/rclmain_w.cpp index 3ffbaf50..78e6e4d6 100644 --- a/src/qtgui/rclmain_w.cpp +++ b/src/qtgui/rclmain_w.cpp @@ -72,6 +72,7 @@ using std::pair; #include "firstidx.h" #include "idxsched.h" #include "crontool.h" +#include "rtitool.h" using namespace confgui; @@ -235,6 +236,8 @@ void RclMain::init() this, SLOT(showSpellDialog())); connect(indexConfigAction, SIGNAL(activated()), this, SLOT(showIndexConfig())); + connect(indexScheduleAction, SIGNAL(activated()), + this, SLOT(showIndexSched())); connect(queryPrefsAction, SIGNAL(activated()), this, SLOT(showUIPrefs())); connect(extIdxAction, SIGNAL(activated()), @@ -713,9 +716,12 @@ void RclMain::showIndexSched(bool modal) this, SLOT (fileExit())); connect(indexSched->cronCLB, SIGNAL(clicked()), this, SLOT(execCronTool())); - connect(indexSched->rtidxCLB, SIGNAL(clicked()), - this, SLOT(execRTITool())); - + if (theconfig && theconfig->isDefaultConfig()) { + connect(indexSched->rtidxCLB, SIGNAL(clicked()), + this, SLOT(execRTITool())); + } else { + indexSched->rtidxCLB->setEnabled(false); + } } else { // Close and reopen, in hope that makes us visible... indexSched->close(); @@ -755,6 +761,33 @@ void RclMain::showCronTool(bool modal) } } +void RclMain::showRTITool() +{ + showRTITool(false); +} +void RclMain::execRTITool() +{ + showRTITool(true); +} +void RclMain::showRTITool(bool modal) +{ + LOGDEB(("showRTITool()\n")); + if (rtiTool == 0) { + rtiTool = new RTIToolW(0); + connect(new QShortcut(quitKeySeq, rtiTool), SIGNAL (activated()), + this, SLOT (fileExit())); + } else { + // Close and reopen, in hope that makes us visible... + rtiTool->close(); + } + if (modal) { + rtiTool->exec(); + rtiTool->setModal(false); + } else { + rtiTool->show(); + } +} + void RclMain::showUIPrefs() { if (uiprefs == 0) { diff --git a/src/qtgui/rclmain_w.h b/src/qtgui/rclmain_w.h index 26243c41..0cf4b192 100644 --- a/src/qtgui/rclmain_w.h +++ b/src/qtgui/rclmain_w.h @@ -36,6 +36,7 @@ class ExecCmd; class Preview; class ResTable; class CronToolW; +class RTIToolW; #include "ui_rclmain.h" @@ -58,6 +59,7 @@ public: indexConfig(0), indexSched(0), cronTool(0), + rtiTool(0), spellform(0), periodictimer(0), restable(0), @@ -96,6 +98,8 @@ public slots: virtual void execIndexConfig(); virtual void showCronTool(); virtual void execCronTool(); + virtual void showRTITool(); + virtual void execRTITool(); virtual void showIndexSched(); virtual void execIndexSched(); virtual void setUIPrefs(); @@ -144,6 +148,7 @@ private: ConfIndexW *indexConfig; IdxSchedW *indexSched; CronToolW *cronTool; + RTIToolW *rtiTool; SpellW *spellform; QTimer *periodictimer; ResTable *restable; @@ -169,6 +174,7 @@ private: virtual void showIndexConfig(bool modal); virtual void showIndexSched(bool modal); virtual void showCronTool(bool modal); + virtual void showRTITool(bool modal); }; #endif // RCLMAIN_W_H diff --git a/src/qtgui/recoll.pro.in b/src/qtgui/recoll.pro.in index c418014b..eb93f80a 100644 --- a/src/qtgui/recoll.pro.in +++ b/src/qtgui/recoll.pro.in @@ -16,6 +16,7 @@ HEADERS += \ rclmain_w.h \ reslist.h \ restable.h \ + rtitool.h \ searchclause_w.h \ spell_w.h \ ssearch_w.h \ @@ -36,6 +37,7 @@ SOURCES += \ rclmain_w.cpp \ reslist.cpp \ restable.cpp \ + rtitool.cpp \ searchclause_w.cpp \ spell_w.cpp \ ssearch_w.cpp \ @@ -52,6 +54,7 @@ FORMS = \ listdialog.ui \ rclmain.ui \ restable.ui \ + rtitool.ui \ spell.ui \ ssearchb.ui \ uiprefs.ui \ diff --git a/src/qtgui/rtitool.cpp b/src/qtgui/rtitool.cpp new file mode 100644 index 00000000..426b0ebf --- /dev/null +++ b/src/qtgui/rtitool.cpp @@ -0,0 +1,172 @@ +/* Copyright (C) 2005 J.F.Dockes + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +#include "autoconfig.h" + +#include +#include +#include +#include + +#include +using std::string; + +#include +#include + +#include "recoll.h" +#include "rtitool.h" +#include "smallut.h" +#include "pathut.h" +#include "copyfile.h" +#include "readfile.h" +#include "execmd.h" + +static const char *rautostartfile = ".config/autostart/recollindex.desktop"; + +// Just in case we don't find the file in the shared dir, have a +// default text ready +static const char *desktopfiletext = + "[Desktop Entry]\n" + "Name=Recoll real time indexer\n" + "Comment=Runs in background to extract and index text from modified " + "documents\n" + "Icon=system-run\n" + "Exec=recollindex -w 60 -m\n" + "Terminal=false\n" + "TerminalOptions=\n" + "Type=Application\n" + "Categories=Utility;Filesystem;Database;\n" + "NoDisplay=true\n" + "X-GNOME-Autostart-enabled=true\n" + "X-KDE-autostart-after=panel\n" + "X-KDE-UniqueApplet=true\n" + ; + +void RTIToolW::init() +{ + connect(this->sesCB, SIGNAL(clicked(bool)), + this, SLOT(sesclicked(bool))); + string autostartfile = path_cat(path_home(), rautostartfile); + if (access(autostartfile.c_str(), 0) == 0) { + sesCB->setChecked(true); + } +} + +void RTIToolW::sesclicked(bool on) +{ + nowCB->setEnabled(on); + if (!on) + nowCB->setChecked(false); +} + +void RTIToolW::accept() +{ + bool exitdial = false; + string autostartfile = path_cat(path_home(), rautostartfile); + + if (sesCB->isChecked()) { + // Setting up daemon indexing autostart + + if (::access(autostartfile.c_str(), 0) == 0) { + QString msg = tr("Replacing: ") + + QString::fromLocal8Bit(autostartfile.c_str()); + + QMessageBox::Button rep = + QMessageBox::question(this, tr("Replacing file"), msg, + QMessageBox::Ok | QMessageBox::Cancel); + if (rep != QMessageBox::Ok) { + goto out; + } + } + + string text; + if (theconfig) { + string sourcefile = path_cat(theconfig->getDatadir(), "examples"); + sourcefile = path_cat(sourcefile, "recollindex.desktop"); + if (::access(sourcefile.c_str(), 0) == 0) { + file_to_string(sourcefile, text); + } + } + if (text.empty()) + text = desktopfiletext; + + int fd = ::open(autostartfile.c_str(), O_WRONLY|O_CREAT, 0644); + if (fd < 0 || ::write(fd, text.c_str(), size_t(text.size())) + != ssize_t(text.size()) || ::close(fd) != 0) { + if (fd >=0) + ::close(fd); + QString msg = tr("Can't create: ") + + QString::fromLocal8Bit(autostartfile.c_str()); + QMessageBox::warning(0, tr("Warning"), msg, QMessageBox::Ok); + return; + } + ::close(fd); + + if (nowCB->isChecked()) { + ExecCmd cmd; + list args; + int status; + + args.push_back("-m"); + args.push_back("-w"); + args.push_back("0"); + status = cmd.doexec("recollindex", args, 0, 0); + if (status) { + QMessageBox::warning(0, tr("Warning"), + tr("Could not execute recollindex"), + QMessageBox::Ok); + goto out; + } + } + + exitdial = true; + } else { + // Turning autostart off + if (::access(autostartfile.c_str(), 0) == 0) { + QString msg = tr("Deleting: ") + + QString::fromLocal8Bit(autostartfile.c_str()); + + QMessageBox::Button rep = + QMessageBox::question(this, tr("Deleting file"), msg, + QMessageBox::Ok | QMessageBox::Cancel); + if (rep == QMessageBox::Ok) { + exitdial = true; + unlink(autostartfile.c_str()); + if (theconfig) { + Pidfile pidfile(theconfig->getPidfile()); + pid_t pid; + if ((pid = pidfile.open()) != 0) { + QMessageBox::Button rep = + QMessageBox::question(this, + tr("Removing autostart"), + tr("Autostart file deleted. Kill current process too ?"), + QMessageBox::Yes | QMessageBox::No); + if (rep == QMessageBox::Yes) { + kill(pid, SIGTERM); + } + } + } + } + } else { + exitdial = true; + } + } + +out: + if (exitdial) + QDialog::accept(); +} diff --git a/src/qtgui/firstidx.cpp b/src/qtgui/rtitool.h similarity index 64% rename from src/qtgui/firstidx.cpp rename to src/qtgui/rtitool.h index c760f990..8b64e890 100644 --- a/src/qtgui/firstidx.cpp +++ b/src/qtgui/rtitool.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2005 J.F.Dockes +/* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -14,4 +14,28 @@ * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "autoconfig.h" +#ifndef _RTITOOL_W_H_INCLUDED_ +#define _RTITOOL_W_H_INCLUDED_ + +#include "ui_rtitool.h" + +class QPushButton; + +class RTIToolW : public QDialog, public Ui::RTIToolW { + Q_OBJECT + public: + RTIToolW(QWidget * parent = 0) + : QDialog(parent) + { + setupUi(this); + init(); + } +public slots: + void sesclicked(bool); + void accept(); +private: + void init(); +}; + + +#endif /* _RTITOOL_W_H_INCLUDED_ */ diff --git a/src/qtgui/rtitool.ui b/src/qtgui/rtitool.ui new file mode 100644 index 00000000..2e8bed3e --- /dev/null +++ b/src/qtgui/rtitool.ui @@ -0,0 +1,123 @@ + + + RTIToolW + + + + 0 + 0 + 409 + 182 + + + + Real time indexing automatic start + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Recoll</span> indexing can be set up to run as a daemon, updating the index as files change, in real time. You gain an always up to date index, but system resources are used permanently.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html> + + + true + + + + + + + Start indexing daemon with my desktop session. + + + + + + + + + Qt::Horizontal + + + + 28 + 20 + + + + + + + + false + + + + 1 + 0 + + + + Also start indexing daemon right now. + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + RTIToolW + accept() + + + 204 + 159 + + + 204 + 90 + + + + + buttonBox + rejected() + RTIToolW + reject() + + + 204 + 159 + + + 204 + 90 + + + + + diff --git a/src/recollinstall.in b/src/recollinstall.in index 2b56c7d2..0cd2827a 100755 --- a/src/recollinstall.in +++ b/src/recollinstall.in @@ -111,6 +111,7 @@ ${INSTALL} -m 0755 desktop/hotrecoll.py \ ${datadir}/recoll/filters/ || exit 1 ${INSTALL} -m 0444 \ + desktop/recollindex.desktop \ sampleconf/mimeconf \ sampleconf/mimeview \ sampleconf/recoll.conf \ diff --git a/src/utils/ecrontab.cpp b/src/utils/ecrontab.cpp index e9043677..fbe16183 100644 --- a/src/utils/ecrontab.cpp +++ b/src/utils/ecrontab.cpp @@ -17,6 +17,8 @@ #ifndef TEST_ECRONTAB #include "autoconfig.h" +#include + #include "ecrontab.h" #include "execmd.h" #include "smallut.h" @@ -126,8 +128,8 @@ bool checkCrontabUnmanaged(const string& marker, const string& data) bool getCrontabSched(const string& marker, const string& id, vector& sched) { - fprintf(stderr, "getCrontabSched: marker[%s], id[%s]\n", - marker.c_str(), id.c_str()); + LOGDEB0(("getCrontabSched: marker[%s], id[%s]\n", + marker.c_str(), id.c_str())); vector lines; if (!eCrontabGetLines(lines)) { // No crontab, answer is no