version 2.1.5 - merge from fork - most important change is the session starter tab (moved back from pop up)

remotes/origin/HEAD
Tobias Weiss 7 years ago
parent e162f1cd8b
commit bd7a10645f

@ -10,6 +10,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed
### Removed
## [v2.1.5] - 2017-10-21
### Added
* Dialog for Upload folder button
* Open browser on clients
* Full Control VNC Button
* LineEdit for zLeaf CMD
### Changed
* Session popup is now a tab
* Tab layout separated in prep / session / admin / info
* Version info displayed in info
## [v2.1.0] - 2016-10-12
### Added
* Manual printing of _z-Tree_ payment files

@ -8,8 +8,6 @@ SOURCES += src/localzleafstarter.cpp \
src/main.cpp \
src/mainwindow.cpp \
src/manualprintingsetup.cpp \
src/sessiondisplay.cpp \
src/sessionstarter.cpp \
src/Lib/client.cpp \
src/Lib/clienthelpnotificationserver.cpp \
src/Lib/clientpinger.cpp \
@ -25,8 +23,6 @@ SOURCES += src/localzleafstarter.cpp \
HEADERS += src/localzleafstarter.h \
src/mainwindow.h \
src/manualprintingsetup.h \
src/sessiondisplay.h \
src/sessionstarter.h \
src/Lib/client.h \
src/Lib/clienthelpnotificationserver.h \
src/Lib/clientpinger.h \
@ -42,9 +38,7 @@ HEADERS += src/localzleafstarter.h \
FORMS += src/localzleafstarter.ui \
src/mainwindow.ui \
src/manualprintingsetup.ui \
src/sessiondisplay.ui \
src/sessionstarter.ui
src/manualprintingsetup.ui
QMAKE_CXXFLAGS += -std=c++11

@ -1,11 +1,33 @@
[General]
# The user names of all users which shall be able to conduct administrative tasks with Labcontrol
admin_users="UserA|UserB|UserC"
# The browser in which ORSEE shall be displayed
browser_command=/usr/bin/firefox
### Server settings
# The IP of the server running zTree
server_ip=192.168.1.200
# Network broadcast address
network_broadcast_address=192.168.1.255
# The port which shall be used by zTree by default
initial_port=8000
# The port the client help server shall listen on
client_help_server_port=XXXX
# Client settings
# User names of all users which shall be able to conduct administrative tasks with Labcontrol
admin_users="UserA|UserB|UserC"
# The public keys to access the clients as root
pkey_path_root=/usr/local/share/labcontrol/id_labclient_root
# The public keys to access the clients as unprivileged user
pkey_path_user=/usr/local/share/labcontrol/id_labclient_dsa
# The default name for locally started zLeaves
local_zLeaf_name=local
# Default dimension for locally started zLeaves
local_zLeaf_size=1280x1024
# If multiple receipts are availabe, this indicates, which one will be shown by default (the index counting from 0 following an alphabetical ordering)
default_receipt_index=0
# The URL address of your lab's ORSEE
orsee_url=http://yourORSEEserver.tld
# URLs to available webcams
webcams=http://user:pass@webcam_right|http://user:pass@webcam_left
# Display names for the webcams
webcams_names="Webcam right|Webcam left"
### Client settings
# The client settings are represented as an array. So the info of the first client stands in the first field in every section and the same is valid for the other clients with other indices each.
client_ips=192.168.1.1|192.168.1.2|192.168.1.3|192.168.1.4|192.168.1.5|192.168.1.6|192.168.1.7|192.168.1.8|192.168.1.9|192.168.1.10|192.168.1.11|192.168.1.12|192.168.1.13|192.168.1.14|192.168.1.15|192.168.1.16|192.168.1.17|192.168.1.18|192.168.1.19|192.168.1.20|192.168.1.21|192.168.1.22|192.168.1.23|192.168.1.24
client_macs=00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00|00:00:00:00:00:00
@ -16,50 +38,57 @@ client_quantity=24
# The following two coordinates specify where the client will be shown in the coordinate grid at the bottom of the Labcontrol screen
client_xpos=1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24
client_ypos=1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1|1
# If multiple receipts are availabe, this indicates, which one will be shown by default (the index counting from 0 following an alphabetical ordering)
default_receipt_index=0
dvips_command=/usr/bin/dvips
file_manager=/usr/bin/dolphin
# The port which shall be used by zTree by default
initial_port=8000
# The name of the user of the clients which is used to conduct experiments
user_name_on_clients=user
### Binary paths
# Path to your lpr binary
lpr_command=/usr/bin/lpr
# Path to your netstat binary
netstat_command=/bin/netstat
# The command used to kill 'zleaf.exe' instances (part of the 'psmisc' package)
killall_command=/usr/bin/killall
# Where all Labcontrol data got installed
labcontrol_installation_directory=/usr/local/share/labcontrol
#DOTO: REMOVE VAGUE NAME WHEN NOT NEEDED ANYMORE (AFTER 2.1.4 MIRGRATION)
labcontrol_data_directory=/usr/local/share/labcontrol
labcontrol_data_directory=/usr/local/share/labcontrol
# Path to your latex binary
latex_command=/usr/bin/latex
# The default name for locally started zLeaves
local_zLeaf_name=local
local_zLeaf_size=1280x1024
lpr_command=/usr/bin/lpr
netstat_command=/bin/netstat
network_broadcast_address=192.168.1.255
# The URL address of your lab's ORSEE
orsee_url=http://yourORSEEserver.tld
# Path to your dvips binary
dvips_command=/usr/bin/dvips
# Path to your filemanager binary
file_manager=/usr/bin/dolphin
# Path to your ping binary
ping_command=/bin/ping
# The public keys to access the clients
pkey_path_root=/usr/local/share/labcontrol/id_labclient_root
pkey_path_user=/usr/local/share/labcontrol/id_labclient_dsa
# Path to PDF/Postscript viewer binary
postscript_viewer=/usr/bin/okular
# Path to ps2pdf binary
ps2pdf_command=/usr/bin/ps2pdf
# Path to rm binary
rm_command=/bin/rm
# Path to SCP binary
scp_command=/usr/bin/scp
# The IP of the server running zTree
server_ip=192.168.1.200
# The browser in which ORSEE shall be displayed
browser_command=/usr/bin/firefox
# Path to wmctrl binary
ssh_command=/usr/bin/ssh
# Path to taskset binary
taskset_command=/usr/bin/taskset
terminal_emulator_command=/usr/bin/konsole
# The name of the user of the clients which is used to conduct experiments
user_name_on_clients=user
# Path to terminal-emulator binary
terminal_emulator_command=/usr/bin/gnome-terminal
# Path to wine binary
wine_command=/usr/bin/wine
# Path to wmctrl binary
wmctrl_command=/usr/bin/wmctrl
# Path to xset binary
xset_command=/usr/bin/xset
# Path to VNC viewer binary
vnc_viewer=/usr/bin/vinagre
# Path to wakeonlan binary
wakeonlan_command=/usr/bin/wakeonlan
# The program used to view the laboratory's webcams
webcam_command=/usr/local/bin/WebcamDisplay
# URLs to available webcams
webcams="webcam_left|webcam_right"
wine_command=/usr/bin/wine
wmctrl_command=/usr/bin/wmctrl
xset_command=/usr/bin/xset
# The folder were all zTree versions are installed (in subfolders matching the scheme zTree_X.Y.Z)
ztree_installation_directory=/opt/z-Leaves
# Script to be called after session crash
restart_crashed_session_script=/home/scripts/start_zTree_after_crash.sh
# Script to be called after session crash
restart_crashed_session_script=/home/scripts/start_zTree_after_crash.sh

@ -93,7 +93,7 @@ Like already mentioned all \emph{z-Tree} and \emph{z-Leaf} versions should be co
The directories in the \texttt{data} directory should be copied to the \emph{zTree installation directory}.
Afterwards place the \texttt{Labcontrol.conf} in a subfolder \texttt{Economic Laboratory} in the place where \emph{QSettings} stores its definitions on your platform (on \emph{Linux} this would be \texttt{/etc/xdg/Economic Laboratory/Labcontrol.conf}) and adjust it to your needs and prerequisites.
Afterwards place the \texttt{Labcontrol.conf} in a subfolder \texttt{Labcontrol} in the place where \emph{QSettings} stores its definitions on your platform (on \emph{Linux} this would be \texttt{/etc/xdg/Labcontrol/Labcontrol.conf}) and adjust it to your needs and prerequisites.
To allow \emph{Labcontrol} to control the clients password-less public-key authentication must be available at least for the experiment user on the clients. For administration this is also required for \texttt{root}. Also all clients should be known by \texttt{ /etc/ssh/ssh\_known\_hosts}. This file must be readable by the users! If this is missing \emph{Labcontrol} will query the user on every connection attempt, which is not user-friendly.

