/** Return the operative system file path if it exists. otherwise it returns an empty string @param index: to find the entry @return The operative system path or empty string */ QString RepoModel::filePath(const QModelIndex & index) { RepoItem * item = static_cast<RepoItem*>(index.internalPointer()); // qDebug() << "Get file path from : " << item->path()<< endl; Mantid::API::SCRIPTSTATUS state = repo_ptr->fileStatus(item->path().toStdString()); if (state == Mantid::API::REMOTE_ONLY) return ""; Mantid::API::ScriptInfo info = repo_ptr->fileInfo(item->path().toStdString()); if (info.directory) return ""; QString path = repo_path + "/" + item->path(); return path; }
QString RepoModel::author(const QModelIndex & index) { RepoItem * item = static_cast<RepoItem*>(index.internalPointer()); QString author = "Not defined"; if (!item) return author; try { author = QString::fromStdString(repo_ptr->info(item->path().toStdString()).author); } catch(...) { // just ignore } return author; }
/** Return the description of the file for a defined entry **/ QString RepoModel::fileDescription(const QModelIndex & index) { RepoItem * item = static_cast<RepoItem*>(index.internalPointer()); if (!item) return ""; QString desc; try { desc = QString::fromStdString(repo_ptr->description(item->path().toStdString())); } catch(...) { // just ignore } return desc; }
bool RepoModel::isUploading(const QModelIndex & index)const { RepoItem *item = static_cast<RepoItem*>(index.internalPointer()); if (item) return item->path() == uploading_path; return false; }
/** The ScriptRepository allows to download and upload file and folders. And to * configure the AutoUpdate option for the entries. These actions will be available * through the setData method. * * The setData will recognize only the EditRole as a valid Role. * The RepoModel will recognize the following entries. The path can not be edited * (column 0) is not editable. the AutoUpdate flag (column 2) will accept the following * actions: setTrue and setFalse, to enable or disable the automatic update. * * The Status (column 1) will accept the following actions: Download and Upload. * * * */ bool RepoModel::setData(const QModelIndex & index, const QVariant & value, int role) { if (!index.isValid()) return false; if (role != Qt::EditRole) // only EditRole is acceptable for the role return false; if (index.column() == 0) // the path can not be changed return false; int count_changed = 0; RepoItem * item = static_cast<RepoItem*>(index.internalPointer()); std::string path = item->path().toStdString(); bool ret = false; // get the action QString action = value.toString(); if (index.column() ==2) { // set auto update bool option; if (action == "setTrue") option = true; else if (action == "setFalse") option = false; else return false; // only setTrue and setFalse are allowed values for set auto update. count_changed = repo_ptr->setAutoUpdate(path, option); ret = true; } if (index.column() == 1) { // trigger actions: Download and Upload if (action == "Download") { if (!download_threads.isFinished()) { QWidget * father = qobject_cast<QWidget*>(QObject::parent()); QMessageBox::information(father, "Wait", "Downloading... "); return false; } downloading_path = QString::fromStdString(path); download_index = index; emit executingThread(true); download_threads = QtConcurrent::run(download_thread, repo_ptr, path); download_watcher.setFuture(download_threads); ret = true; } else if (action == "Upload") { if (!upload_threads.isFinished()) { QWidget * father = qobject_cast<QWidget*>(QObject::parent()); QMessageBox::information(father, "Wait", "Uploading... "); return false; } QWidget * father = qobject_cast<QWidget*>(QObject::parent()); if (repo_ptr->fileInfo(path).directory) { QMessageBox::information(father, "Not Supported", "The current version does not support uploading recursively. Please, upload one-by-one"); return false; }; UploadForm * form = new UploadForm(QString::fromStdString(path), father); QSettings settings; settings.beginGroup("Mantid/ScriptRepository"); QString email = settings.value("UploadEmail",QString()).toString(); QString author = settings.value("UploadAuthor",QString()).toString(); bool lastChk = settings.value("UploadSaveInfo",false).toBool(); if (!email.isEmpty()) form->setEmail(email); if (!author.isEmpty()) form->setAuthor(author); form->lastSaveOption(lastChk); if (form->exec()) { settings.setValue("UploadEmail",form->saveInfo()?form->email():""); settings.setValue("UploadAuthor",form->saveInfo()?form->author():""); settings.setValue("UploadSaveInfo",form->saveInfo()); qDebug() << "Uploading... "<< QString::fromStdString(path) << form->comment() << form->author() << form->email() << endl; uploading_path = QString::fromStdString(path); upload_index = index; emit executingThread(true); upload_threads = QtConcurrent::run(upload_thread, repo_ptr, path, form->email(), form->author(), form->comment()); upload_watcher.setFuture(upload_threads); ret = true; } else { ret = false; } settings.endGroup(); delete form; } } if (index.column() == 3) { // trigger actions: delete using namespace Mantid::API; if (action != "delete") return false; // used to show qwidgets QWidget * father = qobject_cast<QWidget*>(QObject::parent()); SCRIPTSTATUS status = repo_ptr->fileStatus(path); /* We do not remove files directly from the central repository, but, usually, this option is not available from the GUI (no button), so, just return false*/ if (!(status == LOCAL_CHANGED || status == BOTH_UNCHANGED)) return false; // it requires a new connection to the uploader server if (!upload_threads.isFinished()) { QWidget * father = qobject_cast<QWidget*>(QObject::parent()); QMessageBox::information(father, "Wait", "The connection with the server is busy now, wait a while and try again. "); return false; } //query the user if he wants to delete only locally or remote as well. DeleteQueryBox * box = new DeleteQueryBox(QString::fromStdString(path), father); if (box->exec() != QMessageBox::Yes) { // the user gave up deleting this entry, release memory delete box; box = 0; return false; } // get the options from the user QString comment(box->comment()); { // release memory delete box; box = 0; } // remove from central repository // currently, directories can not be deleted recursively if (repo_ptr->fileInfo(path).directory) { QMessageBox::information(father, "Not Supported", "The current version does not support deleting from the central repository recursively. Please, delete one-by-one"); return false; }; // check if the reason was given and it is valid if (comment.isEmpty()) { QMessageBox::information(father, "Not Allowed", "You are not allowed to delete one file without a reason"); return false; } // we will not allow them to remove if they have no e-mail and author saved QSettings settings; settings.beginGroup("Mantid/ScriptRepository"); QString email = settings.value("UploadEmail",QString()).toString(); QString author = settings.value("UploadAuthor",QString()).toString(); settings.endGroup(); if (author.isEmpty() || email.isEmpty()) { QMessageBox::information(father, "You have not uploaded this file", "You are not allowed to remove files that you have not updloaded through ScriptRepository"); return false; } // we have all we need to delete from the central repository // execute the delete in a separate thread, we will use the upload established way, because, // it will connect to the same server to delete. upload_index = index; uploading_path = QString::fromStdString(path); emit executingThread(true); upload_threads = QtConcurrent::run(delete_thread, repo_ptr, path, email, author, comment); upload_watcher.setFuture(upload_threads); ret = true; }// end delete action if (ret) emit dataChanged(index, this->index(count_changed,0,index)); return ret; }
/**Provide access to the data through the defined QAbstractItemModel definition. The index parameter defines how to access the corresponded data while the role define the kind of information desired from RepoModel. This method will be queried from QView in order to populate the view. From the index.internalPointer the RepoModel will have access to the path, which uniquely define its entry on ScriptRepository. The RepoModel defines 4 columns: - Path - Status - AutoUpdate - Delete The path, provides the name of the file. The status, give information on the ScriptRepository entries. Currently, an entry may be found on the following states: - LOCAL_ONLY: The file only exists locally. - REMTOE_ONLY: The file has not been downloaded. - REMOTE_CHANGED: A new version of the file is available. - LOCAL_CHANGED: The file has been changed from the original one. - BOTH_CHANGED: Locally and remotelly changed. - UPDATED: The remote and local file are identical. The AutoUpdate allow to flag the entries to receive the updates automatically when new files are available at the central repository. The delete column will return a string "protected" or "deletable" that will be used to know if it can be deleted or not. For the current version, folders are protected, and files are deletable. The repomodel will react to the following roles: - DisplayRole: to provide the main information. - DecorationRole: to provide icons to make easier and fancier to identify the files and folders. - ToolTipRole: to provide user help to interact with this class. */ QVariant RepoModel::data(const QModelIndex &index, int role) const { using namespace Mantid::API; if (!index.isValid()) return QVariant(); RepoItem *item = static_cast<RepoItem*>(index.internalPointer()); try { QString path = item->path(); Mantid::API::ScriptInfo inf ; Mantid::API::SCRIPTSTATUS status; // return the data for the display role if (role == Qt::DisplayRole) { switch(index.column()) { case 0: // return the label (the path of the file/folder) return item->label(); break; case 1: // ask for the status if (isDownloading(index)) return downloadSt(); if (isUploading(index)) return uploadSt(); status = repo_ptr->fileStatus(path.toStdString()); return fromStatus(status); break; case 2:// autoupdate option status = repo_ptr->fileStatus(path.toStdString()); if (status == REMOTE_ONLY || status == LOCAL_ONLY) return QVariant(); inf = repo_ptr->fileInfo(path.toStdString()); return inf.auto_update?QString("true"):QString("false"); break; case 3:// delete action inf = repo_ptr->fileInfo(path.toStdString()); if (inf.directory) return PROTECTEDENTRY; status = repo_ptr->fileStatus(path.toStdString()); if (!(status == LOCAL_CHANGED || status == BOTH_UNCHANGED)) return PROTECTEDENTRY; return DELETABLEENTRY; break; } } // return the data for the DecorationRole if (role == Qt::DecorationRole) { if (index.column() == 0) { inf = repo_ptr->fileInfo(path.toStdString()); if (inf.directory) { status = repo_ptr->fileStatus(path.toStdString()); if (status == Mantid::API::REMOTE_ONLY) return QIcon::fromTheme("folder-remote",QIcon(QPixmap(":/win/folder-remote"))); else return QIcon::fromTheme("folder", QIcon(QPixmap(":/win/folder"))); } else { int pos = QString(path).lastIndexOf('.'); if (pos < 0) return QIcon::fromTheme("unknown", QIcon(QPixmap(":/win/unknown"))); if (path.contains("readme",Qt::CaseInsensitive)) return QIcon::fromTheme("text-x-readme", QIcon(QPixmap(":/win/txt_file.png"))); QString extension = QString(path).remove(0,pos); if (extension == ".cpp" || extension == ".CPP" || extension == ".c" || extension == ".C") return QIcon::fromTheme("text-x-c++", QIcon(QPixmap(":/win/unknown"))); else if (extension == ".py" || extension == ".PY") return QIcon::fromTheme("text-x-python", QIcon(QPixmap(":/win/text-x-python"))); else if (extension == ".ui") return QIcon::fromTheme("document", QIcon(QPixmap(":/win/document"))); else if (extension == ".docx" || extension == ".doc" || extension == ".odf") return QIcon::fromTheme("x-office-document", QIcon(QPixmap(":/win/office-document"))); else if (extension == ".pdf") return QIcon::fromTheme("application-pdf", QIcon(QPixmap(":/win/file_pdf"))); else return QIcon::fromTheme("unknown", QIcon(QPixmap(":/win/unknown"))); } } }// end decorationRole // tool tip role if (role == Qt::ToolTipRole) { if (index.column() == 1) { if (isDownloading(index)) return "Downloading... Be patient."; if (isUploading(index)) return "Uploading... Be patient."; status = repo_ptr->fileStatus(path.toStdString()); inf = repo_ptr->fileInfo(path.toStdString()); switch(status) { case REMOTE_ONLY: return (inf.directory)?"Click here to download this folder and all its files" :"Click here to download this file"; break; case BOTH_UNCHANGED: return (inf.directory)? "This folder is up-to-date" : "This file is up-to-date"; break; case LOCAL_CHANGED: return "Click here to publish your changes"; case REMOTE_CHANGED: case BOTH_CHANGED: return (inf.directory)? "There is a new version of the files inside this folder. Click here to install them.": "There is a new version of this file available. Click here to install it."; break; case LOCAL_ONLY: return "Click here to share this file with the Mantid community!"; } } else if (index.column() == 2) { return "Enable or disable this item to be downloaded automatically when new versions will be available"; } else if (index.column() == 3) { if (isUploading(index)) return "Connection busy... Be patient."; inf = repo_ptr->fileInfo(path.toStdString()); if (inf.directory) return QVariant(); status = repo_ptr->fileStatus(path.toStdString()); if (!(status == LOCAL_CHANGED || status == BOTH_UNCHANGED)) return QVariant(); return "Click here to delete this file from the Central Repository"; } }// end tool tip } catch(Mantid::API::ScriptRepoException & ex) { handleExceptions(ex,"",false); } return QVariant(); }