added function to save multiple result selection in restable into files

This commit is contained in:
Jean-Francois Dockes
2013-04-28 09:48:40 +02:00
parent 884234784d
commit caffe8b6f3
7 changed files with 288 additions and 46 deletions
+140
View File
@@ -0,0 +1,140 @@
/* 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 <stdio.h>
#include <string>
#include <set>
#include <sstream>
using namespace std;
#include <QWidget>
#include <QFileDialog>
#include <QMessageBox>
#include "recoll.h"
#include "multisave.h"
#include "smallut.h"
#include "debuglog.h"
#include "pathut.h"
#include "internfile.h"
const unsigned int maxlen = 200;
void multiSave(QWidget *p, vector<Rcl::Doc>& docs)
{
QFileDialog fdialog(p, p->tr("Create or choose save directory"));
fdialog.setAcceptMode(QFileDialog::AcceptSave);
fdialog.setFileMode(QFileDialog::Directory);
fdialog.setOption(QFileDialog::ShowDirsOnly);
if (fdialog.exec() == 0)
return;
QStringList dirl = fdialog.selectedFiles();
if (dirl.size() != 1) {
// Can't happen ?
QMessageBox::warning(0, "Recoll",
p->tr("Choose exactly one directory"));
return;
}
string dir((const char *)dirl[0].toLocal8Bit());
LOGDEB2(("multiSave: got dir %s\n", dir.c_str()));
/* Save doc to files in target directory. Issues:
- It is quite common to have docs in the array with the save
file names, e.g. all messages in a folder have the save file
name (the folder's).
- There is no warranty that the ipath is going to be acceptable
as a file name or interesting at all. We don't use it.
- We have to make sure the names don't end up too long.
If collisions occur, we add a numeric infix (e.g. somefile.23.pdf).
We never overwrite existing files and don't give the user an
option to do it (they can just as well save to an empty
directory and use the file manager to accomplish whatever they
want).
We don't try hard to protect against race-conditions
though. The existing file names are read before beginning the
save sequence, and collisions appearing after this are handled
by aborting. There is a window between existence check and creation
because idoctofile does not use O_EXCL
*/
set<string> existingNames;
string reason;
if (!readdir(dir, reason, existingNames)) {
QMessageBox::warning(0, "Recoll",
p->tr("Could not read directory: ") +
QString::fromLocal8Bit(reason.c_str()));
return;
}
set<string> toBeCreated;
vector<string> filenames;
for (vector<Rcl::Doc>::iterator it = docs.begin(); it != docs.end(); it++) {
string utf8fn;
it->getmeta(Rcl::Doc::keyfn, &utf8fn);
string suffix = path_suffix(utf8fn);
if (suffix.empty() || suffix.size() > 10) {
suffix = theconfig->getSuffixFromMimeType(it->mimetype);
}
string simple = path_basename(utf8fn, suffix);
if (simple.empty())
simple = "rclsave";
if (simple.size() > maxlen) {
simple = simple.substr(0, maxlen);
}
for (int vers = 0; ; vers++) {
ostringstream ss;
ss << simple;
if (vers)
ss << "." << vers;
if (!suffix.empty())
ss << suffix;
string fn =
(const char *)QString::fromUtf8(ss.str().c_str()).toLocal8Bit();
if (existingNames.find(fn) == existingNames.end() &&
toBeCreated.find(fn) == toBeCreated.end()) {
toBeCreated.insert(fn);
filenames.push_back(fn);
break;
}
}
}
for (unsigned int i = 0; i != docs.size(); i++) {
string fn = path_cat(dir, filenames[i]);
if (access(fn.c_str(), 0) == 0) {
QMessageBox::warning(0, "Recoll",
p->tr("Unexpected file name collision, "
"cancelling."));
return;
}
// There is still a race condition here, should we care ?
TempFile temp;// not used
if (!FileInterner::idocToFile(temp, fn, theconfig, docs[i])) {
QMessageBox::warning(0, "Recoll",
p->tr("Cannot extract document: ") +
QString::fromLocal8Bit(docs[i].url.c_str()) +
" | " +
QString::fromLocal8Bit(docs[i].ipath.c_str())
);
}
}
}
+24
View File
@@ -0,0 +1,24 @@
/*
* 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 _MULTISAVE_W_H_INCLUDED_
#define _MULTISAVE_W_H_INCLUDED_
#include <QWidget>
extern void multiSave(QWidget *parent, vector<Rcl::Doc>& docs);
#endif /* _MULTISAVE_W_H_INCLUDED_ */
-1
View File
@@ -68,7 +68,6 @@ FORMS = \
firstidx.ui \
idxsched.ui \
listdialog.ui \
multisave.ui \
ptrans.ui \
rclmain.ui \
restable.ui \
+24
View File
@@ -47,6 +47,7 @@
#include "indexer.h"
#include "respopup.h"
#include "rclmain_w.h"
#include "multisave.h"
static const QKeySequence quitKeySeq("Ctrl+q");
static const QKeySequence closeKeySeq("Ctrl+w");
@@ -759,6 +760,8 @@ void ResTable::createPopupMenu(const QPoint& pos)
QMenu *popup =
ResultPopup::create(this, m_ismainres? ResultPopup::isMain : 0,
m_model->getDocSource(), m_detaildoc);
popup->addAction(this->tr("Save selection to files"),
this, SLOT(menuSaveSelection()));
popup->popup(mapToGlobal(pos));
}
}
@@ -780,6 +783,27 @@ void ResTable::menuSaveToFile()
emit docSaveToFileClicked(m_detaildoc);
}
void ResTable::menuSaveSelection()
{
if (m_model == 0 || m_model->getDocSource().isNull())
return;
QModelIndexList indexl = tableView->selectionModel()->selectedRows();
vector<Rcl::Doc> v;
for (int i = 0; i < indexl.size(); i++) {
Rcl::Doc doc;
if (m_model->getDocSource()->getDoc(indexl[i].row(), doc))
v.push_back(doc);
}
if (v.size() == 0) {
return;
} else if (v.size() == 1) {
emit docSaveToFileClicked(v[0]);
} else {
multiSave(this, v);
}
}
void ResTable::menuPreviewParent()
{
if (m_detaildocnum >= 0 && m_model &&
+1
View File
@@ -134,6 +134,7 @@ public slots:
virtual void createPopupMenu(const QPoint& pos);
virtual void menuPreview();
virtual void menuSaveToFile();
virtual void menuSaveSelection();
virtual void menuEdit();
virtual void menuCopyFN();
virtual void menuCopyURL();