@ -23,8 +23,10 @@
#include "client.h"
#include "settings.h"
#include "lablib.h"
extern std::unique_ptr< lc::Settings > settings;
extern std::unique_ptr< lc::Lablib > lablib;
lc::Client::Client( const QString &argIP, const QString &argMAC, const QString &argName,
unsigned short int argXPosition, unsigned short int argYPosition,
@ -105,22 +107,6 @@ void lc::Client::Boot() {
GotStatusChanged( state_t::BOOTING );
}
void lc::Client::DeactiveScreensaver() {
QStringList arguments;
arguments << "-i" << settings->pkeyPathUser
<< QString{ settings->userNameOnClients + "@" + ip }
<< settings->xsetCmd << "-display" << ":0.0" << "dpms" << "force" << "on";
// Start the process
QProcess deactiveScreensaverProcess;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
deactiveScreensaverProcess.setProcessEnvironment( env );
deactiveScreensaverProcess.startDetached( settings->sshCmd, arguments );
// Output message via the debug messages tab
qDebug() << settings->sshCmd << arguments.join( " " );
}
void lc::Client::GotStatusChanged( state_t argState ) {
if ( ( protectedCycles > 0 ) && ( state == state_t::BOOTING ) && ( argState != state_t::RESPONDING ) ) {
return;
@ -173,22 +159,13 @@ void lc::Client::OpenTerminal( const QString &argCommand, const bool &argOpenAsR
QStringList *arguments = nullptr;
arguments = new QStringList;
if ( !argOpenAsRoot ) {
*arguments << "--title" << name << "-e" <<
QString{ settings->sshCmd + " -i " + settings->pkeyPathUser + " "
*arguments << "-e"
<< QString{ settings->sshCmd + " -i " + settings->pkeyPathUser + " "
+ settings->userNameOnClients + "@" + ip };
} else {
*arguments << "--title" << name << "-e" <<
*arguments << "-e" <<
QString{ settings->sshCmd + " -i " + settings->pkeyPathRoot
+ " " + "root@" + ip };
}
if ( settings->termEmulCmd.contains( "konsole" ) ) {
arguments->prepend( "--new-tab" );
arguments->prepend( "--show-tabbar" );
} else {
if ( settings->termEmulCmd.contains( "gnome-terminal" ) ) {
arguments->prepend( "--tab" );
}
+ " " + "root@" + ip};
}
if ( !argCommand.isEmpty() ) {
@ -224,7 +201,7 @@ void lc::Client::SetStateToZLEAF_RUNNING( QString argClientIP ) {
}
}
void lc::Client::ShowDesktop() {
void lc::Client::ShowDesktopViewOnly() {
QStringList arguments;
arguments << ip;
@ -237,6 +214,19 @@ void lc::Client::ShowDesktop() {
qDebug() << settings->vncViewer << arguments.join( " " );
}
void lc::Client::ShowDesktopFullControl() {
QStringList arguments;
arguments << ip + ":5901";
QProcess showDesktopProcess;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
showDesktopProcess.setProcessEnvironment( env );
showDesktopProcess.startDetached( settings->vncViewer, arguments );
// Output message via the debug messages tab
qDebug() << settings->vncViewer << arguments.join( " " );
}
void lc::Client::Shutdown() {
if ( state == state_t::NOT_RESPONDING || state == state_t::BOOTING
|| state == state_t::SHUTTING_DOWN ) {
@ -262,7 +252,7 @@ void lc::Client::Shutdown() {
GotStatusChanged( state_t::SHUTTING_DOWN );
}
void lc::Client::StartZLeaf( const QString * const argFakeName ) {
void lc::Client::StartZLeaf( const QString * argFakeName, QString cmd ) {
if ( state < state_t::RESPONDING || zLeafVersion.isEmpty() || GetSessionPort() < 7000 ) {
return;
}
@ -281,32 +271,18 @@ void lc::Client::StartZLeaf( const QString * const argFakeName ) {
if ( ( messageBoxRunningZLeafFound.get() != nullptr
&& messageBoxRunningZLeafFound->clickedButton()
== messageBoxRunningZLeafFound->button( QMessageBox::Yes ) )
== messageBoxRunningZLeafFound->button( QMessageBox::Yes ) )
|| state != state_t::ZLEAF_RUNNING ) {
QStringList arguments;
if ( argFakeName == nullptr && GetSessionPort() == 7000 ) {
if ( argFakeName == nullptr ) {
arguments << "-i" << settings->pkeyPathUser
<< QString{ settings->userNameOnClients + "@" + ip }
<< "DISPLAY=:0.0" << settings->tasksetCmd << "0x00000001" << settings->wineCmd
<< QString{ settings->zTreeInstDir + "/zTree_" + GetzLeafVersion() + "/zleaf.exe" }
<< "/server" << settings->serverIP;
<< cmd;
} else {
if ( argFakeName == nullptr ) {
arguments << "-i" << settings->pkeyPathUser
<< QString{ settings->userNameOnClients + "@" + ip }
<< "DISPLAY=:0.0" << settings->tasksetCmd << "0x00000001" << settings->wineCmd
<< QString{ settings->zTreeInstDir + "/zTree_" + GetzLeafVersion() + "/zleaf.exe" }
<< "/server" << settings->serverIP << "/channel"
<< QString::number( GetSessionPort() - 7000 );
} else {
arguments << "-i" << settings->pkeyPathUser
<< QString{ settings->userNameOnClients + "@" + ip }
<< "DISPLAY=:0.0" << settings->tasksetCmd << "0x00000001" << settings->wineCmd
<< QString{ settings->zTreeInstDir + "/zTree_" + GetzLeafVersion() + "/zleaf.exe" }
<< "/server" << settings->serverIP << "/channel"
<< QString::number( GetSessionPort() - 7000 )
<< "/name" << *argFakeName;
}
arguments << "-i" << settings->pkeyPathUser
<< QString{ settings->userNameOnClients + "@" + ip }
<< cmd
<< "/name" << *argFakeName;
}
// Start the process
@ -319,3 +295,50 @@ void lc::Client::StartZLeaf( const QString * const argFakeName ) {
qDebug() << settings->sshCmd << arguments.join( " " );
}
}
void lc::Client::StartClientBrowser( const QString * const argURL, const bool * const argFullscreen ) {
//Declarations
QStringList arguments;
// Build arguments list for SSH command
arguments << "-i" << settings->pkeyPathUser
<< QString{ settings->userNameOnClients + "@" + ip }
<< "DISPLAY=:0.0"
<< settings->clientBrowserCmd
<< *argURL;
// Add fullscreen toggle if checked
if (*argFullscreen == true){
arguments << "& sleep 3 && DISPLAY=:0.0 xdotool key --clearmodifiers F11";
}
// Start the process
QProcess startClientBrowserProcess;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
startClientBrowserProcess.setProcessEnvironment( env );
startClientBrowserProcess.startDetached( settings->sshCmd, arguments );
// Output message via the debug messages tab
qDebug() << settings->sshCmd << arguments.join( " " );
}
void lc::Client::StopClientBrowser() {
//Declarations
QStringList arguments;
//Build arguments list
arguments << "-i" << settings->pkeyPathUser
<< QString{ settings->userNameOnClients + "@" + ip }
<< "killall"
<< settings->clientBrowserCmd
<< "& sleep 1 && rm -R /home/ewfuser/.mozilla/firefox/*";
// Start the process
QProcess startClientBrowserProcess;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
startClientBrowserProcess.setProcessEnvironment( env );
startClientBrowserProcess.startDetached( settings->sshCmd, arguments );
// Output message via the debug messages tab
qDebug() << settings->sshCmd << arguments.join( " " );
}

@ -96,23 +96,36 @@ public:
void OpenFilesystem( const QString * const argUserToBeUsed );
/*!
* \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 (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 SetSessionPort( int argSP ) { sessionPort = argSP; }
void SetzLeafVersion( const QString &argzLeafV ) { zLeafVersion = argzLeafV; }
//! Shows the desktop of the given client
void ShowDesktop();
void ShowDesktopViewOnly();
void ShowDesktopFullControl();
/*!
* \brief Shuts down the client
*/
void Shutdown();
//! 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)
*/
void StartZLeaf(const QString *argFakeName = nullptr, QString cmd = "" );
/*!
* \brief Opens a browser window on the client
* @param argURL URL to open in clients browser
*/
void StartClientBrowser( const QString *argURL = nullptr, const bool *argFullscreen = nullptr );
/*!
@param argFakeName The name the zLeaf instance shall have (if not the default, which is the hostname of the client)
* \brief Closes all browser instances
*/
void StartZLeaf( const QString * const argFakeName = nullptr );
void StopClientBrowser();
private:
const QString &GetzLeafVersion() const { return zLeafVersion; }

@ -26,7 +26,7 @@
lc::Lablib::Lablib( QObject *argParent ) :
QObject{ argParent },
labSettings{ "Economic Laboratory", "Labcontrol", this },
labSettings{ "Labcontrol", "Labcontrol", this },
sessionsModel{ new SessionsModel{ this } }
{
for ( const auto &s : settings->GetClients() ) {
@ -107,7 +107,7 @@ void lc::Lablib::ShowPreprints() {
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
showPreprintsProcess.setProcessEnvironment( env );
QString program{ settings->fileMngr };
QStringList arguments{ QStringList{} << settings->lcInstDir + "/preprints" };
QStringList arguments{ QStringList{} << settings->lcDataDir + "/preprints" };
showPreprintsProcess.startDetached( program, arguments );
// Output message via the debug messages tab
@ -167,3 +167,21 @@ void lc::Lablib::SetLocalZLeafDefaultName( const QString &argName ) {
settings->SetLocalzLeafName( argName );
labSettings.setValue( "local_zLeaf_name", argName );
}
//Returns the commandline that is issued on the client when zleaf is started
QStringList lc::Lablib::getzLeafArgs( int sessionPort, QString zleafVersion ){
QStringList arguments;
if ( sessionPort == 7000 ) {
arguments << "DISPLAY=:0.0" << settings->tasksetCmd << "0x00000001" << settings->wineCmd
<< QString{ settings->zTreeInstDir + "/zTree_" + zleafVersion + "/zleaf.exe" }
<< "/server" << settings->serverIP;
} else {
arguments << "DISPLAY=:0.0" << settings->tasksetCmd << "0x00000001" << settings->wineCmd
<< QString{ settings->zTreeInstDir + "/zTree_" + zleafVersion + "/zleaf.exe" }
<< "/server" << settings->serverIP << "/channel"
<< QString::number( sessionPort- 7000 );
}
//Return the crafted QStringList
return arguments;
}

@ -88,13 +88,21 @@ public:
void SetLocalZLeafDefaultName( const QString &argName );
void ShowOrsee();
void ShowPreprints();
public slots:
void StartNewSession( QVector< Client* > argAssocCl, QString argParticipNameReplacement,
bool argPrintLocalReceipts, QString argReceiptsHeader,
QString argzTreeDataTargetPath, quint16 argzTreePort,
QString argzTreeVersion );
/*!
* \brief Returns the commandline to issue on the client(s) in order to start zLeaf
* @param sessionPort The port zLeaf shall connect to
* @param zLeafVersion zLeaf Version to start
*/
QStringList getzLeafArgs( int sessionPort, QString zleafVersion );
public slots:
signals:
void ZLEAF_RUNNING( QString argClientIP );

@ -255,11 +255,11 @@ QVector<QString> *lc::ReceiptsHandler::GetParticipantsDataFromPaymentFile() {
QString *lc::ReceiptsHandler::LoadLatexHeader() {
// Prepare all facilities to read the latex header file
QFile latexHeaderFile( settings->lcInstDir + "/" + latexHeaderName + "_header.tex" );
QFile latexHeaderFile( settings->lcDataDir + "/" + latexHeaderName + "_header.tex" );
if ( !latexHeaderFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) {
QMessageBox messageBox{ QMessageBox::Critical, tr( "LaTeX header could not be loaded" ),
tr( "The LaTeX header at '%1/%2_header.tex' could not be loaded. Receipts printing will not work." )
.arg( settings->lcInstDir ).arg( latexHeaderName ), QMessageBox::Ok };
.arg( settings->lcDataDir ).arg( latexHeaderName ), QMessageBox::Ok };
messageBox.exec();
return nullptr;
}

@ -31,6 +31,9 @@ lc::Settings::Settings( const QSettings &argSettings, QObject *argParent ) :
browserCmd{ ReadSettingsItem( "browser_command",
"Opening ORSEE in a browser will not work.",
argSettings, true ) },
clientBrowserCmd{ ReadSettingsItem( "client_browser_command",
"Opening a browser window on clients will not work.",
argSettings, false ) },
dvipsCmd{ ReadSettingsItem( "dvips_command",
"Receipts creation will not work.",
argSettings, true ) },
@ -43,8 +46,8 @@ lc::Settings::Settings( const QSettings &argSettings, QObject *argParent ) :
latexCmd{ ReadSettingsItem( "latex_command",
"Receipts creation will not work.",
argSettings, true ) },
lcInstDir{ ReadSettingsItem( "labcontrol_installation_directory",
"Labcontrol will missbehave with high propability.",
lcDataDir{ ReadSettingsItem( "labcontrol_data_directory",
"Datapath not set. Labcontrol will missbehave with high propability.",
argSettings, true ) },
localUserName{ GetLocalUserName() },
localzLeafSize{ ReadSettingsItem( "local_zLeaf_size",
@ -109,6 +112,8 @@ lc::Settings::Settings( const QSettings &argSettings, QObject *argParent ) :
argSettings, true ) },
webcams{ argSettings.value( "webcams", "" ).toString().split( '|', QString::SkipEmptyParts,
Qt::CaseInsensitive ) },
webcams_names{ argSettings.value( "webcams_names", "" ).toString().split( '|', QString::SkipEmptyParts,
Qt::CaseInsensitive ) },
wineCmd{ ReadSettingsItem( "wine_command",
"Running z-Leaves or z-Tree will be possible.",
argSettings, true ) },
@ -258,12 +263,12 @@ QMap< QString, lc::Client* > lc::Settings::CreateClIPsToClMap( const QVector< Cl
QStringList lc::Settings::DetectInstalledLaTeXHeaders() const {
QStringList tempLaTeXHeaders{ "None found" };
// Detect the installed LaTeX headers
if ( !lcInstDir.isEmpty() ) {
QDir laTeXDirectory{ lcInstDir, "*_header.tex", QDir::Name,
if ( !lcDataDir.isEmpty() ) {
QDir laTeXDirectory{ lcDataDir, "*_header.tex", QDir::Name,
QDir::CaseSensitive | QDir::Files | QDir::Readable };
if ( !laTeXDirectory.exists() || laTeXDirectory.entryList().isEmpty() ) {
qDebug() << "Receipts printing will not work. No LaTeX headers could be found in"
<< lcInstDir;
<< lcDataDir;
} else {
tempLaTeXHeaders = laTeXDirectory.entryList();
tempLaTeXHeaders.replaceInStrings( "_header.tex", "" );
@ -375,3 +380,12 @@ QString lc::Settings::ReadSettingsItem( const QString &argVariableName,
}
return QString{};
}
void lc::Settings::SetLocalzLeafSize( QString arg) {
localzLeafSize = arg;
}
void lc::Settings::SetChosenZTreePort( const int argPort ){
chosenzTreePort = argPort;
}

@ -48,13 +48,16 @@ public:
const int defaultReceiptIndex = 0;
const QString browserCmd;
const QString clientBrowserCmd;
const QString dvipsCmd;
const QString fileMngr;
const QString killallCmd;
const QString latexCmd;
const QString lcInstDir;
const QString lcDataDir;
const QString localUserName;
const QString localzLeafSize;
QString localzLeafSize;
void SetLocalzLeafSize( QString arg);
QString GetLocalzLeafSize() const { return localzLeafSize; }
const QString lprCmd;
const QString netstatCmd;
const QString netwBrdAddr;
@ -75,6 +78,7 @@ public:
const QString wakeonlanCmd;
const QString webcamDisplayCmd;
const QStringList webcams;
const QStringList webcams_names;
const QString wineCmd;
const QString wmctrlCmd;
const QString xsetCmd;
@ -117,11 +121,6 @@ inline QString lc::Settings::GetLocalzLeafName() const {
return localzLeafName;
}
inline void lc::Settings::SetChosenZTreePort( const int argPort ) {
chosenzTreePort = argPort;
qDebug() << "'chosenZTreePort' set to:" << chosenzTreePort;
}
inline void lc::Settings::SetLocalzLeafName( const QString &argLocalzLeafName ) {
localzLeafName = argLocalzLeafName;
}

@ -33,10 +33,15 @@ lc::LocalzLeafStarter::LocalzLeafStarter( QWidget *argParent ) :
{
ui->setupUi( this );
//Choose initial port from settings
if ( settings->GetChosenZTreePort() ) {
ui->SBzLeafPort->setValue( settings->GetChosenZTreePort() );
}
//Choose initial z-Leave size from settings
ui->LELocalzLeafSize->setText( settings->GetLocalzLeafSize() );
ui->CBzLeafVersion->addItem( tr( "Please choose a version" ) );
if ( !settings->installedZTreeVersions.isEmpty() ) {
ui->CBzLeafVersion->addItems( settings->installedZTreeVersions );
@ -55,6 +60,10 @@ void lc::LocalzLeafStarter::on_PBStartLocalzLeaf_clicked() {
return;
}
//Set chosen z-Leaf size
settings->SetLocalzLeafSize( ui->LELocalzLeafSize->text() );
//Emit start local z-Leaf request to main window
emit LocalzLeafRequested( ui->LEzLeafName->text(), ui->CBzLeafVersion->currentText(),
ui->SBzLeafPort->value() );
}

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>352</width>
<width>371</width>
<height>352</height>
</rect>
</property>
@ -20,7 +20,7 @@
<string>This sets the name with which this local z-Leaf will connect to z-Tree.</string>
</property>
<property name="text">
<string>Set the name of the to be started z-Leaf:</string>
<string>Set the name of the to be started z-Leaf</string>
</property>
</widget>
</item>
@ -30,7 +30,7 @@
<string>This sets the name with which this local z-Leaf will connect to z-Tree.</string>
</property>
<property name="styleSheet">
<string notr="true">background: cyan;</string>
<string notr="true"/>
</property>
<property name="text">
<string>local</string>
@ -43,7 +43,7 @@
<string>Choose of which version the started z-Leaf shall be.</string>
</property>
<property name="text">
<string>Choose the version of the to be started z-Leaf:</string>
<string>Choose the version of the to be started z-Leaf</string>
</property>
</widget>
</item>
@ -53,7 +53,7 @@
<string>Choose of which version the started z-Leaf shall be.</string>
</property>
<property name="styleSheet">
<string notr="true">background: cyan;</string>
<string notr="true"/>
</property>
<property name="maxVisibleItems">
<number>32</number>
@ -66,17 +66,20 @@
<string>Set the port on which the z-Tree which shall be connected to listens.</string>
</property>
<property name="text">
<string>Choose the port the to be started z-Leaf shall listen on:</string>
<string>Choose the port the to be started z-Leaf shall listen on</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="SBzLeafPort">
<property name="cursor">
<cursorShape>ArrowCursor</cursorShape>
</property>
<property name="toolTip">
<string>Set the port on which the z-Tree which shall be connected to listens.</string>
</property>
<property name="styleSheet">
<string notr="true">background: cyan;</string>
<string notr="true"/>
</property>
<property name="minimum">
<number>7000</number>
@ -89,6 +92,23 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="LLocalzLeafSize">
<property name="text">
<string>Choose the size the local z-Leaf shall have</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="LELocalzLeafSize"/>
</item>
<item>
<widget class="Line" name="line_Start">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="PBStartLocalzLeaf">
<property name="toolTip">

@ -28,7 +28,7 @@ std::unique_ptr< lc::Settings > settings;
int main( int argc, char *argv[] ) {
QApplication a{ argc, argv };
settings.reset( new lc::Settings{ QSettings{ "Economic Laboratory", "Labcontrol" } } );
settings.reset( new lc::Settings{ QSettings{ "Labcontrol", "Labcontrol" } } );
lc::MainWindow w;
w.show();

@ -47,6 +47,37 @@ lc::MainWindow::MainWindow( QWidget *argParent ) :
this, &MainWindow::UpdateClientsTableView );
gui_update_timer->start( 500 );
}
/* session actions */
// Add z-Tree versions to the corresponding combo box
ui->CBzTreeVersion->addItem( tr( "Please choose a version:" ) );
ui->CBzTreeVersion->addItems( settings->installedZTreeVersions );
// Add default path to the corresponding combo box
ui->CBDataTargetPath->addItem( tr( "Set a new path HERE" ) );
ui->CBDataTargetPath->addItem( QDir::homePath() );
ui->CBDataTargetPath->addItem( QDir::homePath() + "/zTreeData" );
ui->CBDataTargetPath->setCurrentIndex( 2 );
connect( this, &MainWindow::RequestNewDataTargetPath,
this, &MainWindow::GetNewDataTargetPath );
if ( settings->dvipsCmd.isEmpty() || settings->latexCmd.isEmpty()
|| settings->lcDataDir.isEmpty() || settings->lprCmd.isEmpty()
|| settings->postscriptViewer.isEmpty() || settings->ps2pdfCmd.isEmpty()
|| settings->rmCmd.isEmpty() || settings->vncViewer.isEmpty() ) {
QMessageBox::information( this, tr( "Receipts printing will not work" ),
tr( "Some component essential for receipts creation and"
" printing is missing. No receipts will be created or"
" printed." ), QMessageBox::Ok );
} else {
ui->CBReceiptsHeader->addItems( settings->installedLaTeXHeaders );
if ( settings->defaultReceiptIndex
&& settings->defaultReceiptIndex < ui->CBReceiptsHeader->count() ) {
ui->CBReceiptsHeader->setCurrentIndex( settings->defaultReceiptIndex );
}
}
}
lc::MainWindow::~MainWindow() {
@ -71,20 +102,29 @@ bool lc::MainWindow::CheckIfUserIsAdmin() {
}
void lc::MainWindow::DisableDisfunctionalWidgets() {
const QStringList &zTreeEntries = settings->installedZTreeVersions;
if ( zTreeEntries.isEmpty() ) {
ui->CBClientNames->setEnabled( false );
//ui->GBzTree->setEnabled( false );
ui->L_FakeName->setEnabled( false );
ui->PBRunzLeaf->setEnabled( false );
ui->PBStartLocalzLeaf->setEnabled( false );
ui->PBStartzLeaf->setEnabled( false );
}
// Disable all z-Leaf killing related buttons if the 'killall' command is not available
if ( settings->killallCmd.isEmpty() ) {
ui->PBKillLocalzLeaf->setEnabled( false );
ui->PBKillzLeaf->setEnabled( false );
}
// Disable all functions relying on the labcontrol installation directory if it is not available
if ( settings->lcInstDir.isEmpty() ) {
if ( settings->lcDataDir.isEmpty() ) {
ui->CBClientNames->setEnabled( false );
ui->CBWebcamChooser->setEnabled( false );
ui->GBClientActions->setEnabled( false );
ui->GBzTree->setEnabled( false );
ui->LEFilePath->setEnabled( false );
ui->LFakeName->setEnabled( false );
ui->LWebcamChooser->setEnabled( false );
ui->L_FakeName->setEnabled( false );
ui->L_WebcamChooser->setEnabled( false );
ui->PBBeamFile->setEnabled( false );
ui->PBChooseFile->setEnabled( false );
ui->PBKillLocalzLeaf->setEnabled( false );
@ -114,10 +154,9 @@ void lc::MainWindow::DisableDisfunctionalWidgets() {
|| settings->userNameOnClients.isEmpty() ) {
ui->CBClientNames->setEnabled( false );
ui->LEFilePath->setEnabled( false );
ui->LFakeName->setEnabled( false );
ui->L_FakeName->setEnabled( false );
ui->PBBeamFile->setEnabled( false );
ui->PBChooseFile->setEnabled( false );
ui->PBDeactivateScreensaver->setEnabled( false );
ui->PBKillzLeaf->setEnabled( false );
ui->PBRunzLeaf->setEnabled( false );
ui->PBShutdown->setEnabled( false );
@ -156,7 +195,7 @@ void lc::MainWindow::DisableDisfunctionalWidgets() {
if ( settings->sshCmd.isEmpty() ) {
ui->CBClientNames->setEnabled( false );
ui->GBClientActions->setEnabled( false );
ui->LFakeName->setEnabled( false );
ui->L_FakeName->setEnabled( false );
ui->LEFilePath->setEnabled( false );
ui->PBBeamFile->setEnabled( false );
ui->PBChooseFile->setEnabled( false );
@ -169,7 +208,7 @@ void lc::MainWindow::DisableDisfunctionalWidgets() {
if ( settings->tasksetCmd.isEmpty() ) {
ui->CBClientNames->setEnabled( false );
ui->LFakeName->setEnabled( false );
ui->L_FakeName->setEnabled( false );
ui->PBRunzLeaf->setEnabled( false );
ui->PBStartSession->setEnabled( false );
ui->PBStartLocalzLeaf->setEnabled( false );
@ -184,7 +223,8 @@ void lc::MainWindow::DisableDisfunctionalWidgets() {
// Disable 'PBViewDesktop' if 'vnc_viewer' was not set
if ( settings->vncViewer.isEmpty() ) {
ui->PBViewDesktop->setEnabled( false );
ui->PBViewDesktopViewOnly->setEnabled( false );
ui->PBViewDesktopFullControl->setEnabled( false );
}
// Disable 'PBBoot' if 'wakeonlan_command' was not set
@ -196,26 +236,21 @@ void lc::MainWindow::DisableDisfunctionalWidgets() {
if ( settings->webcamDisplayCmd.isEmpty()
|| settings->webcams.isEmpty() ) {
ui->CBWebcamChooser->setEnabled( false );
ui->LWebcamChooser->setEnabled( false );
ui->L_WebcamChooser->setEnabled( false );
}
if ( settings->wineCmd.isEmpty() ) {
ui->CBClientNames->setEnabled( false );
ui->LFakeName->setEnabled( false );
ui->L_FakeName->setEnabled( false );
ui->PBRunzLeaf->setEnabled( false );
ui->PBStartSession->setEnabled( false );
//ui->PBStartSession->setEnabled( false );
ui->PBStartLocalzLeaf->setEnabled( false );
ui->PBStartzLeaf->setEnabled( false );
}
// Disable the disable screensaver function if the 'xset_command' was not set
if ( settings->xsetCmd.isEmpty() ) {
ui->PBDeactivateScreensaver->setEnabled( false );
}
if ( settings->zTreeInstDir.isEmpty() ) {
ui->CBClientNames->setEnabled( false );
ui->LFakeName->setEnabled( false );
ui->L_FakeName->setEnabled( false );
ui->PBRunzLeaf->setEnabled( false );
ui->PBStartSession->setEnabled( false );
ui->PBStartLocalzLeaf->setEnabled( false );
@ -224,7 +259,7 @@ void lc::MainWindow::DisableDisfunctionalWidgets() {
}
void lc::MainWindow::LoadIconPixmaps() {
if ( settings->lcInstDir.isEmpty() ) {
if ( settings->lcDataDir.isEmpty() ) {
return;
}
@ -237,122 +272,10 @@ void lc::MainWindow::LoadIconPixmaps() {
<< "zLeaf.png" };
for ( int i = 0; i < ( int )icons_t::ICON_QUANTITY; i++ ) {
if ( !icons[ i ].load( settings->lcInstDir + "/icons/" + iconNames[ i ] ) ) {
if ( !icons[ i ].load( settings->lcDataDir + "/icons/" + 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." )
.arg( settings->lcInstDir ).arg( iconNames[ i ] ), QMessageBox::Ok );
}
}
}
void lc::MainWindow::on_CBWebcamChooser_activated( int argIndex ) {
if ( argIndex != 0 ) {
QString program{ settings->webcamDisplayCmd };
QStringList arguments;
arguments << ui->CBWebcamChooser->currentText();
QProcess showWebcamProcess;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
showWebcamProcess.setProcessEnvironment( env );
showWebcamProcess.startDetached( program, arguments );
}
}
void lc::MainWindow::on_PBBeamFile_clicked() {
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes();
const QString fileToBeam{ ui->LEFilePath->text() };
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->BeamFile( fileToBeam, &settings->pkeyPathUser, &settings->userNameOnClients );
}
}
}
void lc::MainWindow::on_PBBoot_clicked() {
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->Boot();
}
}
}
void lc::MainWindow::on_PBChooseFile_clicked() {
QFileDialog *file_dialog = new QFileDialog{ this, tr( "Choose a file to beam" ), QDir::homePath() };
file_dialog->setFileMode( QFileDialog::Directory );
file_dialog->setOption( QFileDialog::DontUseNativeDialog, true );
file_dialog->setOption( QFileDialog::ReadOnly, true );
file_dialog->setOption( QFileDialog::ShowDirsOnly, true );
if(file_dialog->exec()) {
ui->LEFilePath->setText(file_dialog->selectedFiles().at(0));
qDebug() << "Chose file" << ui->LEFilePath->text() << "for beaming.";
}
else {
ui->LEFilePath->setText( tr( "File choosing cancelled" ) );
qDebug() << "File choosing cancelled";
}
delete file_dialog;
}
void lc::MainWindow::on_PBDeactivateScreensaver_clicked() {
for ( auto s : settings->GetClients() ) {
if ( s->GetClientState() >= state_t::RESPONDING )
s->DeactiveScreensaver();
}
}
void lc::MainWindow::on_PBExecute_clicked() {
// This will be set to false, if the command shall be executed only on the chosen clients (that's if not all clients are up)
bool executeOnEveryClient = true;
// Cancel, if not all clients are up and running
for ( auto s: settings->GetClients() ) {
if ( !( s->name.contains( "backup", Qt::CaseInsensitive ) ) ) {
if ( s->GetClientState() < state_t::RESPONDING ) {
QMessageBox messageBox{ QMessageBox::Warning, tr( "Not all clients are running" ),
tr( "Not all clients are running. The command could not be executed on every client and should therefore be canceled to keep the clients consistent.\n\nAre you sure you want to continue only with the currently chosen clients?" ), QMessageBox::No | QMessageBox::Yes, this };
messageBox.setDefaultButton( QMessageBox::No );
messageBox.exec();
executeOnEveryClient = false;
if ( messageBox.clickedButton() == messageBox.button( QMessageBox::No ) ) {
return;
} else {
break;
}
}
}
}
// Get the command to be executed ...
QString command = ui->CBCommandToExecute->currentText();
// Set the correct public key
QString pkeyPathUser;
if ( ui->RBUseUserRoot->isChecked() ) {
pkeyPathUser = settings->pkeyPathRoot;
} else {
pkeyPathUser = settings->pkeyPathUser;
}
// and execute it
if ( executeOnEveryClient ) {
qDebug() << "Executing command" << command << "on every client.";
for ( auto s: settings->GetClients() ) {
if ( !( s->name.contains( "backup", Qt::CaseInsensitive ) ) ) {
s->OpenTerminal( command, ui->RBUseUserRoot->isChecked() );
}
}
} else {
qDebug() << "Executing command" << command << "only on chosen clients.";
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->OpenTerminal( command, ui->RBUseUserRoot->isChecked() );
}
.arg( settings->lcDataDir ).arg( iconNames[ i ] ), QMessageBox::Ok );
}
}
}
@ -374,51 +297,6 @@ void lc::MainWindow::on_PBKillLocalzLeaf_clicked() {
qDebug() << program << arguments;
}
void lc::MainWindow::on_PBKillzLeaf_clicked() {
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->KillZLeaf();
}
}
}
void lc::MainWindow::on_PBOpenFilesystem_clicked() {
// Determine the correct user to be used
QString * userToBeUsed = nullptr;
if ( ui->RBUseUserRoot->isChecked() ) {
userToBeUsed = new QString{ "root" };
} else {
userToBeUsed = new QString{ settings->userNameOnClients };
}
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->OpenFilesystem( userToBeUsed );
}
}
delete userToBeUsed;
}
void lc::MainWindow::on_PBOpenTerminal_clicked() {
QString pkeyPathUser;
if ( ui->RBUseUserRoot->isChecked() ) {
pkeyPathUser = settings->pkeyPathRoot;
} else {
pkeyPathUser = settings->pkeyPathUser;
}
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->OpenTerminal( QString{}, ui->RBUseUserRoot->isChecked() );
}
}
}
void lc::MainWindow::on_PBPrintPaymentFileManually_clicked() {
ManualPrintingSetup *manPrint = new ManualPrintingSetup{ this };
manPrint->setWindowFlags( Qt::Window );
@ -454,107 +332,6 @@ void lc::MainWindow::on_PBRunzLeaf_clicked() {
}
}
void lc::MainWindow::on_PBShowORSEE_clicked() {
lablib->ShowOrsee();
}
void lc::MainWindow::on_PBShowPreprints_clicked() {
lablib->ShowPreprints();
}
void lc::MainWindow::on_PBShowSessions_clicked() {
QWidget *sessionDisplay = new SessionDisplay{ lablib->GetSessionsModel(), this };
sessionDisplay->setWindowFlags( Qt::Window );
sessionDisplay->show();
connect( sessionDisplay, &SessionDisplay::destroyed,
sessionDisplay, &SessionDisplay::deleteLater );
}
void lc::MainWindow::on_PBShutdown_clicked() {
// Confirmation dialog
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Confirm", "Really shutdown the selected clients?", QMessageBox::Yes|QMessageBox::No);
if (reply == QMessageBox::Yes) {
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
// Do not shut down the server itself
if ( client->name == "self"){
QMessageBox::information(NULL, "Shutdown canceled", "It is not allowed to shutdown the server itself via labcontrol!");
} else {
client->Shutdown();
}
}
}
} else {
qDebug() << "Canceled shutting down the selected clients";
}
}
void lc::MainWindow::on_PBStartLocalzLeaf_clicked() {
LocalzLeafStarter *localzLeafStarter = new LocalzLeafStarter{ this };
localzLeafStarter->setWindowFlags( Qt::Window );
localzLeafStarter->show();
connect( localzLeafStarter, &LocalzLeafStarter::LocalzLeafRequested,
this, &MainWindow::StartLocalzLeaf );
connect( localzLeafStarter, SIGNAL( LocalzLeafRequested( QString, QString, int ) ),
localzLeafStarter, SLOT( deleteLater() ) );
}
void lc::MainWindow::on_PBStartSession_clicked() {
SessionStarter *sessionStarter = new SessionStarter{ lablib->GetOccupiedPorts(), this };
sessionStarter->setWindowFlags( Qt::Window );
sessionStarter->show();
connect( sessionStarter, &SessionStarter::RequestNewSession,
lablib, &Lablib::StartNewSession );
connect( sessionStarter, &SessionStarter::destroyed,
sessionStarter, &SessionStarter::deleteLater );
// // Show an error message, if no zTree version was chosen yet
// if (ui->CBzTreeVersion->currentIndex() == 0) {
// QMessageBox messageBox{ QMessageBox::Warning, tr("Unset zTree version"), tr("There is no zTree version chosen yet. Please choose one."), QMessageBox::Ok, this };
// messageBox.exec();
// return;
// }
// // Ask a second time, if no valid LaTeX header was set
// if (ui->CBReceiptsHeader->currentText() == "None found") {
// QMessageBox messageBox{ QMessageBox::Information, tr("No valid LaTeX header chosen"),
// tr("No valid LaTeX header was chosen. Receipts creation and printing will not work. Shall a new zTree instance be started nonetheless?"), QMessageBox::Yes | QMessageBox::No, this };
// messageBox.exec();
// if (messageBox.clickedButton() == messageBox.button(QMessageBox::No))
// return;
// }
// ui->CBDataTargetPath->setStyleSheet( "" );
// ui->CBPrintanonymousreceipts->setStyleSheet( "" );
// ui->CBReceiptsHeader->setStyleSheet( "" );
// ui->CBReceiptsforLocalClients->setStyleSheet( "" );
// ui->SBPort->setStyleSheet( "" );
// lablib->StartNewZTreeInstance();
}
void lc::MainWindow::on_PBStartzLeaf_clicked() {
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->StartZLeaf( nullptr );
}
}
}
void lc::MainWindow::on_PBViewDesktop_clicked() {
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->ShowDesktop();
}
}
}
void lc::MainWindow::on_RBUseLocalUser_toggled(bool checked) {
if ( checked ) {
qDebug() << "'RBUseLocalUser' got toggled.";
@ -593,12 +370,12 @@ void lc::MainWindow::SetupWidgets() {
valid_items->squeeze();
} else {
QMessageBox messageBox{ QMessageBox::Warning, tr( "Could not construct clients view" ),
tr( "The creation of the clients view failed. Please check the file '/etc/xdg/Economic Laboratory/Labcontrol.conf'." ), QMessageBox::Ok, this };
tr( "The creation of the clients view failed. Please check the file '/etc/xdg/Labcontrol/Labcontrol.conf'." ), QMessageBox::Ok, this };
messageBox.exec();
ui->CBClientNames->setEnabled( false );
ui->GBClientActions->setEnabled( false );
ui->LEFilePath->setEnabled( false );
ui->LFakeName->setEnabled( false );
ui->L_FakeName->setEnabled( false );
ui->PBBeamFile->setEnabled( false );
ui->PBChooseFile->setEnabled( false );
ui->PBRunzLeaf->setEnabled( false );
@ -608,28 +385,18 @@ void lc::MainWindow::SetupWidgets() {
// Fill the 'CBWebcamChooser' with all available network webcams
if ( !settings->webcams.isEmpty() ) {
for ( const auto &s : settings->webcams )
for ( const auto &s : settings->webcams_names )
ui->CBWebcamChooser->addItem( s );
}
const QStringList &zTreeEntries = settings->installedZTreeVersions;
if ( zTreeEntries.isEmpty() ) {
ui->CBClientNames->setEnabled( false );
ui->GBzTree->setEnabled( false );
ui->LFakeName->setEnabled( false );
ui->PBRunzLeaf->setEnabled( false );
ui->PBStartLocalzLeaf->setEnabled( false );
ui->PBStartzLeaf->setEnabled( false );
}
// Disable the admin tab if the user has no administrative rights and set it up
if ( CheckIfUserIsAdmin() ) {
ui->TAdminActions->setEnabled( true );
ui->LAdministrativeRights->setText( tr( "You have administrative rights." ) );
ui->L_AdministrativeRights->setText( tr( "You have administrative rights." ) );
} else {
ui->LAdministrativeRights->setText( tr( "You don't have administrative rights." ) );
ui->L_AdministrativeRights->setText( tr( "You don't have administrative rights." ) );
}
ui->LUserName->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() ) {
ui->RBUseLocalUser->setText( settings->userNameOnClients );
} else {
@ -654,10 +421,16 @@ void lc::MainWindow::SetupWidgets() {
<< "apt full-upgrade -y" << "reboot" << "uname -a" );
}
DisableDisfunctionalWidgets();
// Disable buttons which are not configured
//DisableDisfunctionalWidgets();
// Set the info text in LInfo on the TInfo tab
ui->LInfo->setText( "This is Labcontrol.\n\nCopyright 2014-2016 Markus Prasser\n\n\n"
ui->LInfo->setText( "This is Labcontrol version 2.1.5\n\n\n\n\n\n"
"Developers\n\n"
"0day-2016 Henning Prömpers\n"
"2014-2016 Markus Prasser\n"
"2016 - now WiwilabHiwiOrgaization\n\n\n"
"Copyright\n\n"
"Labcontrol is free software: you can redistribute it and/or modify\n"
"it under the terms of the GNU General Public License as published by\n"
"the Free Software Foundation, either version 3 of the License, or\n"
@ -670,27 +443,6 @@ void lc::MainWindow::SetupWidgets() {
"along with Labcontrol. If not, see <http://www.gnu.org/licenses/>.\n\n\n" );
}
void lc::MainWindow::StartLocalzLeaf( QString argzLeafName, QString argzLeafVersion,
int argzTreePort ) {
if ( settings->tasksetCmd.isEmpty() || settings->wineCmd.isEmpty()
|| settings->zTreeInstDir.isEmpty() ) {
return;
}
QProcess startProc;
startProc.setProcessEnvironment( QProcessEnvironment::systemEnvironment() );
QStringList arguments;
arguments << "0x00000001" << settings->wineCmd
<< QString{ settings->zTreeInstDir + "/zTree_" + argzLeafVersion + "/zleaf.exe" }
<< "/server" << "127.0.0.1" << "/channel"
<< QString::number( argzTreePort - 7000 ) << "/name" << argzLeafName;
if ( !settings->localzLeafSize.isEmpty() ) {
arguments << "/size" << QString{ settings->localzLeafSize };
}
startProc.startDetached( settings->tasksetCmd, arguments );
}
void lc::MainWindow::StartReceiptsHandler( QString argzTreeDataTargetPath,
bool argReceiptsForLocalClients,
QString argAnonymousReceiptsPlaceholder,
@ -735,16 +487,200 @@ void lc::MainWindow::UpdateClientsTableView() {
}
}
// TODO: Implement the functionality of the script in here
void lc::MainWindow::on_PBrestartCrashedSession_clicked() {
/* Experiment tab functions */
void lc::MainWindow::on_PBBoot_clicked() {
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->Boot();
}
}
}
void lc::MainWindow::on_PBChooseFile_clicked() {
QFileDialog *file_dialog = new QFileDialog{ this, tr( "Choose a file to beam" ), QDir::homePath() };
file_dialog->setFileMode( QFileDialog::Directory );
file_dialog->setOption( QFileDialog::DontUseNativeDialog, true );
file_dialog->setOption( QFileDialog::ReadOnly, true );
file_dialog->setOption( QFileDialog::ShowDirsOnly, true );
if(file_dialog->exec()) {
ui->LEFilePath->setText(file_dialog->selectedFiles().at(0));
qDebug() << "Chose file" << ui->LEFilePath->text() << "for beaming.";
}
else {
ui->LEFilePath->setText( tr( "File choosing cancelled" ) );
qDebug() << "File choosing cancelled";
}
delete file_dialog;
}
void lc::MainWindow::on_PBBeamFile_clicked() {
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes();
const QString fileToBeam{ ui->LEFilePath->text() };
if(fileToBeam == ""){
QMessageBox::information(this, "Upload failed", "You didn't choose any folder to upload.");
} else {
//Iterate over the selected clients to upload the file
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->BeamFile( fileToBeam, &settings->pkeyPathUser, &settings->userNameOnClients );
}
}
// 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!");
}
}
void lc::MainWindow::on_PBShowORSEE_clicked() {
lablib->ShowOrsee();
}
void lc::MainWindow::on_PBShowPreprints_clicked() {
lablib->ShowPreprints();
}
void lc::MainWindow::on_PBShutdown_clicked() {
// Confirmation dialog
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Confirm", "Really shutdown the selected clients?", QMessageBox::Yes|QMessageBox::No);
if (reply == QMessageBox::Yes) {
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
// Do not shut down the server itself
if ( client->name == "self"){
QMessageBox::information(NULL, "Shutdown canceled", "It is not allowed to shutdown the server itself via labcontrol!");
} else {
client->Shutdown();
}
}
}
} else {
qDebug() << "Canceled shutting down the selected clients";
}
}
void lc::MainWindow::on_CBWebcamChooser_activated( int argIndex ) {
if ( argIndex != 0 ) {
QString program{ settings->webcamDisplayCmd };
QStringList arguments;
// Attention argIndex is NOT 0-based
arguments << settings->webcams[argIndex-1];
qDebug() << "Webcam" << arguments << "will be opened";
QProcess showWebcamProcess;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
showWebcamProcess.setProcessEnvironment( env );
showWebcamProcess.startDetached( program, arguments );
}
}
void lc::MainWindow::on_PBstartBrowser_clicked()
{
QString argURL = ui->LEURL->text();
bool argFullscreen = ui->CBFullscreen->checkState();
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->StartClientBrowser( &argURL, &argFullscreen );
}
}
}
void lc::MainWindow::on_PBstopBrowser_clicked()
{
// Confirmation dialog
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Confirm", "Really kill all selected browser instances?", QMessageBox::Yes|QMessageBox::No);
if (reply == QMessageBox::Yes) {
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->StopClientBrowser( );
}
}
} else {
qDebug() << "Canceled stopping all selected browser processes";
}
}
// View only VNC button
void lc::MainWindow::on_PBViewDesktopViewOnly_clicked()
{
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->ShowDesktopViewOnly();
}
}
}
// Full control VNC button
void lc::MainWindow::on_PBViewDesktopFullControl_clicked()
{
QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activatedItems.cbegin(); it != activatedItems.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->ShowDesktopFullControl();
}
}
}
/* Session tab functions */
void lc::MainWindow::on_PBStartzLeaf_clicked() {
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->StartZLeaf( nullptr, ui->LEzLeafCommandline->text() );
}
}
}
void lc::MainWindow::on_PBStartLocalzLeaf_clicked() {
LocalzLeafStarter *localzLeafStarter = new LocalzLeafStarter{ this };
localzLeafStarter->setWindowFlags( Qt::Window );
localzLeafStarter->show();
connect( localzLeafStarter, &LocalzLeafStarter::LocalzLeafRequested,
this, &MainWindow::StartLocalzLeaf );
connect( localzLeafStarter, SIGNAL( LocalzLeafRequested( QString, QString, int ) ),
localzLeafStarter, SLOT( deleteLater() ) );
}
void lc::MainWindow::StartLocalzLeaf( QString argzLeafName, QString argzLeafVersion,
int argzTreePort ) {
if ( settings->tasksetCmd.isEmpty() || settings->wineCmd.isEmpty()
|| settings->zTreeInstDir.isEmpty() ) {
return;
}
QProcess startProc;
startProc.setProcessEnvironment( QProcessEnvironment::systemEnvironment() );
if ( !settings->restartCrashedSessionScript.isEmpty() ) {
startProc.startDetached( settings->restartCrashedSessionScript);
QStringList arguments;
arguments << "0x00000001" << settings->wineCmd
<< QString{ settings->zTreeInstDir + "/zTree_" + argzLeafVersion + "/zleaf.exe" }
<< "/server" << "127.0.0.1" << "/channel"
<< QString::number( argzTreePort - 7000 ) << "/name" << argzLeafName;
if ( !settings->localzLeafSize.isEmpty() ) {
arguments << "/size" << QString{ settings->localzLeafSize };
}
qDebug() << "Start local zLeaf:" << arguments;
startProc.startDetached( settings->tasksetCmd, arguments );
}
void lc::MainWindow::on_PBKillzTree_clicked()
void lc::MainWindow::on_PBStopZtree_clicked()
{
QString program{ settings->killallCmd };
QStringList arguments;
@ -761,6 +697,191 @@ void lc::MainWindow::on_PBKillzTree_clicked()
// Output message via the debug messages tab
qDebug() << program << arguments;
} else {
qDebug() << "Canceled killing all z-Tree processes";
qDebug() << "Canceled stopping all z-Tree processes";
}
}
void lc::MainWindow::on_PBRecoverCrashedSession_clicked()
{
// TODO: Implement the functionality of the restore session script in here (no zenity script)
QProcess startProc;
startProc.setProcessEnvironment( QProcessEnvironment::systemEnvironment() );
if ( !settings->restartCrashedSessionScript.isEmpty() ) {
startProc.startDetached( settings->restartCrashedSessionScript);
}
}
void lc::MainWindow::on_CBDataTargetPath_activated( int argIndex )
{
if ( !argIndex ) {
emit RequestNewDataTargetPath();
}
ui->CBDataTargetPath->setStyleSheet( "" );
}
// Open a folder chooser dialog for zTree data path
void lc::MainWindow::GetNewDataTargetPath() {
QFileDialog fileDialog{ this };
fileDialog.setFileMode( QFileDialog::Directory );
fileDialog.setDirectory( QDir::homePath() );
fileDialog.setOption( QFileDialog::ShowDirsOnly, true );
fileDialog.setOption( QFileDialog::DontUseNativeDialog, true );
if ( fileDialog.exec() ) {
const QString fileName = fileDialog.selectedFiles().at( 0 );
ui->CBDataTargetPath->addItem( fileName );
ui->CBDataTargetPath->setCurrentText( fileName );
}
}
// Dummy function for enabling anonymous receipts section in UI
void lc::MainWindow::on_CBReceiptsHeader_activated(int argIndex)
{
Q_UNUSED( argIndex );
ui->CBReceiptsHeader->setStyleSheet( "" );
}
// Anonymous receipients header check box
void lc::MainWindow::on_ChBPrintanonymousreceipts_clicked()
{
ui->LReplaceParticipantNames->setEnabled(true);
ui->CBReplaceParticipantNames->setEnabled(true);
}
// Start session button actions
void lc::MainWindow::on_PBStartSession_clicked() {
if ( ui->CBzTreeVersion->currentIndex() == 0 ) {
QMessageBox::information( this, tr( "No z-Tree version chosen" ),
tr( "A z-Tree version was not chosen, yet. This setting is"
" mandatory." ), QMessageBox::Ok );
return;
}
const QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes();
if( !ui->ChBSessionWithoutAttachedClients->isChecked() ) {
if ( !activatedItems.length() ) {
QMessageBox::information( this, tr( "Canceled, no clients were chosen" ),
tr( "The start of a new session was canceled.\n"
" Some clients have to be selected first or the"
" creation of sessions without clients must be"
" allowed with the checkbox." ) );
return;
}
}
QString anonymousReceiptsPlaceholder;
if ( ui->ChBPrintAnonymousReceipts->isChecked() ) {
anonymousReceiptsPlaceholder = ui->CBReplaceParticipantNames->currentText();
}
QVector< Client* > associatedClients;
for ( auto cit = activatedItems.cbegin(); cit != activatedItems.cend(); ++cit ) {
if ( ( *cit ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *cit ).data( Qt::UserRole ).value< void* >() );
client->SetSessionPort( ui->SBPort->value() );
client->SetzLeafVersion( ui->CBzTreeVersion->currentText() );
associatedClients.append( client );
}
}
this->lablib->StartNewSession ( associatedClients, anonymousReceiptsPlaceholder,
ui->ChBReceiptsForLocalClients->isChecked(),
ui->CBReceiptsHeader->currentText(),
ui->CBDataTargetPath->currentText(),
static_cast< quint16 >( ui->SBPort->value() ),
ui->CBzTreeVersion->currentText() );
//Display the command line
QString cmd = this->lablib->getzLeafArgs( ui->SBPort->value(), ui->CBzTreeVersion->currentText()).join(" ");
ui->LEzLeafCommandline->setText(cmd);
//Start z-Leaf on selected clients if checkbox is activated
if( ui->ChBautoStartClientZleaf->isChecked() ) {
for ( auto cit = activatedItems.cbegin(); cit != activatedItems.cend(); ++cit ) {
if ( ( *cit ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *cit ).data( Qt::UserRole ).value< void * >() );
client->StartZLeaf( nullptr, cmd );
}
}
}
// Set chosen Port
settings->SetChosenZTreePort(ui->SBPort->text().toInt());
// Increment port number
int newPort = ui->SBPort->text().toInt() + 1;
ui->SBPort->setValue(newPort);
}
void lc::MainWindow::on_PBKillzLeaf_clicked()
{
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->KillZLeaf();
}
}
}
/* Admin tab functions */
void lc::MainWindow::on_PBOpenFilesystem_clicked() {
// Determine the correct user to be used
QString * userToBeUsed = nullptr;
if ( ui->RBUseUserRoot->isChecked() ) {
userToBeUsed = new QString{ "root" };
} else {
userToBeUsed = new QString{ settings->userNameOnClients };
}
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->OpenFilesystem( userToBeUsed );
}
}
delete userToBeUsed;
}
void lc::MainWindow::on_PBExecute_clicked() {
// Get the command to be executed ...
QString command = ui->CBCommandToExecute->currentText();
// Set the correct public key
QString pkeyPathUser;
if ( ui->RBUseUserRoot->isChecked() ) {
pkeyPathUser = settings->pkeyPathRoot;
} else {
pkeyPathUser = settings->pkeyPathUser;
}
qDebug() << "Executing command" << command << " on chosen clients.";
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->OpenTerminal( command, ui->RBUseUserRoot->isChecked() );
}
}
}
// Issue open terminal call
void lc::MainWindow::on_PBOpenTerminal_clicked() {
QString pkeyPathUser;
if ( ui->RBUseUserRoot->isChecked() ) {
pkeyPathUser = settings->pkeyPathRoot;
} else {
pkeyPathUser = settings->pkeyPathUser;
}
QModelIndexList activated_items = ui->TVClients->selectionModel()->selectedIndexes();
for ( QModelIndexList::ConstIterator it = activated_items.cbegin(); it != activated_items.cend(); ++it ) {
if ( ( *it ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *it ).data( Qt::UserRole ).value< void * >() );
client->OpenTerminal( QString{}, ui->RBUseUserRoot->isChecked() );
}
}
}

