Mantid
Loading...
Searching...
No Matches
RepoModel.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8
10#include <utility>
11#include <vector>
12
14#include "MantidKernel/Logger.h"
15#include "MantidQtIcons/Icon.h"
16#include <QIcon>
17#include <QPixmap>
18
19#include <QCheckBox>
20#include <QDebug>
21#include <QDialogButtonBox>
22#include <QFormLayout>
23#include <QGridLayout>
24#include <QGroupBox>
25#include <QLabel>
26#include <QLineEdit>
27#include <QSettings>
28#include <QTextEdit>
29#include <QTextStream>
30#include <QVBoxLayout>
31#include <QtConcurrentRun>
32#include <stdexcept>
33
34using namespace MantidQt::API;
37
38namespace {
40Mantid::Kernel::Logger g_log("RepoModel");
41} // namespace
42
43// flag to indicate that the thread is delete thread
44const char *delete_mark = "*DELETE*";
45const char *nofile_flag = "nofile";
46
49static QString download_thread(Mantid::API::ScriptRepository_sptr &pt, const std::string &path) {
50 QString result("");
51 try {
52 pt->download(path);
54 QString info = QString::fromStdString(ex.what());
55 // make the exception a nice html message
56 info.replace("\n", "</p><p>");
57 return info;
58 }
59 return result;
60}
61
64static QString upload_thread(Mantid::API::ScriptRepository_sptr &pt, const std::string &path, const QString &email,
65 const QString &author, const QString &comment) {
66 try {
67 pt->upload(path, comment.toStdString(), author.toStdString(), email.toStdString());
69 QString info = QString::fromStdString(ex.what());
70 info.replace("\n", "</p><p>");
71 return info;
72 }
73 return QString();
74}
77static QString delete_thread(Mantid::API::ScriptRepository_sptr &pt, const std::string &path, const QString &email,
78 const QString &author, const QString &comment) {
79 try {
80 pt->remove(path, comment.toStdString(), author.toStdString(), email.toStdString());
82 QString info = QString::fromStdString(ex.what());
83 info.replace("\n", "</p><p>");
84 // it adds the mark *DELETE* so to recognize that it was used to delete an
85 // entry.
86 return info + delete_mark;
87 }
88 return delete_mark;
89}
90
91/*
92 An auxiliary nested class to help RepoModel to rebuild the hierarchical
93 tree of ScriptRepository.
94
95 It will keep track of the path that is the main key to access metadata
96 on ScriptRepository and an auxiliary label to easy the display on a
97 user nicer way.
98
99*/
100RepoModel::RepoItem::RepoItem(QString label, QString path, RepoItem *parent)
101 : m_label(std::move(label)), keypath(std::move(path)), parentItem(parent) {}
103RepoModel::RepoItem::~RepoItem() { qDeleteAll(childItems); }
107void RepoModel::RepoItem::appendChild(RepoItem *child) { childItems.append(child); }
108
120RepoModel::RepoItem *RepoModel::RepoItem::child(int row) const { return childItems.value(row); }
121
125int RepoModel::RepoItem::childCount() const { return childItems.count(); }
130 if (parentItem)
131 return parentItem->childItems.indexOf(const_cast<RepoItem *>(this));
132 return 0;
133}
137 if (row < 0 || row >= childCount())
138 return false;
139
140 childItems.removeAt(row);
141 return true;
142}
143
145// MODEL
147
154RepoModel::RepoModel(QObject *parent) : QAbstractItemModel(parent) {
155 const ConfigServiceImpl &config = ConfigService::Instance();
156 repo_path = QString::fromStdString(config.getString("ScriptLocalRepository"));
157 rootItem = new RepoItem("/");
161 repo_ptr = ScriptRepositoryFactory::Instance().create("ScriptRepositoryImpl");
162 connect(&download_watcher, SIGNAL(finished()), this, SLOT(downloadFinished()));
163 connect(&upload_watcher, SIGNAL(finished()), this, SLOT(uploadFinished()));
167}
168
212QVariant RepoModel::data(const QModelIndex &index, int role) const {
213 using namespace Mantid::API;
214 if (!index.isValid())
215 return QVariant();
216 const auto *item = static_cast<RepoItem *>(index.internalPointer());
217 try {
218 const QString &path = item->path();
221 // return the data for the display role
222 if (role == Qt::DisplayRole) {
223 switch (index.column()) {
224 case 0: // return the label (the path of the file/folder)
225 return item->label();
226 break;
227 case 1: // ask for the status
228 if (isDownloading(index))
229 return downloadSt();
230 if (isUploading(index))
231 return uploadSt();
232 status = repo_ptr->fileStatus(path.toStdString());
233 return fromStatus(status);
234 break;
235 case 2: // autoupdate option
236 status = repo_ptr->fileStatus(path.toStdString());
237 if (status == REMOTE_ONLY || status == LOCAL_ONLY)
238 return QVariant();
239 inf = repo_ptr->fileInfo(path.toStdString());
240 return inf.auto_update ? QString("true") : QString("false");
241 break;
242 case 3: // delete action
243 inf = repo_ptr->fileInfo(path.toStdString());
244 if (inf.directory)
245 return PROTECTEDENTRY;
246 status = repo_ptr->fileStatus(path.toStdString());
247 if (!(status == LOCAL_CHANGED || status == BOTH_UNCHANGED))
248 return PROTECTEDENTRY;
249 return DELETABLEENTRY;
250 break;
251 }
252 }
253
254 // return the data for the DecorationRole
255 if (role == Qt::DecorationRole) {
256 if (index.column() == 0) {
257 inf = repo_ptr->fileInfo(path.toStdString());
258 if (inf.directory) {
259 status = repo_ptr->fileStatus(path.toStdString());
260 if (status == Mantid::API::REMOTE_ONLY) {
261 return Icons::getIcon("mdi.folder-network-outline", "black", 1.2);
262 } else
263 return Icons::getIcon("mdi.folder-open-outline", "black", 1.2);
264 } else {
265 int pos = QString(path).lastIndexOf('.');
266 if (pos < 0)
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);
270
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);
280 else
281 return Icons::getIcon("mdi.file-question", "black", 1.2);
282 }
283 }
284 } // end decorationRole
285
286 // tool tip role
287 if (role == Qt::ToolTipRole) {
288 if (index.column() == 1) {
289 if (isDownloading(index))
290 return "Downloading... Be patient.";
291 if (isUploading(index))
292 return "Uploading... Be patient.";
293 status = repo_ptr->fileStatus(path.toStdString());
294 inf = repo_ptr->fileInfo(path.toStdString());
295 switch (status) {
296
297 case REMOTE_ONLY:
298 return (inf.directory) ? "Click here to download this folder and all its files"
299 : "Click here to download this file";
300 break;
301 case BOTH_UNCHANGED:
302 return (inf.directory) ? "This folder is up-to-date" : "This file is up-to-date";
303 break;
304 case LOCAL_CHANGED:
305 return "Click here to publish your changes";
306 case REMOTE_CHANGED:
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.";
311 case BOTH_CHANGED:
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.";
318 break;
319 case LOCAL_ONLY:
320 return "Click here to share this file with the Mantid community!";
321 }
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) {
326 if (isUploading(index))
327 return "Connection busy... Be patient.";
328 inf = repo_ptr->fileInfo(path.toStdString());
329 if (inf.directory)
330 return QVariant();
331 status = repo_ptr->fileStatus(path.toStdString());
332 if (!(status == LOCAL_CHANGED || status == BOTH_UNCHANGED))
333 return QVariant();
334 return "Click here to delete this file from the Central Repository";
335 }
336 } // end tool tip
338 handleExceptions(ex, "", false);
339 }
340 return QVariant();
341}
342
349 using namespace Mantid::API;
350 switch (status) {
351 case BOTH_UNCHANGED:
352 return updatedSt();
353 case REMOTE_ONLY:
354 return remoteOnlySt();
355 case LOCAL_ONLY:
356 return localOnlySt();
357 case REMOTE_CHANGED:
358 return remoteChangedSt();
359 case LOCAL_CHANGED:
360 return localChangedSt();
361 case BOTH_CHANGED:
362 return bothChangedSt();
363 }
364 return bothChangedSt();
365}
366
384bool RepoModel::setData(const QModelIndex &index, const QVariant &value, int role) {
385 if (!index.isValid())
386 return false;
387 if (role != Qt::EditRole)
388 // only EditRole is acceptable for the role
389 return false;
390 if (index.column() == 0)
391 // the path can not be changed
392 return false;
393 int count_changed = 0;
394 const auto *item = static_cast<RepoItem *>(index.internalPointer());
395 std::string path = item->path().toStdString();
396
397 bool ret = false;
398 // get the action
399 QString action = value.toString();
400 if (index.column() == 2) { // set auto update
401 bool option;
402 if (action == "setTrue")
403 option = true;
404 else if (action == "setFalse")
405 option = false;
406 else
407 return false; // only setTrue and setFalse are allowed values for set auto
408 // update.
409 count_changed = repo_ptr->setAutoUpdate(path, option);
410 ret = true;
411 }
412
413 if (index.column() == 1) { // trigger actions: Download and Upload
414 if (action == "Download") {
415 if (!download_threads.isFinished()) {
416 QWidget *father = qobject_cast<QWidget *>(QObject::parent());
417 QMessageBox::information(father, "Wait", "Downloading... ");
418 return false;
419 }
420 downloading_path = QString::fromStdString(path);
422 emit executingThread(true);
423 download_threads = QtConcurrent::run(download_thread, repo_ptr, path);
425 ret = true;
426 } else if (action == "Upload") {
427 if (!upload_threads.isFinished()) {
428 QWidget *father = qobject_cast<QWidget *>(QObject::parent());
429 QMessageBox::information(father, "Wait", "Uploading... ");
430 return false;
431 }
432
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 "
438 "one-by-one");
439 return false;
440 };
441
442 auto *form = new UploadForm(QString::fromStdString(path), father);
443 QSettings settings;
444 settings.beginGroup("Mantid/ScriptRepository");
445 QString email = settings.value("UploadEmail", QString()).toString();
446 QString uploadAuthor = settings.value("UploadAuthor", QString()).toString();
447 bool lastChk = settings.value("UploadSaveInfo", false).toBool();
448 if (!email.isEmpty())
449 form->setEmail(email);
450 if (!uploadAuthor.isEmpty())
451 form->setAuthor(uploadAuthor);
452 form->lastSaveOption(lastChk);
453 if (form->exec()) {
454 settings.setValue("UploadEmail", form->saveInfo() ? form->email() : "");
455 settings.setValue("UploadAuthor", form->saveInfo() ? form->author() : "");
456 settings.setValue("UploadSaveInfo", form->saveInfo());
457
458 qDebug() << "Uploading... " << QString::fromStdString(path) << form->comment() << form->author()
459 << form->email() << '\n';
460 uploading_path = QString::fromStdString(path);
462 emit executingThread(true);
464 QtConcurrent::run(upload_thread, repo_ptr, path, form->email(), form->author(), form->comment());
466 ret = true;
467 } else {
468 ret = false;
469 }
470 settings.endGroup();
471 delete form;
472 }
473 }
474
475 if (index.column() == 3) { // trigger actions: delete
476 using namespace Mantid::API;
477 if (action != "delete")
478 return false;
479 // used to show qwidgets
480 QWidget *father = qobject_cast<QWidget *>(QObject::parent());
481
482 SCRIPTSTATUS status = repo_ptr->fileStatus(path);
483
484 /* We do not remove files directly from the central repository, but,
485 usually,
486 this option is not available from the GUI (no button), so, just return
487 false*/
488 if (!(status == LOCAL_CHANGED || status == BOTH_UNCHANGED))
489 return false;
490
491 // it requires a new connection to the uploader server
492 if (!upload_threads.isFinished()) {
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 "
497 "try again. ");
498 return false;
499 }
500 // query the user if he wants to delete only locally or remote as well.
501 auto box = DeleteQueryBox(QString::fromStdString(path), father);
502
503 if (box.exec() != QMessageBox::Yes) {
504 // the user gave up deleting this entry, release memory
505 return false;
506 }
507
508 // get the options from the user
509 QString comment(box.comment());
510
511 // remove from central repository
512 // currently, directories can not be deleted recursively
513 if (repo_ptr->fileInfo(path).directory) {
514 QMessageBox::information(father, "Not Supported",
515 "The current version does not support deleting "
516 "from the central repository recursively. "
517 "Please, delete one-by-one");
518 return false;
519 };
520
521 // check if the reason was given and it is valid
522 if (comment.isEmpty()) {
523 QMessageBox::information(father, "Not Allowed", "You are not allowed to delete one file without a reason");
524 return false;
525 }
526
527 // we will not allow them to remove if they have no e-mail and author saved
528 QSettings settings;
529 settings.beginGroup("Mantid/ScriptRepository");
530 QString email = settings.value("UploadEmail", QString()).toString();
531 QString uploadAuthor = settings.value("UploadAuthor", QString()).toString();
532 settings.endGroup();
533
534 if (uploadAuthor.isEmpty() || email.isEmpty()) {
535 QMessageBox::information(father, "You have not uploaded this file",
536 "You are not allowed to remove files that you "
537 "have not updloaded through ScriptRepository");
538 return false;
539 }
540
541 // we have all we need to delete from the central repository
542 // execute the delete in a separate thread, we will use the upload
543 // established way, because,
544 // it will connect to the same server to delete.
546 uploading_path = QString::fromStdString(path);
547 emit executingThread(true);
548 upload_threads = QtConcurrent::run(delete_thread, repo_ptr, path, email, uploadAuthor, comment);
550 ret = true;
551 } // end delete action
552
553 if (ret)
554 emit dataChanged(index, this->index(count_changed, 0, index));
555
556 return ret;
557}
558
566Qt::ItemFlags RepoModel::flags(const QModelIndex &index) const {
567 if (!index.isValid())
568 return {};
569 if (index.column() == 0)
570 return QAbstractItemModel::flags(index);
571 // define that setData will accept the EditRole.
572 return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
573}
574
589QVariant RepoModel::headerData(int section, Qt::Orientation orientation, int role) const {
590 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
591 switch (section) {
592 case 0:
593 return "Path";
594 case 1:
595 return "Status";
596 case 2:
597 return "AutoUpdate";
598 case 3:
599 return "Delete";
600 default:
601 return QVariant();
602 }
603 }
604 return QVariant();
605}
606
621QModelIndex RepoModel::index(int row, int column, const QModelIndex &parent) const {
622 // check if the row and column are allowed,
623 // for example, it will not accept column == 3, or row = 1
624 // for parent that refers to file and not to folder.
625 if (!hasIndex(row, column, parent))
626 return QModelIndex();
627 // retrieve the pointer ot the RepoItem from the parent
628 const RepoItem *parentItem;
629 if (!parent.isValid())
630 parentItem = rootItem;
631 else
632 parentItem = static_cast<RepoItem *>(parent.internalPointer());
633
634 // given the row, we can find the childItem from the RepoItem::child method.
635 RepoItem *childItem = parentItem->child(row);
636
637 if (childItem)
638 return createIndex(row, column, childItem);
639 else
640 return QModelIndex();
641}
642
648QModelIndex RepoModel::parent(const QModelIndex &index) const {
649 if (!index.isValid())
650 return QModelIndex();
651 // the child is the RepoItem pointed by the index.
652 auto *childItem = static_cast<RepoItem *>(index.internalPointer());
653 // the parent is the parent of the RepoItem.
654 RepoItem *parentItem = childItem->parent();
655 // the root item does not have a parent
656 if (parentItem == rootItem)
657 return QModelIndex();
658 // create the index and return
659 return createIndex(parentItem->row(), 0, parentItem);
660}
667int RepoModel::rowCount(const QModelIndex &parent) const {
668 const RepoItem *parentItem;
669
670 if (parent.column() > 0)
671 return 0; // there are rows defined only of the column 0
672
673 if (!parent.isValid())
674 parentItem = rootItem;
675 else
676 parentItem = static_cast<RepoItem *>(parent.internalPointer());
677 // return the number of children
678 return parentItem->childCount();
679}
680
687int RepoModel::columnCount(const QModelIndex & /*parent*/) const { return 4; }
688
691QString RepoModel::fileDescription(const QModelIndex &index) {
692 const auto *item = static_cast<RepoItem *>(index.internalPointer());
693 if (!item)
694 return "";
695 QString desc;
696 try {
697 desc = QString::fromStdString(repo_ptr->description(item->path().toStdString()));
698 } catch (...) {
699 // just ignore
700 }
701 return desc;
702}
703
704QString RepoModel::author(const QModelIndex &index) {
705 const auto *item = static_cast<RepoItem *>(index.internalPointer());
706 QString author = "Not defined";
707 if (!item)
708 return author;
709 try {
710 author = QString::fromStdString(repo_ptr->info(item->path().toStdString()).author);
711 } catch (...) {
712 // just ignore
713 }
714 return author;
715}
721QString RepoModel::filePath(const QModelIndex &index) {
722 const auto *item = static_cast<RepoItem *>(index.internalPointer());
723 // qDebug() << "Get file path from : " << item->path()<< '\n';
724 Mantid::API::SCRIPTSTATUS state = repo_ptr->fileStatus(item->path().toStdString());
725
726 if (state == Mantid::API::REMOTE_ONLY)
727 return "";
728 Mantid::API::ScriptInfo info = repo_ptr->fileInfo(item->path().toStdString());
729 if (info.directory)
730 return "";
731 QString path = repo_path + "/" + item->path();
732 return path;
733}
734
755 // in order to speed the algorithm, check if the
756 // folder is the same of the last folder.
757 if (parents.last()->path() == folder)
758 return parents.last();
759
760 // try to find this
761 if (folder.isEmpty())
762 return parents.first(); // the parents first will always contain the root
763
764 // it will iterate through all the parents of the given folder, in order to
765 // create any folder that has not been created.
766 QStringList folder_parts = folder.split("/");
767 QString aux_folder;
768 RepoItem *father = parents.first();
769 // there is no reason to try to find entry A/B/C if the entry A/B was not
770 // found
771 bool try_to_find = true;
772
773 for (int i = 0; i < folder_parts.size(); i++) {
774 if (i == 0)
775 aux_folder = folder_parts[i];
776 else
777 aux_folder += "/" + folder_parts[i];
778
779 bool found = false;
780
781 if (try_to_find) {
782 // this means that the previous folders were found
783 const auto it = std::find_if(parents.cbegin(), parents.cend(),
784 [&aux_folder](const auto &parent) { return parent->path() == aux_folder; });
785 if (it != parents.cend()) {
786 found = true;
787 father = *it;
788 }
789 }
790 // there is not RepoItem related to the current folder,
791 // create it
792 if (!found) {
793 RepoItem *m = new RepoItem(folder_parts[i], aux_folder, father);
794 father->appendChild(m);
795 parents.append(m);
796 father = m;
797 try_to_find = false;
798 }
799 }
800 return father;
801}
802
815 // check server for updates to repository
816 repo_ptr->check4Update();
817 // get the list of entries inside the scriptrepository
818 std::vector<std::string> list = repo_ptr->listFiles();
819
820 // auxiliary list of pointers to repoitem that are related to folders
821 QList<RepoItem *> parents;
822 // the first one will always be the root
823 parents << root;
824
825 // FOREACH entry in LISTFILES
826 for (const auto &number : list) {
827 // folder or file inside the repository
828 QString lineData = QString::fromStdString(number);
829
830 // Read the column data from the rest of the line.
831 QStringList pathStrings = lineData.split("/");
832 // separate the folder and the current entry (folder or file)
833 QString current_file = pathStrings.last();
834 QString folder = "";
835 pathStrings.removeLast();
836 if (pathStrings.size() > 0)
837 folder = pathStrings.join("/");
838
839 // get parent for this entry
840 RepoItem *parentOfFolder = getParent(folder, parents);
841 // a new folder has started
842 if (parentOfFolder == root) {
843 // this test is just for the sake of performance, to reduce the numbers of
844 // parents
845 parents.clear();
846 parents << root;
847 }
848
849 // check if the current entry is a directory
850 if (repo_ptr->info(lineData.toStdString()).directory) {
851 // directories will be appended to parents list
852 RepoItem *aux = new RepoItem(current_file, lineData, parentOfFolder);
853 parentOfFolder->appendChild(aux);
854 parents << aux;
855 } else {
856 // files will just be created and appended to the parent
857 parentOfFolder->appendChild(new RepoItem(current_file, lineData, parentOfFolder));
858 }
859 }
860}
861
863 bool showWarning) const {
864 g_log.information() << "Download failed " << ex.what() << "\n Detail: " << ex.systemError() << '\n';
865 if (showWarning) {
866
867 QWidget *father = qobject_cast<QWidget *>(QObject::parent());
868 QString info = QString::fromStdString(ex.what());
869 // make the exception a nice html message
870 info.replace("\n", "</p><p>");
871 QMessageBox::warning(father, title, QString("<html><body><p>%1</p></body></html>").arg(info));
872 }
873}
874
876 QString info = download_threads.result();
877 if (!info.isEmpty()) {
878 QMessageBox::warning(qobject_cast<QWidget *>(QObject::parent()), "Download Failed",
879 QString("<html><body><p>%1</p></body></html>").arg(info));
880 }
882 auto *repo_item = static_cast<RepoItem *>(download_index.internalPointer());
883 QModelIndex top_left = createIndex(0, 0, repo_item);
884 QModelIndex bottom_right = createIndex(0, 3, repo_item);
885 emit dataChanged(top_left, bottom_right);
886 emit executingThread(false);
887}
888
889bool RepoModel::isDownloading(const QModelIndex &index) const {
890 const auto *item = static_cast<RepoItem *>(index.internalPointer());
891 if (item)
892 return item->path() == downloading_path;
893 return false;
894}
895
897 QString info = upload_threads.result();
898 QString title = "Upload Failed";
899 if (info.contains(delete_mark)) {
900 info.replace(delete_mark, "");
901 title = "Delete Failed";
902 }
903
904 if (!info.isEmpty()) {
905 QMessageBox::warning(qobject_cast<QWidget *>(QObject::parent()), title,
906 QString("<html><body><p>%1</p></body></html>").arg(info));
907 }
908
910 auto *repo_item = static_cast<RepoItem *>(upload_index.internalPointer());
911 QModelIndex top_left = createIndex(0, 0, repo_item);
912 QModelIndex bottom_right = createIndex(0, 3, repo_item);
913 emit dataChanged(top_left, bottom_right);
914 emit executingThread(false);
915}
916
917bool RepoModel::isUploading(const QModelIndex &index) const {
918 const auto *item = static_cast<RepoItem *>(index.internalPointer());
919 if (item)
920 return item->path() == uploading_path;
921 return false;
922}
923
925const QString &RepoModel::localOnlySt() { return LOCALONLY; }
927const QString &RepoModel::remoteOnlySt() { return REMOTEONLY; }
929const QString &RepoModel::localChangedSt() { return LOCALCHANGED; }
931const QString &RepoModel::remoteChangedSt() { return REMOTECHANGED; }
933const QString &RepoModel::updatedSt() { return BOTHUNCHANGED; }
935const QString &RepoModel::bothChangedSt() { return BOTHCHANGED; }
937const QString &RepoModel::downloadSt() { return DOWNLOADST; }
939const QString &RepoModel::uploadSt() { return UPLOADST; }
940
941RepoModel::UploadForm::UploadForm(const QString &file2upload, QWidget *parent) : QDialog(parent) {
942 author_le = new QLineEdit();
943 email_le = new QLineEdit();
944 save_ck = new QCheckBox("Save your personal information");
945 save_ck->setToolTip("The author and email will be saved and will be written "
946 "to you next time");
947 comment_te = new QTextEdit();
948
949 // setup the layout
950
951 auto *personalGroupBox = new QGroupBox("Personal Group Box");
952 auto *personalLayout = new QFormLayout();
953 personalLayout->addRow("Author", author_le);
954 personalLayout->addRow("Email", email_le);
955 auto *gpBox = new QVBoxLayout();
956 gpBox->addWidget(save_ck);
957 gpBox->addLayout(personalLayout);
958 personalGroupBox->setLayout(gpBox);
959
960 QLabel *cmLabel = new QLabel("Comment");
961 auto *buttonBox = new QDialogButtonBox();
962 buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
963
964 auto *layout = new QVBoxLayout();
965 layout->addWidget(personalGroupBox);
966 layout->addWidget(cmLabel);
967 layout->addWidget(comment_te);
968 layout->addWidget(buttonBox);
969 setLayout(layout);
970
971 setWindowTitle(QString("Upload - %2").arg(file2upload));
972 connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
973 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
974}
976QString RepoModel::UploadForm::email() { return email_le->text(); }
977QString RepoModel::UploadForm::author() { return author_le->text(); }
978QString RepoModel::UploadForm::comment() { return comment_te->toPlainText(); }
979bool RepoModel::UploadForm::saveInfo() { return save_ck->isChecked(); }
980void RepoModel::UploadForm::setEmail(const QString &email) { email_le->setText(email); }
981void RepoModel::UploadForm::setAuthor(const QString &author) { author_le->setText(author); }
983 save_ck->setCheckState(option ? Qt::Checked : Qt::Unchecked);
984}
985
987 : QMessageBox(QMessageBox::Question, "Delete file", "", QMessageBox::Yes | QMessageBox::No, parent) {
988 using namespace Mantid::API;
989 QString info_str;
990 QTextStream info(&info_str);
991
992 info << "<html><head/><body><p>Are you sure you want to delete this file "
993 "from the Repository?</p><p align=\"center\"><span style=\" "
994 "font-style:italic;\">"
995 << path << "</span></p></body></html>";
996
997 // creation of the new widgets
998 comment_te = nullptr;
999
1000 setText(info_str);
1001
1002 QGridLayout *_lay = qobject_cast<QGridLayout *>(layout());
1003 if (_lay) {
1004 QLayoutItem *buttons = _lay->takeAt(_lay->count() - 1);
1005 QLabel *la = new QLabel("Please, give the reason for deleting:", this);
1006 comment_te = new QTextEdit(this);
1007 comment_te->setMaximumHeight(70);
1008 _lay->addWidget(la, _lay->rowCount(), 0, 1, -1);
1009 _lay->addWidget(comment_te, _lay->rowCount(), 0, 2, -1);
1010 _lay->addItem(buttons, _lay->rowCount(), 0, 1, -1);
1011 }
1012}
1013
1016 if (comment_te)
1017 return comment_te->toPlainText();
1018 else
1019 return QString();
1020}
double value
The value of the point.
Definition FitMW.cpp:51
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.
Definition RepoModel.cpp:49
const char * nofile_flag
Definition RepoModel.cpp:45
const char * delete_mark
Definition RepoModel.cpp:44
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.
Definition RepoModel.cpp:64
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.
Definition RepoModel.cpp:77
Auxiliary Dialog to get the option from the user about removing the entries from the local folder or ...
Definition RepoModel.h:153
DeleteQueryBox(const QString &path, QWidget *parent=nullptr)
A nested class to help RepoModel to implement the QAbstractItemModel.
Definition RepoModel.h:87
RepoItem * parent() const
access to the parent of this entry
Definition RepoModel.h:109
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
Definition RepoModel.h:103
RepoItem * child(int row) const
Gives access to the row_th children of RepoItem.
QList< RepoItem * > childItems
track the list of children for this entry
Definition RepoModel.h:115
~RepoItem()
destruct all the childItems.
UploadForm(const QString &file2upload, QWidget *parent=nullptr)
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
Definition RepoModel.h:240
Mantid::API::ScriptRepository_sptr repo_ptr
pointer to the ScriptRepository
Definition RepoModel.h:211
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
Definition RepoModel.h:226
QFutureWatcher< QString > download_watcher
Definition RepoModel.h:225
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
Definition RepoModel.h:237
QString repo_path
ScriptLocalRepository path, to be able to retrieve the absolute path.
Definition RepoModel.h:213
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
Definition RepoModel.h:209
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
Definition RepoModel.h:224
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.
Definition Logger.h:51
void information(const std::string &msg)
Logs at information level.
Definition Logger.cpp:136
const QString LOCALCHANGED
Definition RepoModel.h:29
const QString REMOTECHANGED
Definition RepoModel.h:30
const QString DELETABLEENTRY
Definition RepoModel.h:36
const QString BOTHUNCHANGED
Definition RepoModel.h:31
const QString REMOTEONLY
Definition RepoModel.h:27
const QString LOCALONLY
Definition RepoModel.h:28
const QString UPLOADST
Definition RepoModel.h:33
const QString BOTHCHANGED
Definition RepoModel.h:32
const QString DOWNLOADST
Definition RepoModel.h:34
const QString PROTECTEDENTRY
Definition RepoModel.h:35
std::shared_ptr< ScriptRepository > ScriptRepository_sptr
shared pointer to the function base class
Mantid::Kernel::SingletonHolder< ScriptRepositoryFactoryImpl > ScriptRepositoryFactory
SCRIPTSTATUS
Represent the possible states for a given file:
Kernel::Logger g_log("DetermineSpinStateOrder")
Mantid::Kernel::SingletonHolder< ConfigServiceImpl > ConfigService
STL namespace.
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.