Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
# Created by Mike Wille, SLTE, 2020-03-23
|
||||
#
|
||||
|
||||
ADD_SUBDIRECTORY(Common)
|
||||
ADD_SUBDIRECTORY(ThpManagement)
|
||||
ADD_SUBDIRECTORY(ThpUsbManagement)
|
||||
|
||||
ADD_INTERFACE_LIBRARY(TpmGuiPluginInterface
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tpm_gui_plugin_interface.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
||||
GuiPluginInterface
|
||||
)
|
||||
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# $Id: CMakeLists.txt 51804 2020-07-31 04:47:28Z fritsche_h $
|
||||
# $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/CMakeLists.txt $
|
||||
# $Author: fritsche_h $
|
||||
#
|
||||
# Created by Mike Wille, SLTE, 2020-03-23
|
||||
#
|
||||
|
||||
SET(src
|
||||
logger.cpp
|
||||
logger.h
|
||||
tpm_exported_scripts_model.cpp
|
||||
tpm_exported_scripts_model.h
|
||||
tpm_process_dialog.cpp
|
||||
tpm_process_dialog.h
|
||||
)
|
||||
|
||||
QT5_WRAP_UI(src
|
||||
tpm_process_dialog.ui
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY2(WS ThpCommon SHARED ${src})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(ThpCommon
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../ # export file
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(ThpCommon
|
||||
Qt5::Core
|
||||
Qt5::Concurrent
|
||||
NGLLogger
|
||||
LtsSession
|
||||
AsmDataPluginInterface
|
||||
ExmDataPluginInterface
|
||||
#nglcompression
|
||||
#nglsettings
|
||||
#ngltools
|
||||
#LtsSessionData
|
||||
#httq
|
||||
)
|
||||
|
||||
NGL_INSTALL_TARGET(ThpCommon)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Building Config - logging facility
|
||||
* $Id: logger.cpp 46225 2019-03-25 13:59:56Z rudolphus_g $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/logger.cpp $
|
||||
* $Author: rudolphus_g $
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "TPM.Common.";
|
||||
std::string loggerName;
|
||||
const size_t len = strlen(name);
|
||||
loggerName.reserve(sizeof(ns) + len);
|
||||
loggerName.append(ns, sizeof(ns) - 1);
|
||||
loggerName.append(name, len);
|
||||
|
||||
try
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
|
||||
getNGLLogger(loggerName);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace TakeHomePackageManager
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Logging for CentralEffectSimulation
|
||||
* $Id: logger.h 46225 2019-03-25 13:59:56Z rudolphus_g $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/logger.h $
|
||||
* $Author: rudolphus_g $
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
typedef NGL::INGLLogger &LOGGER_T;
|
||||
|
||||
LOGGER_T getLogger(const char *name);
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
} // namespace TakeHomePackageManager
|
||||
+632
@@ -0,0 +1,632 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Show the exported scripts and allow them to upload them to the server
|
||||
* $Id: tpm_exported_scripts_model.cpp 53111 2021-03-22 08:21:29Z wille_m $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/tpm_exported_scripts_model.cpp $
|
||||
* $Author: wille_m $
|
||||
* Created by Gerlinde Rudolphus, NLE, 2019-03-25
|
||||
*/
|
||||
|
||||
#include "tpm_exported_scripts_model.h"
|
||||
|
||||
#include <ngltools/ngltools_dtg.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
|
||||
ExportedScriptsModel::ExportedScriptsModel(QObject *parent)
|
||||
: LtsWidgets::LtsAbstractTableModel<ExportedScriptInformation>(
|
||||
{ tr("id"), tr("Exercise"), tr("Name"), tr("Created"), tr("Last downloaded"), tr("Location"), tr("Last uploaded"), tr("Server")}, parent)
|
||||
, m_logger(getLogger("ExportedScriptsModel"))
|
||||
{}
|
||||
|
||||
bool ExportedScriptsModel::init(const QString &rootDirectoryToScan)
|
||||
{
|
||||
std::shared_ptr<int> _(nullptr, [this](int *) { endResetModel(); }); // TODO: QScopeGuard
|
||||
m_rootDirectoryToScan = rootDirectoryToScan;
|
||||
beginResetModel();
|
||||
m_vecData.clear();
|
||||
|
||||
QVector <int> localExercises;
|
||||
DEBUG_LOG(m_logger) << "ExportedScriptsModel::init rootDirectoryToScan=" << rootDirectoryToScan
|
||||
/*<< " directoryToScan=" << directoryToScan*/;
|
||||
|
||||
//clear(); multiple inits needed, don't clear
|
||||
|
||||
// die Skripte aller Uebungen auf der lokalen Workstation anzeigen.
|
||||
// Die Uebungen sind in der Datei /tmp/THP-xxxxxxx/data.json im Array Exercises enthalten.
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Get all local exercises rootDirectoryToScan=" << rootDirectoryToScan ;
|
||||
QFile file(rootDirectoryToScan + QDir::separator() + QStringLiteral("exercises.json"));
|
||||
if (!file.open(QFile::ReadOnly)) // file only exists after a first download, but that's okay
|
||||
WARNING_LOG(m_logger) << "Cannot open " << file.fileName() << " for read/write: " << file.errorString();
|
||||
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(file.readAll()));
|
||||
const QJsonObject obj = doc.object(); // okay to be empty
|
||||
const QJsonArray arr = obj[QStringLiteral("Exercises")].toArray();
|
||||
localExercises.reserve(arr.size());
|
||||
for (const auto &ele : arr)
|
||||
localExercises.append(ele.toInt());
|
||||
}
|
||||
|
||||
WARNING_LOG(m_logger) << "local exericses: " << localExercises.count();
|
||||
|
||||
// Alle lokalen Übungen:
|
||||
for (const int exId : qAsConst(localExercises))
|
||||
{
|
||||
const QString baseDir = exercisePath(rootDirectoryToScan, exId);
|
||||
QFile file(baseDir + QDir::separator() + QStringLiteral("data.json"));
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Cannot open " << file.fileName() << " for reading: " << file.errorString() << " - not critical";
|
||||
// There are no local scripts but maybe some are on the server
|
||||
return true;
|
||||
}
|
||||
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(file.readAll()));
|
||||
const QJsonObject obj = doc.object();
|
||||
const QJsonArray presentations = obj[QStringLiteral("presentations")].toArray();
|
||||
|
||||
DEBUG_LOG(m_logger) << "exercise: " << exId << ", presentations: " << presentations.size();
|
||||
|
||||
for (const QJsonValue &val : presentations)
|
||||
{
|
||||
ExportedScriptInformation esi = ExportedScriptInformation::fromJson(val);
|
||||
DEBUG_LOG(m_logger) << "obj=" << QJsonDocument(obj).toJson(QJsonDocument::Compact);
|
||||
const QJsonObject presentationObj = val.toObject();
|
||||
DEBUG_LOG(m_logger) << "presentationObj=" << QJsonDocument(presentationObj).toJson(QJsonDocument::Compact);
|
||||
if (obj.contains(QStringLiteral("exerciseId")))
|
||||
{
|
||||
esi.exerciseId = obj[QStringLiteral("exerciseId")].toInt();
|
||||
esi.exerciseName = obj[QStringLiteral("exerciseName")].toString();
|
||||
if (presentationObj.contains(QStringLiteral("name")) )
|
||||
esi.scriptName = presentationObj[QStringLiteral("name")].toString();
|
||||
if (presentationObj.contains(QStringLiteral("displayName")) )
|
||||
esi.scriptName = presentationObj[QStringLiteral("displayName")].toString();
|
||||
}
|
||||
|
||||
esi.local = true;
|
||||
DEBUG_LOG(m_logger) << "push_back "
|
||||
<< " exportTime=" << esi.exportTime
|
||||
<< " scriptId=" << esi.scriptId
|
||||
<< " scriptName=" << esi.scriptName
|
||||
<< " exerciseId=" << esi.exerciseId
|
||||
<< " exerciseName=" << esi.exerciseName
|
||||
<< " local=" << esi.local;
|
||||
esi.uploaded = ThpUnknownUploadState;
|
||||
|
||||
esi.rootDirectory = rootDirectoryToScan; // to determine if this script is from THP-Download or THP-Export directory (for USB Management, which can copy from both dirs)
|
||||
|
||||
m_vecData.push_back(esi);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ExportedScriptsModel::setServerContent fills the table with local and
|
||||
* server scripts and deletes rows of deleted scripts.
|
||||
* @param jsonArray of scripts from the server
|
||||
* @return true if jsonArray could be parsed and was processed, false if
|
||||
* jsonArray could not be parsed
|
||||
*/
|
||||
void ExportedScriptsModel::setServerContent(const QString &jsonArray)
|
||||
{
|
||||
if (jsonArray.isEmpty()) // no content received yet? no problem, just return
|
||||
return;
|
||||
|
||||
/* these vectors are needed to compare which scripts are already
|
||||
* on the server or are local or are both on the server and local
|
||||
* e.g. if the script was downloaded after it was once uploaded
|
||||
* to the server */
|
||||
QMap<int, QVector<int>> exerciseContentScriptIds; // scripts from server - Key = ExerciseId, value = script ids of exercise
|
||||
QMap<int, QVector<int>> exerciseScriptIds; // scripts from local data.json file - Key = ExerciseId, value = script ids of exercise
|
||||
|
||||
DEBUG_LOG(m_logger) << "ExportedScriptsModel::setServerContent jsonArray =" << jsonArray;
|
||||
QJsonParseError err;
|
||||
const QJsonArray presentations = QJsonDocument::fromJson(jsonArray.toUtf8(), &err).array();
|
||||
DEBUG_LOG(m_logger) << "presentations.size() =" << presentations.size();
|
||||
|
||||
if (err.error != QJsonParseError::NoError)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "json array invalid at offset " << err.offset << ": " << err.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
// put local scripts into local scripts list
|
||||
for (const auto &data : qAsConst(m_vecData))
|
||||
{
|
||||
exerciseScriptIds[data.exerciseId].append(data.scriptId);
|
||||
DEBUG_LOG(m_logger) << "exerciseId=" << data.exerciseId
|
||||
<< " modelScriptIds.append: " << data.scriptId;
|
||||
}
|
||||
|
||||
// put server scripts into server scripts list
|
||||
for (const QJsonValue &val : presentations)
|
||||
{
|
||||
const ExportedScriptInformation esi = ExportedScriptInformation::fromJson(val, false, ThpAlreadyUploaded);
|
||||
exerciseContentScriptIds[esi.exerciseId].append(esi.scriptId);
|
||||
}
|
||||
|
||||
/* look for scripts that are on the server but also on the local side to
|
||||
* either remove the corresponding row from the table if the script is not on
|
||||
* the server and not set as local (that makes it non-local and non-existant
|
||||
* on the server, which means it was at one point on the server, but was
|
||||
* deleted from it after the server script list was received here some
|
||||
* minutes ago) -
|
||||
* or to add the not-uploaded state to the table row if it's local only
|
||||
* (but what about local scripts that were uploaded? => This is handeled at
|
||||
* the next main for-loop below)
|
||||
*/
|
||||
for (int i = m_vecData.size() - 1; i >= 0; --i) // scriptId ist nur im Modell aber nicht im content
|
||||
{
|
||||
const auto &rowData = m_vecData[i];
|
||||
const QVector<int> contentScriptIds = exerciseContentScriptIds.value(rowData.exerciseId);
|
||||
DEBUG_LOG(m_logger) << "m_vecData.at(" << i << ").scriptId=" << rowData.scriptId
|
||||
<< " exerciseId=" << rowData.exerciseId
|
||||
<< " contentScriptIds.contains=" << contentScriptIds.contains(rowData.scriptId)
|
||||
<< " rowData.local=" << rowData.local
|
||||
<< " contentScriptIds.size()=" << contentScriptIds.size();
|
||||
|
||||
if (!contentScriptIds.contains(rowData.scriptId))
|
||||
{
|
||||
// the script already in the table is not available on the server side
|
||||
if (rowData.local == false)
|
||||
{
|
||||
/* script already in table is marked as non-loal, which means - in
|
||||
* combination with the script not being on the server (anymore) - that
|
||||
* the script was removed from the server after the server script list
|
||||
* was received from the server and added to the table. So remove it
|
||||
* from the table */
|
||||
DEBUG_LOG(m_logger) << "removeRow(" << i << ")"
|
||||
<< " ScriptId=" << rowData.scriptId
|
||||
<< " ExerciseId=" << rowData.exerciseId;
|
||||
removeRow(i);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* otherwise, if it's marked as local, that means - in combination
|
||||
* with he script not being on the server (anymore) - that the script
|
||||
* is only locally available */
|
||||
setUploadState(i, ThpUploadNotActive, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* get all server scripts and add them to the table if they're not already in
|
||||
* the table.LtsUtils::ProjectSettings *ps = L
|
||||
* if the corresponding row already exist then set the uploaded-state to
|
||||
* uploaded, because they came from the server list, which means they were
|
||||
* obviously uploaded at some point */
|
||||
for (const QJsonValue &val : presentations)
|
||||
{
|
||||
ExportedScriptInformation esi = ExportedScriptInformation::fromJson(val, false, ThpAlreadyUploaded);
|
||||
QVector<int> modelScriptIds = exerciseScriptIds.value(esi.exerciseId);
|
||||
DEBUG_LOG(m_logger) << " exportTime=" << esi.exportTime
|
||||
<< " scriptId=" << esi.scriptId
|
||||
<< " exerciseId=" << esi.exerciseId
|
||||
<< " exerciseName=" << esi.exerciseName
|
||||
<< " scriptName=" << esi.scriptName
|
||||
<< " fileSize=" << esi.fileSize
|
||||
<< " modelScriptIds.size=" << modelScriptIds.size();
|
||||
|
||||
// if a new script was added on the server and not available in this model already, then add it to the model
|
||||
if (!modelScriptIds.contains(esi.scriptId))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "insertRow()";
|
||||
insertRow(esi);
|
||||
continue;
|
||||
}
|
||||
|
||||
// update model
|
||||
for (int i = 0; i < m_vecData.size(); i++)
|
||||
{
|
||||
const auto &rowData = m_vecData[i];
|
||||
if (rowData.scriptId == esi.scriptId &&
|
||||
rowData.exerciseId == esi.exerciseId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "setUploadState i=" << i
|
||||
<< " esi.scriptId=" << esi.scriptId
|
||||
<< " esi.exerciseId=" << esi.exerciseId
|
||||
<< " esi.fileSize=" << esi.fileSize
|
||||
<< " esi.uploadTime=" << esi.uploadTime;
|
||||
setUploadState(i, ThpAlreadyUploaded, esi.uploadTime, esi.fileSize);
|
||||
break; // can only match 1 time
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
qint64 ExportedScriptsModel::downloadTime(const ExportedScriptInformation &val) const
|
||||
{
|
||||
if (!val.local) // can't be downloaded if it's not local
|
||||
return 0;
|
||||
|
||||
QString filename(QStringLiteral("%1/THP-Download/Exercise_%2/%3/index.html").arg(QDir::tempPath()).arg(val.exerciseId).arg(val.scriptId));
|
||||
DEBUG_LOG(m_logger) << "downloadTime: filename " << filename;
|
||||
|
||||
QFileInfo fi(filename);
|
||||
if (!fi.exists())
|
||||
return 0;
|
||||
|
||||
return fi.lastModified().toMSecsSinceEpoch();
|
||||
}
|
||||
|
||||
|
||||
QVariant ExportedScriptsModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!indexIsValid(index))
|
||||
return QVariant();
|
||||
|
||||
const ExportedScriptInformation &val = m_vecData[index.row()];
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::FontRole:
|
||||
{
|
||||
if (!m_isOC
|
||||
/* because non-oc app has no "downloaded" column, telling the
|
||||
* user he has a newer version to download (by making the uploaded
|
||||
* cell fat) makes no sense */
|
||||
|
||||
|| !val.local
|
||||
/* non-downloaded scripts can't be older than the script on the server
|
||||
* because there obviously is no downloaded (local) script */
|
||||
|
||||
|| index.column() != ColUploadedTime
|
||||
|
||||
|| val.uploadTime <= (downloadTime(val) + (10 * 1000) /* 10 second grace */))
|
||||
/* if the script was downloaded from the server before the script was
|
||||
* updated / uploaded to the server again, mark the uploaded time cell
|
||||
* as fat to indicate the local, downloaded script is outdated */
|
||||
break;
|
||||
|
||||
QFont font;
|
||||
font.setBold(true);
|
||||
return font;
|
||||
}
|
||||
|
||||
case Qt::DisplayRole:
|
||||
{
|
||||
switch (index.column())
|
||||
{
|
||||
case ColId:
|
||||
return val.scriptId;
|
||||
case ColExercise:
|
||||
return val.exerciseName;
|
||||
case ColName:
|
||||
return val.scriptName;
|
||||
case ColCreated:
|
||||
return QDateTime::fromMSecsSinceEpoch(val.exportTime);
|
||||
case ColDownloaded:
|
||||
{
|
||||
qint64 dlTime = downloadTime(val);
|
||||
if (dlTime == 0)
|
||||
return QVariant();
|
||||
return QDateTime::fromMSecsSinceEpoch(dlTime);
|
||||
}
|
||||
case ColUploadedTime:
|
||||
return QDateTime::fromMSecsSinceEpoch(val.uploadTime);
|
||||
case ColLocation:
|
||||
return val.local ? tr("Local") : tr("Server");
|
||||
case ColUploaded:
|
||||
switch (val.uploaded)
|
||||
{
|
||||
case ThpConnectToHost:
|
||||
return tr("Connect to host");
|
||||
case ThpUploadActive:
|
||||
return tr("Upload Active");
|
||||
case ThpUploadError:
|
||||
return tr("Upload Error");
|
||||
case ThpUploadNotActive:
|
||||
return tr("Not uploaded");
|
||||
case ThpUnknownUploadState:
|
||||
return tr("Unknown upload status");
|
||||
case ThpAlreadyUploaded:
|
||||
return tr("Already uploaded");
|
||||
}
|
||||
}
|
||||
|
||||
case Qt::UserRole:
|
||||
{
|
||||
return val.scriptId;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool ExportedScriptsModel::createDataJson(const QString &rootDirectory,
|
||||
const std::shared_ptr<ExerciseManagement::Interface::Dtc> &exmDtc,
|
||||
const std::shared_ptr<AssetManagement::Interface::Dtc> &asmDtc,
|
||||
int exerciseId) const // TODO: static, static logger
|
||||
{
|
||||
const QString baseDir = exercisePath(rootDirectory, exerciseId);
|
||||
|
||||
if (!QDir().mkpath(baseDir)) // NOTE: returns true if already exists
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Failed to create path " << baseDir;
|
||||
return false;
|
||||
}
|
||||
|
||||
QFile file(baseDir + QStringLiteral("data.json"));
|
||||
DEBUG_LOG(m_logger) << "createDataJson=" << file.fileName();
|
||||
if (!file.open(QFile::ReadWrite))
|
||||
{
|
||||
QString msg(tr("Could not open data file in script directory: %1").arg(file.errorString()));
|
||||
ERROR_LOG(m_logger) << msg << " - " << file.fileName();
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonDocument doc(QJsonDocument::fromJson(file.readAll()));
|
||||
QJsonObject obj = doc.object();
|
||||
if (obj[QStringLiteral("exerciseId")].toInt() == exerciseId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << baseDir << " exists for exerciseId " << QString::number(exerciseId);
|
||||
return true;
|
||||
}
|
||||
|
||||
const ExerciseManagement::Exercise exercise = exmDtc->exercise(exerciseId);
|
||||
const AssetManagement::TrainingArea ta = asmDtc->trainingArea(exercise.trainingAreaId());
|
||||
|
||||
obj[QStringLiteral("title")] = QString::fromStdString(exercise.name());
|
||||
obj[QStringLiteral("exerciseId")] = exercise.id();
|
||||
obj[QStringLiteral("exerciseName")] = QString::fromStdString(exercise.name());
|
||||
obj[QStringLiteral("exerciseArea")] = QString::fromStdString(ta.name());
|
||||
obj[QStringLiteral("cycleTime")] = QString(QDateTime::fromMSecsSinceEpoch(exercise.beginTime()).toString() +
|
||||
QStringLiteral(" - ") + QDateTime::fromMSecsSinceEpoch(exercise.endTime()).toString());
|
||||
obj[QStringLiteral("exerciseStart")] = exercise.beginTime();
|
||||
obj[QStringLiteral("exerciseEnd")] = exercise.endTime();
|
||||
obj[QStringLiteral("exercisingForces")] = QString::fromStdString(exercise.forces());
|
||||
obj[QStringLiteral("exercisingPurpose")] = QString::fromStdString(exercise.description());
|
||||
|
||||
file.resize(0);
|
||||
file.write(QJsonDocument(obj).toJson());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ExportedScriptsModel::addDownloadData(const ExportedScriptInformation &esi)
|
||||
{
|
||||
// Add exercise to ExportRootPath
|
||||
{
|
||||
// modify exercises.json
|
||||
DEBUG_LOG(m_logger) << "Add exercise to ExportRootPath";
|
||||
|
||||
if (!QDir(esi.rootDirectory).exists())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Cannot modify exercises.json as the info's root directory '"<<esi.rootDirectory<<"' does not exist!";
|
||||
return;
|
||||
}
|
||||
|
||||
QFile file(esi.rootDirectory + QDir::separator() + QStringLiteral("exercises.json"));
|
||||
if (!file.open(QFile::ReadWrite))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Can not open " << file.fileName() << " for read/write: " << file.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
const QString key = QStringLiteral("Exercises");
|
||||
QJsonDocument doc(QJsonDocument::fromJson(file.readAll()));
|
||||
QJsonObject obj = doc.object();
|
||||
QJsonArray arr = obj.value(key).toArray();
|
||||
|
||||
if (!arr.contains(esi.exerciseId))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "arr.append Exercise=" << esi.exerciseId;
|
||||
arr.append(esi.exerciseId);
|
||||
}
|
||||
|
||||
obj.insert(key, arr);
|
||||
file.resize(0);
|
||||
file.write(QJsonDocument(obj).toJson());
|
||||
INFO_LOG(m_logger) << " file.write " << QJsonDocument(obj).toJson();
|
||||
file.close();
|
||||
}
|
||||
|
||||
|
||||
// NOTE: mkdir actually not necessary because the decompressed bzip file of the script already created the exercise directory
|
||||
const QString baseDir = exercisePath(esi.rootDirectory, esi.exerciseId);
|
||||
if (!QDir().mkpath(baseDir)) // NOTE: returns true if dir already exists
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Cannot create destination path " << baseDir;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// modify data.json
|
||||
QFile file(baseDir + QDir::separator() + QStringLiteral("data.json"));
|
||||
DEBUG_LOG(m_logger) << "File= " << file.fileName();
|
||||
if (!file.open(QFile::ReadWrite))
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Can not open " << file.fileName() << " for read/write: " << file.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
const QString keyArray = QStringLiteral("presentations");
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(file.readAll()));
|
||||
QJsonObject obj = doc.object();
|
||||
QJsonArray arr = obj.value(keyArray).toArray();
|
||||
bool exported = false;
|
||||
DEBUG_LOG(m_logger) << "arr.size=" << arr.size();
|
||||
|
||||
for (int i = 0; i < arr.size(); ++i)
|
||||
{
|
||||
auto arresi = ExportedScriptInformation::fromJson(arr.at(i));
|
||||
if (arresi.scriptId == esi.scriptId &&
|
||||
arresi.exerciseId == esi.exerciseId)
|
||||
{
|
||||
arresi.jsonPath = esi.jsonPath;
|
||||
arr[i] = esi.toJson();
|
||||
exported = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exported)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "info scriptId=" << esi.scriptId
|
||||
<< " Name=" << esi.scriptName
|
||||
<< " Exercise=" << esi.exerciseName;
|
||||
arr.append(esi.toJson());
|
||||
}
|
||||
|
||||
obj.insert(keyArray, arr);
|
||||
auto content = QJsonDocument(obj).toJson();
|
||||
|
||||
DEBUG_LOG(m_logger) << "content =" << content;
|
||||
|
||||
file.resize(0);
|
||||
file.write(content);
|
||||
file.close();
|
||||
}
|
||||
|
||||
|
||||
bool ExportedScriptsModel::setLocalState(const int row, const bool localHost)
|
||||
{
|
||||
ExportedScriptInformation data = getRowData(row);
|
||||
|
||||
data.local = localHost;
|
||||
//data.exportTime = exportTime;
|
||||
|
||||
DEBUG_LOG(m_logger) << "setLocalState row=" << row
|
||||
<< " scriptId=" << data.scriptId
|
||||
<< " data.scriptName=" << data.scriptName
|
||||
<< " Exercise=" << data.exerciseName;
|
||||
|
||||
bool result = setRowData(row, data);
|
||||
if (result && localHost && m_rootDirectoryToScan.contains(QStringLiteral("Download")))
|
||||
{
|
||||
data.rootDirectory = m_rootDirectoryToScan;
|
||||
setRowData(row, data); //again for new download path mabe not needed
|
||||
addDownloadData(data);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ExportedScriptsModel::setUploadState(const int row,
|
||||
const UploadState uploadState,
|
||||
const qint64 uploadTime,
|
||||
const qint64 fileSize)
|
||||
{
|
||||
ExportedScriptInformation data = getRowData(row);
|
||||
data.uploaded = uploadState;
|
||||
data.uploadTime = uploadTime;
|
||||
data.fileSize = fileSize;
|
||||
return setRowData(row, data);
|
||||
}
|
||||
|
||||
bool ExportedScriptsModel::removeRow(int row)
|
||||
{
|
||||
ExportedScriptInformation data = getRowData(row);
|
||||
|
||||
if (!LtsWidgets::LtsAbstractTableModel<ExportedScriptInformation>::removeRow(row))
|
||||
return false;
|
||||
|
||||
QString baseDir = exercisePath(data.rootDirectory, data.exerciseId);
|
||||
QString filename = baseDir + QStringLiteral("data.json");
|
||||
DEBUG_LOG(m_logger) << "filename= '" << filename << "'";
|
||||
QFile file(baseDir + QStringLiteral("data.json"));
|
||||
|
||||
if (!file.open(QIODevice::ReadWrite))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "!file.open '" << filename << "'"
|
||||
<< " no local scripts";
|
||||
return true;
|
||||
}
|
||||
|
||||
const QJsonDocument doc(QJsonDocument::fromJson(file.readAll()));
|
||||
QJsonObject obj = doc.object();
|
||||
const int exId = obj.value(QStringLiteral("exerciseId")).toInt();
|
||||
QJsonArray arr;
|
||||
|
||||
for (const auto &esi : qAsConst(m_vecData))
|
||||
{
|
||||
if (esi.exerciseId == exId)
|
||||
arr += esi.toJson();
|
||||
}
|
||||
|
||||
obj[QStringLiteral("presentations")] = arr;
|
||||
file.resize(0);
|
||||
auto content = QJsonDocument(obj).toJson();
|
||||
DEBUG_LOG(m_logger) << "content =" << content;
|
||||
|
||||
return file.write(QJsonDocument(obj).toJson());
|
||||
}
|
||||
|
||||
QString ExportedScriptsModel::exercisePath(const QString &rootDirectory, const int exerciseId) const
|
||||
{
|
||||
QString path = QStringLiteral("%1/Exercise_%2/").arg(rootDirectory).arg(exerciseId);
|
||||
#ifndef WIN32
|
||||
path.prepend(QStringLiteral("/"));
|
||||
#endif
|
||||
return path;
|
||||
}
|
||||
|
||||
//
|
||||
// ExportedScriptInformation
|
||||
//
|
||||
QJsonValue ExportedScriptInformation::toJson() const
|
||||
{
|
||||
return QJsonObject({
|
||||
{ QStringLiteral("displayName"), scriptName },
|
||||
{ QStringLiteral("path"), jsonPath },
|
||||
{ QStringLiteral("scriptId"), scriptId },
|
||||
{ QStringLiteral("exportTime"), exportTime },
|
||||
{ QStringLiteral("fileSize"), fileSize },
|
||||
{ QStringLiteral("uploadTime"), uploadTime },
|
||||
{ QStringLiteral("exerciseName"), exerciseName },
|
||||
{ QStringLiteral("exerciseId"), exerciseId }
|
||||
});
|
||||
}
|
||||
|
||||
ExportedScriptInformation ExportedScriptInformation::fromJson(const QJsonValue &val,
|
||||
const bool local,
|
||||
const UploadState uploadState)
|
||||
{
|
||||
const QJsonObject obj = val.toObject();
|
||||
|
||||
ExportedScriptInformation esi;
|
||||
esi.local = local;
|
||||
esi.scriptName = obj[QStringLiteral("displayName")].toString();
|
||||
if (esi.scriptName.isEmpty())
|
||||
esi.scriptName = obj[QStringLiteral("name")].toString();
|
||||
esi.jsonPath = obj[QStringLiteral("path")].toString();
|
||||
esi.scriptId = obj[QStringLiteral("scriptId")].toInt();
|
||||
esi.exportTime = qRound64(obj[QStringLiteral("exportTime")].toDouble());
|
||||
esi.fileSize = obj[QStringLiteral("fileSize")].toInt();
|
||||
esi.uploaded = uploadState;
|
||||
esi.uploadTime = qRound64(obj[QStringLiteral("uploadTime")].toDouble());
|
||||
esi.exerciseName = obj[QStringLiteral("exerciseName")].toString();
|
||||
esi.exerciseId = obj[QStringLiteral("exerciseId")].toInt();
|
||||
|
||||
Q_ASSERT(esi.scriptId != -1);
|
||||
Q_ASSERT(esi.exerciseId != -1);
|
||||
|
||||
if (esi.scriptId != -1 && esi.exerciseId != -1)
|
||||
esi.valid = true;
|
||||
|
||||
return esi;
|
||||
}
|
||||
|
||||
} // namespace TakeHomePackageManager
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Show the exported scripts and allow them to upload them to the server
|
||||
* $Id: tpm_exported_scripts_model.h 53111 2021-03-22 08:21:29Z wille_m $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/tpm_exported_scripts_model.h $
|
||||
* $Author: wille_m $
|
||||
* Created by Gerlinde Rudolphus, NLE, 2019-03-25
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <logger.h>
|
||||
|
||||
#include <LtsWidgets/lts_abstract_table_model.h>
|
||||
#include <Plugins/ExerciseManagement/exm_data_plugin_interface.h>
|
||||
#include <Plugins/AssetManagement/asm_data_plugin_interface.h>
|
||||
#include <Common/thpcommon_export.h>
|
||||
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
|
||||
enum UploadState
|
||||
{
|
||||
ThpUnknownUploadState,
|
||||
ThpUploadNotActive,
|
||||
ThpConnectToHost,
|
||||
ThpUploadActive,
|
||||
ThpAlreadyUploaded,
|
||||
ThpUploadError,
|
||||
};
|
||||
|
||||
struct ExportedScriptInformation
|
||||
{
|
||||
bool valid { false };
|
||||
|
||||
QString exerciseName;
|
||||
QString scriptName;
|
||||
QString jsonPath;
|
||||
QString rootDirectory; // temp
|
||||
qint64 exerciseId = -1;
|
||||
qint64 exportTime = 0;
|
||||
qint64 fileSize = 0;
|
||||
bool local = true; // On local Host
|
||||
UploadState uploaded = ThpUnknownUploadState;
|
||||
qint64 uploadTime = 0;
|
||||
int scriptId = -1;
|
||||
|
||||
int id() const { return scriptId; }
|
||||
|
||||
QJsonValue toJson() const;
|
||||
static ExportedScriptInformation fromJson(const QJsonValue &val,
|
||||
const bool local = true,
|
||||
const UploadState uploadStates = ThpUnknownUploadState);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class THPCOMMON_EXPORT ExportedScriptsModel : public LtsWidgets::LtsAbstractTableModel<ExportedScriptInformation>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Columns
|
||||
{
|
||||
ColId,
|
||||
ColExercise,
|
||||
ColName,
|
||||
ColCreated,
|
||||
ColDownloaded,
|
||||
ColLocation,
|
||||
ColUploadedTime,
|
||||
ColUploaded,
|
||||
};
|
||||
explicit ExportedScriptsModel(QObject *parent = nullptr);
|
||||
|
||||
bool init(const QString &rootDirectoryToScan);
|
||||
void setServerContent(const QString &jsonArray);
|
||||
void setOC(bool isOC) { m_isOC = isOC; }
|
||||
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool removeRow(int row) override;
|
||||
bool setLocalState(const int row, const bool localHost);
|
||||
bool setUploadState(const int row, const UploadState uploadState, const qint64 uploadTime, const qint64 fileSize);
|
||||
bool createDataJson(const QString &rootDirectory, const std::shared_ptr<ExerciseManagement::Interface::Dtc> &exmDtc,
|
||||
const std::shared_ptr<AssetManagement::Interface::Dtc> &asmDtc,
|
||||
int exerciseId) const;
|
||||
void addDownloadData(const ExportedScriptInformation &esi);
|
||||
|
||||
private:
|
||||
QString exercisePath(const QString &rootDirectory, const int exerciseId) const;
|
||||
qint64 downloadTime(const ExportedScriptInformation &val) const;
|
||||
|
||||
private:
|
||||
bool m_isOC { false };
|
||||
QString m_rootDirectoryToScan;
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#include "tpm_process_dialog.h"
|
||||
#include "ui_tpm_process_dialog.h"
|
||||
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
ProcessOverlay::ProcessOverlay(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, m_ui(new Ui::ProcessOverlay)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
|
||||
connect(m_ui->pbCancel, &QPushButton::clicked,
|
||||
this, [this]()
|
||||
{
|
||||
m_ui->pbCancel->setEnabled(false);
|
||||
emit signalCancel();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ProcessOverlay::~ProcessOverlay()
|
||||
{
|
||||
delete m_ui;
|
||||
}
|
||||
|
||||
|
||||
void ProcessOverlay::setCancelEnabled(bool enabled)
|
||||
{
|
||||
m_ui->pbCancel->setEnabled(enabled);
|
||||
}
|
||||
|
||||
|
||||
void ProcessOverlay::setStatus(const QString &text, qint64 totalFiles, qint64 curFile, qint64 totalSize, qint64 curPos, const QString &curName)
|
||||
{
|
||||
if (!text.isEmpty()) // only set new text if not empty (we dont want to send the text on every update..
|
||||
m_ui->lblStatus->setText(text);
|
||||
|
||||
if (!curName.isEmpty()) // only set new text if not empty (we dont want to send the text on every update..
|
||||
m_ui->lblFilename->setText(curName);
|
||||
|
||||
double progressBytes = (totalSize == 0) ? (double)0 : ((double)curPos / (double)totalSize);
|
||||
double progressFiles = (((double)curFile - 1) / (double)totalFiles);
|
||||
double progressTotal = progressFiles + (progressBytes / (double)totalFiles);
|
||||
|
||||
progressBytes = qRound(progressBytes * 100);
|
||||
progressFiles = qRound(progressFiles * 100);
|
||||
progressTotal = qRound(progressTotal * 100);
|
||||
|
||||
m_ui->pbarFiles->setValue(progressFiles);
|
||||
m_ui->pbarBytes->setValue(progressBytes);
|
||||
m_ui->pbarProgress->setValue(progressTotal);
|
||||
|
||||
QLocale l;
|
||||
|
||||
if (curFile == 0)
|
||||
m_ui->lblFiles->setText(QStringLiteral(" - "));
|
||||
else
|
||||
m_ui->lblFiles->setText(QStringLiteral("%1 / %2").arg(l.toString(curFile)).arg(l.toString(totalFiles)));
|
||||
|
||||
if (curPos == 0)
|
||||
m_ui->lblBytes->setText(QStringLiteral(" - "));
|
||||
else
|
||||
m_ui->lblBytes->setText(QStringLiteral("%1 / %2").arg(l.toString(curPos)).arg(l.toString(totalSize)));
|
||||
}
|
||||
} // namespace TakehomePackageManager
|
||||
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <Common/thpcommon_export.h>
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ProcessOverlay;
|
||||
}
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
class THPCOMMON_EXPORT ProcessOverlay : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ProcessOverlay(QWidget *parent = nullptr);
|
||||
~ProcessOverlay();
|
||||
|
||||
void setStatus(const QString &text = QString(), qint64 totalFiles = 1, qint64 curFile = 1, qint64 totalSize = 0, qint64 curPos = 0, const QString &curName = QString());
|
||||
void setCancelEnabled(bool enabled = true);
|
||||
|
||||
signals:
|
||||
void signalCancel();
|
||||
|
||||
private:
|
||||
Ui::ProcessOverlay *m_ui;
|
||||
bool m_decompressing { false };
|
||||
};
|
||||
} // namespace TakehomePackageManager
|
||||
@@ -0,0 +1,174 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ProcessOverlay</class>
|
||||
<widget class="QWidget" name="ProcessOverlay">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>700</width>
|
||||
<height>220</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>700</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="lblBytes">
|
||||
<property name="text">
|
||||
<string notr="true"> - </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Progress</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QProgressBar" name="pbarFiles">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="lblFiles">
|
||||
<property name="text">
|
||||
<string notr="true"> - </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lblStatus">
|
||||
<property name="text">
|
||||
<string notr="true">Preparing ...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Files</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QProgressBar" name="pbarBytes">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbCancel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="3">
|
||||
<widget class="Line" name="line">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="lblFilename">
|
||||
<property name="text">
|
||||
<string notr="true"> - </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Bytes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="2">
|
||||
<widget class="QProgressBar" name="pbarProgress">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Filename</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="3">
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,48 @@
|
||||
#
|
||||
# $Id: CMakeLists.txt 51804 2020-07-31 04:47:28Z fritsche_h $
|
||||
# $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/CMakeLists.txt $
|
||||
# $Author: fritsche_h $
|
||||
#
|
||||
# Created by Gerlinde Rudolphus, NLE, 2019-03-25
|
||||
#
|
||||
|
||||
#
|
||||
# Common
|
||||
#
|
||||
SET(thp_SRCS
|
||||
tpm_gui_plugin.cpp
|
||||
tpm_gui_plugin.h
|
||||
tpm_exported_scripts_dialog.cpp
|
||||
tpm_exported_scripts_dialog.h
|
||||
logger.cpp
|
||||
logger.h
|
||||
)
|
||||
|
||||
QT5_WRAP_UI(thp_SRCS
|
||||
tpm_exported_scripts_dialog.ui
|
||||
)
|
||||
|
||||
#TODO: auto-remove "libTakeHomePackageManagerGuiPlugin.so" from lib as this lib replaces it
|
||||
|
||||
NGL_ADD_LIBRARY2(WS ThpManagementGuiPlugin MODULE ${thp_SRCS})
|
||||
NGL_TARGET_LINK_LIBRARIES(ThpManagementGuiPlugin
|
||||
ThpCommon
|
||||
TpmGuiPluginInterface
|
||||
Qt5::Widgets
|
||||
Qt5::Network
|
||||
Qt5::WebSockets
|
||||
NGLLogger
|
||||
LtsWidgets
|
||||
LtsSession
|
||||
LtsDataView
|
||||
nglcompression
|
||||
nglsettings
|
||||
ngltools
|
||||
AsmDataPluginInterface
|
||||
ExmDataPluginInterface
|
||||
LtsSessionData
|
||||
httq
|
||||
)
|
||||
|
||||
NGL_INSTALL_TARGET(ThpManagementGuiPlugin)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Building Config - logging facility
|
||||
* $Id: logger.cpp 46225 2019-03-25 13:59:56Z rudolphus_g $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/logger.cpp $
|
||||
* $Author: rudolphus_g $
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "TPM.";
|
||||
std::string loggerName;
|
||||
const size_t len = strlen(name);
|
||||
loggerName.reserve(sizeof(ns) + len);
|
||||
loggerName.append(ns, sizeof(ns) - 1);
|
||||
loggerName.append(name, len);
|
||||
|
||||
try
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
|
||||
getNGLLogger(loggerName);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace TakeHomePackageManager
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Logging for CentralEffectSimulation
|
||||
* $Id: logger.h 46225 2019-03-25 13:59:56Z rudolphus_g $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/logger.h $
|
||||
* $Author: rudolphus_g $
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
typedef NGL::INGLLogger &LOGGER_T;
|
||||
|
||||
LOGGER_T getLogger(const char *name);
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
} // namespace TakeHomePackageManager
|
||||
+1244
File diff suppressed because it is too large.
Load diff
+214
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Show the exported scripts and allow them to upload them to the server
|
||||
* $Id: tpm_exported_scripts_dialog.h 51804 2020-07-31 04:47:28Z fritsche_h $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/tpm_exported_scripts_dialog.h $
|
||||
* $Author: fritsche_h $
|
||||
*
|
||||
* Created by Gerlinde Rudolphus, NLE, 2019-03-25
|
||||
* Rebuilt to use httq by Mike Wille, NLE, 2020-07-07
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <Common/tpm_exported_scripts_model.h>
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
#include <QUrlQuery>
|
||||
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ExportedScriptsDialog;
|
||||
}
|
||||
namespace NGL
|
||||
{
|
||||
class Compress;
|
||||
}
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
|
||||
class QTemporaryFile;
|
||||
class QNetworkAccessManager;
|
||||
class QNetworkReply;
|
||||
class QNetworkRequest;
|
||||
class QFileSystemWatcher;
|
||||
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
class ProcessOverlay;
|
||||
|
||||
class HttpProcess : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HttpProcess(ExportedScriptInformation &&esi, QObject *parent);
|
||||
virtual ~HttpProcess();
|
||||
|
||||
ProcessOverlay *process() const { return m_process; }
|
||||
|
||||
|
||||
signals:
|
||||
void signalReadyRead();
|
||||
//void signalFailed(int status, const QString &msg);
|
||||
void signalSuccess();
|
||||
void signalTimeout();
|
||||
void signalCancel();
|
||||
void signalError();
|
||||
|
||||
|
||||
private slots:
|
||||
void slotReadyRead();
|
||||
void slotError();
|
||||
void slotSuccess();
|
||||
|
||||
|
||||
protected slots:
|
||||
void stopTimeout();
|
||||
void resetTimeout();
|
||||
|
||||
|
||||
private:
|
||||
void doConnections(QNetworkReply *r);
|
||||
|
||||
|
||||
protected:
|
||||
// do not connect to QNetworkReply's readyRead, connect to this classe's signalReadyRead
|
||||
QNetworkReply *post(const QString &path, QIODevice *data, const QUrlQuery &q = QUrlQuery(), const QString &contentType = QStringLiteral("application/octet-stream"));
|
||||
QNetworkReply *get(const QString &path, const QUrlQuery &q = QUrlQuery());
|
||||
QNetworkReply *deleteResource(const QString &path, const QUrlQuery &q = QUrlQuery());
|
||||
|
||||
ExportedScriptInformation m_esi;
|
||||
bool m_isError { false };
|
||||
NGL::INGLLogger &m_logger;
|
||||
ProcessOverlay *m_process;
|
||||
bool m_wasCanceled { false };
|
||||
bool m_isTimeout { false };
|
||||
|
||||
|
||||
private:
|
||||
static QNetworkRequest forgeRequest(const QString &path, const QUrlQuery &q, const QString &contentType = QString());
|
||||
|
||||
QNetworkAccessManager *m_nam;
|
||||
QTimer *m_timeout;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class UploadProcess : public HttpProcess
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
UploadProcess(const QString &rootFolder, ExportedScriptInformation &&esi, QObject *parent);
|
||||
|
||||
signals:
|
||||
//void signalDone();
|
||||
|
||||
private slots:
|
||||
void compressionDone();
|
||||
|
||||
private:
|
||||
void abortCompress();
|
||||
|
||||
QTemporaryFile *m_tempFile;
|
||||
NGL::Compress *m_compress;
|
||||
QString m_rootDir;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class DownloadProcess : public HttpProcess
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DownloadProcess(const QString &rootFolder, int modelRowId, ExportedScriptInformation &&esi, QObject *parent);
|
||||
|
||||
int modelRowId() const { return m_modelRowId; }
|
||||
|
||||
private slots:
|
||||
void downloadFinished();
|
||||
|
||||
signals:
|
||||
void signalDone();
|
||||
|
||||
private:
|
||||
QTemporaryFile *m_tempFile;
|
||||
NGL::Compress *m_compress { nullptr };
|
||||
int m_modelRowId { -1 };
|
||||
QString m_rootFolder;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class RemoveProcess : public HttpProcess
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RemoveProcess(int modelRowId, ExportedScriptInformation &&esi, QObject *parent);
|
||||
int modelRowId() const { return m_modelRowId; }
|
||||
|
||||
signals:
|
||||
void signalDone();
|
||||
|
||||
private:
|
||||
int m_modelRowId { -1 };
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ExportedScriptsDialog : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ExportedScriptsDialog(QWidget *parent = nullptr);
|
||||
~ExportedScriptsDialog();
|
||||
|
||||
void retranslate() override;
|
||||
bool init(LtsSession::LtsSession *session);
|
||||
static QString getContentFolder(const QString &rootFolder, int exerciseId);
|
||||
|
||||
private slots:
|
||||
void uploadScript();
|
||||
void downloadScript();
|
||||
void removeScriptFromServer();
|
||||
void removeScriptLocal();
|
||||
void openScript();
|
||||
void onSelectionChanged();
|
||||
|
||||
private:
|
||||
enum class WsConnectionStatus
|
||||
{
|
||||
NotConnected,
|
||||
Connecting,
|
||||
Disconnected,
|
||||
Error,
|
||||
Connected,
|
||||
};
|
||||
|
||||
void startUpload();
|
||||
QString getContentFolder(int exerciseId) const;
|
||||
QString getRootFolder() const;
|
||||
bool initModel();
|
||||
void setWsConnectionStatus(WsConnectionStatus status);
|
||||
void setWsConnectionStatusLabel();
|
||||
|
||||
private:
|
||||
ExportedScriptsModel *m_model;
|
||||
Ui::ExportedScriptsDialog *m_ui;
|
||||
LtsSession::LtsSession *m_session;
|
||||
int m_exerciseId;
|
||||
QFileSystemWatcher *m_fsWatcher;
|
||||
QString m_lastServerContent;
|
||||
WsConnectionStatus m_wsStatus { WsConnectionStatus::NotConnected };
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
} // namespace TakeHomePackageManager
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ExportedScriptsDialog</class>
|
||||
<widget class="QWidget" name="ExportedScriptsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>834</width>
|
||||
<height>491</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>The following Scripts are already exported. You can remove them from your local hard disk or upload them to the server here.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Server connection status:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblWsStatus">
|
||||
<property name="text">
|
||||
<string notr="true">-</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="LtsDataView::LtsDataView" name="ltsDataView">
|
||||
<property name="showColumnCount" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolButtonsVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LtsDataView::LtsDataView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>LtsDataView/lts_data_view.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* GUI Plugin for ExerciseManangement
|
||||
* $Id: tpm_gui_plugin.cpp 48572 2019-10-02 11:47:04Z rudolphus_g $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/tpm_gui_plugin.cpp $
|
||||
* $Author: rudolphus_g $
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-02-29
|
||||
*/
|
||||
|
||||
#include "tpm_gui_plugin.h"
|
||||
#include "tpm_exported_scripts_dialog.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
|
||||
{
|
||||
return std::make_shared<InterfaceImpl>(session);
|
||||
}
|
||||
|
||||
|
||||
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
|
||||
: GuiPluginBase::Interface(session, getLogger("Plugins.Gui.Tpm"))
|
||||
{}
|
||||
|
||||
|
||||
bool InterfaceImpl::fetchInterfaces()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QString InterfaceImpl::menuGroup() const
|
||||
{
|
||||
return tr("Presentation");
|
||||
}
|
||||
|
||||
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
||||
{
|
||||
QVector<LtsWidgets::PluginData> ret;
|
||||
LtsWidgets::PluginData plData;
|
||||
plData.menuGroup = menuGroup();
|
||||
if (m_session->app() == LtsAppDescriptor::App::Scripts)
|
||||
plData.exercisePart = LtsWidgets::ExercisePart::eSpecial;
|
||||
else
|
||||
plData.exercisePart = LtsWidgets::ExercisePart::eAfterAction;
|
||||
plData.identifier = QLatin1String("PresentationManagement.ScriptDialog.ManageExportedScripts");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:export_documents.svg"));
|
||||
plData.menuText = tr("Manage Exported Scripts");
|
||||
// plData.operatorRight = OperatorRights::ScriptEditorEdit;
|
||||
plData.createWidgetFunc = [this](QWidget *)
|
||||
{
|
||||
return LtsWidgets::initDialog(new ExportedScriptsDialog(), m_session);
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace TakeHomePackageManager
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for MarkerManagement
|
||||
* $Id: tpm_gui_plugin.h 49807 2020-02-06 09:53:16Z ehrlicher $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/tpm_gui_plugin.h $
|
||||
* $Author: ehrlicher $
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-02-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <OldTHP/tpm_gui_plugin_interface.h>
|
||||
|
||||
#include "logger.h"
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
|
||||
{
|
||||
Q_PLUGIN_METADATA(IID "gui:3:tpm.man")
|
||||
Q_INTERFACES(GuiPluginBase::Plugin)
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
GuiPlugin() = default;
|
||||
~GuiPlugin() = default;
|
||||
|
||||
QString pluginName() override { return QLatin1String("TakeHomePackageManager"); }
|
||||
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
|
||||
bool availableInPartition(IDL::PartitionType partition) const override
|
||||
{
|
||||
return partition == IDL::PartitionType::Exercise;
|
||||
}
|
||||
};
|
||||
|
||||
class InterfaceImpl final : public QObject, public GuiPluginBase::Interface, public ForeignTpmGuiInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InterfaceImpl(LtsSession::LtsSession *session);
|
||||
|
||||
bool fetchInterfaces() override;
|
||||
QString menuGroup() const override;
|
||||
QVector<LtsWidgets::PluginData> getActions() override;
|
||||
bool availableInPartition(IDL::PartitionType partition) const override { return partition == IDL::PartitionType::Exercise; }
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
} // namespace TakeHomePackageManager
|
||||
@@ -0,0 +1,44 @@
|
||||
#
|
||||
# $Id: CMakeLists.txt 51804 2020-07-31 04:47:28Z fritsche_h $
|
||||
# $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/CMakeLists.txt $
|
||||
# $Author: fritsche_h $
|
||||
#
|
||||
# Created by Mike Wille, SLTE, 2020-03-23
|
||||
#
|
||||
|
||||
SET(src
|
||||
tpm_usb_gui_plugin.cpp
|
||||
tpm_usb_gui_plugin.h
|
||||
tpm_usb_dialog.cpp
|
||||
tpm_usb_dialog.h
|
||||
logger.cpp
|
||||
logger.h
|
||||
)
|
||||
|
||||
QT5_WRAP_UI(src
|
||||
tpm_usb_dialog.ui
|
||||
)
|
||||
|
||||
NGL_ADD_LIBRARY2(WS ThpUsbManagementGuiPlugin MODULE ${src})
|
||||
NGL_TARGET_LINK_LIBRARIES(ThpUsbManagementGuiPlugin
|
||||
ThpCommon
|
||||
TpmGuiPluginInterface
|
||||
Qt5::Widgets
|
||||
Qt5::Network
|
||||
Qt5::WebSockets
|
||||
NGLLogger
|
||||
LtsWidgets
|
||||
LtsSession
|
||||
LtsDataView
|
||||
nglcompression
|
||||
nglsettings
|
||||
ngltools
|
||||
LtsSessionData
|
||||
|
||||
# for creating data.json
|
||||
AsmDataPluginInterface
|
||||
ExmDataPluginInterface
|
||||
)
|
||||
|
||||
NGL_INSTALL_TARGET(ThpUsbManagementGuiPlugin)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Building Config - logging facility
|
||||
* $Id: logger.cpp 46225 2019-03-25 13:59:56Z rudolphus_g $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/logger.cpp $
|
||||
* $Author: rudolphus_g $
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "TPM.USB.";
|
||||
std::string loggerName;
|
||||
const size_t len = strlen(name);
|
||||
loggerName.reserve(sizeof(ns) + len);
|
||||
loggerName.append(ns, sizeof(ns) - 1);
|
||||
loggerName.append(name, len);
|
||||
|
||||
try
|
||||
{
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
|
||||
getNGLLogger(loggerName);
|
||||
}
|
||||
catch (const std::exception &ex)
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace TakeHomePackageManager
|
||||
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Logging for CentralEffectSimulation
|
||||
* $Id: logger.h 46225 2019-03-25 13:59:56Z rudolphus_g $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/logger.h $
|
||||
* $Author: rudolphus_g $
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
typedef NGL::INGLLogger &LOGGER_T;
|
||||
|
||||
LOGGER_T getLogger(const char *name);
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
} // namespace TakeHomePackageManager
|
||||
+1699
File diff suppressed because it is too large.
Load diff
+138
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Show the exported scripts and allow them to upload them to the server
|
||||
* $Id: tpm_exported_scripts_dialog.h 51804 2020-07-31 04:47:28Z fritsche_h $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/tpm_exported_scripts_dialog.h $
|
||||
* $Author: fritsche_h $
|
||||
*
|
||||
* Created by Mike Wille, SLTE, 2020-03-23
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <LtsWidgets/lts_dialog.h>
|
||||
|
||||
#include <QFileInfoList>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class USBDialog;
|
||||
}
|
||||
namespace LtsSession
|
||||
{
|
||||
class LtsSession;
|
||||
}
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
class ExportedScriptsModel;
|
||||
|
||||
enum eLayerType
|
||||
{
|
||||
elevation,
|
||||
map,
|
||||
sceneObject,
|
||||
scene
|
||||
};
|
||||
|
||||
struct layerMappinEntry
|
||||
{
|
||||
eLayerType type;
|
||||
QString description;
|
||||
int maxScale;
|
||||
int minScale;
|
||||
QString name;
|
||||
QString url;
|
||||
|
||||
public:
|
||||
|
||||
layerMappinEntry()
|
||||
: type(eLayerType::map), description(QStringLiteral("NOTSET")), maxScale(125), minScale(-1), name(QStringLiteral("_name")), url(QStringLiteral("_url"))
|
||||
{
|
||||
|
||||
}
|
||||
layerMappinEntry(eLayerType _type, QString _description, int _maxScale, int _minScale, QString _name, QString _url)
|
||||
: type(_type), description(_description), maxScale(_maxScale), minScale(_minScale), name(_name), url(_url)
|
||||
{
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
class USBDialog : public LtsWidgets::LtsDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief USBDialog => WARNING: throws! catch exception!
|
||||
* @param session
|
||||
* @param parent
|
||||
*/
|
||||
explicit USBDialog(LtsSession::LtsSession *session, QWidget *parent = nullptr);
|
||||
~USBDialog();
|
||||
|
||||
void retranslate() override;
|
||||
|
||||
static QString getContentFolder(const QString &rootFolder, int exerciseId);
|
||||
QString getContentFolder(const QString &rootFolder) const;
|
||||
|
||||
static QString exerciseDirectoryName(int exerciseId);
|
||||
static QString getScriptFolder(const QString &rootFolder, int exerciseId, int scriptId);
|
||||
|
||||
signals:
|
||||
void nextMap();
|
||||
|
||||
private slots:
|
||||
void slotSelectionChanged();
|
||||
|
||||
void slotCopy();
|
||||
void slotCopyMaps();
|
||||
void slotCopyWinBin();
|
||||
void slotCopyWinBinP2();
|
||||
void slotCopyWinBinP3();
|
||||
|
||||
void slotRemove();
|
||||
void slotRemoveMaps();
|
||||
|
||||
void slotChangePath();
|
||||
void onNextMap();
|
||||
void generateLayerMappingXML();
|
||||
|
||||
|
||||
|
||||
private:
|
||||
enum class What
|
||||
{
|
||||
ScriptWasDeletedFromExercise,
|
||||
ExerciseDirectoryWasDeleted,
|
||||
NewExerciseDirectoryWasCreated,
|
||||
ScriptWasCopiedToExercise,
|
||||
};
|
||||
|
||||
void adjustJsonFiles(What what);
|
||||
void initModel();
|
||||
void initUsbModel();
|
||||
void scriptDeleted(int scriptId);
|
||||
void scriptCopied(int scriptId);
|
||||
QFileInfoList prepareFileInfoListForFolder(QString src, QFileInfoList fil);
|
||||
|
||||
QString getContentFolder(int exerciseId) const;
|
||||
QString getContentFolder() const;
|
||||
QString getRootFolder(bool forceDownloadDir = false) const;
|
||||
QString exerciseDirectoryName() const;
|
||||
QString getScriptFolder(const QString &rootFolder, int scriptId) const;
|
||||
QString getScriptFolder(int scriptId) const;
|
||||
|
||||
ExportedScriptsModel *m_localThpModel;
|
||||
ExportedScriptsModel *m_usbThpModel;
|
||||
Ui::USBDialog *m_ui;
|
||||
LtsSession::LtsSession *m_session;
|
||||
int m_exerciseId;
|
||||
int m_paths;
|
||||
QMap<QString, QFileInfoList> m_files;
|
||||
|
||||
QString m_usbRoot;
|
||||
NGL::INGLLogger &m_logger;
|
||||
int m_finished_mapCopys;
|
||||
};
|
||||
} // namespace TakeHomePackageManager
|
||||
+274
@@ -0,0 +1,274 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>USBDialog</class>
|
||||
<widget class="QWidget" name="USBDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1081</width>
|
||||
<height>541</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string notr="true">Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="verticalGroupBox">
|
||||
<property name="title">
|
||||
<string>Local</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="verticalLayoutWidget_3">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>THPs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="tvLocal">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbCopy">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy selected THPs to USB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="verticalLayoutWidget_4">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Maps</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tvLocalMaps">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Path</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbCopyMaps">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copy selected Maps to USB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="verticalGroupBox_2">
|
||||
<property name="title">
|
||||
<string>On USB</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblPath">
|
||||
<property name="text">
|
||||
<string>(none)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbCHange">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Change path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>THPs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tvUSB">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::ExtendedSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbRemove">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove selected THPs from USB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="verticalLayoutWidget_5">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Maps</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tvUSBMaps">
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pbRemoveMaps">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove selected Maps from USB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* GUI Plugin for ExerciseManangement
|
||||
* $Id: tpm_gui_plugin.cpp 48572 2019-10-02 11:47:04Z rudolphus_g $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/tpm_gui_plugin.cpp $
|
||||
* $Author: rudolphus_g $
|
||||
*
|
||||
* Created by Mike Wille, SLTE, 2020-03-23
|
||||
*/
|
||||
|
||||
#include "tpm_usb_gui_plugin.h"
|
||||
#include "tpm_usb_dialog.h"
|
||||
#include "logger.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
std::shared_ptr<GuiPluginBase::Interface> GuiPlugin::createGuiInterface(LtsSession::LtsSession *session)
|
||||
{
|
||||
return std::make_shared<InterfaceImpl>(session);
|
||||
}
|
||||
|
||||
|
||||
InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session)
|
||||
: GuiPluginBase::Interface(session, getLogger("Plugin"))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool InterfaceImpl::fetchInterfaces()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QString InterfaceImpl::menuGroup() const
|
||||
{
|
||||
return tr("Presentation");
|
||||
}
|
||||
|
||||
QVector<LtsWidgets::PluginData> InterfaceImpl::getActions()
|
||||
{
|
||||
|
||||
QVector<LtsWidgets::PluginData> ret;
|
||||
|
||||
LtsWidgets::PluginData plData;
|
||||
plData.menuGroup = menuGroup();
|
||||
|
||||
if (m_session->app() == LtsAppDescriptor::App::Scripts)
|
||||
plData.exercisePart = LtsWidgets::ExercisePart::eSpecial;
|
||||
else
|
||||
plData.exercisePart = LtsWidgets::ExercisePart::eAfterAction;
|
||||
|
||||
plData.identifier = QLatin1String("THP.USB.Dialog");
|
||||
plData.menuIcon = QIcon(QLatin1String("icon:export_documents.svg"));
|
||||
plData.menuText = tr("USB Management");
|
||||
// plData.operatorRight = OperatorRights::ScriptEditorEdit;
|
||||
plData.createWidgetFunc = [this](QWidget *)
|
||||
{
|
||||
return LtsWidgets::createThrowableDialog<USBDialog>(m_session);
|
||||
};
|
||||
ret.append(plData);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace TakeHomePackageManager
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Gui Plugin for MarkerManagement
|
||||
* $Id: tpm_gui_plugin.h 49807 2020-02-06 09:53:16Z ehrlicher $
|
||||
* $HeadURL: svn://slssvn/TDS/branches/product/iterations/21_03_salted_caramel/Lts/Plugins/TakeHomePackageManager/tpm_gui_plugin.h $
|
||||
* $Author: ehrlicher $
|
||||
*
|
||||
* Created by Mike Wille, SLTE, 2020-03-23
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <OldTHP/tpm_gui_plugin_interface.h>
|
||||
|
||||
#include "logger.h"
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <PluginInterfaces/gui_plugin_interface.h>
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
class GuiPlugin final : public QObject, public GuiPluginBase::Plugin
|
||||
{
|
||||
Q_PLUGIN_METADATA(IID "gui:3:tpm.usb")
|
||||
Q_INTERFACES(GuiPluginBase::Plugin)
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
GuiPlugin() = default;
|
||||
~GuiPlugin() = default;
|
||||
|
||||
QString pluginName() override { return QLatin1String("ThpUsbManager"); }
|
||||
std::shared_ptr<GuiPluginBase::Interface> createGuiInterface(LtsSession::LtsSession *session) override;
|
||||
bool availableInPartition(IDL::PartitionType partition) const override
|
||||
{
|
||||
return partition == IDL::PartitionType::Exercise;
|
||||
}
|
||||
};
|
||||
|
||||
class InterfaceImpl final : public QObject, public GuiPluginBase::Interface, public ForeignTpmGuiInterface
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit InterfaceImpl(LtsSession::LtsSession *session);
|
||||
|
||||
bool fetchInterfaces() override;
|
||||
QString menuGroup() const override;
|
||||
QVector<LtsWidgets::PluginData> getActions() override;
|
||||
bool availableInPartition(IDL::PartitionType partition) const override { return partition == IDL::PartitionType::Exercise; }
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
} // namespace TakeHomePackageManager
|
||||
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* HMI Plugin for Exercisemanagemt (Interface for access from other Plugins)
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2016-02-29
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <QString>
|
||||
|
||||
|
||||
namespace TakeHomePackageManager
|
||||
{
|
||||
|
||||
class ForeignTpmGuiInterface
|
||||
{
|
||||
public:
|
||||
ForeignTpmGuiInterface() = default;
|
||||
virtual ~ForeignTpmGuiInterface() = default;
|
||||
static QString pluginName() { return QStringLiteral("TpmGuiPlugin"); }
|
||||
};
|
||||
|
||||
} // namespace TakeHomePackageManager
|
||||
Reference in new issue
Block a user