Add clang-format style file and format accordingly

remotes/origin/HEAD
markuspg 6 years ago
parent ea2e335f8f
commit d5fe3526d1

@ -0,0 +1,118 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
...

@ -25,44 +25,37 @@
#include <QRegularExpression> #include <QRegularExpression>
#include "client.h" #include "client.h"
#include "settings.h"
#include "lablib.h" #include "lablib.h"
#include "settings.h"
extern std::unique_ptr<lc::Settings> settings; extern std::unique_ptr<lc::Settings> settings;
extern std::unique_ptr<lc::Lablib> lablib; extern std::unique_ptr<lc::Lablib> lablib;
lc::Client::Client( const QString &argIP, const QString &argMAC, const QString &argName, lc::Client::Client(const QString &argIP, const QString &argMAC,
unsigned short int argXPosition, unsigned short int argYPosition, const QString &argName, unsigned short int argXPosition,
const QString &argPingCmd ): unsigned short int argYPosition, const QString &argPingCmd)
ip{ argIP }, : ip{argIP}, mac{argMAC}, name{argName}, xPosition{argXPosition},
mac{ argMAC }, yPosition{argYPosition}, protectedCycles{0} {
name{ argName },
xPosition{ argXPosition },
yPosition{ argYPosition },
protectedCycles{ 0 }
{
qRegisterMetaType<state_t>("STATE"); qRegisterMetaType<state_t>("STATE");
if (!argPingCmd.isEmpty()) { if (!argPingCmd.isEmpty()) {
pinger = new ClientPinger{ip, argPingCmd}; pinger = new ClientPinger{ip, argPingCmd};
pinger->moveToThread(&pingerThread); pinger->moveToThread(&pingerThread);
connect( &pingerThread, &QThread::finished, connect(&pingerThread, &QThread::finished, pinger, &QObject::deleteLater);
pinger, &QObject::deleteLater ); connect(this, &Client::PingWanted, pinger, &ClientPinger::doPing);
connect( this, &Client::PingWanted, connect(pinger, &ClientPinger::PingFinished, this,
pinger, &ClientPinger::doPing ); &Client::GotStatusChanged);
connect( pinger, &ClientPinger::PingFinished,
this, &Client::GotStatusChanged );
pingerThread.start(); pingerThread.start();
pingTimer = new QTimer{this}; pingTimer = new QTimer{this};
connect( pingTimer, &QTimer::timeout, connect(pingTimer, &QTimer::timeout, this, &Client::RequestAPing);
this, &Client::RequestAPing ) ;
pingTimer->start(3000); pingTimer->start(3000);
} }
qDebug() << "Created client" << name << "with MAC" << mac << "and IP" << ip qDebug() << "Created client" << name << "with MAC" << mac << "and IP" << ip
<< "at position" << QString{ QString::number( xPosition ) + "x" << "at position"
+ QString::number( yPosition ) }; << QString{QString::number(xPosition) + "x" +
QString::number(yPosition)};
} }
lc::Client::~Client() { lc::Client::~Client() {
@ -74,14 +67,19 @@ lc::Client::~Client() {
pingerThread.wait(); pingerThread.wait();
} }
void lc::Client::BeamFile( const QString &argFileToBeam, const QString * const argPublickeyPathUser, const QString * const argUserNameOnClients ) { void lc::Client::BeamFile(const QString &argFileToBeam,
const QString *const argPublickeyPathUser,
const QString *const argUserNameOnClients) {
if (state < state_t::RESPONDING) { if (state < state_t::RESPONDING) {
return; return;
} }
QStringList arguments; QStringList arguments;
arguments << "-2" << "-i" << *argPublickeyPathUser << "-l" << "32768" << "-r" arguments << "-2"
<< argFileToBeam << QString{ *argUserNameOnClients + "@" + ip + ":media4ztree" }; << "-i" << *argPublickeyPathUser << "-l"
<< "32768"
<< "-r" << argFileToBeam
<< QString{*argUserNameOnClients + "@" + ip + ":media4ztree"};
// Start the process // Start the process
QProcess beamFileProcess; QProcess beamFileProcess;
@ -111,21 +109,26 @@ void lc::Client::Boot() {
} }
void lc::Client::GotStatusChanged(state_t argState) { void lc::Client::GotStatusChanged(state_t argState) {
if ( ( protectedCycles > 0 ) && ( state == state_t::BOOTING ) && ( argState != state_t::RESPONDING ) ) { if ((protectedCycles > 0) && (state == state_t::BOOTING) &&
(argState != state_t::RESPONDING)) {
return; return;
} }
if ( ( protectedCycles > 0 ) && ( state == state_t::SHUTTING_DOWN ) && argState != state_t::NOT_RESPONDING ) { if ((protectedCycles > 0) && (state == state_t::SHUTTING_DOWN) &&
argState != state_t::NOT_RESPONDING) {
return; return;
} }
state = argState; state = argState;
qDebug() << name << "status changed to:" << static_cast< unsigned short int >( argState ); qDebug() << name
<< "status changed to:" << static_cast<unsigned short int>(argState);
} }
void lc::Client::KillZLeaf() { void lc::Client::KillZLeaf() {
QStringList arguments; QStringList arguments;
arguments << "-i" << settings->pkeyPathUser arguments << "-i" << settings->pkeyPathUser
<< QString{settings->userNameOnClients + "@" + ip} << QString{settings->userNameOnClients + "@" + ip}
<< settings->killallCmd << "-I" << "-q" << "zleaf.exe"; << settings->killallCmd << "-I"
<< "-q"
<< "zleaf.exe";
// Start the process // Start the process
QProcess killZLeafProcess; QProcess killZLeafProcess;
@ -144,7 +147,8 @@ void lc::Client::OpenFilesystem( const QString * const argUserToBeUsed ) {
if (state < state_t::RESPONDING) { if (state < state_t::RESPONDING) {
return; return;
} }
QStringList arguments = QStringList{} << QString{ "sftp://" + *argUserToBeUsed + "@" + ip }; QStringList arguments = QStringList{}
<< QString{"sftp://" + *argUserToBeUsed + "@" + ip};
QProcess openFilesystemProcess; QProcess openFilesystemProcess;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
@ -153,7 +157,8 @@ void lc::Client::OpenFilesystem( const QString * const argUserToBeUsed ) {
qDebug() << settings->fileMngr << arguments.join(" "); qDebug() << settings->fileMngr << arguments.join(" ");
} }
void lc::Client::OpenTerminal( const QString &argCommand, const bool &argOpenAsRoot ) { void lc::Client::OpenTerminal(const QString &argCommand,
const bool &argOpenAsRoot) {
if (!settings->termEmulCmd.isEmpty()) { if (!settings->termEmulCmd.isEmpty()) {
if (state < state_t::RESPONDING) { if (state < state_t::RESPONDING) {
return; return;
@ -163,12 +168,12 @@ void lc::Client::OpenTerminal( const QString &argCommand, const bool &argOpenAsR
arguments = new QStringList; arguments = new QStringList;
if (!argOpenAsRoot) { if (!argOpenAsRoot) {
*arguments << "-e" *arguments << "-e"
<< QString{ settings->sshCmd + " -i " + settings->pkeyPathUser + " " << QString{settings->sshCmd + " -i " + settings->pkeyPathUser +
+ settings->userNameOnClients + "@" + ip }; " " + settings->userNameOnClients + "@" + ip};
} else { } else {
*arguments << "-e" << *arguments << "-e"
QString{ settings->sshCmd + " -i " + settings->pkeyPathRoot << QString{settings->sshCmd + " -i " + settings->pkeyPathRoot +
+ " " + "root@" + ip}; " " + "root@" + ip};
} }
if (!argCommand.isEmpty()) { if (!argCommand.isEmpty()) {
@ -231,13 +236,14 @@ void lc::Client::ShowDesktopFullControl() {
} }
void lc::Client::Shutdown() { void lc::Client::Shutdown() {
if ( state == state_t::NOT_RESPONDING || state == state_t::BOOTING if (state == state_t::NOT_RESPONDING || state == state_t::BOOTING ||
|| state == state_t::SHUTTING_DOWN ) { state == state_t::SHUTTING_DOWN) {
return; return;
} }
QStringList arguments; QStringList arguments;
arguments << "-i" << settings->pkeyPathUser arguments << "-i" << settings->pkeyPathUser
<< QString{ settings->userNameOnClients + "@" + ip } << "sudo shutdown -P now"; << QString{settings->userNameOnClients + "@" + ip}
<< "sudo shutdown -P now";
// Start the process // Start the process
QProcess shutdownProcess; QProcess shutdownProcess;
@ -248,7 +254,8 @@ void lc::Client::Shutdown() {
// Output message via the debug messages tab // Output message via the debug messages tab
qDebug() << settings->sshCmd << arguments.join(" "); qDebug() << settings->sshCmd << arguments.join(" ");
// This additional 'ping_timer' start is needed for the case that the clients are shut down without prior closing of zLeaves // This additional 'ping_timer' start is needed for the case that the clients
// are shut down without prior closing of zLeaves
pingTimer->start(3000); pingTimer->start(3000);
protectedCycles = 3; protectedCycles = 3;
@ -256,35 +263,36 @@ void lc::Client::Shutdown() {
} }
void lc::Client::StartZLeaf(const QString *argFakeName, QString cmd) { void lc::Client::StartZLeaf(const QString *argFakeName, QString cmd) {
if ( state < state_t::RESPONDING || zLeafVersion.isEmpty() || GetSessionPort() < 7000 ) { if (state < state_t::RESPONDING || zLeafVersion.isEmpty() ||
GetSessionPort() < 7000) {
return; return;
} }
// Create a QMessageBox for user interaction if there is already a zLeaf running // Create a QMessageBox for user interaction if there is already a zLeaf
// running
std::unique_ptr<QMessageBox> messageBoxRunningZLeafFound; std::unique_ptr<QMessageBox> messageBoxRunningZLeafFound;
if (state == state_t::ZLEAF_RUNNING) { if (state == state_t::ZLEAF_RUNNING) {
messageBoxRunningZLeafFound.reset( new QMessageBox{ QMessageBox::Warning, "Running zLeaf found", messageBoxRunningZLeafFound.reset(new QMessageBox{
QMessageBox::Warning, "Running zLeaf found",
QString{"There is already a zLeaf running on " + name + "."}, QString{"There is already a zLeaf running on " + name + "."},
QMessageBox::No | QMessageBox::Yes}); QMessageBox::No | QMessageBox::Yes});
messageBoxRunningZLeafFound->setInformativeText( "Do you want to start a zLeaf on client " messageBoxRunningZLeafFound->setInformativeText(
+ name + " nonetheless?" ); "Do you want to start a zLeaf on client " + name + " nonetheless?");
messageBoxRunningZLeafFound->setDefaultButton(QMessageBox::No); messageBoxRunningZLeafFound->setDefaultButton(QMessageBox::No);
messageBoxRunningZLeafFound->exec(); messageBoxRunningZLeafFound->exec();
} }
if ( ( messageBoxRunningZLeafFound.get() != nullptr if ((messageBoxRunningZLeafFound.get() != nullptr &&
&& messageBoxRunningZLeafFound->clickedButton() messageBoxRunningZLeafFound->clickedButton() ==
== messageBoxRunningZLeafFound->button( QMessageBox::Yes ) ) messageBoxRunningZLeafFound->button(QMessageBox::Yes)) ||
|| state != state_t::ZLEAF_RUNNING ) { state != state_t::ZLEAF_RUNNING) {
QStringList arguments; QStringList arguments;
if (argFakeName == nullptr) { if (argFakeName == nullptr) {
arguments << "-i" << settings->pkeyPathUser arguments << "-i" << settings->pkeyPathUser
<< QString{ settings->userNameOnClients + "@" + ip } << QString{settings->userNameOnClients + "@" + ip} << cmd;
<< cmd;
} else { } else {
arguments << "-i" << settings->pkeyPathUser arguments << "-i" << settings->pkeyPathUser
<< QString{ settings->userNameOnClients + "@" + ip } << QString{settings->userNameOnClients + "@" + ip} << cmd
<< cmd
<< "/name" << *argFakeName; << "/name" << *argFakeName;
} }
@ -299,7 +307,9 @@ void lc::Client::StartZLeaf( const QString * argFakeName, QString cmd ) {
} }
} }
void lc::Client::StartClientBrowser( const QString * const argURL, const bool * const argFullscreen, const QString * const argBrowser ) { void lc::Client::StartClientBrowser(const QString *const argURL,
const bool *const argFullscreen,
const QString *const argBrowser) {
// Declarations // Declarations
QStringList arguments; QStringList arguments;
@ -312,8 +322,7 @@ void lc::Client::StartClientBrowser( const QString * const argURL, const bool *
// Build arguments list for SSH command // Build arguments list for SSH command
arguments << "-i" << settings->pkeyPathUser arguments << "-i" << settings->pkeyPathUser
<< QString{settings->userNameOnClients + "@" + ip} << QString{settings->userNameOnClients + "@" + ip}
<< "DISPLAY=:0.0" << "DISPLAY=:0.0" << settings->clientBrowserCmd
<< settings->clientBrowserCmd
<< processedArgUrl; << processedArgUrl;
// Add fullscreen toggle if checked // Add fullscreen toggle if checked
@ -324,8 +333,7 @@ void lc::Client::StartClientBrowser( const QString * const argURL, const bool *
// Build arguments list for SSH command // Build arguments list for SSH command
arguments << "-i" << settings->pkeyPathUser arguments << "-i" << settings->pkeyPathUser
<< QString{settings->userNameOnClients + "@" + ip} << QString{settings->userNameOnClients + "@" + ip}
<< "DISPLAY=:0.0" << "DISPLAY=:0.0" << settings->clientChromiumCmd
<< settings->clientChromiumCmd
<< "--noerrdialogs --kiosk" << "--noerrdialogs --kiosk"
<< "--app='" + processedArgUrl + "'" << "--app='" + processedArgUrl + "'"
<< "> /dev/null 2>&1 &disown"; << "> /dev/null 2>&1 &disown";
@ -347,12 +355,10 @@ void lc::Client::StopClientBrowser() {
// Build arguments list // Build arguments list
arguments << "-i" << settings->pkeyPathUser arguments << "-i" << settings->pkeyPathUser
<< QString{ settings->userNameOnClients + "@" + ip } << QString{settings->userNameOnClients + "@" + ip} << "killall"
<< "killall"
<< settings->clientBrowserCmd << settings->clientBrowserCmd
<< "& sleep 1 && rm -R /home/ewfuser/.mozilla/firefox/*" << "& sleep 1 && rm -R /home/ewfuser/.mozilla/firefox/*"
<< "& killall" << "& killall" << settings->clientChromiumCmd;
<< settings->clientChromiumCmd;
// Start the process // Start the process
QProcess startClientBrowserProcess; QProcess startClientBrowserProcess;
@ -372,11 +378,13 @@ void lc::Client::ControlRMB(bool enable) {
if (enable) { if (enable) {
arguments << "-i" << settings->pkeyPathUser arguments << "-i" << settings->pkeyPathUser
<< QString{settings->userNameOnClients + "@" + ip} << QString{settings->userNameOnClients + "@" + ip}
<< "DISPLAY=:0 xinput set-button-map 'Microsoft Basic Optical Mouse' 1 2 3 4 5 6 7 8 9 10 11 12 > /dev/null 2>&1 &disown;"; << "DISPLAY=:0 xinput set-button-map 'Microsoft Basic Optical "
"Mouse' 1 2 3 4 5 6 7 8 9 10 11 12 > /dev/null 2>&1 &disown;";
} else { } else {
arguments << "-i" << settings->pkeyPathUser arguments << "-i" << settings->pkeyPathUser
<< QString{settings->userNameOnClients + "@" + ip} << QString{settings->userNameOnClients + "@" + ip}
<< "DISPLAY=:0 xinput set-button-map 'Microsoft Basic Optical Mouse' 1 2 0 4 5 6 7 8 9 10 11 12 > /dev/null 2>&1 &disown;"; << "DISPLAY=:0 xinput set-button-map 'Microsoft Basic Optical "
"Mouse' 1 2 0 4 5 6 7 8 9 10 11 12 > /dev/null 2>&1 &disown;";
} }
// Start the process // Start the process

@ -28,14 +28,15 @@
#include <QThread> #include <QThread>
#include <QTimer> #include <QTimer>
#include "global.h"
#include "clientpinger.h" #include "clientpinger.h"
#include "global.h"
namespace lc { namespace lc {
//! Class which represents the clients in the lab //! Class which represents the clients in the lab
/*! /*!
This class contains elements and functions needed to represent all functions of a client. This class contains elements and functions needed to represent all functions
of a client.
*/ */
class Client : public QObject { class Client : public QObject {
Q_OBJECT Q_OBJECT
@ -66,17 +67,22 @@ public:
~Client(); ~Client();
//! Beams the chosen file to the client's 'media4ztree' directory //! Beams the chosen file to the client's 'media4ztree' directory
/*! /*!
@param argFileToBeam The file which shall be beamed to the client's 'media4ztree' directory @param argFileToBeam The file which shall be beamed to the
@param argPublickeyPathUser The path to the publickey for user login on the clients client's 'media4ztree' directory
@param argPublickeyPathUser The path to the publickey for user
login on the clients
@param argUserNameOnClients The name of the user on the clients @param argUserNameOnClients The name of the user on the clients
*/ */
void BeamFile( const QString &argFileToBeam, const QString * const argPublickeyPathUser, const QString * const argUserNameOnClients ); void BeamFile(const QString &argFileToBeam,
const QString *const argPublickeyPathUser,
const QString *const argUserNameOnClients);
/*! /*!
* \brief Boots the client * \brief Boots the client
*/ */
void Boot(); void Boot();
/*! /*!
* \brief DeactiveScreensaver deactivates potentially running screensavers on the client * \brief DeactiveScreensaver deactivates potentially running screensavers on
* the client
*/ */
void DeactiveScreensaver(); void DeactiveScreensaver();
//! Returns the current state of the client //! Returns the current state of the client
@ -96,8 +102,9 @@ public:
void OpenFilesystem(const QString *const argUserToBeUsed); void OpenFilesystem(const QString *const argUserToBeUsed);
/*! /*!
* \brief Opens a terminal for the client * \brief Opens a terminal for the client
* \param argCommand A command which shall be executed in the terminal window (Pass an empty QString if not wanted) * \param argCommand A command which shall be executed in the terminal window
* \param argOpenAsRoot Run the terminal session as root (true) or as normal user (false) * (Pass an empty QString if not wanted) \param argOpenAsRoot Run the terminal
* session as root (true) or as normal user (false)
*/ */
void OpenTerminal(const QString &argCommand, const bool &argOpenAsRoot); void OpenTerminal(const QString &argCommand, const bool &argOpenAsRoot);
void SetSessionPort(int argSP) { sessionPort = argSP; } void SetSessionPort(int argSP) { sessionPort = argSP; }
@ -112,7 +119,8 @@ public:
/*! /*!
* \brief Starts a zLeaf instance on the client * \brief Starts a zLeaf instance on the client
* @param argFakeName The name the zLeaf instance shall have (if not the default, which is the hostname of the client) * @param argFakeName The name the zLeaf instance shall have (if not the
* default, which is the hostname of the client)
*/ */
void StartZLeaf(const QString *argFakeName = nullptr, QString cmd = ""); void StartZLeaf(const QString *argFakeName = nullptr, QString cmd = "");
@ -120,7 +128,9 @@ public:
* \brief Opens a browser window on the client * \brief Opens a browser window on the client
* @param argURL URL to open in clients browser * @param argURL URL to open in clients browser
*/ */
void StartClientBrowser( const QString *argURL = nullptr, const bool *argFullscreen = nullptr, const QString *argBrowser = nullptr ); void StartClientBrowser(const QString *argURL = nullptr,
const bool *argFullscreen = nullptr,
const QString *argBrowser = nullptr);
/*! /*!
* \brief Closes all browser instances * \brief Closes all browser instances
@ -139,7 +149,8 @@ private:
ClientPinger *pinger = nullptr; ClientPinger *pinger = nullptr;
QThread pingerThread; QThread pingerThread;
state_t state = state_t::UNINITIALIZED; state_t state = state_t::UNINITIALIZED;
QTimer *pingTimer = nullptr; //! QTimer used to trigger pings by pinger's ClientPinger instance QTimer *pingTimer = nullptr; //! QTimer used to trigger pings by pinger's
//! ClientPinger instance
int sessionPort = 0; int sessionPort = 0;
QString zLeafVersion; QString zLeafVersion;
@ -151,6 +162,6 @@ signals:
void PingWanted(); void PingWanted();
}; };
} } // namespace lc
#endif // CLIENT_H #endif // CLIENT_H

@ -24,33 +24,36 @@
extern std::unique_ptr<lc::Settings> settings; extern std::unique_ptr<lc::Settings> settings;
lc::ClientHelpNotificationServer::ClientHelpNotificationServer( QObject *argParent ) : lc::ClientHelpNotificationServer::ClientHelpNotificationServer(
QObject{ argParent }, QObject *argParent)
hostAddress{ settings->serverIP } : QObject{argParent}, hostAddress{settings->serverIP} {
{
QNetworkConfigurationManager manager; QNetworkConfigurationManager manager;
if ( manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired ) { if (manager.capabilities() &
QNetworkConfigurationManager::NetworkSessionRequired) {
// Get saved network configuration // Get saved network configuration
QSettings settings{QSettings::UserScope, QLatin1String{"QtProject"}}; QSettings settings{QSettings::UserScope, QLatin1String{"QtProject"}};
settings.beginGroup(QLatin1String{"QtNetwork"}); settings.beginGroup(QLatin1String{"QtNetwork"});
const QString id = settings.value( QLatin1String{ "DefaultNetworkConfiguration" } ).toString(); const QString id =
settings.value(QLatin1String{"DefaultNetworkConfiguration"}).toString();
settings.endGroup(); settings.endGroup();
// If the saved network configuration is not currently discovered use the system default // If the saved network configuration is not currently discovered use the
// system default
QNetworkConfiguration config = manager.configurationFromIdentifier(id); QNetworkConfiguration config = manager.configurationFromIdentifier(id);
if ( ( config.state() & QNetworkConfiguration::Discovered ) != QNetworkConfiguration::Discovered ) { if ((config.state() & QNetworkConfiguration::Discovered) !=
QNetworkConfiguration::Discovered) {
config = manager.defaultConfiguration(); config = manager.defaultConfiguration();
} }
networkSession = new QNetworkSession{config, this}; networkSession = new QNetworkSession{config, this};
connect( networkSession, &QNetworkSession::opened, connect(networkSession, &QNetworkSession::opened, this,
this, &ClientHelpNotificationServer::OpenSession ); &ClientHelpNotificationServer::OpenSession);
networkSession->open(); networkSession->open();
} else { } else {
OpenSession(); OpenSession();
} }
connect( helpMessageServer, &QTcpServer::newConnection, connect(helpMessageServer, &QTcpServer::newConnection, this,
this, &ClientHelpNotificationServer::SendReply ); &ClientHelpNotificationServer::SendReply);
} }
void lc::ClientHelpNotificationServer::OpenSession() { void lc::ClientHelpNotificationServer::OpenSession() {
@ -59,7 +62,9 @@ void lc::ClientHelpNotificationServer::OpenSession() {
QNetworkConfiguration config = networkSession->configuration(); QNetworkConfiguration config = networkSession->configuration();
QString id; QString id;
if (config.type() == QNetworkConfiguration::UserChoice) { if (config.type() == QNetworkConfiguration::UserChoice) {
id = networkSession->sessionProperty( QLatin1String{ "UserChoiceConfiguration" } ).toString(); id = networkSession
->sessionProperty(QLatin1String{"UserChoiceConfiguration"})
.toString();
} else { } else {
id = config.identifier(); id = config.identifier();
} }
@ -71,9 +76,15 @@ void lc::ClientHelpNotificationServer::OpenSession() {
} }
helpMessageServer = new QTcpServer{this}; helpMessageServer = new QTcpServer{this};
if ( !helpMessageServer->listen( hostAddress, settings->clientHelpNotificationServerPort ) ) { if (!helpMessageServer->listen(hostAddress,
QMessageBox messageBox{ QMessageBox::Critical, tr( "Unable to start the client help notification server" ), settings->clientHelpNotificationServerPort)) {
tr( "Unable to start the client help notification server.\nThe following error occurred:\n\n%1." ).arg( helpMessageServer->errorString() ), QMessageBox::Ok }; QMessageBox messageBox{
QMessageBox::Critical,
tr("Unable to start the client help notification server"),
tr("Unable to start the client help notification server.\nThe "
"following error occurred:\n\n%1.")
.arg(helpMessageServer->errorString()),
QMessageBox::Ok};
messageBox.exec(); messageBox.exec();
return; return;
} }
@ -98,16 +109,20 @@ void lc::ClientHelpNotificationServer::SendReply() {
unknownClient = true; unknownClient = true;
} }
connect( clientConnection, &QTcpSocket::disconnected, clientConnection, &QTcpSocket::deleteLater ); connect(clientConnection, &QTcpSocket::disconnected, clientConnection,
&QTcpSocket::deleteLater);
clientConnection->write(block); clientConnection->write(block);
clientConnection->disconnectFromHost(); clientConnection->disconnectFromHost();
if (unknownClient) { if (unknownClient) {
QMessageBox requestReceivedBox{ QMessageBox::Information, tr( "Unknown client asked for help."), QMessageBox requestReceivedBox{
tr( "An unknown client with IP '%1' asked for help.").arg( peerAddress ), QMessageBox::Ok }; QMessageBox::Information, tr("Unknown client asked for help."),
tr("An unknown client with IP '%1' asked for help.").arg(peerAddress),
QMessageBox::Ok};
requestReceivedBox.exec(); requestReceivedBox.exec();
} else { } else {
QMessageBox requestReceivedBox{ QMessageBox::Information, tr( "'%1' asked for help.").arg( peerName ), QMessageBox requestReceivedBox{
QMessageBox::Information, tr("'%1' asked for help.").arg(peerName),
tr("'%1' asked for help.").arg(peerName), QMessageBox::Ok}; tr("'%1' asked for help.").arg(peerName), QMessageBox::Ok};
requestReceivedBox.exec(); requestReceivedBox.exec();
} }

@ -22,9 +22,9 @@
#include "src/Lib/client.h" #include "src/Lib/client.h"
#include <QObject>
#include <QHostAddress> #include <QHostAddress>
#include <QMessageBox> #include <QMessageBox>
#include <QObject>
#include <QtNetwork> #include <QtNetwork>
namespace lc { namespace lc {
@ -48,6 +48,6 @@ private slots:
void SendReply(); void SendReply();
}; };
} } // namespace lc
#endif // CLIENTHELPNOTIFICATIONSERVER_H #endif // CLIENTHELPNOTIFICATIONSERVER_H

@ -20,22 +20,25 @@
#include "clientpinger.h" #include "clientpinger.h"
lc::ClientPinger::ClientPinger(const QString &argIP, lc::ClientPinger::ClientPinger(const QString &argIP,
const QString &argPingCommand, QObject *argParent ) : const QString &argPingCommand,
QObject{ argParent }, QObject *argParent)
// Arguments: -c 1 (send 1 ECHO_REQUEST packet) -w 1 (timeout after 1 second) -q (quiet output) : QObject{argParent},
pingArguments{ QStringList{} << "-c" << "1" << "-w" << "1" << "-q" << argIP }, // Arguments: -c 1 (send 1 ECHO_REQUEST packet) -w 1 (timeout after 1
// second) -q (quiet output)
pingArguments{QStringList{} << "-c"
<< "1"
<< "-w"
<< "1"
<< "-q" << argIP},
pingCommand{argPingCommand}, pingCommand{argPingCommand},
pingProcess{ new QProcess{ this } }, pingProcess{new QProcess{this}}, state{state_t::UNINITIALIZED} {
state{ state_t::UNINITIALIZED }
{
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
pingProcess->setProcessEnvironment(env); pingProcess->setProcessEnvironment(env);
// emit ping_string(new QString(*ping_command + " " + ping_arguments->join(" "))); // emit ping_string(new QString(*ping_command + " " + ping_arguments->join("
// ")));
} }
lc::ClientPinger::~ClientPinger() { lc::ClientPinger::~ClientPinger() { delete pingProcess; }
delete pingProcess;
}
void lc::ClientPinger::doPing() { void lc::ClientPinger::doPing() {
// Initialize the new state to be queried // Initialize the new state to be queried

@ -28,7 +28,8 @@
namespace lc { namespace lc {
//! The ClientPinger class is used to do repetitive pings of the owning Client instance's client. //! The ClientPinger class is used to do repetitive pings of the owning Client
//! instance's client.
/*! /*!
This class is just used for executing repetitive pings. This class is just used for executing repetitive pings.
*/ */
@ -38,9 +39,12 @@ class ClientPinger : public QObject {
public: public:
//! ClientPinger's constructor //! ClientPinger's constructor
/*! /*!
@param argIP A reference to the owning Client instance's IP address @param argIP A reference to the owning Client instance's IP
@param argPingCommand The path were the command to be executed for pings resides address
@param argParent The ClientPinger's parent owning this instance of it @param argPingCommand The path were the command to be executed for pings
resides
@param argParent The ClientPinger's parent owning this instance of
it
*/ */
explicit ClientPinger(const QString &argIP, const QString &argPingCommand, explicit ClientPinger(const QString &argIP, const QString &argPingCommand,
QObject *argParent = nullptr); QObject *argParent = nullptr);
@ -50,21 +54,24 @@ public:
public slots: public slots:
//! This slot executes a ping when called. //! This slot executes a ping when called.
void doPing(); void doPing();
//! Retrieves the information, that zLeaf is running (otherwise restarting will not result in status updates) //! Retrieves the information, that zLeaf is running (otherwise restarting
//! will not result in status updates)
void setStateToZLEAF_RUNNING(); void setStateToZLEAF_RUNNING();
private: private:
const QStringList pingArguments; //! The arguments for the 'ping' command const QStringList pingArguments; //! The arguments for the 'ping' command
const QString pingCommand; //! The 'ping' command itself const QString pingCommand; //! The 'ping' command itself
QProcess * pingProcess; //! The 'ping' process which will be executed on every call of 'do_ping()' QProcess *pingProcess; //! The 'ping' process which will be executed on every
//! call of 'do_ping()'
state_t state; //! Stores the current state of the client state_t state; //! Stores the current state of the client
signals: signals:
//! This signal was just implemented for testing purposes //! This signal was just implemented for testing purposes
//! This signal is emitted if the ping finished and the state of the client changed //! This signal is emitted if the ping finished and the state of the client
//! changed
void PingFinished(state_t state); void PingFinished(state_t state);
}; };
} } // namespace lc
#endif // CLIENTPINGER_H #endif // CLIENTPINGER_H

@ -32,12 +32,14 @@ enum class state_t : unsigned short int {
NOT_RESPONDING, NOT_RESPONDING,
//! The client is shutting down but not yet stopped responding //! The client is shutting down but not yet stopped responding
SHUTTING_DOWN, SHUTTING_DOWN,
//! The client's state is not yet defined (should only occur directly after client creation) //! The client's state is not yet defined (should only occur directly after
//! client creation)
UNINITIALIZED, UNINITIALIZED,
//! The client is responding to pings //! The client is responding to pings
RESPONDING, RESPONDING,
//! The client is running a zLeaf //! The client is running a zLeaf
ZLEAF_RUNNING}; ZLEAF_RUNNING
};
Q_DECLARE_METATYPE(state_t) Q_DECLARE_METATYPE(state_t)
#endif // GLOBAL_H #endif // GLOBAL_H

@ -24,14 +24,11 @@
#include "lablib.h" #include "lablib.h"
lc::Lablib::Lablib( QObject *argParent ) : lc::Lablib::Lablib(QObject *argParent)
QObject{ argParent }, : QObject{argParent}, labSettings{"Labcontrol", "Labcontrol", this},
labSettings{ "Labcontrol", "Labcontrol", this }, sessionsModel{new SessionsModel{this}} {
sessionsModel{ new SessionsModel{ this } }
{
for (const auto &s : settings->GetClients()) { for (const auto &s : settings->GetClients()) {
connect( this, &Lablib::ZLEAF_RUNNING, connect(this, &Lablib::ZLEAF_RUNNING, s, &Client::SetStateToZLEAF_RUNNING);
s, &Client::SetStateToZLEAF_RUNNING );
} }
DetectInstalledZTreeVersionsAndLaTeXHeaders(); DetectInstalledZTreeVersionsAndLaTeXHeaders();
@ -39,18 +36,20 @@ lc::Lablib::Lablib( QObject *argParent ) :
if (!settings->netstatCmd.isEmpty()) { if (!settings->netstatCmd.isEmpty()) {
netstatAgent = new NetstatAgent{settings->netstatCmd}; netstatAgent = new NetstatAgent{settings->netstatCmd};
netstatAgent->moveToThread(&netstatThread); netstatAgent->moveToThread(&netstatThread);
connect( &netstatThread, &QThread::finished, netstatAgent, &QObject::deleteLater ); connect(&netstatThread, &QThread::finished, netstatAgent,
connect( netstatAgent, &NetstatAgent::QueryFinished, &QObject::deleteLater);
this, &Lablib::GotNetstatQueryResult ); connect(netstatAgent, &NetstatAgent::QueryFinished, this,
&Lablib::GotNetstatQueryResult);
netstatThread.start(); netstatThread.start();
netstatTimer = new QTimer{this}; netstatTimer = new QTimer{this};
connect( netstatTimer, &QTimer::timeout, connect(netstatTimer, &QTimer::timeout, netstatAgent,
netstatAgent, &NetstatAgent::QueryClientConnections ); &NetstatAgent::QueryClientConnections);
netstatTimer->start(500); netstatTimer->start(500);
} }
// Initialize the server for client help requests retrieval // Initialize the server for client help requests retrieval
if ( settings->clientHelpNotificationServerPort && !settings->serverIP.isEmpty() ) { if (settings->clientHelpNotificationServerPort &&
!settings->serverIP.isEmpty()) {
clientHelpNotificationServer = new ClientHelpNotificationServer{this}; clientHelpNotificationServer = new ClientHelpNotificationServer{this};
} }
} }
@ -67,15 +66,15 @@ lc::Lablib::~Lablib () {
bool lc::Lablib::CheckIfUserIsAdmin() const { bool lc::Lablib::CheckIfUserIsAdmin() const {
for (const auto &s : settings->adminUsers) { for (const auto &s : settings->adminUsers) {
if (s == settings->localUserName) { if (s == settings->localUserName) {
qDebug() << "User" << settings->localUserName << "has administrative rights."; qDebug() << "User" << settings->localUserName
<< "has administrative rights.";
return true; return true;
} }
} }
return false; return false;
} }
void lc::Lablib::DetectInstalledZTreeVersionsAndLaTeXHeaders() { void lc::Lablib::DetectInstalledZTreeVersionsAndLaTeXHeaders() {}
}
void lc::Lablib::GotNetstatQueryResult(QStringList *argActiveZLeafConnections) { void lc::Lablib::GotNetstatQueryResult(QStringList *argActiveZLeafConnections) {
if (argActiveZLeafConnections != nullptr) { if (argActiveZLeafConnections != nullptr) {
@ -83,8 +82,7 @@ void lc::Lablib::GotNetstatQueryResult( QStringList *argActiveZLeafConnections )
// Set all given clients' statuses to 'ZLEAF_RUNNING' // Set all given clients' statuses to 'ZLEAF_RUNNING'
emit ZLEAF_RUNNING(s); emit ZLEAF_RUNNING(s);
} }
} } else
else
qDebug() << "Netstat status query failed."; qDebug() << "Netstat status query failed.";
delete argActiveZLeafConnections; delete argActiveZLeafConnections;
} }
@ -116,17 +114,22 @@ void lc::Lablib::ShowPreprints() {
void lc::Lablib::StartNewSession(QVector<Client *> argAssocCl, void lc::Lablib::StartNewSession(QVector<Client *> argAssocCl,
QString argParticipNameReplacement, QString argParticipNameReplacement,
bool argPrintLocalReceipts, QString argReceiptsHeader, bool argPrintLocalReceipts,
QString argzTreeDataTargetPath, quint16 argzTreePort, QString argReceiptsHeader,
QString argzTreeDataTargetPath,
quint16 argzTreePort,
QString argzTreeVersion) { QString argzTreeVersion) {
if (!QDir(argzTreeDataTargetPath).exists()) { if (!QDir(argzTreeDataTargetPath).exists()) {
QMessageBox messageBox{ QMessageBox::Critical, tr( "Data target path does not exist" ), QMessageBox messageBox{QMessageBox::Critical,
tr("Data target path does not exist"),
tr("Your chosen data target path does not exist." tr("Your chosen data target path does not exist."
" Do you want it to be created automatically?"), " Do you want it to be created automatically?"),
QMessageBox::Yes | QMessageBox::No}; QMessageBox::Yes | QMessageBox::No};
messageBox.exec(); messageBox.exec();
if (messageBox.clickedButton() == messageBox.button(QMessageBox::No)) { if (messageBox.clickedButton() == messageBox.button(QMessageBox::No)) {
QMessageBox messageBox{ QMessageBox::Critical, tr( "Data target directory will not" QMessageBox messageBox{
QMessageBox::Critical,
tr("Data target directory will not"
" be created"), " be created"),
tr("Your chosen data target directory does not exist and" tr("Your chosen data target directory does not exist and"
" will not be created. Please choose another one."), " will not be created. Please choose another one."),
@ -135,27 +138,28 @@ void lc::Lablib::StartNewSession( QVector< Client* > argAssocCl,
return; return;
} else { } else {
if (!QDir().mkpath(argzTreeDataTargetPath)) { if (!QDir().mkpath(argzTreeDataTargetPath)) {
QMessageBox messageBox{ QMessageBox::Critical, tr( "Data target directory could" QMessageBox messageBox{
QMessageBox::Critical,
tr("Data target directory could"
" not be created"), " not be created"),
tr("Your chosen data target directory does not exist" tr("Your chosen data target directory does not exist"
" and could not be created. Please choose another" " and could not be created. Please choose another"
" one." ), QMessageBox::Ok }; " one."),
QMessageBox::Ok};
messageBox.exec(); messageBox.exec();
return; return;
} }
} }
} }
try { try {
sessionsModel->push_back( new Session{ std::move( argAssocCl ), sessionsModel->push_back(
argzTreeDataTargetPath, new Session{std::move(argAssocCl), argzTreeDataTargetPath, argzTreePort,
argzTreePort, argzTreeVersion, argzTreeVersion, argPrintLocalReceipts,
argPrintLocalReceipts, argParticipNameReplacement, argReceiptsHeader});
argParticipNameReplacement,
argReceiptsHeader } );
occupiedPorts.append(sessionsModel->back()->zTreePort); occupiedPorts.append(sessionsModel->back()->zTreePort);
} } catch (Session::lcDataTargetPathCreationFailed) {
catch ( Session::lcDataTargetPathCreationFailed ) { QMessageBox::information(
QMessageBox::information( nullptr, tr( "Chosen data target path could not be created" ), nullptr, tr("Chosen data target path could not be created"),
tr("The path specified by your chosen data target path '%1'" tr("The path specified by your chosen data target path '%1'"
" could not be created. Please check if it is a valid" " could not be created. Please check if it is a valid"
" location and you have all needed permissions.") " location and you have all needed permissions.")
@ -172,12 +176,16 @@ void lc::Lablib::SetLocalZLeafDefaultName( const QString &argName ) {
QStringList lc::Lablib::getzLeafArgs(int sessionPort, QString zleafVersion) { QStringList lc::Lablib::getzLeafArgs(int sessionPort, QString zleafVersion) {
QStringList arguments; QStringList arguments;
if (sessionPort == 7000) { if (sessionPort == 7000) {
arguments << "DISPLAY=:0.0" << settings->tasksetCmd << "0x00000001" << settings->wineCmd arguments << "DISPLAY=:0.0" << settings->tasksetCmd << "0x00000001"
<< QString{ settings->zTreeInstDir + "/zTree_" + zleafVersion + "/zleaf.exe" } << settings->wineCmd
<< QString{settings->zTreeInstDir + "/zTree_" + zleafVersion +
"/zleaf.exe"}
<< "/server" << settings->serverIP; << "/server" << settings->serverIP;
} else { } else {
arguments << "DISPLAY=:0.0" << settings->tasksetCmd << "0x00000001" << settings->wineCmd arguments << "DISPLAY=:0.0" << settings->tasksetCmd << "0x00000001"
<< QString{ settings->zTreeInstDir + "/zTree_" + zleafVersion + "/zleaf.exe" } << settings->wineCmd
<< QString{settings->zTreeInstDir + "/zTree_" + zleafVersion +
"/zleaf.exe"}
<< "/server" << settings->serverIP << "/channel" << "/server" << settings->serverIP << "/channel"
<< QString::number(sessionPort - 7000); << QString::number(sessionPort - 7000);
} }

@ -51,10 +51,10 @@ namespace lc {
//! This class represents the entire lab and running sessions. //! This class represents the entire lab and running sessions.
/*! /*!
This class contains elements and functions needed to represent the lab and running sessions. This class contains elements and functions needed to represent the lab and
running sessions.
*/ */
class Lablib : public QObject class Lablib : public QObject {
{
Q_OBJECT Q_OBJECT
public: public:
/*! /*!
@ -66,12 +66,14 @@ public:
*/ */
~Lablib(); ~Lablib();
/*! /*!
* \brief CheckIfUserIsAdmin checks if the account with the passed user name has administrative rights * \brief CheckIfUserIsAdmin checks if the account with the passed user name
* \param argUserName The account name which shall checked for administrative rights * has administrative rights \param argUserName The account name which shall
* \return True, if the account has administrative rights; false, otherwise * checked for administrative rights \return True, if the account has
* administrative rights; false, otherwise
*/ */
bool CheckIfUserIsAdmin() const; bool CheckIfUserIsAdmin() const;
/** Returns a pointer to a QVector<unsigned int> containing all by sessions occupied ports /** Returns a pointer to a QVector<unsigned int> containing all by sessions
* occupied ports
* *
* @return A pointer to a QVector<unsigned int> containing all occupied ports * @return A pointer to a QVector<unsigned int> containing all occupied ports
*/ */
@ -88,19 +90,20 @@ public:
void SetLocalZLeafDefaultName(const QString &argName); void SetLocalZLeafDefaultName(const QString &argName);
void ShowOrsee(); void ShowOrsee();
void ShowPreprints(); void ShowPreprints();
void StartNewSession( QVector< Client* > argAssocCl, QString argParticipNameReplacement, void StartNewSession(QVector<Client *> argAssocCl,
QString argParticipNameReplacement,
bool argPrintLocalReceipts, QString argReceiptsHeader, bool argPrintLocalReceipts, QString argReceiptsHeader,
QString argzTreeDataTargetPath, quint16 argzTreePort, QString argzTreeDataTargetPath, quint16 argzTreePort,
QString argzTreeVersion); QString argzTreeVersion);
/*! /*!
* \brief Returns the commandline to issue on the client(s) in order to start zLeaf * \brief Returns the commandline to issue on the client(s) in order to start
* zLeaf
* @param sessionPort The port zLeaf shall connect to * @param sessionPort The port zLeaf shall connect to
* @param zLeafVersion zLeaf Version to start * @param zLeafVersion zLeaf Version to start
*/ */
QStringList getzLeafArgs(int sessionPort, QString zleafVersion); QStringList getzLeafArgs(int sessionPort, QString zleafVersion);
public slots: public slots:
signals: signals:
@ -117,15 +120,20 @@ private:
*/ */
void ReadSettings(); void ReadSettings();
ClientHelpNotificationServer *clientHelpNotificationServer = nullptr; //! A server to retrieve help requests from the clients ClientHelpNotificationServer *clientHelpNotificationServer =
nullptr; //! A server to retrieve help requests from the clients
QSettings labSettings; QSettings labSettings;
NetstatAgent *netstatAgent = nullptr; //! Tries to detect active zLeaf connections from the clients NetstatAgent *netstatAgent =
nullptr; //! Tries to detect active zLeaf connections from the clients
QThread netstatThread; QThread netstatThread;
QTimer *netstatTimer = nullptr; //! A timer for regular execution of the NetstatAgent instance's request mechanism QTimer *netstatTimer = nullptr; //! A timer for regular execution of the
//! NetstatAgent instance's request mechanism
QVector<quint16> occupiedPorts; QVector<quint16> occupiedPorts;
SessionsModel *sessionsModel = nullptr; //! A derivation from QAbstractTableModel used to store the single Session instances SessionsModel *sessionsModel =
nullptr; //! A derivation from QAbstractTableModel used to store the
//! single Session instances
}; };
} } // namespace lc
#endif // LABLIB_H #endif // LABLIB_H

@ -19,14 +19,14 @@
#include "netstatagent.h" #include "netstatagent.h"
lc::NetstatAgent::NetstatAgent( const QString &argNetstatCommand, QObject *argParent ) : lc::NetstatAgent::NetstatAgent(const QString &argNetstatCommand,
QObject{ argParent }, QObject *argParent)
extractionRegexp{ "\\d+\\.\\d+\\.\\d+\\.\\d+" }, : QObject{argParent}, extractionRegexp{"\\d+\\.\\d+\\.\\d+\\.\\d+"},
netstatArguments{ QStringList{} << "-anp" << "--tcp" }, netstatArguments{QStringList{} << "-anp"
netstatCommand{ argNetstatCommand }, << "--tcp"},
netstatQueryProcess{ this }, netstatCommand{argNetstatCommand}, netstatQueryProcess{this},
searchRegexp{ "\\W(ESTABLISHED|VERBUNDEN)( +)(\\d+)(/ztree.exe)\\W", QRegularExpression::CaseInsensitiveOption } searchRegexp{"\\W(ESTABLISHED|VERBUNDEN)( +)(\\d+)(/ztree.exe)\\W",
{ QRegularExpression::CaseInsensitiveOption} {
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
netstatQueryProcess.setProcessEnvironment(env); netstatQueryProcess.setProcessEnvironment(env);
} }
@ -36,15 +36,19 @@ void lc::NetstatAgent::QueryClientConnections() {
if (!netstatQueryProcess.waitForFinished(400)) { if (!netstatQueryProcess.waitForFinished(400)) {
emit QueryFinished(nullptr); emit QueryFinished(nullptr);
} else { } else {
// Get all 'netstat_query_process' standard output and store it temporarily in 'temp_strings' // Get all 'netstat_query_process' standard output and store it temporarily
QByteArray netstatQueryProcessOutputByteArray = netstatQueryProcess.readAllStandardOutput(); // in 'temp_strings'
QByteArray netstatQueryProcessOutputByteArray =
netstatQueryProcess.readAllStandardOutput();
QString netstatQueryProcessOutputString(netstatQueryProcessOutputByteArray); QString netstatQueryProcessOutputString(netstatQueryProcessOutputByteArray);
QStringList tempStrings = netstatQueryProcessOutputString.split( '\n', QString::SkipEmptyParts ); QStringList tempStrings =
netstatQueryProcessOutputString.split('\n', QString::SkipEmptyParts);
QStringList *netstatQueryProcessOutput = new QStringList; QStringList *netstatQueryProcessOutput = new QStringList;
for (auto s : tempStrings) { for (auto s : tempStrings) {
if (s.contains(searchRegexp)) { if (s.contains(searchRegexp)) {
QRegularExpressionMatch match = extractionRegexp.match( s, s.indexOf( ':', 0, Qt::CaseInsensitive ) ); QRegularExpressionMatch match =
extractionRegexp.match(s, s.indexOf(':', 0, Qt::CaseInsensitive));
netstatQueryProcessOutput->append(match.captured()); netstatQueryProcessOutput->append(match.captured());
} }
} }

@ -27,7 +27,8 @@
namespace lc { namespace lc {
//! The NetstatAgent class is used to do repetitive runs of the 'netstat' program to check for active zLeaf connections. //! The NetstatAgent class is used to do repetitive runs of the 'netstat'
//! program to check for active zLeaf connections.
/*! /*!
This class is just used for repetive executions of netstat. This class is just used for repetive executions of netstat.
*/ */
@ -35,10 +36,12 @@ class NetstatAgent : public QObject {
Q_OBJECT Q_OBJECT
public: public:
explicit NetstatAgent( const QString &argNetstatCommand, QObject *argParent = nullptr ); explicit NetstatAgent(const QString &argNetstatCommand,
QObject *argParent = nullptr);
signals: signals:
//! This signal is emitted if the query of the currently active zLeaf connections finished //! This signal is emitted if the query of the currently active zLeaf
//! connections finished
void QueryFinished(QStringList *argActiveZLeafConnections); void QueryFinished(QStringList *argActiveZLeafConnections);
public slots: public slots:
@ -52,6 +55,6 @@ private:
const QRegularExpression searchRegexp; const QRegularExpression searchRegexp;
}; };
} } // namespace lc
#endif // NETSTATAGENT_H #endif // NETSTATAGENT_H

@ -26,45 +26,41 @@
extern std::unique_ptr<lc::Settings> settings; extern std::unique_ptr<lc::Settings> settings;
lc::ReceiptsHandler::ReceiptsHandler( const QString &argZTreeDataTargetPath, lc::ReceiptsHandler::ReceiptsHandler(
bool argPrintReceiptsForLocalClients, const QString &argZTreeDataTargetPath, bool argPrintReceiptsForLocalClients,
const QString &argAnonymousReceiptsPlaceholder, const QString &argAnonymousReceiptsPlaceholder,
const QString &argLatexHeaderName, const QString &argLatexHeaderName, QObject *argParent)
QObject *argParent ) : : QObject{argParent},
QObject{ argParent },
anonymousReceiptsPlaceholder{argAnonymousReceiptsPlaceholder}, anonymousReceiptsPlaceholder{argAnonymousReceiptsPlaceholder},
dateString{QDateTime::currentDateTime().toString("yyMMdd_hhmm")}, dateString{QDateTime::currentDateTime().toString("yyMMdd_hhmm")},
expectedPaymentFileName{dateString + ".pay"}, expectedPaymentFileName{dateString + ".pay"},
expectedPaymentFilePath{ argZTreeDataTargetPath + "/" + dateString + ".pay" }, expectedPaymentFilePath{argZTreeDataTargetPath + "/" + dateString +
latexHeaderName{ argLatexHeaderName }, ".pay"},
paymentFile{ expectedPaymentFilePath }, latexHeaderName{argLatexHeaderName}, paymentFile{expectedPaymentFilePath},
printReceiptsForLocalClients{argPrintReceiptsForLocalClients}, printReceiptsForLocalClients{argPrintReceiptsForLocalClients},
timer{ new QTimer{ this } }, timer{new QTimer{this}}, zTreeDataTargetPath{argZTreeDataTargetPath} {
zTreeDataTargetPath{ argZTreeDataTargetPath }
{
qDebug() << "Expected payment file name is:" << expectedPaymentFilePath; qDebug() << "Expected payment file name is:" << expectedPaymentFilePath;
// Create a QTimer regularly checking if the payment file was created and print it if so // Create a QTimer regularly checking if the payment file was created and
connect( timer, &QTimer::timeout, // print it if so
this, &ReceiptsHandler::PrintReceipts ); connect(timer, &QTimer::timeout, this, &ReceiptsHandler::PrintReceipts);
timer->start(2000); timer->start(2000);
} }
lc::ReceiptsHandler::ReceiptsHandler( const QString &argZTreeDataTargetPath, lc::ReceiptsHandler::ReceiptsHandler(
bool argPrintReceiptsForLocalClients, const QString &argZTreeDataTargetPath, bool argPrintReceiptsForLocalClients,
const QString &argAnonymousReceiptsPlaceholder, const QString &argAnonymousReceiptsPlaceholder,
const QString &argLatexHeaderName, const QString &argLatexHeaderName, const QString &argDateString,
const QString &argDateString, QObject *argParent ) : QObject *argParent)
QObject{ argParent }, : QObject{argParent},
anonymousReceiptsPlaceholder{argAnonymousReceiptsPlaceholder}, anonymousReceiptsPlaceholder{argAnonymousReceiptsPlaceholder},
dateString{ argDateString }, dateString{argDateString}, expectedPaymentFileName{argDateString +
expectedPaymentFileName{ argDateString + ".pay" }, ".pay"},
expectedPaymentFilePath{ argZTreeDataTargetPath + "/" + argDateString + ".pay" }, expectedPaymentFilePath{argZTreeDataTargetPath + "/" + argDateString +
latexHeaderName{ argLatexHeaderName }, ".pay"},
paymentFile{ expectedPaymentFilePath }, latexHeaderName{argLatexHeaderName}, paymentFile{expectedPaymentFilePath},
printReceiptsForLocalClients{argPrintReceiptsForLocalClients}, printReceiptsForLocalClients{argPrintReceiptsForLocalClients},
zTreeDataTargetPath{ argZTreeDataTargetPath } zTreeDataTargetPath{argZTreeDataTargetPath} {
{
qDebug() << "Expected payment file name is:" << expectedPaymentFilePath; qDebug() << "Expected payment file name is:" << expectedPaymentFilePath;
PrintReceipts(); PrintReceipts();
@ -87,7 +83,8 @@ void lc::ReceiptsHandler::CreateReceiptsFromPaymentFile() {
QVector<QString> *rawParticipantsData = nullptr; QVector<QString> *rawParticipantsData = nullptr;
rawParticipantsData = GetParticipantsDataFromPaymentFile(); rawParticipantsData = GetParticipantsDataFromPaymentFile();
for (int i = 0; i < rawParticipantsData->size(); i++) { for (int i = 0; i < rawParticipantsData->size(); i++) {
qDebug() << "Payment file line" << QString::number( i ) << ":\t" << rawParticipantsData->at( i ); qDebug() << "Payment file line" << QString::number(i) << ":\t"
<< rawParticipantsData->at(i);
} }
// Extract the data of the participant's whose receipts shall be printed // Extract the data of the participant's whose receipts shall be printed
@ -96,14 +93,18 @@ void lc::ReceiptsHandler::CreateReceiptsFromPaymentFile() {
*/ */
QVector<paymentEntry_t *> *participants = new QVector<paymentEntry_t *>; QVector<paymentEntry_t *> *participants = new QVector<paymentEntry_t *>;
double overall_payoff = 0.0; double overall_payoff = 0.0;
for ( QVector<QString>::iterator it = rawParticipantsData->begin(); it != rawParticipantsData->end() - 1; ++it ) { for (QVector<QString>::iterator it = rawParticipantsData->begin();
// Split the lines containing the participants' data into their inidivual parts it != rawParticipantsData->end() - 1; ++it) {
QStringList temp_participant_data = it->split('\t', QString::KeepEmptyParts); // Split the lines containing the participants' data into their inidivual
// parts
QStringList temp_participant_data =
it->split('\t', QString::KeepEmptyParts);
qDebug() << temp_participant_data.join(" - "); qDebug() << temp_participant_data.join(" - ");
if ( !printReceiptsForLocalClients && temp_participant_data.at( 3 ).contains( "local" ) ) { if (!printReceiptsForLocalClients &&
qDebug() << "Receipt for local client" << temp_participant_data.at( 1 ) << "will not be printed."; temp_participant_data.at(3).contains("local")) {
} qDebug() << "Receipt for local client" << temp_participant_data.at(1)
else { << "will not be printed.";
} else {
// Create a new struct instance for participant data and fill it // Create a new struct instance for participant data and fill it
paymentEntry_t *participant = new paymentEntry_t; paymentEntry_t *participant = new paymentEntry_t;
participant->computer = temp_participant_data.at(1); participant->computer = temp_participant_data.at(1);
@ -116,7 +117,8 @@ void lc::ReceiptsHandler::CreateReceiptsFromPaymentFile() {
delete rawParticipantsData; delete rawParticipantsData;
rawParticipantsData = nullptr; rawParticipantsData = nullptr;
// Make receipts overview anonymous if requested (at this stage just names are removed, so that the overview still containts the client names // Make receipts overview anonymous if requested (at this stage just names are
// removed, so that the overview still containts the client names
if (!anonymousReceiptsPlaceholder.isEmpty()) { if (!anonymousReceiptsPlaceholder.isEmpty()) {
MakeReceiptsAnonymous(participants, false); MakeReceiptsAnonymous(participants, false);
} }
@ -136,7 +138,9 @@ void lc::ReceiptsHandler::CreateReceiptsFromPaymentFile() {
latexText->append("\n\\COMPREHENSION{\n"); latexText->append("\n\\COMPREHENSION{\n");
unsigned short int zeile = 0; unsigned short int zeile = 0;
for (auto s : *participants) { for (auto s : *participants) {
latexText->append( expectedPaymentFileName + " & " + s->computer + " & " + s->name + " & " + QString::number( s->payoff, 'f', 2 ) + " \\EUR\\\\\n" ); latexText->append(expectedPaymentFileName + " & " + s->computer + " & " +
s->name + " & " + QString::number(s->payoff, 'f', 2) +
" \\EUR\\\\\n");
if (zeile % 2 == 0) { if (zeile % 2 == 0) {
latexText->append("\\rowcolor[gray]{0.9}\n"); latexText->append("\\rowcolor[gray]{0.9}\n");
} }
@ -145,21 +149,26 @@ void lc::ReceiptsHandler::CreateReceiptsFromPaymentFile() {
// MISSING: Appending show up entries to the overview // MISSING: Appending show up entries to the overview
// Make also the clients on the receipts anonymous. This is done as second step, so that the beforehand created overview still contains the clients // Make also the clients on the receipts anonymous. This is done as second
// step, so that the beforehand created overview still contains the clients
if (!anonymousReceiptsPlaceholder.isEmpty()) { if (!anonymousReceiptsPlaceholder.isEmpty()) {
MakeReceiptsAnonymous(participants, true); MakeReceiptsAnonymous(participants, true);
} }
// Add the LaTeX middle sequence // Add the LaTeX middle sequence
latexText->append( "}{" + QString::number( overall_payoff, 'f', 2 ) + "}\n\n%%Einzelquittungen\n" ); latexText->append("}{" + QString::number(overall_payoff, 'f', 2) +
"}\n\n%%Einzelquittungen\n");
// Write the single receipts // Write the single receipts
for (auto s : *participants) { for (auto s : *participants) {
if (s->payoff >= 0) { if (s->payoff >= 0) {
latexText->append( "\\GAINRECEIPT{" + expectedPaymentFileName + "}{" + s->computer + "}{" + s->name + "}{" + QString::number( s->payoff, 'f', 2 ) + "}\n" ); latexText->append("\\GAINRECEIPT{" + expectedPaymentFileName + "}{" +
} s->computer + "}{" + s->name + "}{" +
else { QString::number(s->payoff, 'f', 2) + "}\n");
latexText->append( "\\LOSSRECEIPT{" + expectedPaymentFileName + "}{" + s->computer + "}{" + s->name + "}{" + QString::number( s->payoff, 'f', 2 ) + "}\n" ); } else {
latexText->append("\\LOSSRECEIPT{" + expectedPaymentFileName + "}{" +
s->computer + "}{" + s->name + "}{" +
QString::number(s->payoff, 'f', 2) + "}\n");
} }
delete s; delete s;
} }
@ -173,19 +182,27 @@ void lc::ReceiptsHandler::CreateReceiptsFromPaymentFile() {
// Create the tex file // Create the tex file
QFile *texFile = new QFile{zTreeDataTargetPath + "/" + dateString + ".tex"}; QFile *texFile = new QFile{zTreeDataTargetPath + "/" + dateString + ".tex"};
qDebug() << "Tex file" << texFile->fileName() << "will be created for receipts printing."; qDebug() << "Tex file" << texFile->fileName()
<< "will be created for receipts printing.";
// Clean up any already existing files // Clean up any already existing files
if (texFile->exists()) { if (texFile->exists()) {
if (!texFile->remove()) { if (!texFile->remove()) {
QMessageBox messageBox( QMessageBox::Critical, "Tex file removing failed", "There already exists a tex file at '" + texFile->fileName() QMessageBox messageBox(QMessageBox::Critical, "Tex file removing failed",
+ "' which cannot be removed. The creation of the receipts printout may fail.", QMessageBox::Ok ); "There already exists a tex file at '" +
texFile->fileName() +
"' which cannot be removed. The creation of "
"the receipts printout may fail.",
QMessageBox::Ok);
messageBox.exec(); messageBox.exec();
} }
} }
// Create a new file // Create a new file
if (!texFile->open(QIODevice::Text | QIODevice::WriteOnly)) { if (!texFile->open(QIODevice::Text | QIODevice::WriteOnly)) {
QMessageBox messageBox( QMessageBox::Critical, "Tex file creation failed", "The creation of the tex file for receipts printing at '" + texFile->fileName() QMessageBox messageBox(
+ "' failed. Receipts printing will not work.", QMessageBox::Ok ); QMessageBox::Critical, "Tex file creation failed",
"The creation of the tex file for receipts printing at '" +
texFile->fileName() + "' failed. Receipts printing will not work.",
QMessageBox::Ok);
messageBox.exec(); messageBox.exec();
return; return;
} }
@ -199,10 +216,10 @@ void lc::ReceiptsHandler::CreateReceiptsFromPaymentFile() {
receiptsPrinter = new ReceiptsPrinter{dateString, zTreeDataTargetPath, this}; receiptsPrinter = new ReceiptsPrinter{dateString, zTreeDataTargetPath, this};
receiptsPrinter->start(); receiptsPrinter->start();
connect( receiptsPrinter, &ReceiptsPrinter::PrintingFinished, connect(receiptsPrinter, &ReceiptsPrinter::PrintingFinished, this,
this, &ReceiptsHandler::DeleteReceiptsPrinterInstance ); &ReceiptsHandler::DeleteReceiptsPrinterInstance);
connect( receiptsPrinter, &ReceiptsPrinter::ErrorOccurred, connect(receiptsPrinter, &ReceiptsPrinter::ErrorOccurred, this,
this, &ReceiptsHandler::DisplayMessageBox ); &ReceiptsHandler::DisplayMessageBox);
// Clean up // Clean up
texFile->close(); texFile->close();
@ -219,8 +236,10 @@ void lc::ReceiptsHandler::DeleteReceiptsPrinterInstance() {
emit PrintingFinished(); emit PrintingFinished();
} }
void lc::ReceiptsHandler::DisplayMessageBox( QString *argErrorMessage, QString *argHeading ) { void lc::ReceiptsHandler::DisplayMessageBox(QString *argErrorMessage,
QMessageBox messageBox( QMessageBox::Warning, *argHeading, *argErrorMessage, QMessageBox::Ok ); QString *argHeading) {
QMessageBox messageBox(QMessageBox::Warning, *argHeading, *argErrorMessage,
QMessageBox::Ok);
delete argHeading; delete argHeading;
delete argErrorMessage; delete argErrorMessage;
messageBox.exec(); messageBox.exec();
@ -255,11 +274,16 @@ QVector<QString> *lc::ReceiptsHandler::GetParticipantsDataFromPaymentFile() {
QString *lc::ReceiptsHandler::LoadLatexHeader() { QString *lc::ReceiptsHandler::LoadLatexHeader() {
// Prepare all facilities to read the latex header file // Prepare all facilities to read the latex header file
QFile latexHeaderFile( settings->lcDataDir + "/" + latexHeaderName + "_header.tex" ); QFile latexHeaderFile(settings->lcDataDir + "/" + latexHeaderName +
"_header.tex");
if (!latexHeaderFile.open(QIODevice::ReadOnly | QIODevice::Text)) { if (!latexHeaderFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
QMessageBox messageBox{ QMessageBox::Critical, tr( "LaTeX header could not be loaded" ), QMessageBox messageBox{QMessageBox::Critical,
tr( "The LaTeX header at '%1/%2_header.tex' could not be loaded. Receipts printing will not work." ) tr("LaTeX header could not be loaded"),
.arg( settings->lcDataDir ).arg( latexHeaderName ), QMessageBox::Ok }; tr("The LaTeX header at '%1/%2_header.tex' could "
"not be loaded. Receipts printing will not work.")
.arg(settings->lcDataDir)
.arg(latexHeaderName),
QMessageBox::Ok};
messageBox.exec(); messageBox.exec();
return nullptr; return nullptr;
} }
@ -273,16 +297,18 @@ QString *lc::ReceiptsHandler::LoadLatexHeader() {
return header; return header;
} }
void lc::ReceiptsHandler::MakeReceiptsAnonymous( QVector<paymentEntry_t*> *argDataVector, bool argAlsoAnonymizeClients ) { void lc::ReceiptsHandler::MakeReceiptsAnonymous(
QVector<paymentEntry_t *> *argDataVector, bool argAlsoAnonymizeClients) {
if (!argAlsoAnonymizeClients) { if (!argAlsoAnonymizeClients) {
qDebug() << "Names are made anonymous"; qDebug() << "Names are made anonymous";
for ( QVector< paymentEntry_t* >::iterator it = argDataVector->begin(); it != argDataVector->end(); ++it ) { for (QVector<paymentEntry_t *>::iterator it = argDataVector->begin();
it != argDataVector->end(); ++it) {
(*it)->name = anonymousReceiptsPlaceholder; (*it)->name = anonymousReceiptsPlaceholder;
} }
} } else {
else {
qDebug() << "Clients and names are made anonymous"; qDebug() << "Clients and names are made anonymous";
for ( QVector< paymentEntry_t* >::iterator it = argDataVector->begin(); it != argDataVector->end(); ++it ) { for (QVector<paymentEntry_t *>::iterator it = argDataVector->begin();
it != argDataVector->end(); ++it) {
(*it)->name = anonymousReceiptsPlaceholder; (*it)->name = anonymousReceiptsPlaceholder;
(*it)->computer = "\\hspace{1cm}"; (*it)->computer = "\\hspace{1cm}";
} }

@ -34,13 +34,20 @@ namespace lc {
//! A struct representing one payoff entry. //! A struct representing one payoff entry.
/*! /*!
This class represents a single payoff entry which will be used in the receipts creation process. Multiple instances of this will be used to represent the individual participants' outcomes. This class represents a single payoff entry which will be used in the receipts
creation process. Multiple instances of this will be used to represent the
individual participants' outcomes.
*/ */
struct paymentEntry_t {QString computer; QString name; double payoff;}; struct paymentEntry_t {
QString computer;
QString name;
double payoff;
};
//! A class to handle receipts printing. //! A class to handle receipts printing.
/*! /*!
This class is element of every session and is used to handle the receipts printing. This class is element of every session and is used to handle the receipts
printing.
*/ */
class ReceiptsHandler : public QObject { class ReceiptsHandler : public QObject {
Q_OBJECT Q_OBJECT
@ -49,12 +56,14 @@ public:
explicit ReceiptsHandler(const QString &argZTreeDataTargetPath, explicit ReceiptsHandler(const QString &argZTreeDataTargetPath,
bool argPrintReceiptsForLocalClients, bool argPrintReceiptsForLocalClients,
const QString &argAnonymousReceiptsPlaceholder, const QString &argAnonymousReceiptsPlaceholder,
const QString &argLatexHeaderName, QObject *argParent = nullptr ); const QString &argLatexHeaderName,
QObject *argParent = nullptr);
explicit ReceiptsHandler(const QString &argZTreeDataTargetPath, explicit ReceiptsHandler(const QString &argZTreeDataTargetPath,
bool argPrintReceiptsForLocalClients, bool argPrintReceiptsForLocalClients,
const QString &argAnonymousReceiptsPlaceholder, const QString &argAnonymousReceiptsPlaceholder,
const QString &argLatexHeaderName, const QString &argLatexHeaderName,
const QString &argDateString, QObject *argParent = nullptr ); const QString &argDateString,
QObject *argParent = nullptr);
signals: signals:
void PrintingFinished(); void PrintingFinished();
@ -63,7 +72,8 @@ private slots:
/*! Deletes the ReceiptsPrinter instance after successful printing /*! Deletes the ReceiptsPrinter instance after successful printing
*/ */
void DeleteReceiptsPrinterInstance(); void DeleteReceiptsPrinterInstance();
/*! Displays QMessageBox widgets for errors given by the ReceiptsPrinter instance /*! Displays QMessageBox widgets for errors given by the ReceiptsPrinter
* instance
*/ */
void DisplayMessageBox(QString *argErrorMessage, QString *argHeading); void DisplayMessageBox(QString *argErrorMessage, QString *argHeading);
/*! Prints the receipts /*! Prints the receipts
@ -74,20 +84,33 @@ private:
void CreateReceiptsFromPaymentFile(); void CreateReceiptsFromPaymentFile();
QVector<QString> *GetParticipantsDataFromPaymentFile(); QVector<QString> *GetParticipantsDataFromPaymentFile();
QString *LoadLatexHeader(); QString *LoadLatexHeader();
void MakeReceiptsAnonymous( QVector<paymentEntry_t*> *argDataVector, bool argAlsoAnonymizeClients ); void MakeReceiptsAnonymous(QVector<paymentEntry_t *> *argDataVector,
bool argAlsoAnonymizeClients);
const QString anonymousReceiptsPlaceholder; //!< Placeholder which shall be inserted for participant names if anonymous printing is desired (QString != "") const QString
const QString dateString; //!< The expected date string of the payment file in form 'yyMMdd_hhmm' anonymousReceiptsPlaceholder; //!< Placeholder which shall be inserted for
const QString expectedPaymentFileName; //!< The name of the expected payment file //!< participant names if anonymous printing
const QString expectedPaymentFilePath; //!< The path of the expected payment file //!< is desired (QString != "")
const QString latexHeaderName; //!< The name of the chosen LaTeX header template const QString dateString; //!< The expected date string of the payment file in
QFile paymentFile; //!< A pointer to the '*.pay' file being watched for existance and starting the printing process //!< form 'yyMMdd_hhmm'
const bool printReceiptsForLocalClients; //!< Stores if receipts shall be printed for local clients const QString
ReceiptsPrinter *receiptsPrinter = nullptr; //!< Creates new thread for receipts printing expectedPaymentFileName; //!< The name of the expected payment file
QTimer *timer = nullptr; //!< Used for regular checking if the payment file was created const QString
const QString zTreeDataTargetPath; //!< A reference to the data target path stored in the session class instance expectedPaymentFilePath; //!< The path of the expected payment file
const QString
latexHeaderName; //!< The name of the chosen LaTeX header template
QFile paymentFile; //!< A pointer to the '*.pay' file being watched for
//!< existance and starting the printing process
const bool printReceiptsForLocalClients; //!< Stores if receipts shall be
//!< printed for local clients
ReceiptsPrinter *receiptsPrinter =
nullptr; //!< Creates new thread for receipts printing
QTimer *timer =
nullptr; //!< Used for regular checking if the payment file was created
const QString zTreeDataTargetPath; //!< A reference to the data target path
//!< stored in the session class instance
}; };
} } // namespace lc
#endif // RECEIPTS_HANDLER_H #endif // RECEIPTS_HANDLER_H

@ -26,16 +26,9 @@ extern std::unique_ptr< lc::Settings > settings;
lc::ReceiptsPrinter::ReceiptsPrinter(const QString &argDateString, lc::ReceiptsPrinter::ReceiptsPrinter(const QString &argDateString,
const QString &argWorkpath, const QString &argWorkpath,
QObject *argParent ) : QObject *argParent)
QThread{ argParent }, : QThread{argParent}, dateString{argDateString},
dateString{ argDateString }, dvipsCmd{settings->dvipsCmd}, latexCmd{settings->latexCmd},
dvipsCmd{ settings->dvipsCmd }, lprCmd{settings->lprCmd}, postscriptViewer{settings->postscriptViewer},
latexCmd{ settings->latexCmd }, ps2pdfCmd{settings->ps2pdfCmd}, rmCmd{settings->rmCmd},
lprCmd{ settings->lprCmd }, vncViewer{settings->vncViewer}, workpath{argWorkpath} {}
postscriptViewer{ settings->postscriptViewer },
ps2pdfCmd{ settings->ps2pdfCmd },
rmCmd{ settings->rmCmd },
vncViewer{ settings->vncViewer },
workpath{ argWorkpath }
{
}

@ -38,7 +38,8 @@ class ReceiptsPrinter : public QThread {
void run() Q_DECL_OVERRIDE { void run() Q_DECL_OVERRIDE {
// Compile the TeX file to dvi // Compile the TeX file to dvi
QStringList arguments; QStringList arguments;
arguments << "-interaction" << "batchmode" << QString{ dateString + ".tex" }; arguments << "-interaction"
<< "batchmode" << QString{dateString + ".tex"};
QProcess *process = nullptr; QProcess *process = nullptr;
process = new QProcess{}; process = new QProcess{};
@ -47,7 +48,11 @@ class ReceiptsPrinter : public QThread {
process->setWorkingDirectory(workpath); process->setWorkingDirectory(workpath);
process->start(latexCmd, arguments); process->start(latexCmd, arguments);
if (!process->waitForFinished(processTimeOut)) { if (!process->waitForFinished(processTimeOut)) {
QMessageBox message_box{ QMessageBox::Warning, "dvi creation failed", "The creation of the receipts dvi timed out after 30 seconds. Automatic receipts creation will not work.", QMessageBox::Ok }; QMessageBox message_box{
QMessageBox::Warning, "dvi creation failed",
"The creation of the receipts dvi timed out after 30 seconds. "
"Automatic receipts creation will not work.",
QMessageBox::Ok};
message_box.exec(); message_box.exec();
delete process; delete process;
process = nullptr; process = nullptr;
@ -58,14 +63,20 @@ class ReceiptsPrinter : public QThread {
// Convert the dvi file to postscript // Convert the dvi file to postscript
arguments = QStringList{}; arguments = QStringList{};
arguments << "-q*" << "-o" << QString{ dateString + ".ps" } << QString{ dateString + ".dvi" }; arguments << "-q*"
<< "-o" << QString{dateString + ".ps"}
<< QString{dateString + ".dvi"};
process = new QProcess{}; process = new QProcess{};
process->setProcessEnvironment(env); process->setProcessEnvironment(env);
process->setWorkingDirectory(workpath); process->setWorkingDirectory(workpath);
process->start(dvipsCmd, arguments); process->start(dvipsCmd, arguments);
if (!process->waitForFinished(processTimeOut)) { if (!process->waitForFinished(processTimeOut)) {
emit ErrorOccurred(new QString{ "The conversion of the receipts dvi to postscript timed out after 30 seconds. Automatic receipts creation will not work." }, new QString{ "dvi to postscript conversion failed" } ); emit ErrorOccurred(
new QString{
"The conversion of the receipts dvi to postscript timed out "
"after 30 seconds. Automatic receipts creation will not work."},
new QString{"dvi to postscript conversion failed"});
delete process; delete process;
process = nullptr; process = nullptr;
return; return;
@ -83,7 +94,10 @@ class ReceiptsPrinter : public QThread {
process->setWorkingDirectory(workpath); process->setWorkingDirectory(workpath);
process->start(lprCmd, arguments); process->start(lprCmd, arguments);
if (!process->waitForFinished(processTimeOut)) { if (!process->waitForFinished(processTimeOut)) {
emit ErrorOccurred( new QString{ "The receipts postscript file was successfully created but could not be printed." }, new QString{ "Printing failed" } ); emit ErrorOccurred(
new QString{"The receipts postscript file was successfully created "
"but could not be printed."},
new QString{"Printing failed"});
} }
delete process; delete process;
process = nullptr; process = nullptr;
@ -92,14 +106,18 @@ class ReceiptsPrinter : public QThread {
// Convert the postscript file to pdf // Convert the postscript file to pdf
if (!ps2pdfCmd.isEmpty()) { if (!ps2pdfCmd.isEmpty()) {
arguments = QStringList{}; arguments = QStringList{};
arguments << QString{ workpath + "/" + dateString + ".ps" } << QString{ workpath + "/" + dateString + ".pdf" }; arguments << QString{workpath + "/" + dateString + ".ps"}
<< QString{workpath + "/" + dateString + ".pdf"};
process = new QProcess{}; process = new QProcess{};
process->setProcessEnvironment(env); process->setProcessEnvironment(env);
process->setWorkingDirectory(workpath); process->setWorkingDirectory(workpath);
process->start(ps2pdfCmd, arguments); process->start(ps2pdfCmd, arguments);
if (!process->waitForFinished(processTimeOut)) { if (!process->waitForFinished(processTimeOut)) {
emit ErrorOccurred( new QString{ "The receipts were successfully printed but the creation of the PDF file failed." }, new QString{ "PDF creation failed" } ); emit ErrorOccurred(
new QString{"The receipts were successfully printed but the "
"creation of the PDF file failed."},
new QString{"PDF creation failed"});
} }
delete process; delete process;
process = nullptr; process = nullptr;
@ -131,7 +149,11 @@ class ReceiptsPrinter : public QThread {
process->setWorkingDirectory(workpath); process->setWorkingDirectory(workpath);
process->start(rmCmd, arguments); process->start(rmCmd, arguments);
if (!process->waitForFinished(processTimeOut)) { if (!process->waitForFinished(processTimeOut)) {
emit ErrorOccurred(new QString("The cleanup of the temporary files for receipts creation timed out. Some spare files may be left in your zTree working directory."), new QString("Cleanup failed")); emit ErrorOccurred(
new QString("The cleanup of the temporary files for receipts "
"creation timed out. Some spare files may be left in "
"your zTree working directory."),
new QString("Cleanup failed"));
} }
delete process; delete process;
process = nullptr; process = nullptr;
@ -139,6 +161,7 @@ class ReceiptsPrinter : public QThread {
emit PrintingFinished(); emit PrintingFinished();
} }
public: public:
explicit ReceiptsPrinter(const QString &argDateString, explicit ReceiptsPrinter(const QString &argDateString,
const QString &argWorkpath, const QString &argWorkpath,
@ -154,13 +177,15 @@ private:
const QString latexCmd; const QString latexCmd;
const QString lprCmd; const QString lprCmd;
const QString postscriptViewer; const QString postscriptViewer;
const int processTimeOut = 15000; //! The maximum time which will be granted to a started process const int processTimeOut =
15000; //! The maximum time which will be granted to a started process
const QString ps2pdfCmd; const QString ps2pdfCmd;
const QString rmCmd; const QString rmCmd;
const QString vncViewer; const QString vncViewer;
const QString workpath; //!< The path were zTree was ordered to store all its data const QString
workpath; //!< The path were zTree was ordered to store all its data
}; };
} } // namespace lc
#endif // RECEIPTSPRINTER_H #endif // RECEIPTSPRINTER_H

@ -25,20 +25,21 @@
extern std::unique_ptr<lc::Settings> settings; extern std::unique_ptr<lc::Settings> settings;
lc::Session::Session(QVector<Client *> &&argAssocClients, lc::Session::Session(QVector<Client *> &&argAssocClients,
const QString &argZTreeDataTargetPath, const quint16 argZTreePort, const QString &argZTreeDataTargetPath,
const QString &argZTreeVersionPath, bool argPrintReceiptsForLocalClients, const quint16 argZTreePort,
const QString &argZTreeVersionPath,
bool argPrintReceiptsForLocalClients,
const QString &argAnonymousReceiptsPlaceholder, const QString &argAnonymousReceiptsPlaceholder,
const QString &argLatexHeaderName, QObject *argParent ): const QString &argLatexHeaderName, QObject *argParent)
QObject{ argParent }, : QObject{argParent}, zTreePort{argZTreePort},
zTreePort{ argZTreePort },
anonymousReceiptsPlaceholder{argAnonymousReceiptsPlaceholder}, anonymousReceiptsPlaceholder{argAnonymousReceiptsPlaceholder},
assocClients{std::move(argAssocClients)}, assocClients{std::move(argAssocClients)},
latexHeaderName{argLatexHeaderName}, latexHeaderName{argLatexHeaderName},
printReceiptsForLocalClients{argPrintReceiptsForLocalClients}, printReceiptsForLocalClients{argPrintReceiptsForLocalClients},
zTreeDataTargetPath{ argZTreeDataTargetPath }, zTreeDataTargetPath{argZTreeDataTargetPath}, zTreeVersionPath{
zTreeVersionPath{ argZTreeVersionPath } argZTreeVersionPath} {
{ // This part ensures, that both class instances are created in the same
// This part ensures, that both class instances are created in the same minute, so that the payment file name can be guessed correctly // minute, so that the payment file name can be guessed correctly
QDateTime current_time; QDateTime current_time;
current_time = QDateTime::currentDateTime(); current_time = QDateTime::currentDateTime();
@ -64,7 +65,8 @@ lc::Session::~Session() {
QVariant lc::Session::GetDataItem(int argIndex) { QVariant lc::Session::GetDataItem(int argIndex) {
switch (argIndex) { switch (argIndex) {
case 0: case 0:
return QVariant{ zTreeVersionPath.split( '_', QString::KeepEmptyParts, Qt::CaseInsensitive )[ 1 ] }; return QVariant{zTreeVersionPath.split('_', QString::KeepEmptyParts,
Qt::CaseInsensitive)[1]};
case 1: case 1:
return QVariant{zTreePort}; return QVariant{zTreePort};
default: default:
@ -76,18 +78,22 @@ void lc::Session::InitializeClasses() {
// Create the new data directory // Create the new data directory
QDir dir{zTreeDataTargetPath}; QDir dir{zTreeDataTargetPath};
QString date_string(QDateTime::currentDateTime().toString("yyMMdd_hhmm")); QString date_string(QDateTime::currentDateTime().toString("yyMMdd_hhmm"));
if ( !dir.mkdir( zTreeDataTargetPath + "/" + date_string + "-" + QString::number( zTreePort ) ) ) { if (!dir.mkdir(zTreeDataTargetPath + "/" + date_string + "-" +
QString::number(zTreePort))) {
throw lcDataTargetPathCreationFailed{}; throw lcDataTargetPathCreationFailed{};
} }
zTreeDataTargetPath.append( "/" + date_string + "-" + QString::number( zTreePort ) ); zTreeDataTargetPath.append("/" + date_string + "-" +
qDebug() << "New session's chosen_zTree_data_target_path:" << zTreeDataTargetPath; QString::number(zTreePort));
qDebug() << "New session's chosen_zTree_data_target_path:"
zTreeInstance = new ZTree{ zTreeDataTargetPath, zTreePort, zTreeVersionPath, this }; << zTreeDataTargetPath;
connect( zTreeInstance, &ZTree::ZTreeClosed,
this, &Session::OnzTreeClosed ); zTreeInstance =
// Only create a 'Receipts_Handler' instance, if all neccessary variables were set new ZTree{zTreeDataTargetPath, zTreePort, zTreeVersionPath, this};
if ( latexHeaderName != "None found" && !settings->dvipsCmd.isEmpty() connect(zTreeInstance, &ZTree::ZTreeClosed, this, &Session::OnzTreeClosed);
&& !settings->latexCmd.isEmpty() ) { // Only create a 'Receipts_Handler' instance, if all neccessary variables were
// set
if (latexHeaderName != "None found" && !settings->dvipsCmd.isEmpty() &&
!settings->latexCmd.isEmpty()) {
new ReceiptsHandler{zTreeDataTargetPath, printReceiptsForLocalClients, new ReceiptsHandler{zTreeDataTargetPath, printReceiptsForLocalClients,
anonymousReceiptsPlaceholder, latexHeaderName, this}; anonymousReceiptsPlaceholder, latexHeaderName, this};
} else { } else {
@ -96,7 +102,8 @@ void lc::Session::InitializeClasses() {
} }
void lc::Session::OnzTreeClosed(int argExitCode) { void lc::Session::OnzTreeClosed(int argExitCode) {
qDebug() << "z-Tree running on port" << zTreePort << "closed with exit code" << argExitCode; qDebug() << "z-Tree running on port" << zTreePort << "closed with exit code"
<< argExitCode;
emit SessionFinished(this); emit SessionFinished(this);
} }
@ -104,7 +111,9 @@ void lc::Session::RenameWindow() {
// Example: wmctrl -r <window name> -T <new name> // Example: wmctrl -r <window name> -T <new name>
QStringList arguments; QStringList arguments;
arguments << "-r" << "zTree - Untitled Treatment 1" << "-T" << QString{ "zTree on port " + QString::number( zTreePort ) }; arguments << "-r"
<< "zTree - Untitled Treatment 1"
<< "-T" << QString{"zTree on port " + QString::number(zTreePort)};
// Start the process // Start the process
QProcess renameZTreeWindowProcess; QProcess renameZTreeWindowProcess;

@ -32,16 +32,19 @@ class Client;
//! A class containing an entire session. //! A class containing an entire session.
/*! /*!
This class represents an entire session with its zTree instance and the corresponding lcReceiptsHandler instance. This class represents an entire session with its zTree instance and the
corresponding lcReceiptsHandler instance.
*/ */
class Session : public QObject { class Session : public QObject {
Q_OBJECT Q_OBJECT
public: public:
const int zTreePort = 7000; //! The port this session's zTree instance is running on const int zTreePort =
7000; //! The port this session's zTree instance is running on
Session( QVector< Client* > &&argAssocClients, const QString &argZTreeDataTargetPath, Session(QVector<Client *> &&argAssocClients,
const quint16 argZTreePort, const QString &argZTreeVersionPath, const QString &argZTreeDataTargetPath, const quint16 argZTreePort,
const QString &argZTreeVersionPath,
bool argPrintReceiptsForLocalClients, bool argPrintReceiptsForLocalClients,
const QString &argAnonymousReceiptsPlaceholder, const QString &argAnonymousReceiptsPlaceholder,
const QString &argLatexHeaderName, QObject *argParent = nullptr); const QString &argLatexHeaderName, QObject *argParent = nullptr);
@ -53,7 +56,8 @@ public:
*/ */
QVariant GetDataItem(int argIndex); QVariant GetDataItem(int argIndex);
//! This gets thrown as an exception if the chosen data target path could not be created. //! This gets thrown as an exception if the chosen data target path could not
//! be created.
class lcDataTargetPathCreationFailed {}; class lcDataTargetPathCreationFailed {};
signals: signals:
@ -64,20 +68,27 @@ private slots:
*/ */
void InitializeClasses(); void InitializeClasses();
void OnzTreeClosed(int argExitCode); void OnzTreeClosed(int argExitCode);
/*! Changes zTree's window title to contain its port number to make zTree windows distinguishable /*! Changes zTree's window title to contain its port number to make zTree
* windows distinguishable
*/ */
void RenameWindow(); void RenameWindow();
private: private:
const QString anonymousReceiptsPlaceholder; //! Placeholder which shall be inserted for participant names if anonymous printing is desired (QString != "") const QString
anonymousReceiptsPlaceholder; //! Placeholder which shall be inserted for
//! participant names if anonymous printing
//! is desired (QString != "")
const QVector<Client *> assocClients; const QVector<Client *> assocClients;
const QString latexHeaderName; //! The name of the chosen LaTeX header const QString latexHeaderName; //! The name of the chosen LaTeX header
const bool printReceiptsForLocalClients = true; //! True if receipts shall be printed for local clients const bool printReceiptsForLocalClients =
QString zTreeDataTargetPath; //! The path were the data of this zTree instance's session will be saved true; //! True if receipts shall be printed for local clients
QString zTreeDataTargetPath; //! The path were the data of this zTree
//! instance's session will be saved
ZTree *zTreeInstance = nullptr; //! The session's zTree instance ZTree *zTreeInstance = nullptr; //! The session's zTree instance
const QString zTreeVersionPath; //! The path to the version of zTree used by this session's instance const QString zTreeVersionPath; //! The path to the version of zTree used by
//! this session's instance
}; };
} } // namespace lc
#endif // SESSION_H #endif // SESSION_H

@ -21,14 +21,10 @@
#include "sessionsmodel.h" #include "sessionsmodel.h"
lc::SessionsModel::SessionsModel( QObject *argParent ) : lc::SessionsModel::SessionsModel(QObject *argParent)
QAbstractTableModel{ argParent } : QAbstractTableModel{argParent} {}
{
}
lc::Session *lc::SessionsModel::back() const { lc::Session *lc::SessionsModel::back() const { return sessionsList.back(); }
return sessionsList.back();
}
int lc::SessionsModel::columnCount(const QModelIndex &parent) const { int lc::SessionsModel::columnCount(const QModelIndex &parent) const {
Q_UNUSED(parent); Q_UNUSED(parent);
@ -48,7 +44,8 @@ QVariant lc::SessionsModel::data(const QModelIndex &index, int role) const {
return QVariant{}; return QVariant{};
} }
QVariant lc::SessionsModel::headerData(int section, Qt::Orientation orientation, int role) const { QVariant lc::SessionsModel::headerData(int section, Qt::Orientation orientation,
int role) const {
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) { switch (section) {
case 0: case 0:
@ -67,15 +64,16 @@ QVariant lc::SessionsModel::headerData(int section, Qt::Orientation orientation,
} }
void lc::SessionsModel::push_back(Session *argSession) { void lc::SessionsModel::push_back(Session *argSession) {
connect( argSession, &Session::SessionFinished, connect(argSession, &Session::SessionFinished, this,
this, &SessionsModel::RemoveSession ); &SessionsModel::RemoveSession);
argSession->setParent(this); argSession->setParent(this);
sessionsList.push_back(argSession); sessionsList.push_back(argSession);
} }
void lc::SessionsModel::RemoveSession(Session *argSession) { void lc::SessionsModel::RemoveSession(Session *argSession) {
if (sessionsList.removeAll(argSession)) { if (sessionsList.removeAll(argSession)) {
qDebug() << "Successfully removed" << argSession << "from lc::SessionsModel"; qDebug() << "Successfully removed" << argSession
<< "from lc::SessionsModel";
argSession->deleteLater(); argSession->deleteLater();
} }
} }

@ -49,6 +49,6 @@ private slots:
void RemoveSession(Session *argSession); void RemoveSession(Session *argSession);
}; };
} } // namespace lc
#endif // SESSIONSMODEL_H #endif // SESSIONSMODEL_H

@ -25,43 +25,46 @@
#include "client.h" #include "client.h"
#include "settings.h" #include "settings.h"
lc::Settings::Settings( const QSettings &argSettings, QObject *argParent ) : lc::Settings::Settings(const QSettings &argSettings, QObject *argParent)
QObject{ argParent }, : QObject{argParent}, defaultReceiptIndex{GetDefaultReceiptIndex(
defaultReceiptIndex{ GetDefaultReceiptIndex( argSettings ) }, argSettings)},
browserCmd{ReadSettingsItem("browser_command", browserCmd{ReadSettingsItem("browser_command",
"Opening ORSEE in a browser will not work.", "Opening ORSEE in a browser will not work.",
argSettings, true)}, argSettings, true)},
clientBrowserCmd{ ReadSettingsItem( "client_browser_command", clientBrowserCmd{
ReadSettingsItem("client_browser_command",
"Opening a browser window on clients will not work.", "Opening a browser window on clients will not work.",
argSettings, false)}, argSettings, false)},
clientChromiumCmd{ ReadSettingsItem( "client_chromium_command", clientChromiumCmd{ReadSettingsItem(
"Opening a chromium window on clients will not work.", "client_chromium_command",
argSettings, false ) }, "Opening a chromium window on clients will not work.", argSettings,
false)},
dvipsCmd{ReadSettingsItem("dvips_command", dvipsCmd{ReadSettingsItem("dvips_command",
"Receipts creation will not work.", "Receipts creation will not work.", argSettings,
argSettings, true ) }, true)},
fileMngr{ReadSettingsItem("file_manager", fileMngr{ReadSettingsItem("file_manager",
"The display of preprints will not work.", "The display of preprints will not work.",
argSettings, true)}, argSettings, true)},
killallCmd{ ReadSettingsItem( "killall_command", killallCmd{ReadSettingsItem(
"Killing 'zleaf.exe' instances will not work.", "killall_command", "Killing 'zleaf.exe' instances will not work.",
argSettings, true)}, argSettings, true)},
latexCmd{ReadSettingsItem("latex_command", latexCmd{ReadSettingsItem("latex_command",
"Receipts creation will not work.", "Receipts creation will not work.", argSettings,
argSettings, true ) }, true)},
lcDataDir{ ReadSettingsItem( "labcontrol_data_directory", lcDataDir{ReadSettingsItem(
"labcontrol_data_directory",
"Datapath not set. Labcontrol will missbehave with high propability.", "Datapath not set. Labcontrol will missbehave with high propability.",
argSettings, true)}, argSettings, true)},
localUserName{ GetLocalUserName() }, localUserName{GetLocalUserName()}, localzLeafSize{ReadSettingsItem(
localzLeafSize{ ReadSettingsItem( "local_zLeaf_size", "local_zLeaf_size",
"Resolution of local zLeaf window", "Resolution of local zLeaf window",
argSettings, false)}, argSettings, false)},
lprCmd{ ReadSettingsItem( "lpr_command", lprCmd{ReadSettingsItem("lpr_command", "Receipts printing will not work.",
"Receipts printing will not work.",
argSettings, true ) },
netstatCmd{ ReadSettingsItem( "netstat_command",
"Detection of active zLeaf connections will not work.",
argSettings, true)}, argSettings, true)},
netstatCmd{ReadSettingsItem(
"netstat_command",
"Detection of active zLeaf connections will not work.", argSettings,
true)},
netwBrdAddr{ReadSettingsItem("network_broadcast_address", netwBrdAddr{ReadSettingsItem("network_broadcast_address",
"Booting the clients will not work.", "Booting the clients will not work.",
argSettings, false)}, argSettings, false)},
@ -71,38 +74,47 @@ lc::Settings::Settings( const QSettings &argSettings, QObject *argParent ) :
pingCmd{ReadSettingsItem("ping_command", pingCmd{ReadSettingsItem("ping_command",
"Status updates for the clients will not work.", "Status updates for the clients will not work.",
argSettings, true)}, argSettings, true)},
postscriptViewer{ ReadSettingsItem( "postscript_viewer", postscriptViewer{ReadSettingsItem(
"postscript_viewer",
"Viewing the generated receipts postscript file will not work.", "Viewing the generated receipts postscript file will not work.",
argSettings, true)}, argSettings, true)},
ps2pdfCmd{ ReadSettingsItem( "ps2pdf_command", ps2pdfCmd{ReadSettingsItem(
"ps2pdf_command",
"Converting and viewing the generated receipts file will not work.", "Converting and viewing the generated receipts file will not work.",
argSettings, true)}, argSettings, true)},
pkeyPathRoot{ReadSettingsItem("pkey_path_root", pkeyPathRoot{ReadSettingsItem("pkey_path_root",
"Administration actions concerning the clients will not be available.", "Administration actions concerning the "
"clients will not be available.",
argSettings, true)}, argSettings, true)},
pkeyPathUser{ ReadSettingsItem( "pkey_path_user", pkeyPathUser{ReadSettingsItem(
"pkey_path_user",
"Many actions concerning the clients will not be available.", "Many actions concerning the clients will not be available.",
argSettings, true)}, argSettings, true)},
rmCmd{ ReadSettingsItem( "rm_command", rmCmd{ReadSettingsItem(
"Cleanup of the zTree data target path will not work.", "rm_command", "Cleanup of the zTree data target path will not work.",
argSettings, true)}, argSettings, true)},
scpCmd{ ReadSettingsItem( "scp_command", scpCmd{ReadSettingsItem(
"Beaming files to the clients will not be possible.", "scp_command", "Beaming files to the clients will not be possible.",
argSettings, true)}, argSettings, true)},
serverIP{ ReadSettingsItem( "server_ip", serverIP{ReadSettingsItem(
"server_ip",
"Starting zLeaves and retrieving client help messages will not work.", "Starting zLeaves and retrieving client help messages will not work.",
argSettings, false)}, argSettings, false)},
sshCmd{ ReadSettingsItem( "ssh_command", sshCmd{ReadSettingsItem(
"ssh_command",
"All actions concerning the clients will not be possible.", "All actions concerning the clients will not be possible.",
argSettings, true)}, argSettings, true)},
tasksetCmd{ ReadSettingsItem( "taskset_command", tasksetCmd{ReadSettingsItem(
"Running z-Leaves or z-Tree will be possible.", "taskset_command", "Running z-Leaves or z-Tree will be possible.",
argSettings, true ) },
termEmulCmd{ ReadSettingsItem( "terminal_emulator_command",
"Conducting administrative tasks will not be possible.",
argSettings, true)}, argSettings, true)},
userNameOnClients{ ReadSettingsItem( "user_name_on_clients", termEmulCmd{ReadSettingsItem(
"All actions concerning the clients performed by the experiment user will not work.", "terminal_emulator_command",
"Conducting administrative tasks will not be possible.", argSettings,
true)},
userNameOnClients{
ReadSettingsItem("user_name_on_clients",
"All actions concerning the clients performed by "
"the experiment user will not work.",
argSettings, false)}, argSettings, false)},
vncViewer{ReadSettingsItem("vnc_viewer", vncViewer{ReadSettingsItem("vnc_viewer",
"Viewing the clients' screens will not work.", "Viewing the clients' screens will not work.",
@ -110,46 +122,55 @@ lc::Settings::Settings( const QSettings &argSettings, QObject *argParent ) :
wakeonlanCmd{ReadSettingsItem("wakeonlan_command", wakeonlanCmd{ReadSettingsItem("wakeonlan_command",
"Booting the clients will not work.", "Booting the clients will not work.",
argSettings, true)}, argSettings, true)},
webcamDisplayCmd{ ReadSettingsItem( "webcam_command", webcamDisplayCmd{
ReadSettingsItem("webcam_command",
"Displaying the laboratory's webcams will not work.", "Displaying the laboratory's webcams will not work.",
argSettings, true)}, argSettings, true)},
webcams{ argSettings.value( "webcams", "" ).toString().split( '|', QString::SkipEmptyParts, webcams{argSettings.value("webcams", "")
Qt::CaseInsensitive ) }, .toString()
webcams_names{ argSettings.value( "webcams_names", "" ).toString().split( '|', QString::SkipEmptyParts, .split('|', QString::SkipEmptyParts, Qt::CaseInsensitive)},
Qt::CaseInsensitive ) }, webcams_names{
argSettings.value("webcams_names", "")
.toString()
.split('|', QString::SkipEmptyParts, Qt::CaseInsensitive)},
wineCmd{ReadSettingsItem("wine_command", wineCmd{ReadSettingsItem("wine_command",
"Running z-Leaves or z-Tree will be possible.", "Running z-Leaves or z-Tree will be possible.",
argSettings, true)}, argSettings, true)},
wmctrlCmd{ ReadSettingsItem( "wmctrl_command", wmctrlCmd{ReadSettingsItem(
"wmctrl_command",
"Setting zTree's window title to its port number will not work.", "Setting zTree's window title to its port number will not work.",
argSettings, true)}, argSettings, true)},
xsetCmd{ ReadSettingsItem( "xset_command", xsetCmd{ReadSettingsItem(
"xset_command",
"Deactivating the screen saver on the clients will not be possible.", "Deactivating the screen saver on the clients will not be possible.",
argSettings, true)}, argSettings, true)},
zTreeInstDir{ReadSettingsItem("ztree_installation_directory", zTreeInstDir{ReadSettingsItem("ztree_installation_directory",
"zTree will not be available.", "zTree will not be available.", argSettings,
argSettings, true ) }, true)},
restartCrashedSessionScript{ ReadSettingsItem( "restart_crashed_session_script", restartCrashedSessionScript{ReadSettingsItem(
"Script to be called after session crash", "restart_crashed_session_script",
argSettings, false ) }, "Script to be called after session crash", argSettings, false)},
adminUsers{GetAdminUsers(argSettings)}, adminUsers{GetAdminUsers(argSettings)},
installedLaTeXHeaders{DetectInstalledLaTeXHeaders()}, installedLaTeXHeaders{DetectInstalledLaTeXHeaders()},
installedZTreeVersions{DetectInstalledzTreeVersions()}, installedZTreeVersions{DetectInstalledzTreeVersions()},
clientHelpNotificationServerPort{ GetClientHelpNotificationServerPort( argSettings ) }, clientHelpNotificationServerPort{
chosenzTreePort{ GetInitialPort( argSettings ) }, GetClientHelpNotificationServerPort(argSettings)},
clients{ CreateClients( argSettings, pingCmd ) }, chosenzTreePort{GetInitialPort(argSettings)}, clients{CreateClients(
localzLeafName{ ReadSettingsItem( "local_zLeaf_name", argSettings, pingCmd)},
"The local zLeaf default name will default to 'local'.", localzLeafName{ReadSettingsItem(
argSettings, false ) }, "local_zLeaf_name",
clIPsToClMap{ CreateClIPsToClMap( clients ) } "The local zLeaf default name will default to 'local'.", argSettings,
{ false)},
// Let the local zLeaf name default to 'local' if none was given in the settings clIPsToClMap{CreateClIPsToClMap(clients)} {
// Let the local zLeaf name default to 'local' if none was given in the
// settings
if (localzLeafName.isEmpty()) { if (localzLeafName.isEmpty()) {
qDebug() << "'local_zLeaf_name' was not set, defaulting to 'local'"; qDebug() << "'local_zLeaf_name' was not set, defaulting to 'local'";
localzLeafName = "local"; localzLeafName = "local";
} }
if (webcams.isEmpty()) { if (webcams.isEmpty()) {
qDebug() << "'webcams' was not properly set. No stationary webcams will be available."; qDebug() << "'webcams' was not properly set. No stationary webcams will be "
"available.";
} else { } else {
qDebug() << "The following webcams where loaded:" << webcams; qDebug() << "The following webcams where loaded:" << webcams;
} }
@ -157,12 +178,14 @@ lc::Settings::Settings( const QSettings &argSettings, QObject *argParent ) :
} }
lc::Settings::~Settings() { lc::Settings::~Settings() {
for ( QVector< Client* >::iterator it = clients.begin(); it != clients.end(); ++it ) { for (QVector<Client *>::iterator it = clients.begin(); it != clients.end();
++it) {
delete *it; delete *it;
} }
} }
bool lc::Settings::CheckPathAndComplain( const QString &argPath, const QString &argVariableName, bool lc::Settings::CheckPathAndComplain(const QString &argPath,
const QString &argVariableName,
const QString &argMessage) { const QString &argMessage) {
if (!QFile::exists(argPath)) { if (!QFile::exists(argPath)) {
qDebug() << "The path" << argPath << "specified by" << argVariableName qDebug() << "The path" << argPath << "specified by" << argVariableName
@ -177,13 +200,17 @@ QVector< lc::Client* > lc::Settings::CreateClients( const QSettings &argSettings
const QString &argPingCmd) { const QString &argPingCmd) {
QVector<Client *> tempClientVec; QVector<Client *> tempClientVec;
// Get the client quantity to check the value lists for clients creation for correct length // Get the client quantity to check the value lists for clients creation for
// correct length
int clientQuantity = 0; int clientQuantity = 0;
if (!argSettings.contains("client_quantity")) { if (!argSettings.contains("client_quantity")) {
qWarning() << "'client_quantity' was not set. The client quantity will be guessed" qWarning()
<< "'client_quantity' was not set. The client quantity will be guessed"
" by the amount of client IPs set in 'client_ips'."; " by the amount of client IPs set in 'client_ips'.";
clientQuantity = argSettings.value( "client_ips", "" ).toString() clientQuantity = argSettings.value("client_ips", "")
.split( '/', QString::SkipEmptyParts, Qt::CaseSensitive ).length(); .toString()
.split('/', QString::SkipEmptyParts, Qt::CaseSensitive)
.length();
qDebug() << "'clientQuantity':" << clientQuantity; qDebug() << "'clientQuantity':" << clientQuantity;
} else { } else {
bool ok = true; bool ok = true;
@ -195,47 +222,67 @@ QVector< lc::Client* > lc::Settings::CreateClients( const QSettings &argSettings
} }
// Create all the clients in the lab // Create all the clients in the lab
QStringList clientIPs = argSettings.value( "client_ips" ).toString() QStringList clientIPs =
argSettings.value("client_ips")
.toString()
.split('|', QString::SkipEmptyParts, Qt::CaseSensitive); .split('|', QString::SkipEmptyParts, Qt::CaseSensitive);
if (clientIPs.length() != clientQuantity) { if (clientIPs.length() != clientQuantity) {
qWarning() << "The quantity of client ips does not match the client quantity. Client" qWarning()
<< "The quantity of client ips does not match the client quantity. "
"Client"
" creation will fail. No clients will be available for interaction."; " creation will fail. No clients will be available for interaction.";
return tempClientVec; return tempClientVec;
} }
qDebug() << "Client IPs:" << clientIPs.join(" / "); qDebug() << "Client IPs:" << clientIPs.join(" / ");
QStringList clientMACs = argSettings.value( "client_macs" ).toString() QStringList clientMACs =
argSettings.value("client_macs")
.toString()
.split('|', QString::SkipEmptyParts, Qt::CaseSensitive); .split('|', QString::SkipEmptyParts, Qt::CaseSensitive);
if (clientMACs.length() != clientQuantity) { if (clientMACs.length() != clientQuantity) {
qWarning() << "The quantity of client macs does not match the client quantity. Client" qWarning()
<< "The quantity of client macs does not match the client quantity. "
"Client"
" creation will fail. No clients will be available for interaction."; " creation will fail. No clients will be available for interaction.";
return tempClientVec; return tempClientVec;
} }
qDebug() << "Client MACs:" << clientMACs.join(" / "); qDebug() << "Client MACs:" << clientMACs.join(" / ");
QStringList clientNames = argSettings.value( "client_names" ).toString() QStringList clientNames =
argSettings.value("client_names")
.toString()
.split('|', QString::SkipEmptyParts, Qt::CaseSensitive); .split('|', QString::SkipEmptyParts, Qt::CaseSensitive);
if (clientNames.length() != clientQuantity) { if (clientNames.length() != clientQuantity) {
qWarning() << "The quantity of client names does not match the client quantity. Client" qWarning()
<< "The quantity of client names does not match the client quantity. "
"Client"
" creation will fail. No clients will be available for interaction."; " creation will fail. No clients will be available for interaction.";
return tempClientVec; return tempClientVec;
} }
qDebug() << "Client names:" << clientNames.join(" / "); qDebug() << "Client names:" << clientNames.join(" / ");
QStringList clientXPositions = argSettings.value( "client_xpos" ).toString() QStringList clientXPositions =
argSettings.value("client_xpos")
.toString()
.split('|', QString::SkipEmptyParts, Qt::CaseSensitive); .split('|', QString::SkipEmptyParts, Qt::CaseSensitive);
if (clientXPositions.length() != clientQuantity) { if (clientXPositions.length() != clientQuantity) {
qWarning() << "The quantity of client x positions does not match the client quantity." qWarning() << "The quantity of client x positions does not match the "
" Client creation will fail. No clients will be available for interaction."; "client quantity."
" Client creation will fail. No clients will be available "
"for interaction.";
return tempClientVec; return tempClientVec;
} }
qDebug() << "clientXPositions:" << clientXPositions.join(" / "); qDebug() << "clientXPositions:" << clientXPositions.join(" / ");
QStringList clientYPositions = argSettings.value( "client_ypos" ).toString() QStringList clientYPositions =
argSettings.value("client_ypos")
.toString()
.split('|', QString::SkipEmptyParts, Qt::CaseSensitive); .split('|', QString::SkipEmptyParts, Qt::CaseSensitive);
if (clientYPositions.length() != clientQuantity) { if (clientYPositions.length() != clientQuantity) {
qWarning() << "The quantity of client y positions does not match the client quantity." qWarning() << "The quantity of client y positions does not match the "
" Client creation will fail. No clients will be available for interaction."; "client quantity."
" Client creation will fail. No clients will be available "
"for interaction.";
return tempClientVec; return tempClientVec;
} }
qDebug() << "clientYPositions:" << clientYPositions.join(" / "); qDebug() << "clientYPositions:" << clientYPositions.join(" / ");
@ -243,13 +290,15 @@ QVector< lc::Client* > lc::Settings::CreateClients( const QSettings &argSettings
for (int i = 0; i < clientQuantity; i++) { for (int i = 0; i < clientQuantity; i++) {
tempClientVec.append(new Client{clientIPs[i], clientMACs[i], clientNames[i], tempClientVec.append(new Client{clientIPs[i], clientMACs[i], clientNames[i],
clientXPositions[i].toUShort(), clientXPositions[i].toUShort(),
clientYPositions[ i ].toUShort(), argPingCmd } ); clientYPositions[i].toUShort(),
argPingCmd});
} }
return tempClientVec; return tempClientVec;
} }
QMap< QString, lc::Client* > lc::Settings::CreateClIPsToClMap( const QVector< Client* > &argClients ) { QMap<QString, lc::Client *>
lc::Settings::CreateClIPsToClMap(const QVector<Client *> &argClients) {
QMap<QString, Client *> tempMap; QMap<QString, Client *> tempMap;
for (const auto &s : argClients) { for (const auto &s : argClients) {
tempMap.insert(s->ip, s); tempMap.insert(s->ip, s);
@ -270,7 +319,8 @@ QStringList lc::Settings::DetectInstalledLaTeXHeaders() const {
QDir laTeXDirectory{lcDataDir, "*_header.tex", QDir::Name, QDir laTeXDirectory{lcDataDir, "*_header.tex", QDir::Name,
QDir::CaseSensitive | QDir::Files | QDir::Readable}; QDir::CaseSensitive | QDir::Files | QDir::Readable};
if (!laTeXDirectory.exists() || laTeXDirectory.entryList().isEmpty()) { if (!laTeXDirectory.exists() || laTeXDirectory.entryList().isEmpty()) {
qDebug() << "Receipts printing will not work. No LaTeX headers could be found in" qDebug() << "Receipts printing will not work. No LaTeX headers could be "
"found in"
<< lcDataDir; << lcDataDir;
} else { } else {
tempLaTeXHeaders = laTeXDirectory.entryList(); tempLaTeXHeaders = laTeXDirectory.entryList();
@ -285,8 +335,8 @@ QStringList lc::Settings::DetectInstalledzTreeVersions() const {
QStringList tempInstzTreeVersions; QStringList tempInstzTreeVersions;
if (!zTreeInstDir.isEmpty()) { if (!zTreeInstDir.isEmpty()) {
QDir zTreeDirectory{zTreeInstDir, "zTree_*", QDir::Name, QDir zTreeDirectory{zTreeInstDir, "zTree_*", QDir::Name,
QDir::NoDotAndDotDot | QDir::Dirs QDir::NoDotAndDotDot | QDir::Dirs | QDir::Readable |
| QDir::Readable | QDir::CaseSensitive }; QDir::CaseSensitive};
if (zTreeDirectory.entryList().isEmpty()) { if (zTreeDirectory.entryList().isEmpty()) {
qWarning() << "No zTree versions could be found in" << zTreeInstDir; qWarning() << "No zTree versions could be found in" << zTreeInstDir;
} else { } else {
@ -304,7 +354,9 @@ QStringList lc::Settings::GetAdminUsers( const QSettings &argSettings ) {
" No users will be able to conduct administrative tasks."; " No users will be able to conduct administrative tasks.";
return QStringList{}; return QStringList{};
} else { } else {
QStringList adminUsers{ argSettings.value( "admin_users", "" ).toString() QStringList adminUsers{
argSettings.value("admin_users", "")
.toString()
.split('|', QString::SkipEmptyParts, Qt::CaseInsensitive)}; .split('|', QString::SkipEmptyParts, Qt::CaseInsensitive)};
qDebug() << "'adminUsers':" << adminUsers.join(" / "); qDebug() << "'adminUsers':" << adminUsers.join(" / ");
return adminUsers; return adminUsers;
@ -312,17 +364,20 @@ QStringList lc::Settings::GetAdminUsers( const QSettings &argSettings ) {
return QStringList{}; return QStringList{};
} }
quint16 lc::Settings::GetClientHelpNotificationServerPort( const QSettings &argSettings ) { quint16 lc::Settings::GetClientHelpNotificationServerPort(
const QSettings &argSettings) {
// Read the port the ClientHelpNotificationServer shall listen on // Read the port the ClientHelpNotificationServer shall listen on
quint16 clientHelpNotificationServerPort = argSettings.value( "client_help_server_port", quint16 clientHelpNotificationServerPort =
0 ).toUInt(); argSettings.value("client_help_server_port", 0).toUInt();
if (!clientHelpNotificationServerPort) { if (!clientHelpNotificationServerPort) {
qDebug() << "The 'client_help_server_port' variable was not set or set to zero." qDebug()
<< "The 'client_help_server_port' variable was not set or set to zero."
" The ClientHelpNotificationServer will be deactivated therefore." " The ClientHelpNotificationServer will be deactivated therefore."
" Clients' help requests will be ignored by the server."; " Clients' help requests will be ignored by the server.";
return 0; return 0;
} else { } else {
qDebug() << "'clientHelpNotificationServerPort':" << clientHelpNotificationServerPort; qDebug() << "'clientHelpNotificationServerPort':"
<< clientHelpNotificationServerPort;
return clientHelpNotificationServerPort; return clientHelpNotificationServerPort;
} }
return 0; return 0;
@ -342,7 +397,8 @@ int lc::Settings::GetDefaultReceiptIndex( const QSettings &argSettings ) {
int lc::Settings::GetInitialPort(const QSettings &argSettings) { int lc::Settings::GetInitialPort(const QSettings &argSettings) {
// Read the initial port number // Read the initial port number
if (!argSettings.contains("initial_port")) { if (!argSettings.contains("initial_port")) {
qDebug() << "The 'initial_port' variable was not set." qDebug()
<< "The 'initial_port' variable was not set."
" Labcontrol will default to port 7000 for new zTree instances."; " Labcontrol will default to port 7000 for new zTree instances.";
} }
int initialPort = argSettings.value("initial_port", 7000).toInt(); int initialPort = argSettings.value("initial_port", 7000).toInt();
@ -375,8 +431,8 @@ QString lc::Settings::ReadSettingsItem( const QString &argVariableName,
return QString{}; return QString{};
} else { } else {
QString tempString{argSettings.value(argVariableName).toString()}; QString tempString{argSettings.value(argVariableName).toString()};
if ( argItemIsFile if (argItemIsFile &&
&& !CheckPathAndComplain( tempString, argVariableName, argMessage ) ) { !CheckPathAndComplain(tempString, argVariableName, argMessage)) {
tempString.clear(); tempString.clear();
} }
return tempString; return tempString;
@ -384,11 +440,8 @@ QString lc::Settings::ReadSettingsItem( const QString &argVariableName,
return QString{}; return QString{};
} }
void lc::Settings::SetLocalzLeafSize( QString arg) { void lc::Settings::SetLocalzLeafSize(QString arg) { localzLeafSize = arg; }
localzLeafSize = arg;
}
void lc::Settings::SetChosenZTreePort(const int argPort) { void lc::Settings::SetChosenZTreePort(const int argPort) {
chosenzTreePort = argPort; chosenzTreePort = argPort;
} }

@ -91,15 +91,18 @@ public:
const quint16 clientHelpNotificationServerPort = 0; const quint16 clientHelpNotificationServerPort = 0;
private: private:
static bool CheckPathAndComplain( const QString &argPath, const QString &argVariableName, static bool CheckPathAndComplain(const QString &argPath,
const QString &argVariableName,
const QString &argMessage); const QString &argMessage);
static QVector<Client *> CreateClients(const QSettings &argSettings, static QVector<Client *> CreateClients(const QSettings &argSettings,
const QString &argPingCmd); const QString &argPingCmd);
static QMap< QString, Client* > CreateClIPsToClMap( const QVector< Client* > &argClients ); static QMap<QString, Client *>
CreateClIPsToClMap(const QVector<Client *> &argClients);
QStringList DetectInstalledLaTeXHeaders() const; QStringList DetectInstalledLaTeXHeaders() const;
QStringList DetectInstalledzTreeVersions() const; QStringList DetectInstalledzTreeVersions() const;
static QStringList GetAdminUsers(const QSettings &argSettings); static QStringList GetAdminUsers(const QSettings &argSettings);
static quint16 GetClientHelpNotificationServerPort( const QSettings &argSettings ); static quint16
GetClientHelpNotificationServerPort(const QSettings &argSettings);
static int GetDefaultReceiptIndex(const QSettings &argSettings); static int GetDefaultReceiptIndex(const QSettings &argSettings);
static int GetInitialPort(const QSettings &argSettings); static int GetInitialPort(const QSettings &argSettings);
static QString GetLocalUserName(); static QString GetLocalUserName();
@ -116,7 +119,7 @@ public:
const QMap<QString, Client *> clIPsToClMap; const QMap<QString, Client *> clIPsToClMap;
}; };
} } // namespace lc
inline QString lc::Settings::GetLocalzLeafName() const { inline QString lc::Settings::GetLocalzLeafName() const {
return localzLeafName; return localzLeafName;

@ -27,12 +27,13 @@
extern std::unique_ptr<lc::Settings> settings; extern std::unique_ptr<lc::Settings> settings;
lc::ZTree::ZTree(const QString &argZTreeDataTargetPath, const int &argZTreePort, lc::ZTree::ZTree(const QString &argZTreeDataTargetPath, const int &argZTreePort,
const QString &argZTreeVersionPath, QObject *argParent ) : const QString &argZTreeVersionPath, QObject *argParent)
QObject{ argParent } : QObject{argParent} {
{ QStringList arguments{QStringList{}
QStringList arguments{ QStringList{} << "-c" << "0" << settings->wineCmd << "-c"
<< QString{ settings->zTreeInstDir + "/zTree_" << "0" << settings->wineCmd
+ argZTreeVersionPath + "/ztree.exe" } << QString{settings->zTreeInstDir + "/zTree_" +
argZTreeVersionPath + "/ztree.exe"}
<< "/datadir" << QString{"Z:/" + argZTreeDataTargetPath} << "/datadir" << QString{"Z:/" + argZTreeDataTargetPath}
<< "/privdir" << QString{"Z:/" + argZTreeDataTargetPath} << "/privdir" << QString{"Z:/" + argZTreeDataTargetPath}
<< "/gsfdir" << QString{"Z:/" + argZTreeDataTargetPath} << "/gsfdir" << QString{"Z:/" + argZTreeDataTargetPath}
@ -44,8 +45,8 @@ lc::ZTree::ZTree( const QString &argZTreeDataTargetPath, const int &argZTreePort
zTreeInstance.setProcessEnvironment(env); zTreeInstance.setProcessEnvironment(env);
zTreeInstance.setWorkingDirectory(QDir::homePath()); zTreeInstance.setWorkingDirectory(QDir::homePath());
zTreeInstance.start(settings->tasksetCmd, arguments, QIODevice::NotOpen); zTreeInstance.start(settings->tasksetCmd, arguments, QIODevice::NotOpen);
connect( &zTreeInstance, SIGNAL( finished( int ) ), connect(&zTreeInstance, SIGNAL(finished(int)), this,
this, SIGNAL( ZTreeClosed( int ) ) ); SIGNAL(ZTreeClosed(int)));
qDebug() << settings->tasksetCmd << arguments.join(" "); qDebug() << settings->tasksetCmd << arguments.join(" ");
} }

@ -30,15 +30,15 @@ namespace lc {
//! A class to contain running zTree instances. //! A class to contain running zTree instances.
/*! /*!
This class is element of every session and is used to handle all zTree related data. This class is element of every session and is used to handle all zTree related
data.
*/ */
class ZTree : public QObject { class ZTree : public QObject {
Q_OBJECT Q_OBJECT
public: public:
ZTree( const QString &argZTreeDataTargetPath, ZTree(const QString &argZTreeDataTargetPath, const int &argZTreePort,
const int &argZTreePort, const QString &argZTreeVersionPath, const QString &argZTreeVersionPath, QObject *argParent = nullptr);
QObject *argParent = nullptr );
signals: signals:
void ZTreeClosed(int argExitCode); void ZTreeClosed(int argExitCode);
@ -47,6 +47,6 @@ private:
QProcess zTreeInstance; QProcess zTreeInstance;
}; };
} } // namespace lc
#endif // ZTREE_H #endif // ZTREE_H

@ -21,16 +21,14 @@
#include <QMessageBox> #include <QMessageBox>
#include "Lib/settings.h"
#include "localzleafstarter.h" #include "localzleafstarter.h"
#include "ui_localzleafstarter.h" #include "ui_localzleafstarter.h"
#include "Lib/settings.h"
extern std::unique_ptr<lc::Settings> settings; extern std::unique_ptr<lc::Settings> settings;
lc::LocalzLeafStarter::LocalzLeafStarter( QWidget *argParent ) : lc::LocalzLeafStarter::LocalzLeafStarter(QWidget *argParent)
QWidget{ argParent }, : QWidget{argParent}, ui{new Ui::LocalzLeafStarter} {
ui{ new Ui::LocalzLeafStarter }
{
ui->setupUi(this); ui->setupUi(this);
// Choose initial port from settings // Choose initial port from settings
@ -41,22 +39,21 @@ lc::LocalzLeafStarter::LocalzLeafStarter( QWidget *argParent ) :
// Choose initial z-Leave size from settings // Choose initial z-Leave size from settings
ui->LELocalzLeafSize->setText(settings->GetLocalzLeafSize()); ui->LELocalzLeafSize->setText(settings->GetLocalzLeafSize());
ui->CBzLeafVersion->addItem(tr("Please choose a version")); ui->CBzLeafVersion->addItem(tr("Please choose a version"));
if (!settings->installedZTreeVersions.isEmpty()) { if (!settings->installedZTreeVersions.isEmpty()) {
ui->CBzLeafVersion->addItems(settings->installedZTreeVersions); ui->CBzLeafVersion->addItems(settings->installedZTreeVersions);
} }
} }
lc::LocalzLeafStarter::~LocalzLeafStarter() { lc::LocalzLeafStarter::~LocalzLeafStarter() { delete ui; }
delete ui;
}
void lc::LocalzLeafStarter::on_PBStartLocalzLeaf_clicked() { void lc::LocalzLeafStarter::on_PBStartLocalzLeaf_clicked() {
if (ui->CBzLeafVersion->currentIndex() == 0) { if (ui->CBzLeafVersion->currentIndex() == 0) {
QMessageBox::information( this, tr( "No z-Tree version chosen" ), QMessageBox::information(
this, tr("No z-Tree version chosen"),
tr("The was not chosen a z-Tree version, yet. This is" tr("The was not chosen a z-Tree version, yet. This is"
" mandatory, so please set one" ) , QMessageBox::Ok ); " mandatory, so please set one"),
QMessageBox::Ok);
return; return;
} }
@ -64,6 +61,7 @@ void lc::LocalzLeafStarter::on_PBStartLocalzLeaf_clicked() {
settings->SetLocalzLeafSize(ui->LELocalzLeafSize->text()); settings->SetLocalzLeafSize(ui->LELocalzLeafSize->text());
// Emit start local z-Leaf request to main window // Emit start local z-Leaf request to main window
emit LocalzLeafRequested( ui->LEzLeafName->text(), ui->CBzLeafVersion->currentText(), emit LocalzLeafRequested(ui->LEzLeafName->text(),
ui->CBzLeafVersion->currentText(),
ui->SBzLeafPort->value()); ui->SBzLeafPort->value());
} }

@ -36,7 +36,8 @@ public:
~LocalzLeafStarter(); ~LocalzLeafStarter();
signals: signals:
void LocalzLeafRequested( QString argzLeafName, QString argzLeafVersion, int argzTreePort ); void LocalzLeafRequested(QString argzLeafName, QString argzLeafVersion,
int argzTreePort);
private: private:
Ui::LocalzLeafStarter *ui = nullptr; Ui::LocalzLeafStarter *ui = nullptr;
@ -45,6 +46,6 @@ private slots:
void on_PBStartLocalzLeaf_clicked(); void on_PBStartLocalzLeaf_clicked();
}; };
} } // namespace lc
#endif // LOCALZLEAFSTARTER_H #endif // LOCALZLEAFSTARTER_H

@ -21,8 +21,8 @@
#include <QApplication> #include <QApplication>
#include "mainwindow.h"
#include "Lib/settings.h" #include "Lib/settings.h"
#include "mainwindow.h"
std::unique_ptr<lc::Settings> settings; std::unique_ptr<lc::Settings> settings;

@ -19,22 +19,20 @@
#include <memory> #include <memory>
#include <QtGlobal> #include "Lib/settings.h"
#include <QDebug>
#include <QInputDialog>
#include <QButtonGroup>
#include "localzleafstarter.h" #include "localzleafstarter.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "manualprintingsetup.h" #include "manualprintingsetup.h"
#include "Lib/settings.h" #include <QButtonGroup>
#include <QDebug>
#include <QInputDialog>
#include <QtGlobal>
extern std::unique_ptr<lc::Settings> settings; extern std::unique_ptr<lc::Settings> settings;
lc::MainWindow::MainWindow( QWidget *argParent ) : lc::MainWindow::MainWindow(QWidget *argParent)
QMainWindow{ argParent }, : QMainWindow{argParent},
icons( static_cast< int >( icons_t::ICON_QUANTITY ) ), icons(static_cast<int>(icons_t::ICON_QUANTITY)), ui{new Ui::MainWindow} {
ui{ new Ui::MainWindow }
{
ui->setupUi(this); ui->setupUi(this);
lablib = new Lablib{this}; lablib = new Lablib{this};
@ -43,8 +41,8 @@ lc::MainWindow::MainWindow( QWidget *argParent ) :
SetupWidgets(); SetupWidgets();
if (valid_items) { if (valid_items) {
gui_update_timer = new QTimer{this}; gui_update_timer = new QTimer{this};
connect( gui_update_timer, &QTimer::timeout, connect(gui_update_timer, &QTimer::timeout, this,
this, &MainWindow::UpdateClientsTableView ); &MainWindow::UpdateClientsTableView);
gui_update_timer->start(500); gui_update_timer->start(500);
} }
@ -59,22 +57,24 @@ lc::MainWindow::MainWindow( QWidget *argParent ) :
ui->CBDataTargetPath->addItem(QDir::homePath()); ui->CBDataTargetPath->addItem(QDir::homePath());
ui->CBDataTargetPath->addItem(QDir::homePath() + "/zTreeData"); ui->CBDataTargetPath->addItem(QDir::homePath() + "/zTreeData");
ui->CBDataTargetPath->setCurrentIndex(2); ui->CBDataTargetPath->setCurrentIndex(2);
connect( this, &MainWindow::RequestNewDataTargetPath, connect(this, &MainWindow::RequestNewDataTargetPath, this,
this, &MainWindow::GetNewDataTargetPath ); &MainWindow::GetNewDataTargetPath);
if ( settings->dvipsCmd.isEmpty() || settings->latexCmd.isEmpty() if (settings->dvipsCmd.isEmpty() || settings->latexCmd.isEmpty() ||
|| settings->lcDataDir.isEmpty() || settings->lprCmd.isEmpty() settings->lcDataDir.isEmpty() || settings->lprCmd.isEmpty() ||
|| settings->postscriptViewer.isEmpty() || settings->ps2pdfCmd.isEmpty() settings->postscriptViewer.isEmpty() || settings->ps2pdfCmd.isEmpty() ||
|| settings->rmCmd.isEmpty() || settings->vncViewer.isEmpty() ) { settings->rmCmd.isEmpty() || settings->vncViewer.isEmpty()) {
QMessageBox::information( this, tr( "Receipts printing will not work" ), QMessageBox::information(
this, tr("Receipts printing will not work"),
tr("Some component essential for receipts creation and" tr("Some component essential for receipts creation and"
" printing is missing. No receipts will be created or" " printing is missing. No receipts will be created or"
" printed." ), QMessageBox::Ok ); " printed."),
QMessageBox::Ok);
} else { } else {
ui->CBReceiptsHeader->addItems(settings->installedLaTeXHeaders); ui->CBReceiptsHeader->addItems(settings->installedLaTeXHeaders);
if ( settings->defaultReceiptIndex if (settings->defaultReceiptIndex &&
&& settings->defaultReceiptIndex < ui->CBReceiptsHeader->count() ) { settings->defaultReceiptIndex < ui->CBReceiptsHeader->count()) {
ui->CBReceiptsHeader->setCurrentIndex(settings->defaultReceiptIndex); ui->CBReceiptsHeader->setCurrentIndex(settings->defaultReceiptIndex);
} }
} }
@ -87,7 +87,8 @@ lc::MainWindow::~MainWindow() {
bool lc::MainWindow::CheckIfUserIsAdmin() { bool lc::MainWindow::CheckIfUserIsAdmin() {
if (settings->localUserName.isEmpty()) { if (settings->localUserName.isEmpty()) {
QMessageBox messageBox{ QMessageBox::Warning, tr( "User not detectable" ), QMessageBox messageBox{
QMessageBox::Warning, tr("User not detectable"),
tr("Your user name could not be queryed. The admin tab will be" tr("Your user name could not be queryed. The admin tab will be"
" disabled. You won't be able to perform administrative" " disabled. You won't be able to perform administrative"
" actions but can conduct experiments normally."), " actions but can conduct experiments normally."),
@ -112,12 +113,14 @@ void lc::MainWindow::DisableDisfunctionalWidgets() {
ui->PBStartzLeaf->setEnabled(false); ui->PBStartzLeaf->setEnabled(false);
} }
// Disable all z-Leaf killing related buttons if the 'killall' command is not available // Disable all z-Leaf killing related buttons if the 'killall' command is not
// available
if (settings->killallCmd.isEmpty()) { if (settings->killallCmd.isEmpty()) {
ui->PBKillLocalzLeaf->setEnabled(false); ui->PBKillLocalzLeaf->setEnabled(false);
ui->PBKillzLeaf->setEnabled(false); ui->PBKillzLeaf->setEnabled(false);
} }
// Disable all functions relying on the labcontrol installation directory if it is not available // Disable all functions relying on the labcontrol installation directory if
// it is not available
if (settings->lcDataDir.isEmpty()) { if (settings->lcDataDir.isEmpty()) {
ui->CBClientNames->setEnabled(false); ui->CBClientNames->setEnabled(false);
ui->CBWebcamChooser->setEnabled(false); ui->CBWebcamChooser->setEnabled(false);
@ -144,14 +147,14 @@ void lc::MainWindow::DisableDisfunctionalWidgets() {
} }
// Disable 'PBShowORSEE', if 'orsee_command' was not set // Disable 'PBShowORSEE', if 'orsee_command' was not set
if ( settings->browserCmd.isEmpty() if (settings->browserCmd.isEmpty() || settings->orseeUrl.isEmpty()) {
|| settings->orseeUrl.isEmpty() ) {
ui->PBShowORSEE->setEnabled(false); ui->PBShowORSEE->setEnabled(false);
} }
// Disable all widgets needless if 'public_key_path_user' or 'user_name_on_clients' was not set // Disable all widgets needless if 'public_key_path_user' or
if ( settings->pkeyPathUser.isEmpty() // 'user_name_on_clients' was not set
|| settings->userNameOnClients.isEmpty() ) { if (settings->pkeyPathUser.isEmpty() ||
settings->userNameOnClients.isEmpty()) {
ui->CBClientNames->setEnabled(false); ui->CBClientNames->setEnabled(false);
ui->LEFilePath->setEnabled(false); ui->LEFilePath->setEnabled(false);
ui->L_FakeName->setEnabled(false); ui->L_FakeName->setEnabled(false);
@ -171,8 +174,7 @@ void lc::MainWindow::DisableDisfunctionalWidgets() {
ui->RBUseLocalUser->click(); ui->RBUseLocalUser->click();
} }
if ( settings->pkeyPathRoot.isEmpty() if (settings->pkeyPathRoot.isEmpty() && settings->pkeyPathUser.isEmpty()) {
&& settings->pkeyPathUser.isEmpty() ) {
ui->GBExecuteOnEveryClient->setEnabled(false); ui->GBExecuteOnEveryClient->setEnabled(false);
ui->GBOptionsForAdminActions->setEnabled(false); ui->GBOptionsForAdminActions->setEnabled(false);
ui->PBOpenTerminal->setEnabled(false); ui->PBOpenTerminal->setEnabled(false);
@ -232,9 +234,9 @@ void lc::MainWindow::DisableDisfunctionalWidgets() {
ui->PBBoot->setEnabled(false); ui->PBBoot->setEnabled(false);
} }
// Deactivate the webcam choosing interface if no webcams are available or the viewer is missing // Deactivate the webcam choosing interface if no webcams are available or the
if ( settings->webcamDisplayCmd.isEmpty() // viewer is missing
|| settings->webcams.isEmpty() ) { if (settings->webcamDisplayCmd.isEmpty() || settings->webcams.isEmpty()) {
ui->CBWebcamChooser->setEnabled(false); ui->CBWebcamChooser->setEnabled(false);
ui->L_WebcamChooser->setEnabled(false); ui->L_WebcamChooser->setEnabled(false);
} }
@ -263,8 +265,7 @@ void lc::MainWindow::LoadIconPixmaps() {
return; return;
} }
const QStringList iconNames{ QStringList{} const QStringList iconNames{QStringList{} << "unknown.png"
<< "unknown.png"
<< "off.png" << "off.png"
<< "down.png" << "down.png"
<< "boot.png" << "boot.png"
@ -273,9 +274,12 @@ void lc::MainWindow::LoadIconPixmaps() {
for (int i = 0; i < (int)icons_t::ICON_QUANTITY; i++) { for (int i = 0; i < (int)icons_t::ICON_QUANTITY; i++) {
if (!icons[i].load(settings->lcDataDir + "/icons/" + iconNames[i])) { if (!icons[i].load(settings->lcDataDir + "/icons/" + iconNames[i])) {
QMessageBox::information( this, tr( "Could not load icon '%1'" ).arg( iconNames[ i ] ), QMessageBox::information(
this, tr("Could not load icon '%1'").arg(iconNames[i]),
tr("The icon in '%1/icons/%2' could not be loaded.") tr("The icon in '%1/icons/%2' could not be loaded.")
.arg( settings->lcDataDir ).arg( iconNames[ i ] ), QMessageBox::Ok ); .arg(settings->lcDataDir)
.arg(iconNames[i]),
QMessageBox::Ok);
} }
} }
} }
@ -283,7 +287,9 @@ void lc::MainWindow::LoadIconPixmaps() {
void lc::MainWindow::on_PBKillLocalzLeaf_clicked() { void lc::MainWindow::on_PBKillLocalzLeaf_clicked() {
QString program{settings->killallCmd}; QString program{settings->killallCmd};
QStringList arguments; QStringList arguments;
arguments << "-I" << "-q" << "zleaf.exe"; arguments << "-I"
<< "-q"
<< "zleaf.exe";
// Start the process // Start the process
QProcess killLocalzLeafProc; QProcess killLocalzLeafProc;
@ -301,30 +307,39 @@ void lc::MainWindow::on_PBPrintPaymentFileManually_clicked() {
ManualPrintingSetup *manPrint = new ManualPrintingSetup{this}; ManualPrintingSetup *manPrint = new ManualPrintingSetup{this};
manPrint->setWindowFlags(Qt::Window); manPrint->setWindowFlags(Qt::Window);
manPrint->show(); manPrint->show();
connect( manPrint, SIGNAL( destroyed( QObject* ) ), connect(manPrint, SIGNAL(destroyed(QObject *)), manPrint,
manPrint, SLOT( deleteLater() ) ); SLOT(deleteLater()));
connect( manPrint, &ManualPrintingSetup::RequestReceiptsHandler, connect(manPrint, &ManualPrintingSetup::RequestReceiptsHandler, this,
this, &MainWindow::StartReceiptsHandler ); &MainWindow::StartReceiptsHandler);
} }
void lc::MainWindow::on_PBRunzLeaf_clicked() { void lc::MainWindow::on_PBRunzLeaf_clicked() {
// Check if more than one client is selected and issue a warning message if so // Check if more than one client is selected and issue a warning message if so
unsigned short int numberOfSelectedClients = 0; unsigned short int numberOfSelectedClients = 0;
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes(); QModelIndexList activatedItems =
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) { ui->TVClients->selectionModel()->selectedIndexes();
for (QModelIndexList::ConstIterator it = activatedItems.cbegin();
it != activatedItems.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
++numberOfSelectedClients; ++numberOfSelectedClients;
} }
} }
qDebug() << numberOfSelectedClients << "clients are selected."; qDebug() << numberOfSelectedClients << "clients are selected.";
if (numberOfSelectedClients > 1) { if (numberOfSelectedClients > 1) {
QMessageBox messageBox{ QMessageBox::Information, tr( "Too many clients selected" ), tr( "There are too many clients selected in the table view on the left. Please select only one." ), QMessageBox::Ok, this }; QMessageBox messageBox{
QMessageBox::Information, tr("Too many clients selected"),
tr("There are too many clients selected in the table view on the left. "
"Please select only one."),
QMessageBox::Ok, this};
messageBox.exec(); messageBox.exec();
} else { } else {
const QString * const fakeName = new QString{ ui->CBClientNames->currentText() }; const QString *const fakeName =
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) { new QString{ui->CBClientNames->currentText()};
for (QModelIndexList::ConstIterator it = activatedItems.cbegin();
it != activatedItems.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->StartZLeaf(fakeName); client->StartZLeaf(fakeName);
} }
} }
@ -339,7 +354,8 @@ void lc::MainWindow::on_RBUseLocalUser_toggled(bool checked) {
} }
void lc::MainWindow::SetupWidgets() { void lc::MainWindow::SetupWidgets() {
// Fill the 'CBClientNames' with possible client names and the 'TVClients' with the clients // Fill the 'CBClientNames' with possible client names and the 'TVClients'
// with the clients
if (!settings->GetClients().isEmpty()) { if (!settings->GetClients().isEmpty()) {
valid_items = new QVector<QStandardItem *>; valid_items = new QVector<QStandardItem *>;
valid_items->reserve(settings->GetClients().size()); valid_items->reserve(settings->GetClients().size());
@ -350,7 +366,9 @@ void lc::MainWindow::SetupWidgets() {
// Check if a client already exists at the given position and skip, if so // Check if a client already exists at the given position and skip, if so
if (clients_view_model->item(temp_ypos, temp_xpos)) { if (clients_view_model->item(temp_ypos, temp_xpos)) {
QMessageBox::information(this, tr("Double assignment to one position"), QMessageBox::information(this, tr("Double assignment to one position"),
tr( "Two clients where set for the same position, '%1' will be dropped." ).arg( s->name ) ); tr("Two clients where set for the same "
"position, '%1' will be dropped.")
.arg(s->name));
continue; continue;
} }
@ -369,8 +387,11 @@ void lc::MainWindow::SetupWidgets() {
ui->TVClients->setModel(clients_view_model); ui->TVClients->setModel(clients_view_model);
valid_items->squeeze(); valid_items->squeeze();
} else { } else {
QMessageBox messageBox{ QMessageBox::Warning, tr( "Could not construct clients view" ), QMessageBox messageBox{
tr( "The creation of the clients view failed. Please check the file '/etc/xdg/Labcontrol/Labcontrol.conf'." ), QMessageBox::Ok, this }; QMessageBox::Warning, tr("Could not construct clients view"),
tr("The creation of the clients view failed. Please check the file "
"'/etc/xdg/Labcontrol/Labcontrol.conf'."),
QMessageBox::Ok, this};
messageBox.exec(); messageBox.exec();
ui->CBClientNames->setEnabled(false); ui->CBClientNames->setEnabled(false);
ui->GBClientActions->setEnabled(false); ui->GBClientActions->setEnabled(false);
@ -389,12 +410,14 @@ void lc::MainWindow::SetupWidgets() {
ui->CBWebcamChooser->addItem(s); ui->CBWebcamChooser->addItem(s);
} }
// Disable the admin tab if the user has no administrative rights and set it up // Disable the admin tab if the user has no administrative rights and set it
// up
if (CheckIfUserIsAdmin()) { if (CheckIfUserIsAdmin()) {
ui->TAdminActions->setEnabled(true); ui->TAdminActions->setEnabled(true);
ui->L_AdministrativeRights->setText(tr("You have administrative rights.")); ui->L_AdministrativeRights->setText(tr("You have administrative rights."));
} else { } else {
ui->L_AdministrativeRights->setText( tr( "You don't have administrative rights." ) ); ui->L_AdministrativeRights->setText(
tr("You don't have administrative rights."));
} }
ui->L_UserName->setText(tr("You are user %1").arg(settings->localUserName)); ui->L_UserName->setText(tr("You are user %1").arg(settings->localUserName));
if (!settings->userNameOnClients.isEmpty()) { if (!settings->userNameOnClients.isEmpty()) {
@ -412,20 +435,28 @@ void lc::MainWindow::SetupWidgets() {
// Fill the CBCommandToExecute QComboBox // Fill the CBCommandToExecute QComboBox
if (!settings->userNameOnClients.isEmpty()) { if (!settings->userNameOnClients.isEmpty()) {
ui->CBCommandToExecute->addItems( QStringList{} << "" << "apt update" ui->CBCommandToExecute->addItems(
<< "apt full-upgrade -y" << "reboot" QStringList{} << ""
<< "rm -rfv /home/" + settings->userNameOnClients + "/.mozilla" << "apt update"
<< "apt full-upgrade -y"
<< "reboot"
<< "rm -rfv /home/" + settings->userNameOnClients +
"/.mozilla"
<< "uname -a"); << "uname -a");
} else { } else {
ui->CBCommandToExecute->addItems( QStringList{} << "" << "apt update" ui->CBCommandToExecute->addItems(QStringList{} << ""
<< "apt full-upgrade -y" << "reboot" << "uname -a" ); << "apt update"
<< "apt full-upgrade -y"
<< "reboot"
<< "uname -a");
} }
// Disable buttons which are not configured // Disable buttons which are not configured
// DisableDisfunctionalWidgets(); // DisableDisfunctionalWidgets();
// Set the info text in LInfo on the TInfo tab // Set the info text in LInfo on the TInfo tab
ui->LInfo->setText( "This is Labcontrol version 2.1.6\n\n\n\n\n\n" ui->LInfo->setText(
"This is Labcontrol version 2.1.6\n\n\n\n\n\n"
"Developers\n\n" "Developers\n\n"
"0day-2016 Henning Prömpers\n" "0day-2016 Henning Prömpers\n"
"2014-2016 Markus Prasser\n" "2014-2016 Markus Prasser\n"
@ -440,24 +471,29 @@ void lc::MainWindow::SetupWidgets() {
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
"See the GNU General Public License for more details.\n\n" "See the GNU General Public License for more details.\n\n"
"You should have received a copy of the GNU General Public License\n" "You should have received a copy of the GNU General Public License\n"
"along with Labcontrol. If not, see <http://www.gnu.org/licenses/>.\n\n\n" ); "along with Labcontrol. If not, see "
"<http://www.gnu.org/licenses/>.\n\n\n");
} }
void lc::MainWindow::StartReceiptsHandler( QString argzTreeDataTargetPath, void lc::MainWindow::StartReceiptsHandler(
bool argReceiptsForLocalClients, QString argzTreeDataTargetPath, bool argReceiptsForLocalClients,
QString argAnonymousReceiptsPlaceholder, QString argAnonymousReceiptsPlaceholder, QString argLatexHeaderName,
QString argLatexHeaderName, QString argDateString) { QString argDateString) {
ReceiptsHandler *recHand = new ReceiptsHandler{ argzTreeDataTargetPath, ReceiptsHandler *recHand =
new ReceiptsHandler{argzTreeDataTargetPath,
argReceiptsForLocalClients, argReceiptsForLocalClients,
argAnonymousReceiptsPlaceholder, argAnonymousReceiptsPlaceholder,
argLatexHeaderName, argDateString, this }; argLatexHeaderName,
connect( recHand, &ReceiptsHandler::PrintingFinished, argDateString,
recHand, &ReceiptsHandler::deleteLater ); this};
connect(recHand, &ReceiptsHandler::PrintingFinished, recHand,
&ReceiptsHandler::deleteLater);
} }
void lc::MainWindow::UpdateClientsTableView() { void lc::MainWindow::UpdateClientsTableView() {
for (auto s : *valid_items) { for (auto s : *valid_items) {
state_t state = static_cast< Client* >( s->data( Qt::UserRole ).value<void *>() )->GetClientState(); state_t state = static_cast<Client *>(s->data(Qt::UserRole).value<void *>())
->GetClientState();
switch (state) { switch (state) {
case state_t::RESPONDING: case state_t::RESPONDING:
s->setBackground(QBrush(QColor(128, 255, 128, 255))); s->setBackground(QBrush(QColor(128, 255, 128, 255)));
@ -490,17 +526,21 @@ void lc::MainWindow::UpdateClientsTableView() {
/* Experiment tab functions */ /* Experiment tab functions */
void lc::MainWindow::on_PBBoot_clicked() { void lc::MainWindow::on_PBBoot_clicked() {
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes(); QModelIndexList activatedItems =
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) { ui->TVClients->selectionModel()->selectedIndexes();
for (QModelIndexList::ConstIterator it = activatedItems.cbegin();
it != activatedItems.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->Boot(); client->Boot();
} }
} }
} }
void lc::MainWindow::on_PBChooseFile_clicked() { void lc::MainWindow::on_PBChooseFile_clicked() {
QFileDialog *file_dialog = new QFileDialog{ this, tr( "Choose a file to beam" ), QDir::homePath() }; QFileDialog *file_dialog =
new QFileDialog{this, tr("Choose a file to beam"), QDir::homePath()};
file_dialog->setFileMode(QFileDialog::Directory); file_dialog->setFileMode(QFileDialog::Directory);
file_dialog->setOption(QFileDialog::DontUseNativeDialog, true); file_dialog->setOption(QFileDialog::DontUseNativeDialog, true);
file_dialog->setOption(QFileDialog::ReadOnly, true); file_dialog->setOption(QFileDialog::ReadOnly, true);
@ -509,8 +549,7 @@ void lc::MainWindow::on_PBChooseFile_clicked() {
if (file_dialog->exec()) { if (file_dialog->exec()) {
ui->LEFilePath->setText(file_dialog->selectedFiles().at(0)); ui->LEFilePath->setText(file_dialog->selectedFiles().at(0));
qDebug() << "Chose file" << ui->LEFilePath->text() << "for beaming."; qDebug() << "Chose file" << ui->LEFilePath->text() << "for beaming.";
} } else {
else {
ui->LEFilePath->setText(tr("File choosing cancelled")); ui->LEFilePath->setText(tr("File choosing cancelled"));
qDebug() << "File choosing cancelled"; qDebug() << "File choosing cancelled";
} }
@ -518,43 +557,56 @@ void lc::MainWindow::on_PBChooseFile_clicked() {
} }
void lc::MainWindow::on_PBBeamFile_clicked() { void lc::MainWindow::on_PBBeamFile_clicked() {
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes(); QModelIndexList activatedItems =
ui->TVClients->selectionModel()->selectedIndexes();
const QString fileToBeam{ui->LEFilePath->text()}; const QString fileToBeam{ui->LEFilePath->text()};
if (fileToBeam == "") { if (fileToBeam == "") {
QMessageBox::information(this, "Upload failed", "You didn't choose any folder to upload."); QMessageBox::information(this, "Upload failed",
"You didn't choose any folder to upload.");
} else { } else {
// Iterate over the selected clients to upload the file // Iterate over the selected clients to upload the file
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) { for (QModelIndexList::ConstIterator it = activatedItems.cbegin();
it != activatedItems.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
client->BeamFile( fileToBeam, &settings->pkeyPathUser, &settings->userNameOnClients ); static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->BeamFile(fileToBeam, &settings->pkeyPathUser,
&settings->userNameOnClients);
} }
} }
// Inform the user about the path // Inform the user about the path
QMessageBox::information(this, "Upload completed", "The folder was copied to all selected clients.\nThe path on every client is /home/ewfuser/media4ztree" + fileToBeam.mid(fileToBeam.lastIndexOf('/')) +".\nDon't forget to adjust the media path within zTree!"); QMessageBox::information(
this, "Upload completed",
"The folder was copied to all selected clients.\nThe path on every "
"client is /home/ewfuser/media4ztree" +
fileToBeam.mid(fileToBeam.lastIndexOf('/')) +
".\nDon't forget to adjust the media path within zTree!");
} }
} }
void lc::MainWindow::on_PBShowORSEE_clicked() { void lc::MainWindow::on_PBShowORSEE_clicked() { lablib->ShowOrsee(); }
lablib->ShowOrsee();
}
void lc::MainWindow::on_PBShowPreprints_clicked() { void lc::MainWindow::on_PBShowPreprints_clicked() { lablib->ShowPreprints(); }
lablib->ShowPreprints();
}
void lc::MainWindow::on_PBShutdown_clicked() { void lc::MainWindow::on_PBShutdown_clicked() {
// Confirmation dialog // Confirmation dialog
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Confirm", "Really shutdown the selected clients?", QMessageBox::Yes|QMessageBox::No); reply = QMessageBox::question(this, "Confirm",
"Really shutdown the selected clients?",
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) { if (reply == QMessageBox::Yes) {
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes(); QModelIndexList activatedItems =
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) { ui->TVClients->selectionModel()->selectedIndexes();
for (QModelIndexList::ConstIterator it = activatedItems.cbegin();
it != activatedItems.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
// Do not shut down the server itself // Do not shut down the server itself
if (client->name == "self") { if (client->name == "self") {
QMessageBox::information(NULL, "Shutdown canceled", "It is not allowed to shutdown the server itself via labcontrol!"); QMessageBox::information(NULL, "Shutdown canceled",
"It is not allowed to shutdown the server "
"itself via labcontrol!");
} else { } else {
client->Shutdown(); client->Shutdown();
} }
@ -581,29 +633,35 @@ void lc::MainWindow::on_CBWebcamChooser_activated( int argIndex ) {
} }
} }
void lc::MainWindow::on_PBstartBrowser_clicked() void lc::MainWindow::on_PBstartBrowser_clicked() {
{
QString argURL = ui->LEURL->text(); QString argURL = ui->LEURL->text();
bool argFullscreen = ui->CBFullscreen->checkState(); bool argFullscreen = ui->CBFullscreen->checkState();
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes(); QModelIndexList activated_items =
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) { ui->TVClients->selectionModel()->selectedIndexes();
for (QModelIndexList::ConstIterator it = activated_items.cbegin();
it != activated_items.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->StartClientBrowser(&argURL, &argFullscreen); client->StartClientBrowser(&argURL, &argFullscreen);
} }
} }
} }
void lc::MainWindow::on_PBstopBrowser_clicked() void lc::MainWindow::on_PBstopBrowser_clicked() {
{
// Confirmation dialog // Confirmation dialog
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Confirm", "Really kill all selected browser instances?", QMessageBox::Yes|QMessageBox::No); reply = QMessageBox::question(this, "Confirm",
"Really kill all selected browser instances?",
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) { if (reply == QMessageBox::Yes) {
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes(); QModelIndexList activated_items =
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) { ui->TVClients->selectionModel()->selectedIndexes();
for (QModelIndexList::ConstIterator it = activated_items.cbegin();
it != activated_items.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->StopClientBrowser(); client->StopClientBrowser();
} }
} }
@ -613,36 +671,42 @@ void lc::MainWindow::on_PBstopBrowser_clicked()
} }
// View only VNC button // View only VNC button
void lc::MainWindow::on_PBViewDesktopViewOnly_clicked() void lc::MainWindow::on_PBViewDesktopViewOnly_clicked() {
{ QModelIndexList activatedItems =
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes(); ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) { for (QModelIndexList::ConstIterator it = activatedItems.cbegin();
it != activatedItems.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->ShowDesktopViewOnly(); client->ShowDesktopViewOnly();
} }
} }
} }
// Full control VNC button // Full control VNC button
void lc::MainWindow::on_PBViewDesktopFullControl_clicked() void lc::MainWindow::on_PBViewDesktopFullControl_clicked() {
{ QModelIndexList activatedItems =
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes(); ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) { for (QModelIndexList::ConstIterator it = activatedItems.cbegin();
it != activatedItems.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->ShowDesktopFullControl(); client->ShowDesktopFullControl();
} }
} }
} }
/* Session tab functions */ /* Session tab functions */
void lc::MainWindow::on_PBStartzLeaf_clicked() { void lc::MainWindow::on_PBStartzLeaf_clicked() {
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes(); QModelIndexList activated_items =
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) { ui->TVClients->selectionModel()->selectedIndexes();
for (QModelIndexList::ConstIterator it = activated_items.cbegin();
it != activated_items.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->StartZLeaf(nullptr, ui->LEzLeafCommandline->text()); client->StartZLeaf(nullptr, ui->LEzLeafCommandline->text());
} }
} }
@ -652,16 +716,17 @@ void lc::MainWindow::on_PBStartLocalzLeaf_clicked() {
LocalzLeafStarter *localzLeafStarter = new LocalzLeafStarter{this}; LocalzLeafStarter *localzLeafStarter = new LocalzLeafStarter{this};
localzLeafStarter->setWindowFlags(Qt::Window); localzLeafStarter->setWindowFlags(Qt::Window);
localzLeafStarter->show(); localzLeafStarter->show();
connect( localzLeafStarter, &LocalzLeafStarter::LocalzLeafRequested, connect(localzLeafStarter, &LocalzLeafStarter::LocalzLeafRequested, this,
this, &MainWindow::StartLocalzLeaf ); &MainWindow::StartLocalzLeaf);
connect(localzLeafStarter, SIGNAL(LocalzLeafRequested(QString, QString, int)), connect(localzLeafStarter, SIGNAL(LocalzLeafRequested(QString, QString, int)),
localzLeafStarter, SLOT(deleteLater())); localzLeafStarter, SLOT(deleteLater()));
} }
void lc::MainWindow::StartLocalzLeaf( QString argzLeafName, QString argzLeafVersion, void lc::MainWindow::StartLocalzLeaf(QString argzLeafName,
QString argzLeafVersion,
int argzTreePort) { int argzTreePort) {
if ( settings->tasksetCmd.isEmpty() || settings->wineCmd.isEmpty() if (settings->tasksetCmd.isEmpty() || settings->wineCmd.isEmpty() ||
|| settings->zTreeInstDir.isEmpty() ) { settings->zTreeInstDir.isEmpty()) {
return; return;
} }
@ -669,9 +734,12 @@ void lc::MainWindow::StartLocalzLeaf( QString argzLeafName, QString argzLeafVers
startProc.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); startProc.setProcessEnvironment(QProcessEnvironment::systemEnvironment());
QStringList arguments; QStringList arguments;
arguments << "0x00000001" << settings->wineCmd arguments << "0x00000001" << settings->wineCmd
<< QString{ settings->zTreeInstDir + "/zTree_" + argzLeafVersion + "/zleaf.exe" } << QString{settings->zTreeInstDir + "/zTree_" + argzLeafVersion +
<< "/server" << "127.0.0.1" << "/channel" "/zleaf.exe"}
<< QString::number( argzTreePort - 7000 ) << "/name" << argzLeafName; << "/server"
<< "127.0.0.1"
<< "/channel" << QString::number(argzTreePort - 7000) << "/name"
<< argzLeafName;
if (!settings->localzLeafSize.isEmpty()) { if (!settings->localzLeafSize.isEmpty()) {
arguments << "/size" << QString{settings->localzLeafSize}; arguments << "/size" << QString{settings->localzLeafSize};
} }
@ -680,14 +748,17 @@ void lc::MainWindow::StartLocalzLeaf( QString argzLeafName, QString argzLeafVers
startProc.startDetached(settings->tasksetCmd, arguments); startProc.startDetached(settings->tasksetCmd, arguments);
} }
void lc::MainWindow::on_PBStopZtree_clicked() void lc::MainWindow::on_PBStopZtree_clicked() {
{
QString program{settings->killallCmd}; QString program{settings->killallCmd};
QStringList arguments; QStringList arguments;
arguments << "-I" << "-q" << "ztree.exe"; arguments << "-I"
<< "-q"
<< "ztree.exe";
// Confirmation dialog // Confirmation dialog
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Confirm", "Really kill all z-Tree instances?", QMessageBox::Yes|QMessageBox::No); reply = QMessageBox::question(this, "Confirm",
"Really kill all z-Tree instances?",
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) { if (reply == QMessageBox::Yes) {
// Kill all z-Tree processes // Kill all z-Tree processes
QProcess killLocalzLeafProc; QProcess killLocalzLeafProc;
@ -701,9 +772,9 @@ void lc::MainWindow::on_PBStopZtree_clicked()
} }
} }
void lc::MainWindow::on_PBRecoverCrashedSession_clicked() void lc::MainWindow::on_PBRecoverCrashedSession_clicked() {
{ // TODO: Implement the functionality of the restore session script in here (no
// TODO: Implement the functionality of the restore session script in here (no zenity script) // zenity script)
QProcess startProc; QProcess startProc;
startProc.setProcessEnvironment(QProcessEnvironment::systemEnvironment()); startProc.setProcessEnvironment(QProcessEnvironment::systemEnvironment());
if (!settings->restartCrashedSessionScript.isEmpty()) { if (!settings->restartCrashedSessionScript.isEmpty()) {
@ -711,8 +782,7 @@ void lc::MainWindow::on_PBRecoverCrashedSession_clicked()
} }
} }
void lc::MainWindow::on_CBDataTargetPath_activated( int argIndex ) void lc::MainWindow::on_CBDataTargetPath_activated(int argIndex) {
{
if (!argIndex) { if (!argIndex) {
emit RequestNewDataTargetPath(); emit RequestNewDataTargetPath();
} }
@ -735,15 +805,13 @@ void lc::MainWindow::GetNewDataTargetPath() {
} }
// Dummy function for enabling anonymous receipts section in UI // Dummy function for enabling anonymous receipts section in UI
void lc::MainWindow::on_CBReceiptsHeader_activated(int argIndex) void lc::MainWindow::on_CBReceiptsHeader_activated(int argIndex) {
{
Q_UNUSED(argIndex); Q_UNUSED(argIndex);
ui->CBReceiptsHeader->setStyleSheet(""); ui->CBReceiptsHeader->setStyleSheet("");
} }
// Anonymous receipients header check box // Anonymous receipients header check box
void lc::MainWindow::on_ChBPrintanonymousreceipts_clicked() void lc::MainWindow::on_ChBPrintanonymousreceipts_clicked() {
{
ui->LReplaceParticipantNames->setEnabled(true); ui->LReplaceParticipantNames->setEnabled(true);
ui->CBReplaceParticipantNames->setEnabled(true); ui->CBReplaceParticipantNames->setEnabled(true);
} }
@ -752,16 +820,20 @@ void lc::MainWindow::on_ChBPrintanonymousreceipts_clicked()
void lc::MainWindow::on_PBStartSession_clicked() { void lc::MainWindow::on_PBStartSession_clicked() {
if (ui->CBzTreeVersion->currentIndex() == 0) { if (ui->CBzTreeVersion->currentIndex() == 0) {
QMessageBox::information( this, tr( "No z-Tree version chosen" ), QMessageBox::information(
this, tr("No z-Tree version chosen"),
tr("A z-Tree version was not chosen, yet. This setting is" tr("A z-Tree version was not chosen, yet. This setting is"
" mandatory." ), QMessageBox::Ok ); " mandatory."),
QMessageBox::Ok);
return; return;
} }
const QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes(); const QModelIndexList activatedItems =
ui->TVClients->selectionModel()->selectedIndexes();
if (!ui->ChBSessionWithoutAttachedClients->isChecked()) { if (!ui->ChBSessionWithoutAttachedClients->isChecked()) {
if (!activatedItems.length()) { if (!activatedItems.length()) {
QMessageBox::information( this, tr( "Canceled, no clients were chosen" ), QMessageBox::information(
this, tr("Canceled, no clients were chosen"),
tr("The start of a new session was canceled.\n" tr("The start of a new session was canceled.\n"
" Some clients have to be selected first or the" " Some clients have to be selected first or the"
" creation of sessions without clients must be" " creation of sessions without clients must be"
@ -776,9 +848,11 @@ void lc::MainWindow::on_PBStartSession_clicked() {
} }
QVector<Client *> associatedClients; QVector<Client *> associatedClients;
for ( auto cit = activatedItems.cbegin(); cit != activatedItems.cend(); ++cit ) { for (auto cit = activatedItems.cbegin(); cit != activatedItems.cend();
++cit) {
if ((*cit).data(Qt::DisplayRole).type() != 0) { if ((*cit).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *cit ).data( Qt::UserRole ).value< void* >() ); Client *client =
static_cast<Client *>((*cit).data(Qt::UserRole).value<void *>());
client->SetSessionPort(ui->SBPort->value()); client->SetSessionPort(ui->SBPort->value());
client->SetzLeafVersion(ui->CBzTreeVersion->currentText()); client->SetzLeafVersion(ui->CBzTreeVersion->currentText());
associatedClients.append(client); associatedClients.append(client);
@ -793,14 +867,19 @@ void lc::MainWindow::on_PBStartSession_clicked() {
ui->CBzTreeVersion->currentText()); ui->CBzTreeVersion->currentText());
// Display the command line // Display the command line
QString cmd = this->lablib->getzLeafArgs( ui->SBPort->value(), ui->CBzTreeVersion->currentText()).join(" "); QString cmd =
this->lablib
->getzLeafArgs(ui->SBPort->value(), ui->CBzTreeVersion->currentText())
.join(" ");
ui->LEzLeafCommandline->setText(cmd); ui->LEzLeafCommandline->setText(cmd);
// Start z-Leaf on selected clients if checkbox is activated // Start z-Leaf on selected clients if checkbox is activated
if (ui->ChBautoStartClientZleaf->isChecked()) { if (ui->ChBautoStartClientZleaf->isChecked()) {
for ( auto cit = activatedItems.cbegin(); cit != activatedItems.cend(); ++cit ) { for (auto cit = activatedItems.cbegin(); cit != activatedItems.cend();
++cit) {
if ((*cit).data(Qt::DisplayRole).type() != 0) { if ((*cit).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *cit ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*cit).data(Qt::UserRole).value<void *>());
client->StartZLeaf(nullptr, cmd); client->StartZLeaf(nullptr, cmd);
} }
} }
@ -813,12 +892,14 @@ void lc::MainWindow::on_PBStartSession_clicked() {
ui->SBPort->setValue(newPort); ui->SBPort->setValue(newPort);
} }
void lc::MainWindow::on_PBKillzLeaf_clicked() void lc::MainWindow::on_PBKillzLeaf_clicked() {
{ QModelIndexList activated_items =
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes(); ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) { for (QModelIndexList::ConstIterator it = activated_items.cbegin();
it != activated_items.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->KillZLeaf(); client->KillZLeaf();
} }
} }
@ -835,10 +916,13 @@ void lc::MainWindow::on_PBOpenFilesystem_clicked() {
userToBeUsed = new QString{settings->userNameOnClients}; userToBeUsed = new QString{settings->userNameOnClients};
} }
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes(); QModelIndexList activated_items =
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) { ui->TVClients->selectionModel()->selectedIndexes();
for (QModelIndexList::ConstIterator it = activated_items.cbegin();
it != activated_items.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->OpenFilesystem(userToBeUsed); client->OpenFilesystem(userToBeUsed);
} }
} }
@ -859,14 +943,16 @@ void lc::MainWindow::on_PBExecute_clicked() {
} }
qDebug() << "Executing command" << command << " on chosen clients."; qDebug() << "Executing command" << command << " on chosen clients.";
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes(); QModelIndexList activated_items =
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) { ui->TVClients->selectionModel()->selectedIndexes();
for (QModelIndexList::ConstIterator it = activated_items.cbegin();
it != activated_items.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->OpenTerminal(command, ui->RBUseUserRoot->isChecked()); client->OpenTerminal(command, ui->RBUseUserRoot->isChecked());
} }
} }
} }
// Issue open terminal call // Issue open terminal call
@ -877,27 +963,35 @@ void lc::MainWindow::on_PBOpenTerminal_clicked() {
} else { } else {
pkeyPathUser = settings->pkeyPathUser; pkeyPathUser = settings->pkeyPathUser;
} }
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes(); QModelIndexList activated_items =
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) { ui->TVClients->selectionModel()->selectedIndexes();
for (QModelIndexList::ConstIterator it = activated_items.cbegin();
it != activated_items.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->OpenTerminal(QString{}, ui->RBUseUserRoot->isChecked()); client->OpenTerminal(QString{}, ui->RBUseUserRoot->isChecked());
} }
} }
} }
// Enable RMB // Enable RMB
void lc::MainWindow::on_PBEnableRMB_clicked() void lc::MainWindow::on_PBEnableRMB_clicked() {
{
// Confirmation dialog // Confirmation dialog
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Confirm", "Really enable the right mouse button on selected clients?", QMessageBox::Yes|QMessageBox::No); reply = QMessageBox::question(
this, "Confirm",
"Really enable the right mouse button on selected clients?",
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) { if (reply == QMessageBox::Yes) {
qDebug() << "Enabling RMB on chosen clients."; qDebug() << "Enabling RMB on chosen clients.";
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes(); QModelIndexList activated_items =
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) { ui->TVClients->selectionModel()->selectedIndexes();
for (QModelIndexList::ConstIterator it = activated_items.cbegin();
it != activated_items.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->ControlRMB(true); client->ControlRMB(true);
} }
} }
@ -905,17 +999,22 @@ void lc::MainWindow::on_PBEnableRMB_clicked()
} }
// Disable RMB // Disable RMB
void lc::MainWindow::on_PBDisableRMB_clicked() void lc::MainWindow::on_PBDisableRMB_clicked() {
{
// Confirmation dialog // Confirmation dialog
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Confirm", "Really disable the right mouse button on selected clients?", QMessageBox::Yes|QMessageBox::No); reply = QMessageBox::question(
this, "Confirm",
"Really disable the right mouse button on selected clients?",
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) { if (reply == QMessageBox::Yes) {
qDebug() << "Disabling RMB on chosen clients."; qDebug() << "Disabling RMB on chosen clients.";
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes(); QModelIndexList activated_items =
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) { ui->TVClients->selectionModel()->selectedIndexes();
for (QModelIndexList::ConstIterator it = activated_items.cbegin();
it != activated_items.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() ); Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->ControlRMB(false); client->ControlRMB(false);
} }
} }

@ -20,7 +20,15 @@
#ifndef MAINWINDOW_H #ifndef MAINWINDOW_H
#define MAINWINDOW_H #define MAINWINDOW_H
enum class icons_t : unsigned short int { UNKNOWN, OFF, DOWN, BOOT, ON, ZLEAF, ICON_QUANTITY }; enum class icons_t : unsigned short int {
UNKNOWN,
OFF,
DOWN,
BOOT,
ON,
ZLEAF,
ICON_QUANTITY
};
#include "Lib/client.h" #include "Lib/client.h"
#include "Lib/lablib.h" #include "Lib/lablib.h"
@ -45,7 +53,8 @@ class MainWindow;
//! The class containing the graphical user interface. //! The class containing the graphical user interface.
/*! /*!
This class represents the graphical user interface and all connected functionality. This class represents the graphical user interface and all connected
functionality.
*/ */
class MainWindow : public QMainWindow { class MainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
@ -74,18 +83,20 @@ private slots:
void on_PBViewDesktopViewOnly_clicked(); void on_PBViewDesktopViewOnly_clicked();
void on_PBViewDesktopFullControl_clicked(); void on_PBViewDesktopFullControl_clicked();
void on_RBUseLocalUser_toggled(bool checked); void on_RBUseLocalUser_toggled(bool checked);
void StartLocalzLeaf( QString argzLeafName, QString argzLeafVersion, int argzTreePort ); void StartLocalzLeaf(QString argzLeafName, QString argzLeafVersion,
int argzTreePort);
//! Updates the icons of the QTableView displaying the clients' states //! Updates the icons of the QTableView displaying the clients' states
/*! /*!
* This function iterates over all valid items of the 'TVClients' and sets their states * This function iterates over all valid items of the 'TVClients' and sets
* by querying the represented 'lcClient' instances. * their states by querying the represented 'lcClient' instances.
*/ */
void UpdateClientsTableView(); void UpdateClientsTableView();
signals: signals:
/*Session actions*/ /*Session actions*/
void RequestNewDataTargetPath(); void RequestNewDataTargetPath();
void RequestNewSession( QVector< Client* > argAssocCl, QString argParticipNameReplacement, void RequestNewSession(QVector<Client *> argAssocCl,
QString argParticipNameReplacement,
bool argPrintLocalReceipts, QString argReceiptsHeader, bool argPrintLocalReceipts, QString argReceiptsHeader,
QString argzTreeDataTargetPath, quint16 argzTreePort, QString argzTreeDataTargetPath, quint16 argzTreePort,
QString argzTreeVersion); QString argzTreeVersion);
@ -93,31 +104,43 @@ signals:
private: private:
//! Checks, if the user has administrative rights //! Checks, if the user has administrative rights
/*! /*!
@return Returns true, if the user has administrative rights (If the user is in the 'sudo' group) @return Returns true, if the user has administrative rights (If the user is
in the 'sudo' group)
*/ */
bool CheckIfUserIsAdmin(); bool CheckIfUserIsAdmin();
//! Disables widgets for functions not available due to lacking devices or settings //! Disables widgets for functions not available due to lacking devices or
//! settings
void DisableDisfunctionalWidgets(); void DisableDisfunctionalWidgets();
//! Loads all needed client icon QPixmaps //! Loads all needed client icon QPixmaps
void LoadIconPixmaps(); void LoadIconPixmaps();
//! Sets up all used widgets //! Sets up all used widgets
void SetupWidgets(); void SetupWidgets();
QStandardItemModel *clients_view_model = nullptr; //! The view storing all clients data QStandardItemModel *clients_view_model =
QTimer *gui_update_timer = nullptr; //! A QTimer triggering updates of the graphical user interface nullptr; //! The view storing all clients data
QVector< QPixmap > icons; //! Vector of pixmaps storing the icons indicating the clients' statuses QTimer *gui_update_timer =
Lablib *lablib = nullptr; //! Accumulator of all program logic being accessed by the GUI nullptr; //! A QTimer triggering updates of the graphical user interface
bool localzLeavesAreRunning = false; //! Stores if a local z-Leaf instance is running on the server ('true' if local z-Leaf exists) QVector<QPixmap> icons; //! Vector of pixmaps storing the icons indicating the
QButtonGroup *userChooseButtonGroup = nullptr; //! Used to group the radio buttons choosing which user shall be used for administrative client actions //! clients' statuses
Lablib *lablib =
nullptr; //! Accumulator of all program logic being accessed by the GUI
bool localzLeavesAreRunning =
false; //! Stores if a local z-Leaf instance is running on the server
//! ('true' if local z-Leaf exists)
QButtonGroup *userChooseButtonGroup =
nullptr; //! Used to group the radio buttons choosing which user shall be
//! used for administrative client actions
Ui::MainWindow *ui = nullptr; //! Pointer storing all GUI items Ui::MainWindow *ui = nullptr; //! Pointer storing all GUI items
QVector<QStandardItem *> *valid_items = nullptr; //! Stores all valid Client instances displayed by the table view, its main use is as iterable object for 'update_clients_table_view()' QVector<QStandardItem *> *valid_items =
nullptr; //! Stores all valid Client instances displayed by the table
//! view, its main use is as iterable object for
//! 'update_clients_table_view()'
private slots: private slots:
void StartReceiptsHandler(QString argzTreeDataTargetPath, void StartReceiptsHandler(QString argzTreeDataTargetPath,
bool argReceiptsForLocalClients, bool argReceiptsForLocalClients,
QString argAnonymousReceiptsPlaceholder, QString argAnonymousReceiptsPlaceholder,
QString argLatexHeaderName, QString argLatexHeaderName, QString argDateString);
QString argDateString );
void on_PBstartBrowser_clicked(); void on_PBstartBrowser_clicked();
void on_PBstopBrowser_clicked(); void on_PBstopBrowser_clicked();
@ -133,6 +156,6 @@ private slots:
void on_PBDisableRMB_clicked(); void on_PBDisableRMB_clicked();
}; };
} } // namespace lc
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

@ -21,40 +21,38 @@
#include <QFileDialog> #include <QFileDialog>
#include "Lib/settings.h"
#include "manualprintingsetup.h" #include "manualprintingsetup.h"
#include "ui_manualprintingsetup.h" #include "ui_manualprintingsetup.h"
#include "Lib/settings.h"
extern std::unique_ptr<lc::Settings> settings; extern std::unique_ptr<lc::Settings> settings;
lc::ManualPrintingSetup::ManualPrintingSetup( QWidget *argParent ) : lc::ManualPrintingSetup::ManualPrintingSetup(QWidget *argParent)
QWidget{ argParent }, : QWidget{argParent}, ui{new Ui::ManualPrintingSetup} {
ui{ new Ui::ManualPrintingSetup }
{
ui->setupUi(this); ui->setupUi(this);
if ( settings->dvipsCmd.isEmpty() || settings->latexCmd.isEmpty() if (settings->dvipsCmd.isEmpty() || settings->latexCmd.isEmpty() ||
|| settings->lcDataDir.isEmpty() || settings->lprCmd.isEmpty() settings->lcDataDir.isEmpty() || settings->lprCmd.isEmpty() ||
|| settings->postscriptViewer.isEmpty() || settings->ps2pdfCmd.isEmpty() settings->postscriptViewer.isEmpty() || settings->ps2pdfCmd.isEmpty() ||
|| settings->rmCmd.isEmpty() || settings->vncViewer.isEmpty() ) { settings->rmCmd.isEmpty() || settings->vncViewer.isEmpty()) {
ui->VLManualPrintingSetup->setEnabled(false); ui->VLManualPrintingSetup->setEnabled(false);
QMessageBox::information( this, tr( "Receipts printing will not work" ), QMessageBox::information(
this, tr("Receipts printing will not work"),
tr("Some component essential for receipts creation and" tr("Some component essential for receipts creation and"
" printing is missing. No receipts will be created or" " printing is missing. No receipts will be created or"
" printed." ), QMessageBox::Ok ); " printed."),
QMessageBox::Ok);
} else { } else {
ui->CBReceiptsHeader->addItems(settings->installedLaTeXHeaders); ui->CBReceiptsHeader->addItems(settings->installedLaTeXHeaders);
if ( settings->defaultReceiptIndex if (settings->defaultReceiptIndex &&
&& settings->defaultReceiptIndex < ui->CBReceiptsHeader->count() ) { settings->defaultReceiptIndex < ui->CBReceiptsHeader->count()) {
ui->CBReceiptsHeader->setCurrentIndex(settings->defaultReceiptIndex); ui->CBReceiptsHeader->setCurrentIndex(settings->defaultReceiptIndex);
} }
} }
} }
lc::ManualPrintingSetup::~ManualPrintingSetup() { lc::ManualPrintingSetup::~ManualPrintingSetup() { delete ui; }
delete ui;
}
void lc::ManualPrintingSetup::on_PBSelectFile_clicked() { void lc::ManualPrintingSetup::on_PBSelectFile_clicked() {
QFileDialog fileDialog{this, tr("Please choose a payment file to print."), QFileDialog fileDialog{this, tr("Please choose a payment file to print."),
@ -64,10 +62,11 @@ void lc::ManualPrintingSetup::on_PBSelectFile_clicked() {
if (fileDialog.exec()) { if (fileDialog.exec()) {
ui->PBSelectFile->setStyleSheet(""); ui->PBSelectFile->setStyleSheet("");
const QString tmpFileName{fileDialog.selectedFiles().at(0)}; const QString tmpFileName{fileDialog.selectedFiles().at(0)};
dateString = tmpFileName.split( '/', QString::KeepEmptyParts, dateString =
Qt::CaseInsensitive ).last() tmpFileName.split('/', QString::KeepEmptyParts, Qt::CaseInsensitive)
.split( '.', QString::KeepEmptyParts, .last()
Qt::CaseInsensitive ).first(); .split('.', QString::KeepEmptyParts, Qt::CaseInsensitive)
.first();
workPath = tmpFileName; workPath = tmpFileName;
workPath.truncate(workPath.lastIndexOf('/')); workPath.truncate(workPath.lastIndexOf('/'));
} }
@ -78,7 +77,8 @@ void lc::ManualPrintingSetup::on_CBReceiptsHeader_activated( int argIndex ) {
ui->CBReceiptsHeader->setStyleSheet(""); ui->CBReceiptsHeader->setStyleSheet("");
} }
void lc::ManualPrintingSetup::on_ChBPrintAnonymousReceipts_clicked( bool argChecked ) { void lc::ManualPrintingSetup::on_ChBPrintAnonymousReceipts_clicked(
bool argChecked) {
ui->ChBPrintAnonymousReceipts->setStyleSheet(""); ui->ChBPrintAnonymousReceipts->setStyleSheet("");
ui->LReplaceParticipantNames->setEnabled(argChecked); ui->LReplaceParticipantNames->setEnabled(argChecked);
@ -91,7 +91,8 @@ void lc::ManualPrintingSetup::on_PBPrint_clicked() {
anonymousReceiptsPlaceholder = ui->CBReplaceParticipantNames->currentText(); anonymousReceiptsPlaceholder = ui->CBReplaceParticipantNames->currentText();
} }
emit RequestReceiptsHandler( workPath, ui->ChBReceiptsForLocalClients->isChecked(), emit RequestReceiptsHandler(workPath,
ui->ChBReceiptsForLocalClients->isChecked(),
anonymousReceiptsPlaceholder, anonymousReceiptsPlaceholder,
ui->CBReceiptsHeader->currentText(), dateString); ui->CBReceiptsHeader->currentText(), dateString);

@ -54,6 +54,6 @@ private slots:
void on_PBSelectFile_clicked(); void on_PBSelectFile_clicked();
}; };
} } // namespace lc
#endif // MANUALPRINTINGSETUP_H #endif // MANUALPRINTINGSETUP_H

Loading…
Cancel
Save