@ -24,8 +24,6 @@ enum class icons_t : unsigned short int { UNKNOWN, OFF, DOWN, BOOT, ON, ZLEAF, I
#include "Lib/client.h"
#include "Lib/lablib.h"
#include "sessionstarter.h"
#include "sessiondisplay.h"
#include "ui_mainwindow.h"
#include <cmath>
@ -61,22 +59,20 @@ private slots:
void on_PBBeamFile_clicked();
void on_PBBoot_clicked();
void on_PBChooseFile_clicked();
void on_PBDeactivateScreensaver_clicked();
void on_PBExecute_clicked();
void on_PBKillLocalzLeaf_clicked();
void on_PBKillzLeaf_clicked();
void on_PBOpenFilesystem_clicked();
void on_PBOpenTerminal_clicked();
void on_PBPrintPaymentFileManually_clicked();
void on_PBRunzLeaf_clicked();
void on_PBShowORSEE_clicked();
void on_PBShowPreprints_clicked();
void on_PBShowSessions_clicked();
void on_PBShutdown_clicked();
void on_PBStartLocalzLeaf_clicked();
void on_PBStartSession_clicked();
void on_PBStartzLeaf_clicked();
void on_PBViewDesktop_clicked();
void on_PBViewDesktopViewOnly_clicked();
void on_PBViewDesktopFullControl_clicked();
void on_RBUseLocalUser_toggled(bool checked);
void StartLocalzLeaf( QString argzLeafName, QString argzLeafVersion, int argzTreePort );
//! Updates the icons of the QTableView displaying the clients' states
@ -87,6 +83,12 @@ private slots:
void UpdateClientsTableView();
signals:
/*Session actions*/
void RequestNewDataTargetPath();
void RequestNewSession( QVector< Client* > argAssocCl, QString argParticipNameReplacement,
bool argPrintLocalReceipts, QString argReceiptsHeader,
QString argzTreeDataTargetPath, quint16 argzTreePort,
QString argzTreeVersion );
private:
//! Checks, if the user has administrative rights
@ -116,8 +118,17 @@ private slots:
QString argAnonymousReceiptsPlaceholder,
QString argLatexHeaderName,
QString argDateString );
void on_PBrestartCrashedSession_clicked();
void on_PBKillzTree_clicked();
void on_PBstartBrowser_clicked();
void on_PBstopBrowser_clicked();
/* Session actions */
void on_PBStopZtree_clicked();
void on_PBRecoverCrashedSession_clicked();
void GetNewDataTargetPath();
void on_CBDataTargetPath_activated( int argIndex );
void on_CBReceiptsHeader_activated(int argIndex);
void on_ChBPrintanonymousreceipts_clicked();
void on_PBKillzLeaf_clicked();
};
}

