From b9c64e8591a29088ce8e4712f882053c91b9ca7e Mon Sep 17 00:00:00 2001 From: Jean-Francois Dockes Date: Fri, 2 Dec 2011 19:15:24 +0100 Subject: [PATCH] Gui: help for cron etc. 1st checkpoint --- src/common/rclconfig.cpp | 2 +- src/desktop/recollindex.desktop | 13 +++ src/qtgui/crontool.cpp | 94 ++++++++++++++++++++ src/qtgui/crontool.h | 48 ++++++++++ src/qtgui/crontool.ui | 150 ++++++++++++++++++++++++++++++++ src/qtgui/firstidx.cpp | 17 ++++ src/qtgui/firstidx.h | 32 +++++++ src/qtgui/firstidx.ui | 133 ++++++++++++++++++++++++++++ src/qtgui/idxsched.h | 33 +++++++ src/qtgui/idxsched.ui | 107 +++++++++++++++++++++++ src/qtgui/rclmain_w.cpp | 131 ++++++++++++++++++++-------- src/qtgui/rclmain_w.h | 33 ++++++- src/qtgui/recoll.pro.in | 9 +- src/utils/ecrontab.cpp | 141 ++++++++++++++++++++++-------- src/utils/ecrontab.h | 6 ++ 15 files changed, 868 insertions(+), 81 deletions(-) create mode 100644 src/desktop/recollindex.desktop create mode 100644 src/qtgui/crontool.cpp create mode 100644 src/qtgui/crontool.h create mode 100644 src/qtgui/crontool.ui create mode 100644 src/qtgui/firstidx.cpp create mode 100644 src/qtgui/firstidx.h create mode 100644 src/qtgui/firstidx.ui create mode 100644 src/qtgui/idxsched.h create mode 100644 src/qtgui/idxsched.ui diff --git a/src/common/rclconfig.cpp b/src/common/rclconfig.cpp index 9b429d4f..56b67fea 100644 --- a/src/common/rclconfig.cpp +++ b/src/common/rclconfig.cpp @@ -140,7 +140,7 @@ RclConfig::RclConfig(const string *argcnf) // 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 must exist" + m_reason = "Explicitly specified configuration directory must exist" " (won't be automatically created)"; return; } diff --git a/src/desktop/recollindex.desktop b/src/desktop/recollindex.desktop new file mode 100644 index 00000000..ef75ea26 --- /dev/null +++ b/src/desktop/recollindex.desktop @@ -0,0 +1,13 @@ +[Desktop Entry] +Name=Recoll real time indexer +Comment=Runs in background to extract and index text from modified documents +Icon=system-run +Exec=recollindex -w 60 -m +Terminal=false +TerminalOptions= +Type=Application +Categories=Utility;Filesystem;Database; +NoDisplay=true +X-GNOME-Autostart-enabled=true +X-KDE-autostart-after=panel +X-KDE-UniqueApplet=true diff --git a/src/qtgui/crontool.cpp b/src/qtgui/crontool.cpp new file mode 100644 index 00000000..8f66df9f --- /dev/null +++ b/src/qtgui/crontool.cpp @@ -0,0 +1,94 @@ +/* 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 "recoll.h" +#include "crontool.h" +#include "ecrontab.h" +#include "smallut.h" + +static string marker; + +static string idstring(const string& confdir) +{ + // Quote conf dir, there may be spaces and whatelse in there + return string("RECOLL_CONFDIR=") + escapeShell(confdir); +} + +void CronToolW::init() +{ + marker = "RCLCRON_RCLINDEX="; + + enableButton = new QPushButton(tr("Enable")); + disableButton = new QPushButton(tr("Disable")); + buttonBox->addButton(enableButton, QDialogButtonBox::ActionRole); + buttonBox->addButton(disableButton, QDialogButtonBox::ActionRole); + connect(enableButton, SIGNAL(clicked()), this, SLOT(enableCron())); + connect(disableButton, SIGNAL(clicked()), this, SLOT(disableCron())); + + // Try to read the current values + if (!theconfig) + return; + string id = idstring(theconfig->getConfDir()); + vector sched; + if (getCrontabSched(marker, id, sched)) { + minsLE->setText(QString::fromAscii(sched[0].c_str())); + hoursLE->setText(QString::fromAscii(sched[1].c_str())); + daysLE->setText(QString::fromAscii(sched[4].c_str())); + } +} + +void CronToolW::enableCron() +{ + changeCron(true); +} +void CronToolW::disableCron() +{ + changeCron(false); +} + +void CronToolW::changeCron(bool enable) +{ + if (!theconfig) + return; + + string id = idstring(theconfig->getConfDir()); + string cmd("recollindex -m -w 60"); + + string reason; + + if (!enable) { + editCrontab(marker, id, "", "", reason); + accept(); + } else { + string mins((const char *)minsLE->text().toAscii()); + string hours((const char *)hoursLE->text().toAscii()); + string days((const char *)daysLE->text().toAscii()); + string sched = mins + " " + hours + " * * " + days; + if (editCrontab(marker, id, sched, cmd, reason)) { + accept(); + } else { + QMessageBox::warning(0, "Recoll", + tr("Error installing cron entry. Bad syntax in fields ? ")); + } + } +} diff --git a/src/qtgui/crontool.h b/src/qtgui/crontool.h new file mode 100644 index 00000000..8378b809 --- /dev/null +++ b/src/qtgui/crontool.h @@ -0,0 +1,48 @@ +/* + * 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. + */ +#ifndef _CRONTAB_W_H_INCLUDED_ +#define _CRONTAB_W_H_INCLUDED_ + +#include "ui_crontool.h" + +class QPushButton; + +class CronToolW : public QDialog, public Ui::CronToolW { + Q_OBJECT + public: + CronToolW(QWidget * parent = 0) + : QDialog(parent), + enableButton(0), + disableButton(0) + { + setupUi(this); + init(); + } + QPushButton *enableButton; + QPushButton *disableButton; + +private slots: + void enableCron(); + void disableCron(); +private: + void init(); + void changeCron(bool enable); + +}; + + +#endif /* _CRONTAB_W_H_INCLUDED_ */ diff --git a/src/qtgui/crontool.ui b/src/qtgui/crontool.ui new file mode 100644 index 00000000..38bee435 --- /dev/null +++ b/src/qtgui/crontool.ui @@ -0,0 +1,150 @@ + + + CronToolW + + + + 0 + 0 + 465 + 365 + + + + Cron Dialog + + + + + + + + <!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> batch indexing schedule (cron) </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;">Each field can contain a wildcard (*), a single numeric value, comma-separated lists (1,3,5) and ranges (1-7). More generally, the fields will be used <span style=" font-style:italic;">as is</span> inside the crontab file, and the full crontab syntax can be used, see crontab(5).</p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br />For example, entering <span style=" font-family:'Courier New,courier';">*</span> in <span style=" font-style:italic;">Days, </span><span style=" font-family:'Courier New,courier';">12,19</span> in <span style=" font-style:italic;">Hours</span> and <span style=" font-family:'Courier New,courier';">15</span> in <span style=" font-style:italic;">Minutes</span> would start recollindex every day at 12:15 AM and 7:15 PM</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;">A schedule with very frequent activations is probably less efficient than real time indexing.</p></body></html> + + + true + + + + + + + + + Days of week (* or 0-7, 0 or 7 is Sunday) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + Hours (* or 0-23) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + 0 + 0 + + + + Minutes (0-59) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + + + <!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;">Click <span style=" font-style:italic;">Disable</span> to stop automatic batch indexing, <span style=" font-style:italic;">Enable</span> to activate it, <span style=" font-style:italic;">Cancel</span> to change nothing.</p></body></html> + + + true + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel + + + + + + + + + buttonBox + accepted() + CronToolW + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + CronToolW + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qtgui/firstidx.cpp b/src/qtgui/firstidx.cpp new file mode 100644 index 00000000..c760f990 --- /dev/null +++ b/src/qtgui/firstidx.cpp @@ -0,0 +1,17 @@ +/* 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" diff --git a/src/qtgui/firstidx.h b/src/qtgui/firstidx.h new file mode 100644 index 00000000..620ada9f --- /dev/null +++ b/src/qtgui/firstidx.h @@ -0,0 +1,32 @@ +/* + * 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. + */ +#ifndef _FIRSTIDX_H_INCLUDED_ +#define _FIRSTIDX_H_INCLUDED_ + +#include "ui_firstidx.h" + +class FirstIdxDialog : public QDialog, public Ui::FirstIdxDialog { + Q_OBJECT + public: + FirstIdxDialog(QWidget * parent = 0) + : QDialog(parent) + { + setupUi(this); + } +}; + +#endif /* _FIRSTIDX_H_INCLUDED_ */ diff --git a/src/qtgui/firstidx.ui b/src/qtgui/firstidx.ui new file mode 100644 index 00000000..f9e81d1b --- /dev/null +++ b/src/qtgui/firstidx.ui @@ -0,0 +1,133 @@ + + + FirstIdxDialog + + + + 0 + 0 + 431 + 457 + + + + First indexing setup + + + + + + + + <!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;">It appears that the index for this configuration does not exist.</span><br /><br />If you just want to index your home directory with a set of reasonable defaults, press the <span style=" font-style:italic;">Start indexing now</span> button. You will be able to adjust the details later. </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;">If you want more control, use the following links to adjust the indexing configuration and schedule.</p></body></html> + + + Qt::RichText + + + true + + + + + + + Indexing configuration + + + 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. + + + + + + + Indexing schedule + + + This will let you chose between batch and real-time indexing, and set up an automatic schedule for batch indexing (using cron). + + + + + + + Start indexing now + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + FirstIdxDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + FirstIdxDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + runidxPB + clicked() + FirstIdxDialog + accept() + + + 215 + 400 + + + 215 + 228 + + + + + diff --git a/src/qtgui/idxsched.h b/src/qtgui/idxsched.h new file mode 100644 index 00000000..9db8a443 --- /dev/null +++ b/src/qtgui/idxsched.h @@ -0,0 +1,33 @@ +/* + * 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. + */ +#ifndef _IDXSCHED_H_INCLUDED_ +#define _IDXSCHED_H_INCLUDED_ + +#include "ui_idxsched.h" + +class IdxSchedW : public QDialog, public Ui::IdxSchedW { + Q_OBJECT + public: + IdxSchedW(QWidget * parent = 0) + : QDialog(parent) + { + setupUi(this); + } +}; + + +#endif /* _IDXSCHED_H_INCLUDED_ */ diff --git a/src/qtgui/idxsched.ui b/src/qtgui/idxsched.ui new file mode 100644 index 00000000..95fb0f86 --- /dev/null +++ b/src/qtgui/idxsched.ui @@ -0,0 +1,107 @@ + + + IdxSchedW + + + + 0 + 0 + 400 + 300 + + + + Index scheduling setup + + + + + + + + <!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 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> + + + Qt::AutoText + + + true + + + + + + + Start cron scheduling tool + + + The tool will let you decide at what time indexing should run and will install a crontab entry. + + + + + + + Real time indexing start up options + + + Decide if real time indexing will be started when you log in + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + IdxSchedW + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + IdxSchedW + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/src/qtgui/rclmain_w.cpp b/src/qtgui/rclmain_w.cpp index f22a4eb2..3ffbaf50 100644 --- a/src/qtgui/rclmain_w.cpp +++ b/src/qtgui/rclmain_w.cpp @@ -69,6 +69,9 @@ using std::pair; #include "confguiindex.h" #include "restable.h" #include "listdialog.h" +#include "firstidx.h" +#include "idxsched.h" +#include "crontool.h" using namespace confgui; @@ -91,14 +94,8 @@ void RclMain::init() }; DocSequence::set_translations((const char *)tr("sorted").toUtf8(), (const char *)tr("filtered").toUtf8()); - curPreview = 0; - asearchform = 0; - uiprefs = 0; - indexConfig = 0; - spellform = 0; - m_idxStatusAck = false; + periodictimer = new QTimer(this); - m_periodicToggle = 0; // At least some versions of qt4 don't display the status bar if // it's not created here. @@ -340,48 +337,34 @@ void RclMain::resultCount(int n) // the database and talk to the user if we can't void RclMain::initDbOpen() { - bool needindexconfig = false; bool nodb = false; string reason; bool maindberror; if (!maybeOpenDb(reason, true, &maindberror)) { nodb = true; if (maindberror) { - switch (QMessageBox:: - question - (this, "Recoll", - qApp->translate("Main", "Could not open database in ") + - QString::fromLocal8Bit(theconfig->getDbDir().c_str()) + - qApp->translate("Main", - ".\n" - "Click Cancel if you want to edit the configuration file before indexing starts, or Ok to let it proceed."), - "Ok", "Cancel", 0, 0)) { - - case 0: // Ok: indexing is going to start. - start_indexing(true); - break; - - case 1: // Cancel - needindexconfig = true; - break; - } + FirstIdxDialog fidia(this); + connect(fidia.idxconfCLB, SIGNAL(clicked()), + this, SLOT(execIndexConfig())); + connect(fidia.idxschedCLB, SIGNAL(clicked()), + this, SLOT(execIndexSched())); + connect(fidia.runidxPB, SIGNAL(clicked()), + this, SLOT(toggleIndexing())); + fidia.exec(); + // Don't open adv search or run cmd line search in this case. + return; } else { QMessageBox::warning(0, "Recoll", tr("Could not open external index. Db not open. Check external indexes list.")); } } - if (needindexconfig) { - startIndexingAfterConfig = 1; - showIndexConfig(); - } else { - if (prefs.startWithAdvSearchOpen) - showAdvSearchDialog(); - // If we have something in the search entry, it comes from a - // command line argument - if (!nodb && sSearch->hasSearchString()) - QTimer::singleShot(0, sSearch, SLOT(startSimpleSearch())); - } + if (prefs.startWithAdvSearchOpen) + showAdvSearchDialog(); + // If we have something in the search entry, it comes from a + // command line argument + if (!nodb && sSearch->hasSearchString()) + QTimer::singleShot(0, sSearch, SLOT(startSimpleSearch())); } void RclMain::focusToSearch() @@ -686,6 +669,14 @@ void RclMain::showSpellDialog() } void RclMain::showIndexConfig() +{ + showIndexConfig(false); +} +void RclMain::execIndexConfig() +{ + showIndexConfig(true); +} +void RclMain::showIndexConfig(bool modal) { LOGDEB(("showIndexConfig()\n")); if (indexConfig == 0) { @@ -697,7 +688,71 @@ void RclMain::showIndexConfig() indexConfig->close(); indexConfig->reloadPanels(); } - indexConfig->show(); + if (modal) { + indexConfig->exec(); + indexConfig->setModal(false); + } else { + indexConfig->show(); + } +} + +void RclMain::showIndexSched() +{ + showIndexSched(false); +} +void RclMain::execIndexSched() +{ + showIndexSched(true); +} +void RclMain::showIndexSched(bool modal) +{ + LOGDEB(("showIndexSched()\n")); + if (indexSched == 0) { + indexSched = new IdxSchedW(this); + connect(new QShortcut(quitKeySeq, indexSched), SIGNAL (activated()), + this, SLOT (fileExit())); + connect(indexSched->cronCLB, SIGNAL(clicked()), + this, SLOT(execCronTool())); + connect(indexSched->rtidxCLB, SIGNAL(clicked()), + this, SLOT(execRTITool())); + + } else { + // Close and reopen, in hope that makes us visible... + indexSched->close(); + } + if (modal) { + indexSched->exec(); + indexSched->setModal(false); + } else { + indexSched->show(); + } +} + +void RclMain::showCronTool() +{ + showCronTool(false); +} +void RclMain::execCronTool() +{ + showCronTool(true); +} +void RclMain::showCronTool(bool modal) +{ + LOGDEB(("showCronTool()\n")); + if (cronTool == 0) { + cronTool = new CronToolW(0); + connect(new QShortcut(quitKeySeq, cronTool), SIGNAL (activated()), + this, SLOT (fileExit())); + } else { + // Close and reopen, in hope that makes us visible... + cronTool->close(); + } + if (modal) { + cronTool->exec(); + cronTool->setModal(false); + } else { + cronTool->show(); + } } void RclMain::showUIPrefs() diff --git a/src/qtgui/rclmain_w.h b/src/qtgui/rclmain_w.h index 2c1a6d0c..26243c41 100644 --- a/src/qtgui/rclmain_w.h +++ b/src/qtgui/rclmain_w.h @@ -31,9 +31,11 @@ #include "refcntr.h" #include "pathut.h" +class IdxSchedW; class ExecCmd; class Preview; class ResTable; +class CronToolW; #include "ui_rclmain.h" @@ -49,7 +51,22 @@ class RclMain : public QMainWindow, public Ui::RclMainBase public: RclMain(QWidget * parent = 0) - : QMainWindow(parent), m_sortspecnochange(false) + : QMainWindow(parent), + curPreview(0), + asearchform(0), + uiprefs(0), + indexConfig(0), + indexSched(0), + cronTool(0), + spellform(0), + periodictimer(0), + restable(0), + displayingTable(0), + m_idNoStem(0), + m_idAllStem(0), + m_idxStatusAck(false), + m_sortspecnochange(false), + m_periodicToggle(0) { setupUi(this); init(); @@ -76,6 +93,11 @@ public slots: virtual void showExtIdxDialog(); virtual void showUIPrefs(); virtual void showIndexConfig(); + virtual void execIndexConfig(); + virtual void showCronTool(); + virtual void execCronTool(); + virtual void showIndexSched(); + virtual void execIndexSched(); virtual void setUIPrefs(); virtual void enableNextPage(bool); virtual void enablePrevPage(bool); @@ -120,16 +142,18 @@ private: AdvSearch *asearchform; UIPrefsDialog *uiprefs; ConfIndexW *indexConfig; + IdxSchedW *indexSched; + CronToolW *cronTool; SpellW *spellform; QTimer *periodictimer; ResTable *restable; bool displayingTable; + QAction *m_idNoStem; + QAction *m_idAllStem; vector m_viewers; map m_stemLangToId; vector m_catgbutvec; - QAction * m_idNoStem; - QAction * m_idAllStem; bool m_idxStatusAck; // Did we act on last status? DocSeqFiltSpec m_filtspec; bool m_sortspecnochange; @@ -142,6 +166,9 @@ private: bool next); virtual void setStemLang(const QString& lang); virtual void onSortCtlChanged(); + virtual void showIndexConfig(bool modal); + virtual void showIndexSched(bool modal); + virtual void showCronTool(bool modal); }; #endif // RCLMAIN_W_H diff --git a/src/qtgui/recoll.pro.in b/src/qtgui/recoll.pro.in index 69fe9221..c418014b 100644 --- a/src/qtgui/recoll.pro.in +++ b/src/qtgui/recoll.pro.in @@ -7,6 +7,9 @@ HEADERS += \ advsearch_w.h \ confgui/confgui.h \ confgui/confguiindex.h \ + crontool.h \ + firstidx.h \ + idxsched.h \ listdialog.h \ preview_w.h \ rclhelp.h \ @@ -24,6 +27,7 @@ SOURCES += \ advsearch_w.cpp \ confgui/confgui.cpp \ confgui/confguiindex.cpp \ + crontool.cpp \ guiutils.cpp \ idxthread.cpp \ main.cpp \ @@ -42,10 +46,13 @@ SOURCES += \ FORMS = \ advsearch.ui \ + crontool.ui \ + firstidx.ui \ + idxsched.ui \ listdialog.ui \ rclmain.ui \ restable.ui \ - spell.ui \ + spell.ui \ ssearchb.ui \ uiprefs.ui \ viewaction.ui \ diff --git a/src/utils/ecrontab.cpp b/src/utils/ecrontab.cpp index 8bea776e..e9043677 100644 --- a/src/utils/ecrontab.cpp +++ b/src/utils/ecrontab.cpp @@ -20,9 +20,10 @@ #include "ecrontab.h" #include "execmd.h" #include "smallut.h" +#include "debuglog.h" -bool editCrontab(const string& marker, const string& id, - const string& sched, const string& cmd, string& reason) +// Read crontab file and split it into lines. +static bool eCrontabGetLines(vector& lines) { string crontab; ExecCmd croncmd; @@ -30,21 +31,61 @@ bool editCrontab(const string& marker, const string& id, int status; // Retrieve current crontab contents. An error here means that no - // crontab exists, and is not fatal (just use empty string) + // crontab exists, and is not fatal, but we return a different + // status than for an empty one args.push_back("-l"); if ((status = croncmd.doexec("crontab", args, 0, &crontab))) { + lines.clear(); + return false; + } + + // Split crontab into lines + stringToTokens(crontab, lines, "\n"); + return true; +} + +// Concatenate lines and write crontab +static bool eCrontabWriteFile(const vector& lines, string& reason) +{ + string crontab; + ExecCmd croncmd; + list args; + int status; + + for (vector::const_iterator it = lines.begin(); + it != lines.end(); it++) { + crontab += *it + "\n"; + } + + args.push_back("-"); + if ((status = croncmd.doexec("crontab", args, &crontab, 0))) { + char nbuf[30]; + sprintf(nbuf, "0x%x", status); + reason = string("Exec crontab -l failed: status: ") + nbuf; + return false; + } + return true; +} + +// Add / change / delete entry identified by marker and id +bool editCrontab(const string& marker, const string& id, + const string& sched, const string& cmd, string& reason) +{ + vector lines; + + if (!eCrontabGetLines(lines)) { // Special case: cmd is empty, no crontab, don't create one if (cmd.empty()) return true; } - // Split crontab into lines - vector lines; - stringToTokens(crontab, lines, "\n"); - // Remove old copy if any for (vector::iterator it = lines.begin(); it != lines.end(); it++) { + // Skip comment + if (it->find_first_of("#") == it->find_first_not_of(" \t")) + continue; + if (it->find(marker) != string::npos && it->find(id) != string::npos) { lines.erase(it); @@ -57,42 +98,19 @@ bool editCrontab(const string& marker, const string& id, lines.push_back(nline); } - // Rebuild new crontab and install it - crontab.clear(); - for (vector::iterator it = lines.begin(); - it != lines.end(); it++) { - crontab += *it + "\n"; - } - - args.clear(); - args.push_back("-"); - if ((status = croncmd.doexec("crontab", args, &crontab, 0))) { - char nbuf[30]; - sprintf(nbuf, "0x%x", status); - reason = string("Exec crontab -l failed: status: ") + nbuf; - } + if (!eCrontabWriteFile(lines, reason)) + return false; return true; } bool checkCrontabUnmanaged(const string& marker, const string& data) { - string crontab; - ExecCmd croncmd; - list args; - int status; - - // Retrieve current crontab contents. An error here means that no - // crontab exists. - args.push_back("-l"); - if ((status = croncmd.doexec("crontab", args, 0, &crontab))) { + vector lines; + if (!eCrontabGetLines(lines)) { + // No crontab, answer is no return false; } - - // Split crontab into lines - vector lines; - stringToTokens(crontab, lines, "\n"); - // Scan crontab for (vector::iterator it = lines.begin(); it != lines.end(); it++) { @@ -104,6 +122,38 @@ bool checkCrontabUnmanaged(const string& marker, const string& data) return false; } +/** Retrieve the scheduling for a crontab entry */ +bool getCrontabSched(const string& marker, const string& id, + vector& sched) +{ + fprintf(stderr, "getCrontabSched: marker[%s], id[%s]\n", + marker.c_str(), id.c_str()); + vector lines; + if (!eCrontabGetLines(lines)) { + // No crontab, answer is no + sched.clear(); + return false; + } + string line; + + for (vector::iterator it = lines.begin(); + it != lines.end(); it++) { + // Skip comment + if (it->find_first_of("#") == it->find_first_not_of(" \t")) + continue; + + if (it->find(marker) != string::npos && + it->find(id) != string::npos) { + line = *it; + break; + } + } + + stringToTokens(line, sched); + sched.resize(5); + return true; +} + #else // TEST -> #include @@ -124,7 +174,8 @@ static char *thisprog; static char usage [] = " -a add or replace crontab line \n" -" -a delete crontab line \n" +" -d delete crontab line \n" +" -s get scheduling \n" " -c check for unmanaged lines for string\n" ; static void @@ -140,12 +191,13 @@ static int op_flags; #define OPT_d 0x4 #define OPT_w 0x8 #define OPT_c 0x10 +#define OPT_s 0x20 const string& marker("RCLCRON_RCLINDEX="); // Note of course the -w does not make sense for a cron entry const string& cmd0("recollindex -w "); -const string& id("RECOLL_CONFDIR=/home/dockes/.recoll"); -const string& sched("30 8 * * *"); +const string& id("RECOLL_CONFDIR=\"/home/dockes/.recoll/\""); +const string& sched("30 8 * 1 *"); int main(int argc, char **argv) { @@ -167,6 +219,7 @@ int main(int argc, char **argv) cmd = *(++argv); argc--; goto b1; case 'd': op_flags |= OPT_d; break; + case 's': op_flags |= OPT_s; break; case 'w': op_flags |= OPT_w; if (argc < 2) Usage(); wt = *(++argv); argc--; goto b1; @@ -187,6 +240,18 @@ int main(int argc, char **argv) status = editCrontab(marker, id, sched, cmd, reason); } else if (op_flags & OPT_d) { status = editCrontab(marker, id, sched, "", reason); + } else if (op_flags & OPT_s) { + vector sched; + if (!(status = getCrontabSched(marker, id, sched))) { + cerr << "getCrontabSched failed: " << reason << endl; + exit(1); + } + cout << "sched vec size " << sched.size() << endl; + cout << "mins " << sched[0] << " hours " << sched[1] << + " days of month " << sched[2] << " months " << sched[3] << + " days of week " << sched[4] << endl; + exit(0); + } else if (op_flags & OPT_c) { if ((status = checkCrontabUnmanaged(marker, cmd))) { cerr << "crontab has unmanaged lines for " << cmd << endl; diff --git a/src/utils/ecrontab.h b/src/utils/ecrontab.h index b7a0752e..9f281b94 100644 --- a/src/utils/ecrontab.h +++ b/src/utils/ecrontab.h @@ -33,7 +33,9 @@ */ #include +#include using std::string; +using std::vector; /** Add, replace or delete a command inside a crontab file * @@ -62,4 +64,8 @@ bool editCrontab(const string& marker, const string& id, */ bool checkCrontabUnmanaged(const string& marker, const string& data); +/** Retrieve the scheduling for a crontab entry */ +bool getCrontabSched(const string& marker, const string& id, + vector& sched); + #endif /* _ECRONTAB_H_INCLUDED_ */