15#include "MantidQtIcons/Icon.h"
21#include <QDialogButtonBox>
31#include <QtConcurrentRun>
54 QString info = QString::fromStdString(ex.
what());
56 info.replace(
"\n",
"</p><p>");
65 const QString &author,
const QString &comment) {
67 pt->upload(path, comment.toStdString(), author.toStdString(), email.toStdString());
69 QString info = QString::fromStdString(ex.
what());
70 info.replace(
"\n",
"</p><p>");
78 const QString &author,
const QString &comment) {
80 pt->remove(path, comment.toStdString(), author.toStdString(), email.toStdString());
82 QString info = QString::fromStdString(ex.
what());
83 info.replace(
"\n",
"</p><p>");
101 : m_label(
std::move(label)), keypath(
std::move(path)), parentItem(parent) {}
131 return parentItem->childItems.indexOf(
const_cast<RepoItem *
>(
this));
137 if (row < 0 || row >= childCount())
140 childItems.removeAt(row);
161 repo_ptr = ScriptRepositoryFactory::Instance().create(
"ScriptRepositoryImpl");
214 if (!
index.isValid())
216 auto *item =
static_cast<RepoItem *
>(
index.internalPointer());
218 const QString &path = item->
path();
222 if (role == Qt::DisplayRole) {
223 switch (
index.column()) {
225 return item->label();
232 status =
repo_ptr->fileStatus(path.toStdString());
236 status =
repo_ptr->fileStatus(path.toStdString());
237 if (status == REMOTE_ONLY || status == LOCAL_ONLY)
239 inf =
repo_ptr->fileInfo(path.toStdString());
240 return inf.
auto_update ? QString(
"true") : QString(
"false");
243 inf =
repo_ptr->fileInfo(path.toStdString());
246 status =
repo_ptr->fileStatus(path.toStdString());
247 if (!(status == LOCAL_CHANGED || status == BOTH_UNCHANGED))
255 if (role == Qt::DecorationRole) {
256 if (
index.column() == 0) {
257 inf =
repo_ptr->fileInfo(path.toStdString());
259 status =
repo_ptr->fileStatus(path.toStdString());
261 return Icons::getIcon(
"mdi.folder-network-outline",
"black", 1.2);
263 return Icons::getIcon(
"mdi.folder-open-outline",
"black", 1.2);
265 int pos = QString(path).lastIndexOf(
'.');
267 return Icons::getIcon(
"mdi.file-question",
"black", 1.2);
268 if (path.contains(
"readme", Qt::CaseInsensitive))
269 return Icons::getIcon(
"mdi.file-document-outline",
"black", 1.2);
271 QString extension = QString(path).remove(0, pos);
272 if (extension ==
".py" || extension ==
".PY")
273 return Icons::getIcon(
"mdi.language-python",
"black", 1.2);
274 else if (extension ==
".ui")
275 return Icons::getIcon(
"mdi.file-document-box-outline",
"black", 1.2);
276 else if (extension ==
".docx" || extension ==
".doc" || extension ==
".odf")
277 return Icons::getIcon(
"mdi.file-outline",
"black", 1.2);
278 else if (extension ==
".pdf")
279 return Icons::getIcon(
"mdi.file-pdf-outline",
"black", 1.2);
281 return Icons::getIcon(
"mdi.file-question",
"black", 1.2);
287 if (role == Qt::ToolTipRole) {
288 if (
index.column() == 1) {
290 return "Downloading... Be patient.";
292 return "Uploading... Be patient.";
293 status =
repo_ptr->fileStatus(path.toStdString());
294 inf =
repo_ptr->fileInfo(path.toStdString());
298 return (inf.
directory) ?
"Click here to download this folder and all its files"
299 :
"Click here to download this file";
302 return (inf.
directory) ?
"This folder is up-to-date" :
"This file is up-to-date";
305 return "Click here to publish your changes";
307 return (inf.
directory) ?
"There is a new version of the files inside "
308 "this folder. Click here to install them."
309 :
"There is a new version of this file "
310 "available. Click here to install it.";
312 return (inf.
directory) ?
"Files in this folder may have changed both locally and "
313 "remotely.\nClick here to install the remote version, "
314 "a backup of the local version will also be created."
315 :
"This file may have changed both locally and "
316 "remotely.\nClick here to install the remote version, "
317 "a backup of the local version will also be created.";
320 return "Click here to share this file with the Mantid community!";
322 }
else if (
index.column() == 2) {
323 return "Enable or disable this item to be downloaded automatically "
324 "when new versions will be available";
325 }
else if (
index.column() == 3) {
327 return "Connection busy... Be patient.";
328 inf =
repo_ptr->fileInfo(path.toStdString());
331 status =
repo_ptr->fileStatus(path.toStdString());
332 if (!(status == LOCAL_CHANGED || status == BOTH_UNCHANGED))
334 return "Click here to delete this file from the Central Repository";
385 if (!
index.isValid())
387 if (role != Qt::EditRole)
390 if (
index.column() == 0)
393 int count_changed = 0;
394 auto *item =
static_cast<RepoItem *
>(
index.internalPointer());
395 std::string path = item->
path().toStdString();
399 QString action =
value.toString();
400 if (
index.column() == 2) {
402 if (action ==
"setTrue")
404 else if (action ==
"setFalse")
409 count_changed =
repo_ptr->setAutoUpdate(path, option);
413 if (
index.column() == 1) {
414 if (action ==
"Download") {
416 QWidget *father = qobject_cast<QWidget *>(QObject::parent());
417 QMessageBox::information(father,
"Wait",
"Downloading... ");
426 }
else if (action ==
"Upload") {
428 QWidget *father = qobject_cast<QWidget *>(QObject::parent());
429 QMessageBox::information(father,
"Wait",
"Uploading... ");
433 QWidget *father = qobject_cast<QWidget *>(QObject::parent());
434 if (
repo_ptr->fileInfo(path).directory) {
435 QMessageBox::information(father,
"Not Supported",
436 "The current version does not support "
437 "uploading recursively. Please, upload "
442 auto *form =
new UploadForm(QString::fromStdString(path), father);
444 settings.beginGroup(
"Mantid/ScriptRepository");
445 QString email = settings.value(
"UploadEmail", QString()).toString();
446 QString
author = settings.value(
"UploadAuthor", QString()).toString();
447 bool lastChk = settings.value(
"UploadSaveInfo",
false).toBool();
448 if (!email.isEmpty())
449 form->setEmail(email);
452 form->lastSaveOption(lastChk);
454 settings.setValue(
"UploadEmail", form->saveInfo() ? form->email() :
"");
455 settings.setValue(
"UploadAuthor", form->saveInfo() ? form->author() :
"");
456 settings.setValue(
"UploadSaveInfo", form->saveInfo());
458 qDebug() <<
"Uploading... " << QString::fromStdString(path) << form->comment() << form->author()
459 << form->email() <<
'\n';
475 if (
index.column() == 3) {
477 if (action !=
"delete")
480 QWidget *father = qobject_cast<QWidget *>(QObject::parent());
488 if (!(status == LOCAL_CHANGED || status == BOTH_UNCHANGED))
493 QWidget *mother = qobject_cast<QWidget *>(QObject::parent());
494 QMessageBox::information(mother,
"Wait",
495 "The connection with the server "
496 "is busy now, wait a while and "
501 auto *box =
new DeleteQueryBox(QString::fromStdString(path), father);
503 if (box->exec() != QMessageBox::Yes) {
511 QString comment(box->comment());
519 if (
repo_ptr->fileInfo(path).directory) {
520 QMessageBox::information(father,
"Not Supported",
521 "The current version does not support deleting "
522 "from the central repository recursively. "
523 "Please, delete one-by-one");
528 if (comment.isEmpty()) {
529 QMessageBox::information(father,
"Not Allowed",
"You are not allowed to delete one file without a reason");
535 settings.beginGroup(
"Mantid/ScriptRepository");
536 QString email = settings.value(
"UploadEmail", QString()).toString();
537 QString
author = settings.value(
"UploadAuthor", QString()).toString();
540 if (
author.isEmpty() || email.isEmpty()) {
541 QMessageBox::information(father,
"You have not uploaded this file",
542 "You are not allowed to remove files that you "
543 "have not updloaded through ScriptRepository");
573 if (!
index.isValid())
575 if (
index.column() == 0)
576 return QAbstractItemModel::flags(
index);
578 return QAbstractItemModel::flags(
index) | Qt::ItemIsEditable;
596 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
631 if (!hasIndex(row, column,
parent))
632 return QModelIndex();
644 return createIndex(row, column, childItem);
646 return QModelIndex();
655 if (!
index.isValid())
656 return QModelIndex();
658 auto *childItem =
static_cast<RepoItem *
>(
index.internalPointer());
663 return QModelIndex();
665 return createIndex(parentItem->
row(), 0, parentItem);
698 auto *item =
static_cast<RepoItem *
>(
index.internalPointer());
703 desc = QString::fromStdString(
repo_ptr->description(item->path().toStdString()));
711 auto *item =
static_cast<RepoItem *
>(
index.internalPointer());
712 QString
author =
"Not defined";
716 author = QString::fromStdString(
repo_ptr->info(item->path().toStdString()).author);
728 auto *item =
static_cast<RepoItem *
>(
index.internalPointer());
737 QString path =
repo_path +
"/" + item->path();
763 if (parents.last()->path() == folder)
764 return parents.last();
767 if (folder.isEmpty())
768 return parents.first();
772 QStringList folder_parts = folder.split(
"/");
777 bool try_to_find =
true;
779 for (
int i = 0; i < folder_parts.size(); i++) {
781 aux_folder = folder_parts[i];
783 aux_folder +=
"/" + folder_parts[i];
789 foreach (
RepoItem *the_parent, parents) {
790 if (the_parent->
path() == aux_folder) {
827 std::vector<std::string> list =
repo_ptr->listFiles();
835 for (
const auto &number : list) {
837 QString lineData = QString::fromStdString(number);
840 QStringList pathStrings = lineData.split(
"/");
842 QString current_file = pathStrings.last();
844 pathStrings.removeLast();
845 if (pathStrings.size() > 0)
846 folder = pathStrings.join(
"/");
859 if (
repo_ptr->info(lineData.toStdString()).directory) {
871 bool showWarning)
const {
875 QWidget *father = qobject_cast<QWidget *>(QObject::parent());
876 QString info = QString::fromStdString(ex.
what());
878 info.replace(
"\n",
"</p><p>");
879 QMessageBox::warning(father, title, QString(
"<html><body><p>%1</p></body></html>").arg(info));
885 if (!info.isEmpty()) {
886 QMessageBox::warning(qobject_cast<QWidget *>(QObject::parent()),
"Download Failed",
887 QString(
"<html><body><p>%1</p></body></html>").arg(info));
891 QModelIndex top_left = createIndex(0, 0, repo_item);
892 QModelIndex bottom_right = createIndex(0, 3, repo_item);
893 emit dataChanged(top_left, bottom_right);
898 auto *item =
static_cast<RepoItem *
>(
index.internalPointer());
906 QString title =
"Upload Failed";
909 title =
"Delete Failed";
912 if (!info.isEmpty()) {
913 QMessageBox::warning(qobject_cast<QWidget *>(QObject::parent()), title,
914 QString(
"<html><body><p>%1</p></body></html>").arg(info));
919 QModelIndex top_left = createIndex(0, 0, repo_item);
920 QModelIndex bottom_right = createIndex(0, 3, repo_item);
921 emit dataChanged(top_left, bottom_right);
926 auto *item =
static_cast<RepoItem *
>(
index.internalPointer());
952 save_ck =
new QCheckBox(
"Save your personal information");
953 save_ck->setToolTip(
"The author and email will be saved and will be written "
959 auto *personalGroupBox =
new QGroupBox(
"Personal Group Box");
960 auto *personalLayout =
new QFormLayout();
961 personalLayout->addRow(
"Author",
author_le);
962 personalLayout->addRow(
"Email",
email_le);
963 auto *gpBox =
new QVBoxLayout();
965 gpBox->addLayout(personalLayout);
966 personalGroupBox->setLayout(gpBox);
968 QLabel *cmLabel =
new QLabel(
"Comment");
969 auto *buttonBox =
new QDialogButtonBox();
970 buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
972 auto *layout =
new QVBoxLayout();
973 layout->addWidget(personalGroupBox);
974 layout->addWidget(cmLabel);
976 layout->addWidget(buttonBox);
979 setWindowTitle(QString(
"Upload - %2").arg(file2upload));
980 connect(buttonBox, SIGNAL(accepted()),
this, SLOT(accept()));
981 connect(buttonBox, SIGNAL(rejected()),
this, SLOT(reject()));
991 save_ck->setCheckState(option ? Qt::Checked : Qt::Unchecked);
995 : QMessageBox(QMessageBox::Question,
"Delete file",
"", QMessageBox::Yes | QMessageBox::No,
parent) {
998 QTextStream info(&info_str);
1000 info <<
"<html><head/><body><p>Are you sure you want to delete this file "
1001 "from the Repository?</p><p align=\"center\"><span style=\" "
1002 "font-style:italic;\">"
1003 << path <<
"</span></p></body></html>";
1010 QGridLayout *_lay = qobject_cast<QGridLayout *>(layout());
1012 QLayoutItem *buttons = _lay->takeAt(_lay->count() - 1);
1013 QLabel *la =
new QLabel(
"Please, give the reason for deleting:",
this);
1016 _lay->addWidget(la, _lay->rowCount(), 0, 1, -1);
1017 _lay->addWidget(
comment_te, _lay->rowCount(), 0, 2, -1);
1018 _lay->addItem(buttons, _lay->rowCount(), 0, 1, -1);
1025 return comment_te->toPlainText();
double value
The value of the point.
std::map< DeltaEMode::Type, std::string > index
static QString download_thread(Mantid::API::ScriptRepository_sptr &pt, const std::string &path)
Executes the download from ScriptRepository.
static QString upload_thread(Mantid::API::ScriptRepository_sptr &pt, const std::string &path, const QString &email, const QString &author, const QString &comment)
Execute the upload from ScriptRepository.
static QString delete_thread(Mantid::API::ScriptRepository_sptr &pt, const std::string &path, const QString &email, const QString &author, const QString &comment)
Execute the remove from ScriptRepository.
Auxiliary Dialog to get the option from the user about removing the entries from the local folder or ...
DeleteQueryBox(const QString &path, QWidget *parent=nullptr)
~DeleteQueryBox() override
A nested class to help RepoModel to implement the QAbstractItemModel.
RepoItem * parent() const
access to the parent of this entry
bool removeChild(int row)
allow to remove a child, which allows erasing rows from the view.
void appendChild(RepoItem *child)
This method is the very responsible to allow the reconstruction of the hierarchical tree,...
int row() const
To which row this repoItem belongs?
RepoItem(QString label, QString path="/", RepoItem *parent=nullptr)
int childCount() const
Return the number of children that this entry may find.
const QString & path() const
access to the script repository path
RepoItem * child(int row) const
Gives access to the row_th children of RepoItem.
~RepoItem()
destruct all the childItems.
RepoModel(QObject *parent=nullptr)
constructor
int rowCount(const QModelIndex &parent=QModelIndex()) const override
Count how many file/folders are direct children of the given folder, through the abstraction of QMode...
Qt::ItemFlags flags(const QModelIndex &index) const override
information on the available interaction
static const QString & localChangedSt()
QFutureWatcher< QString > upload_watcher
Mantid::API::ScriptRepository_sptr repo_ptr
pointer to the ScriptRepository
QString filePath(const QModelIndex &index)
Return the operative system file path if it exists.
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
header strings
QModelIndex download_index
QFutureWatcher< QString > download_watcher
void executingThread(bool)
bool isUploading(const QModelIndex &index) const
QString author(const QModelIndex &index)
bool isDownloading(const QModelIndex &index) const
static const QString & remoteChangedSt()
QFuture< QString > upload_threads
QString repo_path
ScriptLocalRepository path, to be able to retrieve the absolute path.
int columnCount(const QModelIndex &parent=QModelIndex()) const override
provide the number of the columns
const QString & fromStatus(Mantid::API::SCRIPTSTATUS status) const
auxiliary method to match the ScriptStatus to string
static const QString & updatedSt()
static const QString & uploadSt()
static const QString & bothChangedSt()
RepoItem * rootItem
pointer to the RepoItem root
RepoItem * getParent(const QString &folder, QList< RepoItem * > &parents)
auxiliary method to help populating the model
QVariant data(const QModelIndex &index, int role) const override
access to the ScriptRepository data
void handleExceptions(const Mantid::API::ScriptRepoException &ex, const QString &title, bool showWarning=true) const
auxiliary method to deal with exceptions
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
change data
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
access to the index
QFuture< QString > download_threads
QModelIndex parent(const QModelIndex &index) const override
access to parent
QString fileDescription(const QModelIndex &index)
Return the description of the file for a defined entry.
static const QString & localOnlySt()
void setupModelData(RepoItem *parent)
auxiliary method to populate the model
static const QString & downloadSt()
static const QString & remoteOnlySt()
~RepoModel() override
destructor
The ScriptRepository class is intended to be used mainly by the users, who will be willing to share a...
const char * what() const noexcept override
Returns the message string.
const std::string & systemError() const
Returns the error description with technical details on the origin and cause.
The ConfigService class provides a simple facade to access the Configuration functionality of the Man...
std::string getString(const std::string &keyName, bool pathAbsolute=true) const
Searches for a configuration property.
The Logger class is in charge of the publishing messages from the framework through various channels.
void information(const std::string &msg)
Logs at information level.
Manage the lifetime of a class intended to be a singleton.
const QString LOCALCHANGED
const QString REMOTECHANGED
const QString DELETABLEENTRY
const QString BOTHUNCHANGED
const QString BOTHCHANGED
const QString PROTECTEDENTRY
std::shared_ptr< ScriptRepository > ScriptRepository_sptr
shared pointer to the function base class
Kernel::Logger g_log("ExperimentInfo")
static logger object
SCRIPTSTATUS
Represent the possible states for a given file:
Information about the files inside the repository.
bool auto_update
Marked for auto update.
bool directory
Directory Flag to indicate if the entry is a directory.