File diff suppressed because it is too large Load Diff

@ -34,7 +34,7 @@ lc::ManualPrintingSetup::ManualPrintingSetup( QWidget *argParent ) :
ui->setupUi( this );
if ( settings->dvipsCmd.isEmpty() || settings->latexCmd.isEmpty()
|| settings->lcInstDir.isEmpty() || settings->lprCmd.isEmpty()
|| settings->lcDataDir.isEmpty() || settings->lprCmd.isEmpty()
|| settings->postscriptViewer.isEmpty() || settings->ps2pdfCmd.isEmpty()
|| settings->rmCmd.isEmpty() || settings->vncViewer.isEmpty() ) {
ui->VLManualPrintingSetup->setEnabled( false );

@ -1,34 +0,0 @@
/*
* Copyright 2014-2016 Markus Prasser
*
* This file is part of Labcontrol.
*
* Labcontrol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Labcontrol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Labcontrol. If not, see <http://www.gnu.org/licenses/>.
*/
#include "sessiondisplay.h"
#include "ui_sessiondisplay.h"
lc::SessionDisplay::SessionDisplay( QAbstractTableModel *argSessionsModel,
QWidget *argParent ) :
QWidget{ argParent },
ui{ new Ui::SessionDisplay }
{
ui->setupUi( this );
ui->TVSessions->setModel( argSessionsModel );
}
lc::SessionDisplay::~SessionDisplay() {
delete ui;
}

@ -1,46 +0,0 @@
/*
* Copyright 2014-2016 Markus Prasser
*
* This file is part of Labcontrol.
*
* Labcontrol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Labcontrol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Labcontrol. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SESSIONDISPLAY_H
#define SESSIONDISPLAY_H
#include <QAbstractTableModel>
#include <QWidget>
namespace lc {
namespace Ui {
class SessionDisplay;
}
class SessionDisplay : public QWidget {
Q_OBJECT
public:
explicit SessionDisplay( QAbstractTableModel *argSessionsModel,
QWidget *argParent = nullptr );
~SessionDisplay();
private:
Ui::SessionDisplay *ui = nullptr;
};
}
#endif // SESSIONDISPLAY_H

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>lc::SessionDisplay</class>
<widget class="QWidget" name="lc::SessionDisplay">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Session Display</string>
</property>
<layout class="QVBoxLayout" name="VLSessionDisplay">
<item>
<widget class="QTableView" name="TVSessions"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

@ -1,206 +0,0 @@
/*
* Copyright 2014-2016 Markus Prasser
*
* This file is part of Labcontrol.
*
* Labcontrol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Labcontrol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Labcontrol. If not, see <http://www.gnu.org/licenses/>.
*/
#include <memory>
#include <QDir>
#include <QFileDialog>
#include <QStandardItemModel>
#include "sessionstarter.h"
#include "ui_sessionstarter.h"
#include "Lib/settings.h"
extern std::unique_ptr< lc::Settings > settings;
lc::SessionStarter::SessionStarter( const QVector< quint16 > &argOccupiedPorts,
QWidget *argParent ) :
QWidget{ argParent },
clientsViewModel{ new QStandardItemModel{ this } },
occupiedPorts{ argOccupiedPorts },
ui{ new Ui::SessionStarter }
{
ui->setupUi( this );
CheckIfPortIsOccupied( settings->GetChosenZTreePort() );
if ( settings->dvipsCmd.isEmpty() || settings->latexCmd.isEmpty()
|| settings->lcInstDir.isEmpty() || settings->lprCmd.isEmpty()
|| settings->postscriptViewer.isEmpty() || settings->ps2pdfCmd.isEmpty()
|| settings->rmCmd.isEmpty() || settings->vncViewer.isEmpty() ) {
ui->GBReceipts->setEnabled( false );
QMessageBox::information( this, tr( "Receipts printing will not work" ),
tr( "Some component essential for receipts creation and"
" printing is missing. No receipts will be created or"
" printed." ), QMessageBox::Ok );
} else {
ui->CBReceiptsHeader->addItems( settings->installedLaTeXHeaders );
if ( settings->defaultReceiptIndex
&& settings->defaultReceiptIndex < ui->CBReceiptsHeader->count() ) {
ui->CBReceiptsHeader->setCurrentIndex( settings->defaultReceiptIndex );
}
}
ui->CBzTreeVersion->addItem( tr( "Please choose a version:" ) );
ui->CBzTreeVersion->addItems( settings->installedZTreeVersions );
ui->CBDataTargetPath->addItem( tr( "Set a new path HERE" ) );
ui->CBDataTargetPath->addItem( QDir::homePath() );
ui->CBDataTargetPath->addItem( QDir::homePath() + "/zTreeData" );
ui->CBDataTargetPath->setCurrentIndex( 2 );
connect( this, &SessionStarter::RequestNewDataTargetPath,
this, &SessionStarter::GetNewDataTargetPath );
for ( auto *s : settings->GetClients() ) {
int tempXPos = s->xPosition - 1, tempYPos = s->yPosition;
if ( clientsViewModel->item( tempYPos, tempXPos ) ) {
QMessageBox::information( this, tr( "Double assignment to one position" ),
tr( "Two client where set for the same position. Client"
" '%1' will be dropped." ).arg( s->name ) );
continue;
}
QStandardItem *item = new QStandardItem( s->name );
item->setEditable( false );
const QString sessionPort{ QString::number( s->GetSessionPort() ) };
if ( sessionPort == "0" ) {
item->setText( s->name );
} else {
item->setBackground( QBrush{ QColor{ 196, 196, 255 } } );
item->setSelectable( false );
item->setText( QString{ "(" + sessionPort + ") " + s->name } );
}
QVariant v = qVariantFromValue( static_cast< void* >( s ) );
item->setData( v, Qt::UserRole );
clientsViewModel->setItem( tempYPos, tempXPos, item );
}
ui->TVClients->setModel( clientsViewModel );
}
lc::SessionStarter::~SessionStarter() {
delete ui;
}
void lc::SessionStarter::CheckIfPortIsOccupied( quint16 argPort ) {
if ( occupiedPorts.contains( argPort ) ) {
CheckIfPortIsOccupied( argPort + 1 );
} else {
ui->SBPort->setValue( argPort );
}
}
void lc::SessionStarter::GetNewDataTargetPath() {
QFileDialog fileDialog{ this };
fileDialog.setFileMode( QFileDialog::Directory );
fileDialog.setDirectory( QDir::homePath() );
fileDialog.setOption( QFileDialog::ShowDirsOnly, true );
fileDialog.setOption( QFileDialog::DontUseNativeDialog, true );
if ( fileDialog.exec() ) {
const QString fileName = fileDialog.selectedFiles().at( 0 );
ui->CBDataTargetPath->addItem( fileName );
ui->CBDataTargetPath->setCurrentText( fileName );
}
}
void lc::SessionStarter::on_CBDataTargetPath_activated( int argIndex ) {
if ( !argIndex ) {
emit RequestNewDataTargetPath();
}
ui->CBDataTargetPath->setStyleSheet( "" );
}
void lc::SessionStarter::on_CBReceiptsHeader_activated( int argIndex ) {
Q_UNUSED( argIndex );
ui->CBReceiptsHeader->setStyleSheet( "" );
}
void lc::SessionStarter::on_CBzTreeVersion_activated( int argIndex ) {
Q_UNUSED( argIndex );
ui->CBzTreeVersion->setStyleSheet( "" );
}
void lc::SessionStarter::on_ChBPrintAnonymousReceipts_clicked( bool argChecked ) {
ui->ChBPrintAnonymousReceipts->setStyleSheet( "" );
ui->LReplaceParticipantNames->setEnabled( argChecked );
ui->CBReplaceParticipantNames->setEnabled( argChecked );
}
void lc::SessionStarter::on_PBStartSession_clicked() {
if ( ui->CBzTreeVersion->currentIndex() == 0 ) {
QMessageBox::information( this, tr( "No z-Tree version chosen" ),
tr( "A z-Tree version was not chosen, yet. This setting is"
" mandatory." ), QMessageBox::Ok );
return;
}
const QModelIndexList activatedItems = ui->TVClients->selectionModel()->selectedIndexes();
if( !ui->ChBSessionWithoutClients->isChecked() ) {
if ( !activatedItems.length() ) {
QMessageBox::information( this, tr( "Canceled, no clients were chosen" ),
tr( "The start of a new session was canceled."
" Some clients have to be selected first or the"
" creation of sessions without clients must be"
" allowed with the checkbox close to the bottom" ) );
return;
}
}
QString anonymousReceiptsPlaceholder;
if ( ui->ChBPrintAnonymousReceipts->isChecked() ) {
anonymousReceiptsPlaceholder = ui->CBReplaceParticipantNames->currentText();
}
QVector< Client* > associatedClients;
for ( auto cit = activatedItems.cbegin(); cit != activatedItems.cend(); ++cit ) {
if ( ( *cit ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *cit ).data( Qt::UserRole ).value< void* >() );
client->SetSessionPort( ui->SBPort->value() );
client->SetzLeafVersion( ui->CBzTreeVersion->currentText() );
associatedClients.append( client );
}
}
emit RequestNewSession( associatedClients, anonymousReceiptsPlaceholder,
ui->ChBReceiptsForLocalClients->isChecked(),
ui->CBReceiptsHeader->currentText(),
ui->CBDataTargetPath->currentText(),
static_cast< quint16 >( ui->SBPort->value() ),
ui->CBzTreeVersion->currentText() );
//Start z-Leaf on selected clients if checkbox is activated
if( ui->ChBautoStartClientZleaf->isChecked() ) {
for ( auto cit = activatedItems.cbegin(); cit != activatedItems.cend(); ++cit ) {
if ( ( *cit ).data( Qt::DisplayRole ).type() != 0 ) {
Client *client = static_cast< Client* >( ( *cit ).data( Qt::UserRole ).value< void * >() );
client->StartZLeaf( nullptr );
}
}
}
this->deleteLater();
}
void lc::SessionStarter::on_SBPort_editingFinished() {
ui->SBPort->setStyleSheet( "" );
CheckIfPortIsOccupied( ui->SBPort->value() );
}

