00001
00046 #include "downloadobjectdialog.h"
00047 #include "ui_downloadobjectdialog.h"
00048
00049 #include <re_object_recorder/qminizip.h>
00050
00051 #include <ros/service.h>
00052 #include <re_srvs/QueryObjects.h>
00053 #include <re_srvs/SearchObjects.h>
00054 #include <re_srvs/GetObjectBinaryFile.h>
00055
00056 #include <QDebug>
00057 #include <QFileDialog>
00058 #include <QMessageBox>
00059 #include <QtCore>
00060 #include <QProgressDialog>
00061
00062 const QString DOWNLOAD_SERVICE = "/re_comm/get_object_binary_file";
00063 const QString QUERY_SERVICE = "/re_comm/search_objects";
00064
00065 DownloadObjectDialog::DownloadObjectDialog(QWidget *parent) :
00066 QDialog(parent),
00067 ui(new Ui::DownloadObjectDialog)
00068 {
00069 ui->setupUi(this);
00070 ui->downloadDirEdit->setText(QDir::tempPath());
00071 }
00072
00073 DownloadObjectDialog::~DownloadObjectDialog()
00074 {
00075 delete ui;
00076 }
00077
00078 void DownloadObjectDialog::on_cancelButton_clicked() {
00079 emit reject();
00080 }
00081
00082 void DownloadObjectDialog::addTableEntry(QString uid, QString filename, QString fileurl) {
00083 int row = ui->resultsTableWidget->rowCount();
00084 ui->resultsTableWidget->insertRow(row);
00085 QTableWidgetItem *checkItem = new QTableWidgetItem();
00086 checkItem->setCheckState(Qt::Unchecked);
00087 QTableWidgetItem *uidItem = new QTableWidgetItem(uid);
00088 QTableWidgetItem *filenameItem = new QTableWidgetItem(filename);
00089 QTableWidgetItem *fileURLItem = new QTableWidgetItem(fileurl);
00090
00091 ui->resultsTableWidget->setItem(row, 0, checkItem);
00092 ui->resultsTableWidget->setItem(row, 1, uidItem);
00093 ui->resultsTableWidget->setItem(row, 2, filenameItem);
00094 ui->resultsTableWidget->setItem(row, 3, fileURLItem);
00095 }
00096
00098 bool searchObjectsServiceCall(re_srvs::SearchObjectsRequest& req, re_srvs::SearchObjectsResponse* resp) {
00099 return ros::service::call(QUERY_SERVICE.toStdString(), req, *resp);
00100 }
00101
00102 void DownloadObjectDialog::on_searchButton_clicked() {
00103 ui->resultsTableWidget->clearContents();
00104 ui->resultsTableWidget->setRowCount(0);
00105
00106 QString searchQStr = ui->searchEdit->text().trimmed();
00107
00108
00109 if (searchQStr.isEmpty()) {
00110 ui->queryFeedbackLbl->setText("Empty queries are not allowed");
00111 return;
00112 }
00113
00114 if (!ros::service::exists(QUERY_SERVICE.toStdString(), true)) {
00115 QMessageBox::warning(this, "Error", "Could not reach syntactic query service. Is re_comm running?");
00116 return;
00117 }
00118
00119 re_srvs::SearchObjectsRequest req;
00120 req.searchID = searchQStr.toStdString();
00121 re_srvs::SearchObjectsResponse resp;
00122 ui->queryFeedbackLbl->setText("Querying...");
00123
00124 {
00125 QProgressDialog dlg("Querying RoboEarth...", "Cancel", 0, 0, this);
00126 dlg.setCancelButton(NULL);
00127 QFutureWatcher<bool> futureWatcher;
00128 QObject::connect(&futureWatcher, SIGNAL(finished()), &dlg, SLOT(reset()));
00129 QObject::connect(&dlg, SIGNAL(canceled()), &futureWatcher, SLOT(cancel()));
00130
00131 QFuture<bool> future = QtConcurrent::run(&searchObjectsServiceCall, req, &resp);
00132 futureWatcher.setFuture(future);
00133
00134 dlg.exec();
00135
00136 futureWatcher.waitForFinished();
00137 if (dlg.wasCanceled()) {
00138 ui->queryFeedbackLbl->setText("Query cancelled by user");
00139 return;
00140 } else if ((future.result() == true) && resp.success) {
00141 ui->queryFeedbackLbl->setText("Query successful");
00142 } else {
00143 ui->queryFeedbackLbl->setText("Query failed");
00144 return;
00145 }
00146 }
00147
00148 for(unsigned int i=0; i<resp.objects.size(); i++) {
00149 QString uid = QString::fromStdString(resp.uids.at(i));
00150 re_msgs::StringArray filenames = resp.filenames.at(i);
00151 re_msgs::StringArray fileURLS = resp.fileURLs.at(i);
00152
00153 for (unsigned int j=0; j<filenames.list.size(); j++) {
00154 addTableEntry(uid, QString::fromStdString(filenames.list.at(j)), QString::fromStdString(fileURLS.list.at(j)));
00155 }
00156 }
00157 }
00158
00159 void DownloadObjectDialog::on_chooseDownloadDirButton_clicked() {
00160 QString dir = QFileDialog::getExistingDirectory(this, "Choose a target directory", ui->downloadDirEdit->text());
00161 if (dir.isEmpty())
00162 return;
00163
00164 ui->downloadDirEdit->setText(dir);
00165 }
00166
00168 bool downloadObjectsServiceCall(re_srvs::GetObjectBinaryFileRequest& req, re_srvs::GetObjectBinaryFileResponse *resp) {
00169 return ros::service::call(DOWNLOAD_SERVICE.toStdString(), req, *resp);
00170 }
00171
00172 bool DownloadObjectDialog::downloadFile(QString uid, QString filename, QDir target_path) {
00173 re_srvs::GetObjectBinaryFileRequest req;
00174 req.objectUID = uid.toStdString();
00175 req.filename = filename.toStdString();
00176 re_srvs::GetObjectBinaryFileResponse resp;
00177 {
00178 QProgressDialog dlg("Downloading Objects", "Cancel", 0, 0, this);
00179 dlg.setCancelButton(NULL);
00180 QFutureWatcher<bool> futureWatcher;
00181 QObject::connect(&futureWatcher, SIGNAL(finished()), &dlg, SLOT(reset()));
00182 QObject::connect(&dlg, SIGNAL(canceled()), &futureWatcher, SLOT(cancel()));
00183
00184 QFuture<bool> future = QtConcurrent::run(&downloadObjectsServiceCall, req, &resp);
00185 futureWatcher.setFuture(future);
00186
00187 dlg.exec();
00188
00189 futureWatcher.waitForFinished();
00190 if (dlg.wasCanceled()) {
00191 QMessageBox::warning(this, "Download cancelled", "Download cancelled by user.");
00192 return false;
00193 } else if ((future.result() == true) && resp.success) {
00194
00195 } else {
00196 QMessageBox::warning(this, "Download failed", "Downloading of '" + uid + "' failed!");
00197 return false;
00198 }
00199 }
00200
00201 QFile out_file(target_path.filePath(QString::fromStdString(resp.file.name)));
00202 if (!out_file.open(QIODevice::WriteOnly)) {
00203 QMessageBox::warning(this, "Download failed", "Could not open '" + out_file.fileName() + "' for writing.");
00204 return false;
00205 }
00206 qDebug() << "writing to " << out_file.fileName();
00207
00208
00209 char *buffer = new char[resp.file.data.size()];
00210 std::copy(resp.file.data.begin(), resp.file.data.end(), buffer);
00211 qint64 written = out_file.write(buffer, resp.file.data.size());
00212 delete [] buffer;
00213
00214 if (written < resp.file.data.size()) {
00215 QMessageBox::warning(this, "Download failed", "Wrote only " + QString::number(written) + " of "
00216 + QString::number(resp.file.data.size()) + " bytes to " + out_file.fileName() + "!");
00217 return false;
00218 }
00219
00220 return true;
00221 }
00222
00223 void DownloadObjectDialog::on_downloadButton_clicked() {
00224 bool service_checked = false;
00225 QDir target_path(ui->downloadDirEdit->text());
00226 for(int i=0; i<ui->resultsTableWidget->rowCount(); i++) {
00227 QTableWidgetItem *checkboxItem = ui->resultsTableWidget->item(i, 0);
00228 QTableWidgetItem *uidItem = ui->resultsTableWidget->item(i, 1);
00229 QTableWidgetItem *fileURLItem = ui->resultsTableWidget->item(i, 3);
00230 if (checkboxItem->checkState() == Qt::Checked) {
00231
00232 QStringList fileURLSplitted = fileURLItem->text().split('/', QString::SkipEmptyParts);
00233 QString realFilename = fileURLSplitted.last();
00234
00235 if (!service_checked && !ros::service::exists(DOWNLOAD_SERVICE.toStdString(), true)) {
00236 QMessageBox::warning(this, "Error", "Could not reach download service. Is re_comm running?");
00237 return;
00238 }
00239 service_checked = true;
00240
00241 bool downloaded = downloadFile(uidItem->text(), realFilename, target_path);
00242 if (downloaded && realFilename.endsWith(".zip", Qt::CaseInsensitive)) {
00243 qDebug() << "extracting into " << target_path;
00244
00245 QMiniZip mz(target_path.filePath(realFilename), QMiniZip::UNZIP);
00246 mz.unzip(target_path);
00247
00248 QStringList zipContents = mz.getContents();
00249 qDebug() << zipContents;
00250 QString created_dir_name = zipContents.first().split('/', QString::SkipEmptyParts).first();
00251
00252 this->downloaded_models.append(target_path.filePath(created_dir_name));
00253 }
00254 }
00255 }
00256
00257 emit accept();
00258 }