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 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 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 author = settings.value("UploadAuthor", QString()).toString();
447 bool lastChk = settings.value("UploadSaveInfo", false).toBool();
448 if (!email.isEmpty())
449 form->setEmail(email);
450 if (!author.isEmpty())
451 form->setAuthor(author);
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 = new DeleteQueryBox(QString::fromStdString(path), father);
502
503 if (box->exec() != QMessageBox::Yes) {
504 // the user gave up deleting this entry, release memory
505 delete box;
506 box = nullptr;
507 return false;
508 }
509
510 // get the options from the user
511 QString comment(box->comment());
512 { // release memory
513 delete box;
514 box = nullptr;
515 }
516
517 // remove from central repository
518 // currently, directories can not be deleted recursively
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");
524 return false;
525 };
526
527 // check if the reason was given and it is valid
528 if (comment.isEmpty()) {
529 QMessageBox::information(father, "Not Allowed", "You are not allowed to delete one file without a reason");
530 return false;
531 }
532
533 // we will not allow them to remove if they have no e-mail and author saved
534 QSettings settings;
535 settings.beginGroup("Mantid/ScriptRepository");
536 QString email = settings.value("UploadEmail", QString()).toString();
537 QString author = settings.value("UploadAuthor", QString()).toString();
538 settings.endGroup();
539
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");
544 return false;
545 }
546
547 // we have all we need to delete from the central repository
548 // execute the delete in a separate thread, we will use the upload
549 // established way, because,
550 // it will connect to the same server to delete.
552 uploading_path = QString::fromStdString(path);
553 emit executingThread(true);
554 upload_threads = QtConcurrent::run(delete_thread, repo_ptr, path, email, author, comment);
556 ret = true;
557 } // end delete action
558
559 if (ret)
560 emit dataChanged(index, this->index(count_changed, 0, index));
561
562 return ret;
563}
564
572Qt::ItemFlags RepoModel::flags(const QModelIndex &index) const {
573 if (!index.isValid())
574 return {};
575 if (index.column() == 0)
576 return QAbstractItemModel::flags(index);
577 // define that setData will accept the EditRole.
578 return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
579}
580
595QVariant RepoModel::headerData(int section, Qt::Orientation orientation, int role) const {
596 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
597 switch (section) {
598 case 0:
599 return "Path";
600 case 1:
601 return "Status";
602 case 2:
603 return "AutoUpdate";
604 case 3:
605 return "Delete";
606 default:
607 return QVariant();
608 }
609 }
610 return QVariant();
611}
612
627QModelIndex RepoModel::index(int row, int column, const QModelIndex &parent) const {
628 // check if the row and column are allowed,
629 // for example, it will not accept column == 3, or row = 1
630 // for parent that refers to file and not to folder.
631 if (!hasIndex(row, column, parent))
632 return QModelIndex();
633 // retrieve the pointer ot the RepoItem from the parent
634 RepoItem *parentItem;
635 if (!parent.isValid())
636 parentItem = rootItem;
637 else
638 parentItem = static_cast<RepoItem *>(parent.internalPointer());
639
640 // given the row, we can find the childItem from the RepoItem::child method.
641 RepoItem *childItem = parentItem->child(row);
642
643 if (childItem)
644 return createIndex(row, column, childItem);
645 else
646 return QModelIndex();
647}
648
654QModelIndex RepoModel::parent(const QModelIndex &index) const {
655 if (!index.isValid())
656 return QModelIndex();
657 // the child is the RepoItem pointed by the index.
658 auto *childItem = static_cast<RepoItem *>(index.internalPointer());
659 // the parent is the parent of the RepoItem.
660 RepoItem *parentItem = childItem->parent();
661 // the root item does not have a parent
662 if (parentItem == rootItem)
663 return QModelIndex();
664 // create the index and return
665 return createIndex(parentItem->row(), 0, parentItem);
666}
673int RepoModel::rowCount(const QModelIndex &parent) const {
674 RepoItem *parentItem;
675
676 if (parent.column() > 0)
677 return 0; // there are rows defined only of the column 0
678
679 if (!parent.isValid())
680 parentItem = rootItem;
681 else
682 parentItem = static_cast<RepoItem *>(parent.internalPointer());
683 // return the number of children
684 return parentItem->childCount();
685}
686
693int RepoModel::columnCount(const QModelIndex & /*parent*/) const { return 4; }
694
697QString RepoModel::fileDescription(const QModelIndex &index) {
698 auto *item = static_cast<RepoItem *>(index.internalPointer());
699 if (!item)
700 return "";
701 QString desc;
702 try {
703 desc = QString::fromStdString(repo_ptr->description(item->path().toStdString()));
704 } catch (...) {
705 // just ignore
706 }
707 return desc;
708}
709
710QString RepoModel::author(const QModelIndex &index) {
711 auto *item = static_cast<RepoItem *>(index.internalPointer());
712 QString author = "Not defined";
713 if (!item)
714 return author;
715 try {
716 author = QString::fromStdString(repo_ptr->info(item->path().toStdString()).author);
717 } catch (...) {
718 // just ignore
719 }
720 return author;
721}
727QString RepoModel::filePath(const QModelIndex &index) {
728 auto *item = static_cast<RepoItem *>(index.internalPointer());
729 // qDebug() << "Get file path from : " << item->path()<< '\n';
730 Mantid::API::SCRIPTSTATUS state = repo_ptr->fileStatus(item->path().toStdString());
731
732 if (state == Mantid::API::REMOTE_ONLY)
733 return "";
734 Mantid::API::ScriptInfo info = repo_ptr->fileInfo(item->path().toStdString());
735 if (info.directory)
736 return "";
737 QString path = repo_path + "/" + item->path();
738 return path;
739}
740
761 // in order to speed the algorithm, check if the
762 // folder is the same of the last folder.
763 if (parents.last()->path() == folder)
764 return parents.last();
765
766 // try to find this
767 if (folder.isEmpty())
768 return parents.first(); // the parents first will always contain the root
769
770 // it will iterate through all the parents of the given folder, in order to
771 // create any folder that has not been created.
772 QStringList folder_parts = folder.split("/");
773 QString aux_folder;
774 RepoItem *father = parents.first();
775 // there is no reason to try to find entry A/B/C if the entry A/B was not
776 // found
777 bool try_to_find = true;
778
779 for (int i = 0; i < folder_parts.size(); i++) {
780 if (i == 0)
781 aux_folder = folder_parts[i];
782 else
783 aux_folder += "/" + folder_parts[i];
784
785 bool found = false;
786
787 if (try_to_find) {
788 // this means that the previous folders were found
789 foreach (RepoItem *the_parent, parents) {
790 if (the_parent->path() == aux_folder) {
791 found = true;
792 father = the_parent;
793 break;
794 }
795 }
796 }
797 // there is not RepoItem related to the current folder,
798 // create it
799 if (!found) {
800 RepoItem *m = new RepoItem(folder_parts[i], aux_folder, father);
801 father->appendChild(m);
802 parents.append(m);
803 father = m;
804 try_to_find = false;
805 }
806 }
807 return father;
808}
809
822
823 QStringList lines;
824 // check server for updates to repository
825 repo_ptr->check4Update();
826 // get the list of entries inside the scriptrepository
827 std::vector<std::string> list = repo_ptr->listFiles();
828
829 // auxiliary list of pointers to repoitem that are related to folders
830 QList<RepoItem *> parents;
831 // the first one will always be the root
832 parents << root;
833
834 // FOREACH entry in LISTFILES
835 for (const auto &number : list) {
836 // folder or file inside the repository
837 QString lineData = QString::fromStdString(number);
838
839 // Read the column data from the rest of the line.
840 QStringList pathStrings = lineData.split("/");
841 // separate the folder and the current entry (folder or file)
842 QString current_file = pathStrings.last();
843 QString folder = "";
844 pathStrings.removeLast();
845 if (pathStrings.size() > 0)
846 folder = pathStrings.join("/");
847
848 // get parent for this entry
849 RepoItem *parent = getParent(folder, parents);
850 // a new folder has started
851 if (parent == root) {
852 // this test is just for the sake of performance, to reduce the numbers of
853 // parents
854 parents.clear();
855 parents << root;
856 }
857
858 // check if the current entry is a directory
859 if (repo_ptr->info(lineData.toStdString()).directory) {
860 // directories will be appended to parents list
861 RepoItem *aux = new RepoItem(current_file, lineData, parent);
862 parent->appendChild(aux);
863 parents << aux;
864 } else {
865 // files will just be created and appended to the parent
866 parent->appendChild(new RepoItem(current_file, lineData, parent));
867 }
868 }
869}
871 bool showWarning) const {
872 g_log.information() << "Download failed " << ex.what() << "\n Detail: " << ex.systemError() << '\n';
873 if (showWarning) {
874
875 QWidget *father = qobject_cast<QWidget *>(QObject::parent());
876 QString info = QString::fromStdString(ex.what());
877 // make the exception a nice html message
878 info.replace("\n", "</p><p>");
879 QMessageBox::warning(father, title, QString("<html><body><p>%1</p></body></html>").arg(info));
880 }
881}
882
884 QString info = download_threads.result();
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));
888 }
890 auto *repo_item = static_cast<RepoItem *>(download_index.internalPointer());
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);
894 emit executingThread(false);
895}
896
897bool RepoModel::isDownloading(const QModelIndex &index) const {
898 auto *item = static_cast<RepoItem *>(index.internalPointer());
899 if (item)
900 return item->path() == downloading_path;
901 return false;
902}
903
905 QString info = upload_threads.result();
906 QString title = "Upload Failed";
907 if (info.contains(delete_mark)) {
908 info.replace(delete_mark, "");
909 title = "Delete Failed";
910 }
911
912 if (!info.isEmpty()) {
913 QMessageBox::warning(qobject_cast<QWidget *>(QObject::parent()), title,
914 QString("<html><body><p>%1</p></body></html>").arg(info));
915 }
916
918 auto *repo_item = static_cast<RepoItem *>(upload_index.internalPointer());
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);
922 emit executingThread(false);
923}
924
925bool RepoModel::isUploading(const QModelIndex &index) const {
926 auto *item = static_cast<RepoItem *>(index.internalPointer());
927 if (item)
928 return item->path() == uploading_path;
929 return false;
930}
931
933const QString &RepoModel::localOnlySt() { return LOCALONLY; }
935const QString &RepoModel::remoteOnlySt() { return REMOTEONLY; }
937const QString &RepoModel::localChangedSt() { return LOCALCHANGED; }
939const QString &RepoModel::remoteChangedSt() { return REMOTECHANGED; }
941const QString &RepoModel::updatedSt() { return BOTHUNCHANGED; }
943const QString &RepoModel::bothChangedSt() { return BOTHCHANGED; }
945const QString &RepoModel::downloadSt() { return DOWNLOADST; }
947const QString &RepoModel::uploadSt() { return UPLOADST; }
948
949RepoModel::UploadForm::UploadForm(const QString &file2upload, QWidget *parent) : QDialog(parent) {
950 author_le = new QLineEdit();
951 email_le = new QLineEdit();
952 save_ck = new QCheckBox("Save your personal information");
953 save_ck->setToolTip("The author and email will be saved and will be written "
954 "to you next time");
955 comment_te = new QTextEdit();
956
957 // setup the layout
958
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();
964 gpBox->addWidget(save_ck);
965 gpBox->addLayout(personalLayout);
966 personalGroupBox->setLayout(gpBox);
967
968 QLabel *cmLabel = new QLabel("Comment");
969 auto *buttonBox = new QDialogButtonBox();
970 buttonBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
971
972 auto *layout = new QVBoxLayout();
973 layout->addWidget(personalGroupBox);
974 layout->addWidget(cmLabel);
975 layout->addWidget(comment_te);
976 layout->addWidget(buttonBox);
977 setLayout(layout);
978
979 setWindowTitle(QString("Upload - %2").arg(file2upload));
980 connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
981 connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
982}
984QString RepoModel::UploadForm::email() { return email_le->text(); }
985QString RepoModel::UploadForm::author() { return author_le->text(); }
986QString RepoModel::UploadForm::comment() { return comment_te->toPlainText(); }
987bool RepoModel::UploadForm::saveInfo() { return save_ck->isChecked(); }
988void RepoModel::UploadForm::setEmail(const QString &email) { email_le->setText(email); }
989void RepoModel::UploadForm::setAuthor(const QString &author) { author_le->setText(author); }
991 save_ck->setCheckState(option ? Qt::Checked : Qt::Unchecked);
992}
993
995 : QMessageBox(QMessageBox::Question, "Delete file", "", QMessageBox::Yes | QMessageBox::No, parent) {
996 using namespace Mantid::API;
997 QString info_str;
998 QTextStream info(&info_str);
999
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>";
1004
1005 // creation of the new widgets
1006 comment_te = nullptr;
1007
1008 setText(info_str);
1009
1010 QGridLayout *_lay = qobject_cast<QGridLayout *>(layout());
1011 if (_lay) {
1012 QLayoutItem *buttons = _lay->takeAt(_lay->count() - 1);
1013 QLabel *la = new QLabel("Please, give the reason for deleting:", this);
1014 comment_te = new QTextEdit(this);
1015 comment_te->setMaximumHeight(70);
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);
1019 }
1020}
1021
1024 if (comment_te)
1025 return comment_te->toPlainText();
1026 else
1027 return QString();
1028}
double value
The value of the point.
Definition: FitMW.cpp:51
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
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)
Definition: RepoModel.cpp:994
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.
Definition: RepoModel.cpp:136
void appendChild(RepoItem *child)
This method is the very responsible to allow the reconstruction of the hierarchical tree,...
Definition: RepoModel.cpp:107
int row() const
To which row this repoItem belongs?
Definition: RepoModel.cpp:129
RepoItem(QString label, QString path="/", RepoItem *parent=nullptr)
Definition: RepoModel.cpp:100
int childCount() const
Return the number of children that this entry may find.
Definition: RepoModel.cpp:125
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.
Definition: RepoModel.cpp:120
~RepoItem()
destruct all the childItems.
Definition: RepoModel.cpp:103
UploadForm(const QString &file2upload, QWidget *parent=nullptr)
Definition: RepoModel.cpp:949
void setEmail(const QString &)
Definition: RepoModel.cpp:988
void setAuthor(const QString &)
Definition: RepoModel.cpp:989
RepoModel(QObject *parent=nullptr)
constructor
Definition: RepoModel.cpp:154
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...
Definition: RepoModel.cpp:673
Qt::ItemFlags flags(const QModelIndex &index) const override
information on the available interaction
Definition: RepoModel.cpp:572
static const QString & localChangedSt()
Definition: RepoModel.cpp:937
QFutureWatcher< QString > upload_watcher
Definition: RepoModel.h:238
Mantid::API::ScriptRepository_sptr repo_ptr
pointer to the ScriptRepository
Definition: RepoModel.h:209
QString filePath(const QModelIndex &index)
Return the operative system file path if it exists.
Definition: RepoModel.cpp:727
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
header strings
Definition: RepoModel.cpp:595
QModelIndex download_index
Definition: RepoModel.h:224
QFutureWatcher< QString > download_watcher
Definition: RepoModel.h:223
bool isUploading(const QModelIndex &index) const
Definition: RepoModel.cpp:925
QString author(const QModelIndex &index)
Definition: RepoModel.cpp:710
bool isDownloading(const QModelIndex &index) const
Definition: RepoModel.cpp:897
static const QString & remoteChangedSt()
Definition: RepoModel.cpp:939
QFuture< QString > upload_threads
Definition: RepoModel.h:235
QString repo_path
ScriptLocalRepository path, to be able to retrieve the absolute path.
Definition: RepoModel.h:211
int columnCount(const QModelIndex &parent=QModelIndex()) const override
provide the number of the columns
Definition: RepoModel.cpp:693
const QString & fromStatus(Mantid::API::SCRIPTSTATUS status) const
auxiliary method to match the ScriptStatus to string
Definition: RepoModel.cpp:348
static const QString & updatedSt()
Definition: RepoModel.cpp:941
static const QString & uploadSt()
Definition: RepoModel.cpp:947
static const QString & bothChangedSt()
Definition: RepoModel.cpp:943
RepoItem * rootItem
pointer to the RepoItem root
Definition: RepoModel.h:207
RepoItem * getParent(const QString &folder, QList< RepoItem * > &parents)
auxiliary method to help populating the model
Definition: RepoModel.cpp:760
QVariant data(const QModelIndex &index, int role) const override
access to the ScriptRepository data
Definition: RepoModel.cpp:212
void handleExceptions(const Mantid::API::ScriptRepoException &ex, const QString &title, bool showWarning=true) const
auxiliary method to deal with exceptions
Definition: RepoModel.cpp:870
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
change data
Definition: RepoModel.cpp:384
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
access to the index
Definition: RepoModel.cpp:627
QFuture< QString > download_threads
Definition: RepoModel.h:222
QModelIndex parent(const QModelIndex &index) const override
access to parent
Definition: RepoModel.cpp:654
QString fileDescription(const QModelIndex &index)
Return the description of the file for a defined entry.
Definition: RepoModel.cpp:697
static const QString & localOnlySt()
Definition: RepoModel.cpp:933
void setupModelData(RepoItem *parent)
auxiliary method to populate the model
Definition: RepoModel.cpp:821
static const QString & downloadSt()
Definition: RepoModel.cpp:945
static const QString & remoteOnlySt()
Definition: RepoModel.cpp:935
QModelIndex upload_index
Definition: RepoModel.h:241
~RepoModel() override
destructor
Definition: RepoModel.cpp:170
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...
Definition: ConfigService.h:63
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:52
void information(const std::string &msg)
Logs at information level.
Definition: Logger.cpp:105
Manage the lifetime of a class intended to be a singleton.
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
Kernel::Logger g_log("ExperimentInfo")
static logger object
SCRIPTSTATUS
Represent the possible states for a given file:
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.