@ -1,69 +0,0 @@
/*
* Copyright 2014-2016 Markus Prasser
*
* This file is part of Labcontrol.
*
* Labcontrol is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Labcontrol is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Labcontrol. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SESSIONSTARTER_H
#define SESSIONSTARTER_H
#include <QWidget>
class QStandardItemModel;
namespace lc {
class Client;
namespace Ui {
class SessionStarter;
}
class SessionStarter : public QWidget {
Q_OBJECT
public:
explicit SessionStarter( const QVector< quint16 > &argOccupiedPorts,
QWidget *argParent = nullptr );
~SessionStarter();
signals:
void RequestNewDataTargetPath();
void RequestNewSession( QVector< Client* > argAssocCl, QString argParticipNameReplacement,
bool argPrintLocalReceipts, QString argReceiptsHeader,
QString argzTreeDataTargetPath, quint16 argzTreePort,
QString argzTreeVersion );
private:
void CheckIfPortIsOccupied( quint16 argPort );
QStandardItemModel *clientsViewModel = nullptr;
const QVector< quint16 > &occupiedPorts;
Ui::SessionStarter *ui = nullptr;
private slots:
void GetNewDataTargetPath();
void on_CBDataTargetPath_activated( int argIndex );
void on_CBReceiptsHeader_activated( int argIndex );
void on_CBzTreeVersion_activated( int argIndex );
void on_ChBPrintAnonymousReceipts_clicked( bool argChecked );
void on_PBStartSession_clicked();
void on_SBPort_editingFinished();
};
}
#endif // SESSIONSTARTER_H

@ -1,319 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>lc::SessionStarter</class>
<widget class="QWidget" name="lc::SessionStarter">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="VLSessionStarter">
<item>
<layout class="QHBoxLayout" name="HLGroupBoxes">
<item>
<widget class="QGroupBox" name="GBzTree">
<property name="title">
<string>z-Tree</string>
</property>
<layout class="QVBoxLayout" name="VLzTree">
<item>
<widget class="QLabel" name="label">
<property name="toolTip">
<string>The z-Tree version which shall be used for the experiment.</string>
</property>
<property name="text">
<string>z-Tree version:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="CBzTreeVersion">
<property name="toolTip">
<string>The z-Tree version which shall be used for the experiment.</string>
</property>
<property name="styleSheet">
<string notr="true">background: cyan;</string>
</property>
<property name="maxVisibleItems">
<number>32</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="LDataTargetPath">
<property name="toolTip">
<string>The path where z-Tree shall store its data.
Please take care that it does not contain any spaces or other special characters.</string>
</property>
<property name="text">
<string>Data target path:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="CBDataTargetPath">
<property name="toolTip">
<string>The path where z-Tree shall store its data.
Please take care that it does not contain any spaces or other special characters.</string>
</property>
<property name="styleSheet">
<string notr="true">background: cyan;</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="HLPort">
<item>
<widget class="QLabel" name="LPort">
<property name="toolTip">
<string>The port which will be used by started z-Tree and z-Leaf instances. This only matters if multiple experiments shall be run in parallel.</string>
</property>
<property name="text">
<string>Port:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="SBPort">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>The port which will be used by started z-Tree and z-Leaf instances. This only matters if multiple experiments shall be run in parallel.</string>
</property>
<property name="styleSheet">
<string notr="true">background: cyan;</string>
</property>
<property name="minimum">
<number>7000</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QCheckBox" name="ChBRamdiskForGamesafeFile">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>This function is not implemented, yet.</string>
</property>
<property name="text">
<string>Use ramdisk for gamesafe file</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="GBReceipts">
<property name="title">
<string>Receipts</string>
</property>
<layout class="QVBoxLayout" name="VLReceipts">
<item>
<widget class="QLabel" name="LReceiptsHeader">
<property name="toolTip">
<string>Choose the LaTeX template which shall be used for receipts creation.</string>
</property>
<property name="text">
<string>Template for receipts:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="CBReceiptsHeader">
<property name="toolTip">
<string>Choose the LaTeX template which shall be used for receipts creation.</string>
</property>
<property name="styleSheet">
<string notr="true">background: cyan;</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="ChBPrintAnonymousReceipts">
<property name="toolTip">
<string>Check this if you want the created receipts to be anonymous.</string>
</property>
<property name="styleSheet">
<string notr="true">background: cyan;</string>
</property>
<property name="text">
<string>Print anonymous receipts</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="LReplaceParticipantNames">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Choose a string which shall replace the participant name on the anonymous receipts.</string>
</property>
<property name="text">
<string>Substitute participants' names with:</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="CBReplaceParticipantNames">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Choose a string which shall replace the participant name on the anonymous receipts.</string>
</property>
<property name="editable">
<bool>true</bool>
</property>
<property name="currentText">
<string>\hspace{5cm}</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<item>
<property name="text">
<string>\hspace{5cm}</string>
</property>
</item>
<item>
<property name="text">
<string>anonym</string>
</property>
</item>
<item>
<property name="text">
<string>anonymous</string>
</property>
</item>
<item>
<property name="text">
<string>nicht ausfüllen</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="QCheckBox" name="ChBReceiptsForLocalClients">
<property name="toolTip">
<string>This decides if receipts shall be printed for any z-Leaf instance running locally on the server.
Warning: If this is disabled no receipts will be printed for ANY participant whose name contains the character string &quot;local&quot;!</string>
</property>
<property name="text">
<string>Print receipts for local clients</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="LClientSelection">
<property name="toolTip">
<string>Select the clients which shall be attached to this session:</string>
</property>
<property name="text">
<string>Select the clients which shall be attached to this session:</string>
</property>
</widget>
</item>
<item>
<widget class="QTableView" name="TVClients">
<property name="toolTip">
<string>Select the clients which shall be attached to this session.</string>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item>
<widget class="QCheckBox" name="ChBSessionWithoutClients">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>This allows an experimenter to override the normally hard requirement of choosing clients to be attached to the started session and start a session without attached clients.</string>
</property>
<property name="text">
<string>Allow session without attached clients</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="ChBautoStartClientZleaf">
<property name="text">
<string>Start z-Leaf on clients with the session</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="PBStartSession">
<property name="toolTip">
<string>Start a new session according to the above made settings.</string>
</property>
<property name="text">
<string>Start session</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="PBCancel">
<property name="toolTip">
<string>Cancel the creation of a new session.</string>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>PBCancel</sender>
<signal>clicked()</signal>
<receiver>lc::SessionStarter</receiver>
<slot>deleteLater()</slot>
<hints>
<hint type="sourcelabel">
<x>319</x>
<y>552</y>
</hint>
<hint type="destinationlabel">
<x>319</x>
<y>287</y>
</hint>
</hints>
</connection>
</connections>
</ui>
Loading…
Cancel
Save