add import/export list items under Edit menu.
[abby.git] / src / util.cpp
blob0d8229e4550d61894c5df8cd9583f1618cecffe9
1 /*
2 * abby Copyright (C) 2009 Toni Gundogdu.
3 * This file is part of abby.
5 * abby is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * abby is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <QString>
20 #include <QProcess>
21 #include <QMessageBox>
22 #include <QFile>
23 #include <QTranslator>
24 #include <QDir>
25 #include <QTreeWidget>
26 #include <QTextEdit>
27 #include <QDateTime>
28 #include <QListWidget>
29 #include <QClipboard>
30 #include <QCoreApplication>
31 #include <QApplication>
32 #include <QMessageBox>
33 #include <QTextStream>
34 //#include <QDebug>
36 #include "util.h"
38 static QString
39 check_path(const QStringList& paths, const QString& exec) {
40 QList<QString>::const_iterator iter;
41 QString path;
43 for (iter=paths.constBegin();
44 iter!=paths.constEnd();
45 ++iter)
47 QString tmp =
48 QString( "%1/%2" )
49 .arg(QDir::fromNativeSeparators(*iter))
50 .arg(exec);
52 tmp = QDir::toNativeSeparators(tmp);
54 if (QFile::exists(tmp)) {
55 path = tmp;
56 break;
59 return path;
62 static void
63 verify_version_output(
64 const QString& path,
65 QString& version,
66 QString& libVersion,
67 QString& libName,
68 bool *isCcliveFlag)
71 version.clear();
72 libVersion.clear();
73 libName.clear();
75 QProcess proc;
76 proc.setEnvironment(QStringList() << "CCLIVE_NO_CONFIG=1");
77 proc.setProcessChannelMode(QProcess::MergedChannels);
78 proc.start(path, QStringList() << "--version");
80 if (isCcliveFlag)
81 *isCcliveFlag = false;
83 if (!proc.waitForFinished()) {
84 throw NoCcliveException(path,
85 proc.exitCode(), proc.errorString());
87 else {
88 const QString output =
89 QString::fromLocal8Bit( proc.readAll() );
91 const int exitCode =
92 proc.exitCode();
94 if (exitCode == 0) {
95 const QString versionOutput = output;
96 // qDebug() << versionOutput;
98 const QStringList tmp =
99 versionOutput.split("\n", QString::SkipEmptyParts);
101 bool enoughOutputFlag = false;
103 if (tmp.size() >= 1) {
105 const QStringList lst =
106 tmp[0].split(" ", QString::SkipEmptyParts);
108 if (lst.size() >= 6) {
109 if (isCcliveFlag)
110 *isCcliveFlag = (lst[0] == "cclive");
112 version = lst[2];
113 libName = lst[4];
114 libVersion = lst[6];
116 enoughOutputFlag = true;
120 if (!enoughOutputFlag) {
121 throw NoCcliveException(path,
122 QObject::
123 tr("Not c/clive or it is an unsupported "
124 "version of it"));
127 else
128 throw NoCcliveException(path, exitCode, output);
132 void
133 Util::detectCclive(
134 QString& path,
135 QString& version,
136 QString& libVersion,
137 QString& libName,
138 bool *isCcliveFlag)
141 const QStringList env =
142 QProcess::systemEnvironment();
144 QRegExp re("^PATH=(.*)", Qt::CaseInsensitive);
145 env.indexOf(re);
147 const QString capt = re.capturedTexts()[1].simplified();
148 QStringList paths = capt.split(":");
150 if (paths.size() < 2) // w32
151 paths = capt.split(";");
153 if (paths.size() < 2)
154 return;
156 path = check_path(paths, "cclive");
157 if (path.isEmpty())
158 path = check_path(paths, "clive");
160 if (path.isEmpty()) {
161 // Detection from $PATH failed. Prompt user
162 // to specify the path in preferences manually.
163 throw NoCcliveException(
164 QObject::tr(
165 "Neither cclive or clive not was found in the path.\n"
166 "Please specify the path to either command in the\n"
167 "preferences."
171 else {
172 // Check --version output.
173 verify_version_output(
174 path,
175 version,
176 libVersion,
177 libName,
178 isCcliveFlag
183 void
184 Util::verifyCclivePath(
185 const QString& path,
186 QString& version,
187 QString& libVersion,
188 QString& libName,
189 bool *isCcliveFlag/*=NULL*/)
191 verify_version_output(
192 path,
193 version,
194 libVersion,
195 libName,
196 isCcliveFlag
200 void
201 Util::checkAllItems(
202 const QTreeWidget *w,
203 const Qt::CheckState& st,
204 const int column/*=0*/)
206 QTreeWidgetItemIterator iter(const_cast<QTreeWidget*>(w));
208 while (*iter) {
209 if ((*iter)->childCount() == 0)
210 (*iter)->setCheckState(column, st);
211 ++iter;
215 void
216 Util::invertAllCheckableItems(
217 const QTreeWidget *w,
218 const int column/*=0*/)
220 QTreeWidgetItemIterator iter(const_cast<QTreeWidget*>(w));
221 while (*iter) {
222 if ((*iter)->childCount() == 0) {
223 (*iter)->setCheckState(column,
224 (*iter)->checkState(column) == Qt::Checked
225 ? Qt::Unchecked
226 : Qt::Checked
229 ++iter;
233 void
234 Util::appendLog(const QTextEdit* w, const QString& s) {
235 QDateTime now = QDateTime::currentDateTime();
236 QString dt = now.toString(Qt::ISODate);
237 const_cast<QTextEdit*>(w)->append(dt+": "+s);
241 Util::countItems(const QTreeWidget *w) {
242 int count = 0;
243 QTreeWidgetItemIterator iter(const_cast<QTreeWidget*>(w));
244 while (*iter) {
245 ++count;
246 ++iter;
248 return count;
251 void
252 Util::addItem(const QListWidget *w, QString lnk) {
253 lnk = lnk.simplified();
255 if (lnk.isEmpty())
256 return;
258 if (!lnk.startsWith("http://", Qt::CaseInsensitive))
259 lnk.insert(0, "http://");
261 QList<QListWidgetItem *> matched =
262 w->findItems(lnk, Qt::MatchExactly);
264 if (matched.size() == 0)
265 const_cast<QListWidget*>(w)->addItem(lnk);
268 void
269 Util::removeSelectedItems(const QWidget *parent, const QListWidget *w) {
270 QList<QListWidgetItem *> s = w->selectedItems();
272 const int size = s.size();
274 if (!size)
275 return;
277 if (QMessageBox::warning(
278 const_cast<QWidget*>(parent),
279 QCoreApplication::applicationName(),
280 QObject::tr("Really remove the selected links?"),
281 QMessageBox::Yes|QMessageBox::No, QMessageBox::No)
282 == QMessageBox::No)
284 return;
287 for (int i=0; i<size; ++i)
288 delete const_cast<QListWidget*>(w)->takeItem( w->row(s[i]) );
291 void
292 Util::clearItems(const QWidget *parent, const QListWidget *w) {
293 if (w->count() == 0)
294 return;
296 if (QMessageBox::warning(
297 const_cast<QWidget*>(parent),
298 QCoreApplication::applicationName(),
299 QObject::tr("Really clear list?"),
300 QMessageBox::Yes|QMessageBox::No, QMessageBox::No)
301 == QMessageBox::No)
303 return;
306 const_cast<QListWidget*>(w)->clear();
309 void
310 Util::paste(const QListWidget *w) {
311 QClipboard *cb = QApplication::clipboard();
312 QStringList lst = cb->text().split("\n");
313 const int size = lst.size();
315 for (int i=0; i<size; ++i)
316 Util::addItem(w, lst[i]);
319 static void
320 msgbox_crit(
321 const QWidget *parent,
322 const QString msg)
324 QMessageBox::critical(
325 const_cast<QWidget*>(parent),
326 QCoreApplication::applicationName(),
327 msg);
330 bool
331 Util::importItems(
332 const QWidget *parent,
333 QStringList& lst,
334 const QString& path)
336 QFile file(path);
338 if (!file.open(QFile::ReadOnly | QIODevice::Text)) {
339 msgbox_crit(parent,
340 QString( QObject::tr("File open error %1") ).arg( file.error() ));
341 return false;
344 QTextStream f(&file);
346 while (!f.atEnd())
347 lst.append(f.readLine().simplified());
349 return !lst.empty();
352 bool
353 Util::exportItems(
354 const QWidget *parent,
355 const QListWidget *w,
356 const QString& path,
357 const bool& append)
359 QFile file(path);
361 QFlags<QIODevice::OpenModeFlag> flags =
362 (QFile::WriteOnly | QIODevice::Text);
364 flags |=
365 append
366 ? QIODevice::Append
367 : QIODevice::Truncate;
369 if (!file.open(flags)) {
370 msgbox_crit(parent,
371 QString( QObject::tr("File open error %1") ).arg( file.error() ));
372 return false;
375 QTextStream out(&file);
377 const int size = w->count();
378 for (int i=0; i<size; ++i)
379 out << w->item(i)->text() << "\n";
381 return true;
384 NoCcliveException::NoCcliveException(const QString& errmsg)
385 : errmsg(errmsg)
389 static const QString defmsg =
390 QObject::tr("Undefined path to c/clive command");
392 NoCcliveException::NoCcliveException(
393 const QString& path,
394 const QString& errmsg)
395 : errmsg(defmsg)
397 if (!path.isEmpty()) {
398 this->errmsg =
399 QString("error: %1:\n%2").arg(path).arg(errmsg);
403 NoCcliveException::NoCcliveException(
404 const QString& path,
405 const int& exitCode,
406 const QString& output)
407 : errmsg(defmsg)
409 if (!path.isEmpty()) {
410 this->errmsg = QString(
411 QObject::
412 tr("%1 exited with %2:\n%3")
413 .arg(path)
414 .arg(exitCode)
415 .arg(output)
420 const QString&
421 NoCcliveException::what() const {
422 return errmsg;