Manually merged freebsd fork from git.floating-in.space/isabell/labcontrol into github.com/markuspg/Labcontrol.

master
Isabell Pflug 5 years ago
parent f5d7d1af7e
commit 78b2af6947

@ -26,6 +26,7 @@ HEADERS += src/localzleafstarter.h \
src/Lib/client.h \ src/Lib/client.h \
src/Lib/clienthelpnotificationserver.h \ src/Lib/clienthelpnotificationserver.h \
src/Lib/clientpinger.h \ src/Lib/clientpinger.h \
src/Lib/global.h \
src/Lib/lablib.h \ src/Lib/lablib.h \
src/Lib/netstatagent.h \ src/Lib/netstatagent.h \
src/Lib/receipts_handler.h \ src/Lib/receipts_handler.h \
@ -51,3 +52,5 @@ OTHER_FILES += \
data/scripts/kill_zLeaf_labcontrol2.sh \ data/scripts/kill_zLeaf_labcontrol2.sh \
data/scripts/start_zLeaf_labcontrol2.sh \ data/scripts/start_zLeaf_labcontrol2.sh \
doc/manual.tex doc/manual.tex
INCLUDEPATH += /usr/local/include/

@ -4,7 +4,7 @@
The easiest way to build and install _Labcontrol_ is to open the `labcontrol.pro` file with _Qt Creator_ and build the project. Afterwards _Labcontrol_ can be started by running the created executable file. To build correctly _Qt5_ has to be available and must be know to _Qt Creator_. The easiest way to build and install _Labcontrol_ is to open the `labcontrol.pro` file with _Qt Creator_ and build the project. Afterwards _Labcontrol_ can be started by running the created executable file. To build correctly _Qt5_ has to be available and must be know to _Qt Creator_.
To work properly _Labcontrol_ requires a file named `labcontrol.conf` in `/etc/xdg/Economic\ Laboratory`. This directory must be created, the existing dummy file be copied there and afterwards be modified according to the laboratory's needs. All _z-Tree_ executables should reside in sub-directories of `/opt/z-Leaves` following the naming scheme `zTree_X.Y.ZZ`. To work properly _Labcontrol_ requires a file named `labcontrol.json` + the folder named `icons` (inside of `data`) in either `/usr/local/etc/Labcontrol` or `/etc/Labcontrol` or next to the Labcontrol binary. This directory must be created, the existing dummy file be copied there and afterwards be modified according to the laboratory's needs. All _z-Tree_ executables should reside in sub-directories of `/opt/z-Leaves` following the naming scheme `zTree_X.Y.ZZ`.
Receipt creation requires at least one receipt template in `/usr/local/share/labcontrol`. The name of the header file should match the pattern `NAMETHEHEADERSHALLHAVE_header.tex` to be recognized. Receipt creation requires at least one receipt template in `/usr/local/share/labcontrol`. The name of the header file should match the pattern `NAMETHEHEADERSHALLHAVE_header.tex` to be recognized.

@ -1,98 +0,0 @@
[General]
### 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
# 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
# These are the names which show up in the interface. They should match the hostnames of the clients
client_names=client01|client02|client03|client04|client05|client06|client07|client08|client09|client10|client11|client12|client13|client14|client15|client16|client17|client18|backupclient01|backupclient02|backupclient03|backupclient04|backupclient05|backupclient06
# This is just a hash to control the correct length of the other client attributes
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
# 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
#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
# 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
# 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 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
# 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
# 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
# Client default browser cmd (firefox) - need to be quoted!
client_browser_command="firefox-esr"
# Client cromium cmd- need to be quoted!
client_chromium_command="chromium"

@ -0,0 +1,79 @@
{
"server": {
"server_ip": "192.168.53.100",
"network_broadcast_address": "192.168.53.255",
"initial_port": 7000,
"client_help_server_port": 19871,
"admin_users": ["okirchkamp", "weiss", "isabell"],
"pkey_path_root": "/usr/share/labcontrol/id_clients_root",
"pkey_path_root_comment": "The public keys to access the clients as root",
"pkey_path_user": "/usr/share/labcontrol/id_clients_ewfuser",
"pkey_path_user_comment": "The public keys to access the clients as unprivileged user",
"local_zLeaf_def_name": "local",
"local_zLeaf_def_size": "1280x1024",
"default_receipt_index": 0,
"default_receipt_index_comment": "If multiple receipts are availabe, this indicates, which one will be shown by default (the index counting from 0 following an alphabetical ordering)",
"orsee_url": "http://yourORSEEserver.tld",
"webcams": { "Webcam right": "http://user:pass@webcam_right", "Webcam left": "http://user:pass@webcam_left"},
"vnc_view_only_argument": "-ViewOnly"
},
"client": {
"clients": { "client01": {"ip": "192.168.53.1", "mac": "4c:72:b9:21:ea:7e", "xpos": "3", "ypos": "4"},
"client02": {"ip": "192.168.53.2", "mac": "4c:72:b9:24:86:60", "xpos": "4", "ypos": "4"},
"client03": {"ip": "192.168.53.3", "mac": "00:1e:8c:f2:5b:7a", "xpos": "5", "ypos": "4"},
"client04": {"ip": "192.168.53.4", "mac": "4c:72:b9:24:85:a6", "xpos": "6", "ypos": "4"},
"client05": {"ip": "192.168.53.5", "mac": "4c:72:b9:24:85:b9", "xpos": "6", "ypos": "3"},
"client06": {"ip": "192.168.53.6", "mac": "00:1e:8c:f2:ac:b9", "xpos": "5", "ypos": "3"},
"client07": {"ip": "192.168.53.7", "mac": "4c:72:b9:24:84:ea", "xpos": "4", "ypos": "3"},
"client08": {"ip": "192.168.53.8", "mac": "4c:72:b9:24:86:d0", "xpos": "4", "ypos": "2"},
"client09": {"ip": "192.168.53.9", "mac": "4c:72:b9:24:80:b1", "xpos": "5", "ypos": "2"},
"client10": {"ip": "192.168.53.10", "mac": "4c:72:b9:21:e8:ba", "xpos": "6", "ypos": "2"},
"client11": {"ip": "192.168.53.11", "mac": "4c:72:b9:24:83:ae", "xpos": "6", "ypos": "1"},
"client12": {"ip": "192.168.53.12", "mac": "4c:72:b9:24:83:81", "xpos": "5", "ypos": "1"},
"client13": {"ip": "192.168.53.13", "mac": "4c:72:b9:21:a3:25", "xpos": "4", "ypos": "1"},
"client14": {"ip": "192.168.53.14", "mac": "4c:72:b9:24:85:10", "xpos": "3", "ypos": "1"},
"client15": {"ip": "192.168.53.15", "mac": "4c:72:b9:24:86:39", "xpos": "2", "ypos": "1"},
"client16": {"ip": "192.168.53.16", "mac": "4c:72:b9:24:83:73", "xpos": "1", "ypos": "1"},
"client17": {"ip": "192.168.53.17", "mac": "4c:72:b9:24:85:df", "xpos": "1", "ypos": "2"},
"client18": {"ip": "192.168.53.18", "mac": "4c:72:b9:24:85:fd", "xpos": "2", "ypos": "2"},
"backupclient01": {"ip": "192.168.53.19", "mac": "00:17:31:5f:7e:21", "xpos": "1", "ypos": "7"},
"backupclient02": {"ip": "192.168.53.20", "mac": "00:17:31:5f:7e:21", "xpos": "2", "ypos": "7"},
"backupclient04": {"ip": "192.168.53.22", "mac": "00:17:31:5f:84:c6", "xpos": "4", "ypos": "7"},
"backupclient05": {"ip": "192.168.53.23", "mac": "00:17:31:5f:84:c6", "xpos": "5", "ypos": "7"},
"backupclient06": {"ip": "192.168.53.24", "mac": "00:17:31:5c:68:89", "xpos": "6", "ypos": "7"},
"server": {"ip": "192.168.53.100", "mac": "4c:72:b9:21:bb:0c", "xpos": "1", "ypos": "5"},
"testclient": {"ip": "192.168.53.48", "mac": "00:27:0e:34:3f:5d", "xpos": "3", "ypos": "2"}},
"user_name_on_clients": "ewfuser"
},
"binary_paths": {
"lpr_command": "lpr",
"netstat_command": "netstat",
"killall_command": "pkill -f",
"zleaf_exe_name": "zleaf.exe",
"ztree_exe_name": "ztree.exe",
"labcontrol_data_directory": ".",
"latex_command": "latex",
"dvips_command": "dvips",
"file_manager": "thunar",
"ping_command": "ping",
"postscript_viewer": "okular",
"ps2pdf_command": "ps2pdf",
"rm_command": "rm",
"scp_command": "scp",
"browser_command": "firefox",
"client_browser_command": "firefox",
"client_chromium_command": "chrome",
"ssh_command": "ssh",
"taskset_command": "LANG=en_US.UTF-8 cpuset -l 1",
"terminal_emulator_command": "gnome-terminal",
"wine_command": "wine",
"wmctrl_command": "wmctrl",
"xset_command": "xset",
"vnc_viewer": "vncviewer",
"wakeonlan_command": "wakeonlan",
"webcam_command": "WebcamDisplay",
"ztree_installation_directory": "/opt/zTree",
"ztree_installation_directory_comment": "The folder where all zTree versions are installed (in subfolders matching the scheme zTree_X.Y.Z)",
"restart_crashed_session_script": "/home/scripts/start_zTree_after_crash.sh"
}
}

@ -49,6 +49,9 @@ lc::Client::Client(const QString &argIP, const QString &argMAC,
pingTimer = new QTimer{this}; pingTimer = new QTimer{this};
connect(pingTimer, &QTimer::timeout, this, &Client::RequestAPing); connect(pingTimer, &QTimer::timeout, this, &Client::RequestAPing);
pingTimer->start(3000); pingTimer->start(3000);
} else {
qDebug() << "ClientPingerArg not found: " << argPingCmd;
exit(127);
} }
qDebug() << "Created client" << name << "with MAC" << mac << "and IP" << ip qDebug() << "Created client" << name << "with MAC" << mac << "and IP" << ip
@ -125,9 +128,7 @@ 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" << settings->killallCmd << " " << settings->zleafExeName;
<< "-q"
<< "zleaf.exe";
// Start the process // Start the process
QProcess killZLeafProcess; QProcess killZLeafProcess;
@ -210,7 +211,11 @@ void lc::Client::SetStateToZLEAF_RUNNING(QString argClientIP) {
void lc::Client::ShowDesktopViewOnly() { void lc::Client::ShowDesktopViewOnly() {
QStringList arguments; QStringList arguments;
#ifdef Q_OS_FREEBSD
arguments << " " << settings->vncViewOnlyArguments << " " << ip;
#else
arguments << ip; arguments << ip;
#endif
QProcess showDesktopProcess; QProcess showDesktopProcess;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
@ -223,8 +228,11 @@ void lc::Client::ShowDesktopViewOnly() {
void lc::Client::ShowDesktopFullControl() { void lc::Client::ShowDesktopFullControl() {
QStringList arguments; QStringList arguments;
arguments << ip + ":5901"; #ifdef Q_OS_FREEBSD
arguments << ip;
#else
arguments << ip + ":5901"; // TODO: command arguments (port, etc.) into config
#endif
QProcess showDesktopProcess; QProcess showDesktopProcess;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
showDesktopProcess.setProcessEnvironment(env); showDesktopProcess.setProcessEnvironment(env);
@ -264,6 +272,7 @@ 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::RESPONDING || zLeafVersion.isEmpty() || if (state < State::RESPONDING || zLeafVersion.isEmpty() ||
GetSessionPort() < 7000) { GetSessionPort() < 7000) {
qDebug() << "zleaf could not be started.";
return; return;
} }
@ -308,7 +317,7 @@ void lc::Client::StartZLeaf(const QString *argFakeName, QString cmd) {
void lc::Client::StartClientBrowser(const QString *const argURL, void lc::Client::StartClientBrowser(const QString *const argURL,
const bool *const argFullscreen, const bool *const argFullscreen,
const QString *const argBrowser) { QString const argBrowser) {
// Declarations // Declarations
QStringList arguments; QStringList arguments;
@ -335,13 +344,14 @@ void lc::Client::StartClientBrowser(const QString *const argURL,
<< "DISPLAY=:0.0" << settings->clientChromiumCmd << "DISPLAY=:0.0" << settings->clientChromiumCmd
<< "--noerrdialogs --kiosk" << "--noerrdialogs --kiosk"
<< "--app='" + processedArgUrl + "'" << "--app='" + processedArgUrl + "'"
<< "> /dev/null 2>&1 &disown"; << "> /dev/null 2>&1";
} }
// Start the process // Start the process
QProcess startClientBrowserProcess; QProcess startClientBrowserProcess;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
startClientBrowserProcess.setProcessEnvironment(env); startClientBrowserProcess.setProcessEnvironment(env);
qDebug() << "arguments: " << arguments << "\nargBrowser: " << argBrowser;
startClientBrowserProcess.startDetached(settings->sshCmd, arguments); startClientBrowserProcess.startDetached(settings->sshCmd, arguments);
// Output message via the debug messages tab // Output message via the debug messages tab
@ -378,12 +388,12 @@ void lc::Client::ControlRMB(bool 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 " << "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;"; "Mouse' 1 2 3 4 5 6 7 8 9 10 11 12 > /dev/null 2>&1;";
} 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 " << "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;"; "Mouse' 1 2 0 4 5 6 7 8 9 10 11 12 > /dev/null 2>&1;";
} }
// Start the process // Start the process

@ -148,7 +148,7 @@ public:
*/ */
void StartClientBrowser(const QString *argURL = nullptr, void StartClientBrowser(const QString *argURL = nullptr,
const bool *argFullscreen = nullptr, const bool *argFullscreen = nullptr,
const QString *argBrowser = nullptr); QString argBrowser = nullptr);
/*! /*!
* \brief Closes all browser instances * \brief Closes all browser instances

@ -24,6 +24,7 @@
#include <QNetworkSession> #include <QNetworkSession>
#include <QTcpServer> #include <QTcpServer>
#include <QTcpSocket> #include <QTcpSocket>
#include <QSettings>
extern std::unique_ptr<lc::Settings> settings; extern std::unique_ptr<lc::Settings> settings;

@ -16,7 +16,6 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with Labcontrol. If not, see <http://www.gnu.org/licenses/>. * along with Labcontrol. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "clientpinger.h" #include "clientpinger.h"
/*! /*!
@ -32,7 +31,11 @@ lc::ClientPinger::ClientPinger(const QString &argIP,
: QObject{argParent}, : QObject{argParent},
// Arguments: -c 1 (send 1 ECHO_REQUEST packet) -w 1 (timeout after 1 // Arguments: -c 1 (send 1 ECHO_REQUEST packet) -w 1 (timeout after 1
// second) -q (quiet output) // second) -q (quiet output)
pingArguments{"-c", "1", "-w", "1", "-q", argIP}, #ifdef Q_OS_FREEBSD
pingArguments{ QStringList{} << "-c" << "1" << "-W" << "1" << "-q" << argIP },
#else
pingArguments{ QStringList{} << "-c" << "1" << "-w" << "1" << "-q" << argIP },
#endif
pingCommand{argPingCommand}, pingProcess{new QProcess{this}} { pingCommand{argPingCommand}, pingProcess{new QProcess{this}} {
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
pingProcess->setProcessEnvironment(env); pingProcess->setProcessEnvironment(env);

@ -175,19 +175,15 @@ void lc::Lablib::SetLocalZLeafDefaultName(const QString &argName) {
// Returns the commandline that is issued on the client when zleaf is started // Returns the commandline that is issued on the client when zleaf is started
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" arguments << "sleep 5 && DISPLAY=:0.0" << settings->tasksetCmd << settings->wineCmd
<< settings->wineCmd << QString{ settings->zTreeInstDir + "/zTree_" + zleafVersion + "/zleaf.exe" }
<< QString{settings->zTreeInstDir + "/zTree_" + zleafVersion +
"/zleaf.exe"}
<< "/server" << settings->serverIP; << "/server" << settings->serverIP;
} else { } else {
arguments << "DISPLAY=:0.0" << settings->tasksetCmd << "0x00000001" arguments << "sleep 5 && DISPLAY=:0.0" << settings->tasksetCmd << settings->wineCmd
<< settings->wineCmd << QString{ settings->zTreeInstDir + "/zTree_" + zleafVersion + "/zleaf.exe" }
<< QString{settings->zTreeInstDir + "/zTree_" + zleafVersion +
"/zleaf.exe"}
<< "/server" << settings->serverIP << "/channel" << "/server" << settings->serverIP << "/channel"
<< QString::number(sessionPort - 7000); << QString::number( sessionPort- 7000 );
} }
// Return the crafted QStringList // Return the crafted QStringList

@ -22,11 +22,12 @@
lc::NetstatAgent::NetstatAgent(const QString &argNetstatCommand, lc::NetstatAgent::NetstatAgent(const QString &argNetstatCommand,
QObject *argParent) QObject *argParent)
: QObject{argParent}, extractionRegexp{"\\d+\\.\\d+\\.\\d+\\.\\d+"}, : QObject{argParent}, extractionRegexp{"\\d+\\.\\d+\\.\\d+\\.\\d+"},
netstatArguments{QStringList{} << "-anp" //netstatArguments{QStringList{} << "-anp" << "--tcp"},
<< "--tcp"}, netstatArguments{QStringList{} << "-4v"},
netstatCommand{argNetstatCommand}, netstatQueryProcess{this}, netstatCommand{argNetstatCommand}, netstatQueryProcess{this},
searchRegexp{"\\W(ESTABLISHED|VERBUNDEN)( +)(\\d+)(/ztree.exe)\\W", //searchRegexp{"\\W(ESTABLISHED|VERBUNDEN)( +)(\\d+)(/ztree.exe)\\W", QRegularExpression::CaseInsensitiveOption} {
QRegularExpression::CaseInsensitiveOption} { searchRegexp{ ".*(wine ).*", QRegularExpression::CaseInsensitiveOption }
{
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
netstatQueryProcess.setProcessEnvironment(env); netstatQueryProcess.setProcessEnvironment(env);
} }

@ -20,160 +20,108 @@
#include <QDebug> #include <QDebug>
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QProcessEnvironment> #include <QProcessEnvironment>
#include <string>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include "client.h" #include "client.h"
#include "settings.h" #include "settings.h"
lc::Settings::Settings(const QSettings &argSettings, QObject *argParent) lc::Settings::Settings( pt::ptree root ) :
: QObject{argParent}, defaultReceiptIndex{GetDefaultReceiptIndex( //defaultReceiptIndex{ GetDefaultReceiptIndex( argSettings ) },
argSettings)}, binary_paths(root.get_child("binary_paths")),
browserCmd{ReadSettingsItem("browser_command", client(root.get_child("client")),
"Opening ORSEE in a browser will not work.", server(root.get_child("server")),
argSettings, true)}, webcams_root(server.get_child("webcams")),
clientBrowserCmd{ clientBrowserCmd(QString::fromStdString(binary_paths.get<std::string>("client_browser_command",
ReadSettingsItem("client_browser_command", "Opening a browser window on clients will not work."))),
"Opening a browser window on clients will not work.", clientChromiumCmd(QString::fromStdString(binary_paths.get<std::string>("client_chromium_command",
argSettings, false)}, "Opening a chromium window on clients will not work."))),
clientChromiumCmd{ReadSettingsItem( dvipsCmd(QString::fromStdString(binary_paths.get<std::string>("dvips_command",
"client_chromium_command", "Receipts creation will not work."))),
"Opening a chromium window on clients will not work.", argSettings, fileMngr(QString::fromStdString(binary_paths.get<std::string>("file_manager",
false)}, "The display of preprints will not work."))),
dvipsCmd{ReadSettingsItem("dvips_command", killallCmd(QString::fromStdString(binary_paths.get<std::string>("killall_command",
"Receipts creation will not work.", argSettings, "Killing 'zleaf.exe' or 'ztree.exe' instances will not work."))),
true)}, zleafExeName(QString::fromStdString(binary_paths.get<std::string>("zleaf_exe_name"))),
fileMngr{ReadSettingsItem("file_manager", ztreeExeName(QString::fromStdString(binary_paths.get<std::string>("ztree_exe_name"))),
"The display of preprints will not work.", latexCmd(QString::fromStdString(binary_paths.get<std::string>("latex_command",
argSettings, true)}, "Receipts creation will not work."))),
killallCmd{ReadSettingsItem( lcDataDir(QString::fromStdString(binary_paths.get<std::string>("labcontrol_data_directory",
"killall_command", "Killing 'zleaf.exe' instances will not work.", "Datapath not set. Labcontrol will missbehave with high propability."))),
argSettings, true)}, localUserName{ GetLocalUserName() },
latexCmd{ReadSettingsItem("latex_command", lprCmd(QString::fromStdString(binary_paths.get<std::string>("lpr_command",
"Receipts creation will not work.", argSettings, "Receipts printing will not work."))),
true)}, netstatCmd(QString::fromStdString(binary_paths.get<std::string>("netstat_command",
lcDataDir{ReadSettingsItem( "Detection of active zLeaf connections will not work."))),
"labcontrol_data_directory", netwBrdAddr(QString::fromStdString(server.get<std::string>( "network_broadcast_address",
"Datapath not set. Labcontrol will missbehave with high propability.", "Booting the clients will not work."))),
argSettings, true)}, orseeUrl(QString::fromStdString(server.get<std::string>("orsee_url",
localUserName{GetLocalUserName()}, localzLeafSize{ReadSettingsItem( "Opening ORSEE in a browser will not work."))),
"local_zLeaf_size", pingCmd(QString::fromStdString(binary_paths.get<std::string>("ping_command",
"Resolution of local zLeaf window", "Status updates for the clients will not work."))),
argSettings, false)}, postscriptViewer(QString::fromStdString(binary_paths.get<std::string>("postscript_viewer",
lprCmd{ReadSettingsItem("lpr_command", "Receipts printing will not work.", "Viewing the generated receipts postscript file will not work."))),
argSettings, true)}, ps2pdfCmd(QString::fromStdString(binary_paths.get<std::string>("ps2pdf_command",
netstatCmd{ReadSettingsItem( "Converting and viewing the generated receipts file will not work."))),
"netstat_command", pkeyPathRoot(QString::fromStdString(server.get<std::string>("pkey_path_root",
"Detection of active zLeaf connections will not work.", argSettings, "Administration actions concerning the clients will not be available."))),
true)}, pkeyPathUser(QString::fromStdString(server.get<std::string>("pkey_path_user",
netwBrdAddr{ReadSettingsItem("network_broadcast_address", "Many actions concerning the clients will not be available."))),
"Booting the clients will not work.", rmCmd(QString::fromStdString(binary_paths.get<std::string>("rm_command",
argSettings, false)}, "Cleanup of the zTree data target path will not work."))),
orseeUrl{ReadSettingsItem("orsee_url", scpCmd(QString::fromStdString(binary_paths.get<std::string>("scp_command", "Beaming files to the clients will not be possible."))),
"Opening ORSEE in a browser will not work.", serverIP(QString::fromStdString(server.get<std::string>("server_ip",
argSettings, false)}, "Starting zLeaves and retrieving client help messages will not work."))),
pingCmd{ReadSettingsItem("ping_command", sshCmd(QString::fromStdString(binary_paths.get<std::string>("ssh_command",
"Status updates for the clients will not work.", "All actions concerning the clients will not be possible."))),
argSettings, true)}, tasksetCmd(QString::fromStdString(binary_paths.get<std::string>("taskset_command",
postscriptViewer{ReadSettingsItem( "Running z-Leaves or z-Tree will be possible."))),
"postscript_viewer", termEmulCmd(QString::fromStdString(binary_paths.get<std::string>("terminal_emulator_command",
"Viewing the generated receipts postscript file will not work.", "Conducting administrative tasks will not be possible."))),
argSettings, true)}, userNameOnClients(QString::fromStdString(client.get<std::string>("user_name_on_clients",
ps2pdfCmd{ReadSettingsItem( "All actions concerning the clients performed by the experiment user will not work."))),
"ps2pdf_command", vncViewer(QString::fromStdString(binary_paths.get<std::string>("vnc_viewer",
"Converting and viewing the generated receipts file will not work.", "Viewing the clients' screens will not work."))),
argSettings, true)}, wakeonlanCmd(QString::fromStdString(binary_paths.get<std::string>("wakeonlan_command",
pkeyPathRoot{ReadSettingsItem("pkey_path_root", "Booting the clients will not work."))),
"Administration actions concerning the " webcamDisplayCmd(QString::fromStdString(binary_paths.get<std::string>("webcam_command",
"clients will not be available.", "Displaying the laboratory's webcams will not work."))),
argSettings, true)}, webcams{ GetWebcams(server) },
pkeyPathUser{ReadSettingsItem( webcams_names{ GetWebcamsNames(server) },
"pkey_path_user", wineCmd(QString::fromStdString(binary_paths.get<std::string>("wine_command",
"Many actions concerning the clients will not be available.", "Running z-Leaves or z-Tree will be possible."))),
argSettings, true)}, wmctrlCmd(QString::fromStdString(binary_paths.get<std::string>("wmctrl_command",
rmCmd{ReadSettingsItem( "Setting zTree's window title to its port number will not work."))),
"rm_command", "Cleanup of the zTree data target path will not work.", xsetCmd(QString::fromStdString(binary_paths.get<std::string>("xset_command",
argSettings, true)}, "Deactivating the screen saver on the clients will not be possible."))),
scpCmd{ReadSettingsItem( zTreeInstDir(QString::fromStdString(binary_paths.get<std::string>("ztree_installation_directory",
"scp_command", "Beaming files to the clients will not be possible.", "zTree will not be available."))),
argSettings, true)}, restartCrashedSessionScript(QString::fromStdString(binary_paths.get<std::string>("restart_crashed_session_script",
serverIP{ReadSettingsItem( "Script to be called after session crash"))),
"server_ip", //adminUsers(server.get<QStringList>("admin_users")),
"Starting zLeaves and retrieving client help messages will not work.", adminUsers{ GetAdminUsers(server) },
argSettings, false)}, installedLaTeXHeaders{ DetectInstalledLaTeXHeaders() },
sshCmd{ReadSettingsItem( installedZTreeVersions{ DetectInstalledzTreeVersions() },
"ssh_command", //clientHelpNotificationServerPort(server.get<unsigned short>("client_help_server_port")),
"All actions concerning the clients will not be possible.", clientHelpNotificationServerPort{ GetClientHelpNotificationServerPort(server) },
argSettings, true)}, vncViewOnlyArguments( QString::fromStdString(server.get<std::string>("vnc_view_only_argument",
tasksetCmd{ReadSettingsItem( "vnc view only mode won't work.")) ),
"taskset_command", "Running z-Leaves or z-Tree will be possible.", chosenzTreePort(server.get<int>("initial_port")),
argSettings, true)}, clients{ CreateClients( client, pingCmd ) },
termEmulCmd{ReadSettingsItem( localzLeafName(QString::fromStdString(server.get<std::string>("local_zLeaf_def_name",
"terminal_emulator_command", "The local zLeaf default name will default to 'local'."))),
"Conducting administrative tasks will not be possible.", argSettings, localzLeafSize(QString::fromStdString(server.get<std::string>("local_zLeaf_size",
true)}, "Resolution of local zLeaf window"))),
userNameOnClients{ clIPsToClMap{ CreateClIPsToClMap( clients ) }
ReadSettingsItem("user_name_on_clients", {
"All actions concerning the clients performed by " // Let the local zLeaf name default to 'local' if none was given in the settings
"the experiment user will not work.", if ( localzLeafName.isEmpty() ) {
argSettings, false)},
vncViewer{ReadSettingsItem("vnc_viewer",
"Viewing the clients' screens will not work.",
argSettings, true)},
wakeonlanCmd{ReadSettingsItem("wakeonlan_command",
"Booting the clients will not work.",
argSettings, true)},
webcamDisplayCmd{
ReadSettingsItem("webcam_command",
"Displaying the laboratory's webcams will not work.",
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)},
wmctrlCmd{ReadSettingsItem(
"wmctrl_command",
"Setting zTree's window title to its port number will not work.",
argSettings, true)},
xsetCmd{ReadSettingsItem(
"xset_command",
"Deactivating the screen saver on the clients will not be possible.",
argSettings, true)},
zTreeInstDir{ReadSettingsItem("ztree_installation_directory",
"zTree will not be available.", argSettings,
true)},
restartCrashedSessionScript{ReadSettingsItem(
"restart_crashed_session_script",
"Script to be called after session crash", argSettings, false)},
adminUsers{GetAdminUsers(argSettings)},
installedLaTeXHeaders{DetectInstalledLaTeXHeaders()},
installedZTreeVersions{DetectInstalledzTreeVersions()},
clientHelpNotificationServerPort{
GetClientHelpNotificationServerPort(argSettings)},
chosenzTreePort{GetInitialPort(argSettings)}, clients{CreateClients(
argSettings, pingCmd)},
localzLeafName{ReadSettingsItem(
"local_zLeaf_name",
"The local zLeaf default name will default to 'local'.", argSettings,
false)},
clIPsToClMap{CreateClIPsToClMap(clients)} {
// Let the local zLeaf name default to 'local' if none was given in the
// settings
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()) {
qDebug() << "'webcams' was not properly set. No stationary webcams will be "
"available.";
} else {
qDebug() << "The following webcams where loaded:" << webcams;
}
qDebug() << "Detected z-Tree versions" << installedZTreeVersions; qDebug() << "Detected z-Tree versions" << installedZTreeVersions;
} }
@ -196,105 +144,70 @@ bool lc::Settings::CheckPathAndComplain(const QString &argPath,
return true; return true;
} }
QVector<lc::Client *> lc::Settings::CreateClients(const QSettings &argSettings, QVector< lc::Client* > lc::Settings::CreateClients( const pt::ptree &clients,
const QString &argPingCmd) { const QString &argPingCmd ) { // TO DO
QVector<Client *> tempClientVec; QVector< Client* > tempClientVec;
// Get the client quantity to check the value lists for clients creation for // Get the client quantity to check the value lists for clients creation for correct length
// correct length int clientQuantity = 0;
int clientQuantity = 0; BOOST_FOREACH(const pt::ptree::value_type &v, clients.get_child("clients")) {
if (!argSettings.contains("client_quantity")) { clientQuantity++;
qWarning()
<< "'client_quantity' was not set. The client quantity will be guessed"
" by the amount of client IPs set in 'client_ips'.";
clientQuantity = argSettings.value("client_ips", "")
.toString()
.split('/', QString::SkipEmptyParts, Qt::CaseSensitive)
.length();
qDebug() << "'clientQuantity':" << clientQuantity;
} else {
bool ok = true;
clientQuantity = argSettings.value("client_quantity").toInt(&ok);
if (!ok) {
qWarning() << "The variable 'client_quantity' was not convertible to int";
} }
qDebug() << "'clientQuantity':" << clientQuantity; qDebug() << "'clientQuantity':" << clientQuantity;
}
// Create all the clients in the lab QStringList clientIPs;
QStringList clientIPs = QStringList clientMACs;
argSettings.value("client_ips") QStringList clientNames;
.toString() QStringList clientXPositions;
.split('|', QString::SkipEmptyParts, Qt::CaseSensitive); QStringList clientYPositions;
if (clientIPs.length() != clientQuantity) {
qWarning()
<< "The quantity of client ips does not match the client quantity. "
"Client"
" creation will fail. No clients will be available for interaction.";
return tempClientVec;
}
qDebug() << "Client IPs:" << clientIPs.join(" / ");
QStringList clientMACs =
argSettings.value("client_macs")
.toString()
.split('|', QString::SkipEmptyParts, Qt::CaseSensitive);
if (clientMACs.length() != clientQuantity) {
qWarning()
<< "The quantity of client macs does not match the client quantity. "
"Client"
" creation will fail. No clients will be available for interaction.";
return tempClientVec;
}
qDebug() << "Client MACs:" << clientMACs.join(" / ");
QStringList clientNames =
argSettings.value("client_names")
.toString()
.split('|', QString::SkipEmptyParts, Qt::CaseSensitive);
if (clientNames.length() != clientQuantity) {
qWarning()
<< "The quantity of client names does not match the client quantity. "
"Client"
" creation will fail. No clients will be available for interaction.";
return tempClientVec;
}
qDebug() << "Client names:" << clientNames.join(" / ");
QStringList clientXPositions =
argSettings.value("client_xpos")
.toString()
.split('|', QString::SkipEmptyParts, Qt::CaseSensitive);
if (clientXPositions.length() != clientQuantity) {
qWarning() << "The quantity of client x positions does not match the "
"client quantity."
" Client creation will fail. No clients will be available "
"for interaction.";
return tempClientVec;
}
qDebug() << "clientXPositions:" << clientXPositions.join(" / ");
QStringList clientYPositions =
argSettings.value("client_ypos")
.toString()
.split('|', QString::SkipEmptyParts, Qt::CaseSensitive);
if (clientYPositions.length() != clientQuantity) {
qWarning() << "The quantity of client y positions does not match the "
"client quantity."
" Client creation will fail. No clients will be available "
"for interaction.";
return tempClientVec;
}
qDebug() << "clientYPositions:" << clientYPositions.join(" / ");
for (int i = 0; i < clientQuantity; i++) { pt::ptree clients_dict = clients.get_child("clients");
tempClientVec.append(new Client{clientIPs[i], clientMACs[i], clientNames[i],
clientXPositions[i].toUShort(), BOOST_FOREACH(const pt::ptree::value_type &v, clients_dict) {
clientYPositions[i].toUShort(), clientNames += QString::fromStdString(v.first);
argPingCmd}); clientIPs += QString::fromStdString(clients_dict.get_child(v.first).get<std::string>("ip"));
} clientMACs += QString::fromStdString(clients_dict.get_child(v.first).get<std::string>("mac"));
clientXPositions += QString::fromStdString(clients_dict.get_child(v.first).get<std::string>("xpos"));
clientYPositions += QString::fromStdString(clients_dict.get_child(v.first).get<std::string>("ypos"));
}
qDebug() << "Client IPs:" << clientIPs.join( " / " );
if ( clientMACs.length() != clientQuantity ) {
qWarning() << "The quantity of client macs does not match the client quantity. Client"
" creation will fail. No clients will be available for interaction.";
return tempClientVec;
}
qDebug() << "Client MACs:" << clientMACs.join( " / " );
return tempClientVec; if ( clientNames.length() != clientQuantity ) {
qWarning() << "The quantity of client names does not match the client quantity. Client"
" creation will fail. No clients will be available for interaction.";
return tempClientVec;
}
qDebug() << "Client names:" << clientNames.join( " / " );
if ( clientXPositions.length() != clientQuantity ) {
qWarning() << "The quantity of client x positions does not match the client quantity."
" Client creation will fail. No clients will be available for interaction.";
return tempClientVec;
}
qDebug() << "clientXPositions:" << clientXPositions.join( " / " );
if ( clientYPositions.length() != clientQuantity ) {
qWarning() << "The quantity of client y positions does not match the client quantity."
" Client creation will fail. No clients will be available for interaction.";
return tempClientVec;
}
qDebug() << "clientYPositions:" << clientYPositions.join( " / " );
for ( int i = 0; i < clientQuantity; i++ ) {
tempClientVec.append( new Client{ clientIPs[ i ], clientMACs[ i ], clientNames[ i ],
clientXPositions[ i ].toUShort(),
clientYPositions[ i ].toUShort(), argPingCmd } );
}
return tempClientVec;
} }
QMap<QString, lc::Client *> QMap<QString, lc::Client *>
@ -347,63 +260,44 @@ QStringList lc::Settings::DetectInstalledzTreeVersions() const {
return tempInstzTreeVersions; return tempInstzTreeVersions;
} }
QStringList lc::Settings::GetAdminUsers(const QSettings &argSettings) { template <typename T>
// Read the list of users with administrative rights std::vector<T> as_vector(pt::ptree const& pt, pt::ptree::key_type const& key) {
if (!argSettings.contains("admin_users")) { std::vector<T> r;
qDebug() << "The 'admin_users' variable was not set." for (auto& item : pt.get_child(key))
" No users will be able to conduct administrative tasks."; r.push_back(item.second.get_value<T>());
return QStringList{}; return r;
} else {
QStringList adminUsers{
argSettings.value("admin_users", "")
.toString()
.split('|', QString::SkipEmptyParts, Qt::CaseInsensitive)};
qDebug() << "'adminUsers':" << adminUsers.join(" / ");
return adminUsers;
}
return QStringList{};
} }
quint16 lc::Settings::GetClientHelpNotificationServerPort( QStringList lc::Settings::GetAdminUsers( const pt::ptree server ) {
const QSettings &argSettings) { // Read the list of users with administrative rights
// Read the port the ClientHelpNotificationServer shall listen on
quint16 clientHelpNotificationServerPort =
argSettings.value("client_help_server_port", 0).toUInt();
if (!clientHelpNotificationServerPort) {
qDebug()
<< "The 'client_help_server_port' variable was not set or set to zero."
" The ClientHelpNotificationServer will be deactivated therefore."
" Clients' help requests will be ignored by the server.";
return 0;
} else {
qDebug() << "'clientHelpNotificationServerPort':"
<< clientHelpNotificationServerPort;
return clientHelpNotificationServerPort;
}
return 0;
}
int lc::Settings::GetDefaultReceiptIndex(const QSettings &argSettings) { QStringList adminUsers;
// Read the default receipt index for the 'CBReceipts' combobox for (auto adminUser : as_vector<std::string>(server, "admin_users")) {
if (!argSettings.contains("default_receipt_index")) { adminUsers << QString::fromStdString(adminUser);
qDebug() << "'default_receipt_index' was not set. It will default to '0'."; }
return 0;
} if ( !adminUsers.length() ) {
int tempIndex = argSettings.value("default_receipt_index", 0).toInt(); qDebug() << "The 'admin_users' variable was not set."
qDebug() << "'defaultReceiptIndex':" << tempIndex; " No users will be able to conduct administrative tasks.";
return tempIndex; return QStringList{};
} else {
qDebug() << "'adminUsers':" << adminUsers.join( " / " );
return adminUsers;
}
} }
int lc::Settings::GetInitialPort(const QSettings &argSettings) { quint16 lc::Settings::GetClientHelpNotificationServerPort( const pt::ptree server ) {
// Read the initial port number // Read the port the ClientHelpNotificationServer shall listen on
if (!argSettings.contains("initial_port")) { quint16 clientHelpNotificationServerPort = server.get<unsigned short>( "client_help_server_port", 0 );
qDebug() if ( !clientHelpNotificationServerPort ) {
<< "The 'initial_port' variable was not set." qDebug() << "The 'client_help_server_port' variable was not set or set to zero."
" Labcontrol will default to port 7000 for new zTree instances."; " The ClientHelpNotificationServer will be deactivated therefore."
} " Clients' help requests will be ignored by the server.";
int initialPort = argSettings.value("initial_port", 7000).toInt(); return 0;
qDebug() << "'initial_port':" << initialPort; } else {
return initialPort; qDebug() << "'clientHelpNotificationServerPort':" << clientHelpNotificationServerPort;
return clientHelpNotificationServerPort;
}
} }
QString lc::Settings::GetLocalUserName() { QString lc::Settings::GetLocalUserName() {
@ -422,26 +316,38 @@ QString lc::Settings::GetLocalUserName() {
return userName; return userName;
} }
QString lc::Settings::ReadSettingsItem(const QString &argVariableName,
const QString &argMessage,
const QSettings &argSettings,
bool argItemIsFile) {
if (!argSettings.contains(argVariableName)) {
qDebug() << argVariableName << "was not set." << argMessage;
return QString{};
} else {
QString tempString{argSettings.value(argVariableName).toString()};
if (argItemIsFile &&
!CheckPathAndComplain(tempString, argVariableName, argMessage)) {
tempString.clear();
}
return tempString;
}
return QString{};
}
void lc::Settings::SetLocalzLeafSize(QString arg) { localzLeafSize = arg; } void lc::Settings::SetLocalzLeafSize(QString arg) { localzLeafSize = arg; }
void lc::Settings::SetChosenZTreePort(const int argPort) { void lc::Settings::SetChosenZTreePort(const int argPort) {
chosenzTreePort = argPort; chosenzTreePort = argPort;
} }
QStringList lc::Settings::GetWebcams(const pt::ptree server) {
if ( !server.count("webcams") ) {
qDebug() << "'webcams' was not properly set. No stationary webcams will be available.";
return QStringList{};
} else {
std::stringstream webcam_stream;
QStringList webcams;
BOOST_FOREACH(const pt::ptree::value_type &v, server.get_child("webcams")) {
webcam_stream << v.first << ": " << &v.second << ", ";
webcams << QString::fromStdString(v.second.get_value<std::string>());
}
qDebug() << "The following webcams where loaded:" << qPrintable(QString::fromStdString(webcam_stream.str()));
return webcams;
}
}
QStringList lc::Settings::GetWebcamsNames(const pt::ptree server) {
if ( !server.count("webcams") ) {
qDebug() << "'webcams' was not properly set. No stationary webcams will be available.";
return QStringList{};
} else {
std::stringstream webcam_stream;
QStringList webcam_names;
BOOST_FOREACH(const pt::ptree::value_type &v, server.get_child("webcams")) {
webcam_names << QString::fromStdString(v.first);
}
return webcam_names;
}
}

@ -22,111 +22,115 @@
#include <QDebug> #include <QDebug>
#include <QObject> #include <QObject>
#include <QSettings>
#include <string>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include "client.h" #include "client.h"
namespace pt = boost::property_tree;
namespace lc { namespace lc {
class Settings : public QObject { class Settings : public QObject {
Q_OBJECT Q_OBJECT
public: public:
Settings() = delete; Settings() = delete;
explicit Settings(const QSettings &argSettings, QObject *argParent = nullptr); explicit Settings( pt::ptree root );
Settings(const Settings &argSettings) = delete; Settings( const Settings &argSettings ) = delete;
Settings &operator=(const Settings &argSettings) = delete; Settings& operator=( const Settings &argSettings ) = delete;
Settings(Settings &&argSettings) = delete; Settings( Settings &&argSettings ) = delete;
Settings &operator=(Settings &&argSettings) = delete; Settings& operator=( Settings &&argSettings ) = delete;
~Settings(); ~Settings();
int GetChosenZTreePort() const { return chosenzTreePort; } QVector< Client* > &GetClients() { return clients; }
QVector<Client *> &GetClients() { return clients; }
QString GetLocalzLeafName() const; // get and set functions
void SetChosenZTreePort(const int argPort); int GetChosenZTreePort() const { return chosenzTreePort; }
void SetLocalzLeafName(const QString &argLocalzLeafName); void SetChosenZTreePort( const int argPort );
QString GetLocalzLeafName() const { return localzLeafName; }
const int defaultReceiptIndex = 0; void SetLocalzLeafName( const QString &argLocalzLeafName ) { localzLeafName = argLocalzLeafName; }
const QString browserCmd; QString GetLocalzLeafSize() const { return localzLeafSize; }
const QString clientBrowserCmd; void SetLocalzLeafSize( QString arg);
const QString clientChromiumCmd;
const QString dvipsCmd; // ptree childs
const QString fileMngr; const pt::ptree root;
const QString killallCmd; const pt::ptree binary_paths;
const QString latexCmd; const pt::ptree client;
const QString lcDataDir; const pt::ptree server;
const QString localUserName; const pt::ptree webcams_root;
QString localzLeafSize;
void SetLocalzLeafSize(QString arg); // constants
QString GetLocalzLeafSize() const { return localzLeafSize; } const int defaultReceiptIndex = 0;
const QString lprCmd; const QString browserCmd;
const QString netstatCmd; const QString clientBrowserCmd;
const QString netwBrdAddr; const QString clientChromiumCmd;
const QString orseeUrl; const QString dvipsCmd;
const QString pingCmd; const QString fileMngr;
const QString postscriptViewer; const QString killallCmd;
const QString ps2pdfCmd; const QString zleafExeName;
const QString pkeyPathRoot; const QString ztreeExeName;
const QString pkeyPathUser; const QString latexCmd;
const QString rmCmd; const QString lcDataDir;
const QString scpCmd; const QString localUserName;
const QString serverIP; const QString lprCmd;
const QString sshCmd; const QString netstatCmd;
const QString tasksetCmd; const QString netwBrdAddr;
const QString termEmulCmd; const QString orseeUrl;
const QString userNameOnClients; const QString pingCmd;
const QString vncViewer; const QString postscriptViewer;
const QString wakeonlanCmd; const QString ps2pdfCmd;
const QString webcamDisplayCmd; const QString pkeyPathRoot;
const QStringList webcams; const QString pkeyPathUser;
const QStringList webcams_names; const QString rmCmd;
const QString wineCmd; const QString scpCmd;
const QString wmctrlCmd; const QString serverIP;
const QString xsetCmd; const QString sshCmd;
const QString zTreeInstDir; const QString tasksetCmd;
const QString restartCrashedSessionScript; const QString termEmulCmd;
const QStringList adminUsers; const QString userNameOnClients;
const QStringList installedLaTeXHeaders; const QString vncViewer;
const QStringList installedZTreeVersions; const QString wakeonlanCmd;
const quint16 clientHelpNotificationServerPort = 0; const QString webcamDisplayCmd;
const QStringList webcams;
const QStringList webcams_names;
const QString wineCmd;
const QString wmctrlCmd;
const QString xsetCmd;
const QString zTreeInstDir;
const QString restartCrashedSessionScript;
const QStringList adminUsers;
const QStringList installedLaTeXHeaders;
const QStringList installedZTreeVersions;
const quint16 clientHelpNotificationServerPort = 0;
const QString vncViewOnlyArguments;
private: private:
static bool CheckPathAndComplain(const QString &argPath, static bool CheckPathAndComplain( const QString &argPath, const QString &argVariableName,
const QString &argVariableName, const QString &argMessage );
const QString &argMessage); static QVector< Client* > CreateClients( const pt::ptree &clients,
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 *> QStringList DetectInstalledLaTeXHeaders() const;
CreateClIPsToClMap(const QVector<Client *> &argClients); QStringList DetectInstalledzTreeVersions() const;
QStringList DetectInstalledLaTeXHeaders() const; static QStringList GetAdminUsers( const pt::ptree server );
QStringList DetectInstalledzTreeVersions() const; static quint16 GetClientHelpNotificationServerPort( const pt::ptree server );
static QStringList GetAdminUsers(const QSettings &argSettings); static QString GetLocalUserName();
static quint16 static QStringList GetWebcams(const pt::ptree server);
GetClientHelpNotificationServerPort(const QSettings &argSettings); static QStringList GetWebcamsNames(const pt::ptree server);
static int GetDefaultReceiptIndex(const QSettings &argSettings);
static int GetInitialPort(const QSettings &argSettings); int chosenzTreePort = 0;
static QString GetLocalUserName(); QVector< Client* > clients;
static QString ReadSettingsItem(const QString &argVariableName, QString localzLeafName;
const QString &argMessage, QString localzLeafSize;
const QSettings &argSettings,
bool argItemIsFile);
int chosenzTreePort = 0;
QVector<Client *> clients;
QString localzLeafName;
public: public:
const QMap<QString, Client *> clIPsToClMap; const QMap< QString, Client* > clIPsToClMap;
}; };
} // namespace lc
inline QString lc::Settings::GetLocalzLeafName() const {
return localzLeafName;
}
inline void lc::Settings::SetLocalzLeafName(const QString &argLocalzLeafName) {
localzLeafName = argLocalzLeafName;
} }
#endif // SETTINGS_H #endif // SETTINGS_H

@ -38,30 +38,21 @@ extern std::unique_ptr<lc::Settings> settings;
* \param[in] argParent The instance's parent QObject * \param[in] argParent The instance's parent QObject
*/ */
lc::ZTree::ZTree(const QString &argZTreeDataTargetPath, const int &argZTreePort, lc::ZTree::ZTree(const QString &argZTreeDataTargetPath, const int &argZTreePort,
const QString &argZTreeVersion, QObject *const argParent) const QString &argZTreeVersionPath, QObject *const argParent)
: QObject{argParent}, zTreeInstance{new QProcess{this}} { : QObject{argParent}, zTreeInstance{new QProcess{this}} {
const QStringList arguments{"-c", const QStringList arguments{ QStringList{} << QString{ settings->zTreeInstDir + "/zTree_" // first line before: << settings->wineCmd
"0", + argZTreeVersionPath + "/ztree.exe" }
settings->wineCmd, << "/datadir" << QString{ "Z:/" + argZTreeDataTargetPath }
QString{settings->zTreeInstDir + "/zTree_" + << "/privdir" << QString{ "Z:/" + argZTreeDataTargetPath }
argZTreeVersion + "/ztree.exe"}, << "/gsfdir" << QString{ "Z:/" + argZTreeDataTargetPath }
"/datadir", << "/tempdir" << QString{ "Z:/" + argZTreeDataTargetPath }
QString{"Z:/" + argZTreeDataTargetPath}, << "/leafdir" << QString{ "Z:/" + argZTreeDataTargetPath }
"/privdir", << "/channel" << QString::number( argZTreePort - 7000 ) };
QString{"Z:/" + argZTreeDataTargetPath},
"/gsfdir",
QString{"Z:/" + argZTreeDataTargetPath},
"/tempdir",
QString{"Z:/" + argZTreeDataTargetPath},
"/leafdir",
QString{"Z:/" + argZTreeDataTargetPath},
"/channel",
QString::number(argZTreePort - 7000)};
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
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 ); // old
zTreeInstance->start( settings->wineCmd, arguments, QIODevice::NotOpen );
connect(zTreeInstance, connect(zTreeInstance,
static_cast<void (QProcess::*)(int)>(&QProcess::finished), this, static_cast<void (QProcess::*)(int)>(&QProcess::finished), this,
&ZTree::ZTreeClosed); &ZTree::ZTreeClosed);

@ -20,6 +20,7 @@
#include <memory> #include <memory>
#include <QApplication> #include <QApplication>
#include <QDebug>
#include "Lib/settings.h" #include "Lib/settings.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -33,9 +34,23 @@ int main(int argc, char *argv[]) {
qRegisterMetaType<lc::Client::State>("Client::State"); qRegisterMetaType<lc::Client::State>("Client::State");
qRegisterMetaType<lc::Client::State>("lc::Client::State"); qRegisterMetaType<lc::Client::State>("lc::Client::State");
settings.reset(new lc::Settings{QSettings{"Labcontrol", "Labcontrol"}}); unsigned long i = 0;
lc::MainWindow w; // hard coded, you can edit here, if you prefer a different location for your config file:
w.show(); std::vector<std::string> filenames = {"/usr/local/etc/Labcontrol/Labcontrol.json", "/etc/Labcontrol/Labcontrol.json", "./Labcontrol.json"};
for (i; i < filenames.size(); i++) { // if a configuration file was found, the loop breaks
return a.exec(); std::ifstream f(filenames[i].c_str());
pt::ptree root;
if (f.good()) {
pt::read_json(f, root);
settings.reset( new lc::Settings{root} );
// clients?
lc::MainWindow w;
w.show();
return a.exec();
break;
}
}
if (i == filenames.size()) QMessageBox::critical(NULL, QString("Error"), QString("No configuration file found."));
} }

@ -285,22 +285,23 @@ void lc::MainWindow::LoadIconPixmaps() {
} }
void lc::MainWindow::on_PBKillLocalzLeaf_clicked() { void lc::MainWindow::on_PBKillLocalzLeaf_clicked() {
QString program{settings->killallCmd}; QString program{ settings->killallCmd + " " + settings->zleafExeName};
QStringList arguments; /*QStringList arguments;
arguments << "-I" arguments << "-I"
<< "-q" << "-q"
<< "zleaf.exe"; << "zleaf.exe";*/
// ps aux | grep zleaf.exe | cut -f 5 -d " "
// Start the process // Start the process
QProcess killLocalzLeafProc; QProcess killLocalzLeafProc;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
killLocalzLeafProc.setProcessEnvironment(env); killLocalzLeafProc.setProcessEnvironment(env);
killLocalzLeafProc.startDetached(program, arguments); killLocalzLeafProc.startDetached(program);
localzLeavesAreRunning = false; localzLeavesAreRunning = false;
// Output message via the debug messages tab // Output message via the debug messages tab
qDebug() << program << arguments; qDebug() << program;
} }
void lc::MainWindow::on_PBPrintPaymentFileManually_clicked() { void lc::MainWindow::on_PBPrintPaymentFileManually_clicked() {
@ -338,6 +339,7 @@ void lc::MainWindow::on_PBRunzLeaf_clicked() {
for (QModelIndexList::ConstIterator it = activatedItems.cbegin(); for (QModelIndexList::ConstIterator it = activatedItems.cbegin();
it != activatedItems.cend(); ++it) { it != activatedItems.cend(); ++it) {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
qDebug() << "chosen fakename: " << fakeName;
Client *client = Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>()); static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->StartZLeaf(fakeName); client->StartZLeaf(fakeName);
@ -455,7 +457,7 @@ void lc::MainWindow::SetupWidgets() {
// 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( /*ui->LInfo->setText(
"This is Labcontrol version 2.1.6\n\n\n\n\n\n" "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"
@ -472,7 +474,7 @@ void lc::MainWindow::SetupWidgets() {
"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 " "along with Labcontrol. If not, see "
"<http://www.gnu.org/licenses/>.\n\n\n"); "<http://www.gnu.org/licenses/>.\n\n\n");*/
} }
void lc::MainWindow::StartReceiptsHandler( void lc::MainWindow::StartReceiptsHandler(
@ -513,7 +515,7 @@ void lc::MainWindow::UpdateClientsTableView() {
s->setIcon(icons[(int)icons_t::DOWN]); s->setIcon(icons[(int)icons_t::DOWN]);
break; break;
case Client::State::ZLEAF_RUNNING: case Client::State::ZLEAF_RUNNING:
s->setBackground(QBrush(QColor(0, 255, 0, 255))); s->setBackground(QBrush(QColor(0, 255, 0, 255))); // overthink this color, thx
s->setIcon(icons[(int)icons_t::ZLEAF]); s->setIcon(icons[(int)icons_t::ZLEAF]);
break; break;
case Client::State::UNINITIALIZED: case Client::State::UNINITIALIZED:
@ -644,7 +646,7 @@ void lc::MainWindow::on_PBstartBrowser_clicked() {
if ((*it).data(Qt::DisplayRole).type() != 0) { if ((*it).data(Qt::DisplayRole).type() != 0) {
Client *client = Client *client =
static_cast<Client *>((*it).data(Qt::UserRole).value<void *>()); static_cast<Client *>((*it).data(Qt::UserRole).value<void *>());
client->StartClientBrowser(&argURL, &argFullscreen); client->StartClientBrowser( &argURL, &argFullscreen, ui->CB_BrowserSelection->currentText() );
} }
} }
} }
@ -741,20 +743,20 @@ void lc::MainWindow::StartLocalzLeaf(const QString &argzLeafName,
<< "127.0.0.1" << "127.0.0.1"
<< "/channel" << QString::number(argzTreePort - 7000) << "/name" << "/channel" << QString::number(argzTreePort - 7000) << "/name"
<< argzLeafName; << argzLeafName;
if (!settings->localzLeafSize.isEmpty()) { if (!settings->GetLocalzLeafSize().isEmpty()) {
arguments << "/size" << QString{settings->localzLeafSize}; arguments << "/size" << QString{settings->GetLocalzLeafSize()};
} }
qDebug() << "Start local zLeaf:" << arguments; qDebug() << "Start local zLeaf:" << arguments;
startProc.startDetached(settings->tasksetCmd, arguments); startProc.startDetached(settings->wineCmd, arguments ); // before: settings->tasksetCmd
} }
void lc::MainWindow::on_PBStopZtree_clicked() { void lc::MainWindow::on_PBStopZtree_clicked() {
QString program{settings->killallCmd}; QString program{settings->killallCmd + " " + settings->ztreeExeName };
QStringList arguments; /*QStringList arguments;
arguments << "-I" arguments << "-I"
<< "-q" << "-q"
<< "ztree.exe"; << "ztree.exe";*/
// Confirmation dialog // Confirmation dialog
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "Confirm", reply = QMessageBox::question(this, "Confirm",
@ -765,9 +767,9 @@ void lc::MainWindow::on_PBStopZtree_clicked() {
QProcess killLocalzLeafProc; QProcess killLocalzLeafProc;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
killLocalzLeafProc.setProcessEnvironment(env); killLocalzLeafProc.setProcessEnvironment(env);
killLocalzLeafProc.startDetached(program, arguments); killLocalzLeafProc.startDetached(program);
// Output message via the debug messages tab // Output message via the debug messages tab
qDebug() << program << arguments; qDebug() << program;
} else { } else {
qDebug() << "Canceled stopping all z-Tree processes"; qDebug() << "Canceled stopping all z-Tree processes";
} }
@ -812,7 +814,7 @@ void lc::MainWindow::on_CBReceiptsHeader_activated(int argIndex) {
} }
// 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);
} }

@ -150,10 +150,10 @@ private slots:
void GetNewDataTargetPath(); void GetNewDataTargetPath();
void on_CBDataTargetPath_activated(int argIndex); void on_CBDataTargetPath_activated(int argIndex);
void on_CBReceiptsHeader_activated(int argIndex); void on_CBReceiptsHeader_activated(int argIndex);
void on_ChBPrintanonymousreceipts_clicked();
void on_PBKillzLeaf_clicked(); void on_PBKillzLeaf_clicked();
void on_PBEnableRMB_clicked(); void on_PBEnableRMB_clicked();
void on_PBDisableRMB_clicked(); void on_PBDisableRMB_clicked();
void on_ChBPrintAnonymousReceipts_clicked();
}; };
} // namespace lc } // namespace lc

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>730</width> <width>730</width>
<height>900</height> <height>850</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -16,6 +16,18 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>0</width>
<height>850</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>850</height>
</size>
</property>
<property name="windowTitle"> <property name="windowTitle">
<string>Labcontrol</string> <string>Labcontrol</string>
</property> </property>
@ -48,7 +60,13 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>640</width> <width>640</width>
<height>580</height> <height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>800</height>
</size> </size>
</property> </property>
<property name="baseSize"> <property name="baseSize">
@ -176,7 +194,7 @@
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>40</height> <height>0</height>
</size> </size>
</property> </property>
</spacer> </spacer>
@ -214,24 +232,28 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="PBBoot"> <layout class="QHBoxLayout" name="HLBootShutdown">
<property name="toolTip"> <item>
<string>Boots the selected clients.</string> <widget class="QPushButton" name="PBShutdown">
</property> <property name="toolTip">
<property name="text"> <string>Turn off the selected clients.</string>
<string>Boot</string> </property>
</property> <property name="text">
</widget> <string>Shutdown</string>
</item> </property>
<item> </widget>
<widget class="QPushButton" name="PBShutdown"> </item>
<property name="toolTip"> <item>
<string>Turns off the selected clients.</string> <widget class="QPushButton" name="PBBoot">
</property> <property name="toolTip">
<property name="text"> <string>Boot the selected clients.</string>
<string>Shutdown</string> </property>
</property> <property name="text">
</widget> <string>Boot</string>
</property>
</widget>
</item>
</layout>
</item> </item>
<item> <item>
<widget class="Line" name="line_bootActions"> <widget class="Line" name="line_bootActions">
@ -243,30 +265,33 @@
<item> <item>
<widget class="QLabel" name="L_VNC"> <widget class="QLabel" name="L_VNC">
<property name="text"> <property name="text">
<string>Remote control the selected clients</string> <string>Remote Control selected clients</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="PBViewDesktopViewOnly">
<property name="toolTip">
<string>Shows the desktop of the selected clients.</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="L_VNC">
<property name="text">
<string>View desktop (view only)</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="PBViewDesktopFullControl"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="text"> <item>
<string>Control desktop (mouse and keyboard)</string> <widget class="QPushButton" name="PBViewDesktopFullControl">
</property> <property name="toolTip">
</widget> <string>Control mouse and keyboard</string>
</property>
<property name="text">
<string>Control desktop</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="PBViewDesktopViewOnly">
<property name="toolTip">
<string>View only</string>
</property>
<property name="text">
<string>Show desktop</string>
</property>
</widget>
</item>
</layout>
</item> </item>
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
@ -357,13 +382,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QLabel" name="L_ClientPlaceholder">
<property name="text">
<string>%CLIENT% is a placeholder for hostname in URL</string>
</property>
</widget>
</item>
<item> <item>
<layout class="QHBoxLayout" name="HLURL"> <layout class="QHBoxLayout" name="HLURL">
<item> <item>
@ -375,6 +393,12 @@
</item> </item>
<item> <item>
<widget class="QLineEdit" name="LEURL"> <widget class="QLineEdit" name="LEURL">
<property name="toolTip">
<string>%CLIENT% is a placeholder for the hostname in the URL</string>
</property>
<property name="toolTipDuration">
<number>-1</number>
</property>
<property name="text"> <property name="text">
<string>http://localhost:8000/%CLIENT%</string> <string>http://localhost:8000/%CLIENT%</string>
</property> </property>
@ -383,25 +407,35 @@
</layout> </layout>
</item> </item>
<item> <item>
<widget class="QLabel" name="L_BrowserSelection"> <layout class="QHBoxLayout" name="horizontalLayout">
<property name="text">
<string>Use the following browser</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="CB_BrowserSelection">
<item> <item>
<property name="text"> <widget class="QLabel" name="L_BrowserSelection">
<string>chromium</string> <property name="text">
</property> <string>Use browser:</string>
</property>
</widget>
</item> </item>
<item> <item>
<property name="text"> <widget class="QComboBox" name="CB_BrowserSelection">
<string>firefox</string> <property name="minimumSize">
</property> <size>
<width>240</width>
<height>0</height>
</size>
</property>
<item>
<property name="text">
<string>chromium</string>
</property>
</item>
<item>
<property name="text">
<string>firefox</string>
</property>
</item>
</widget>
</item> </item>
</widget> </layout>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="CBFullscreen"> <widget class="QCheckBox" name="CBFullscreen">
@ -439,7 +473,7 @@
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>40</height> <height>0</height>
</size> </size>
</property> </property>
</spacer> </spacer>
@ -537,7 +571,7 @@
<x>10</x> <x>10</x>
<y>88</y> <y>88</y>
<width>691</width> <width>691</width>
<height>468</height> <height>539</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="VLNewSession"> <layout class="QVBoxLayout" name="VLNewSession">
@ -738,7 +772,7 @@
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>40</height> <height>0</height>
</size> </size>
</property> </property>
</spacer> </spacer>
@ -878,7 +912,7 @@
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>40</height> <height>0</height>
</size> </size>
</property> </property>
</spacer> </spacer>
@ -941,7 +975,7 @@
<item> <item>
<widget class="QRadioButton" name="RBUseUserRoot"> <widget class="QRadioButton" name="RBUseUserRoot">
<property name="text"> <property name="text">
<string>root</string> <string>roo&amp;t</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -1007,26 +1041,6 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="TInfo">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<attribute name="title">
<string>Info</string>
</attribute>
<layout class="QVBoxLayout" name="VLInfo">
<item>
<widget class="QLabel" name="LInfo">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
</item> </item>
<item> <item>
@ -1043,7 +1057,13 @@
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>0</width> <width>0</width>
<height>256</height> <height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>200</height>
</size> </size>
</property> </property>
<property name="font"> <property name="font">
@ -1081,24 +1101,24 @@
<attribute name="horizontalHeaderCascadingSectionResizes"> <attribute name="horizontalHeaderCascadingSectionResizes">
<bool>true</bool> <bool>true</bool>
</attribute> </attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>115</number>
</attribute>
<attribute name="horizontalHeaderMinimumSectionSize"> <attribute name="horizontalHeaderMinimumSectionSize">
<number>30</number> <number>30</number>
</attribute> </attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>115</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection"> <attribute name="horizontalHeaderStretchLastSection">
<bool>false</bool> <bool>false</bool>
</attribute> </attribute>
<attribute name="verticalHeaderVisible"> <attribute name="verticalHeaderVisible">
<bool>false</bool> <bool>false</bool>
</attribute> </attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>35</number>
</attribute>
<attribute name="verticalHeaderMinimumSectionSize"> <attribute name="verticalHeaderMinimumSectionSize">
<number>25</number> <number>25</number>
</attribute> </attribute>
<attribute name="verticalHeaderDefaultSectionSize">
<number>35</number>
</attribute>
<attribute name="verticalHeaderStretchLastSection"> <attribute name="verticalHeaderStretchLastSection">
<bool>false</bool> <bool>false</bool>
</attribute> </attribute>

Loading…
Cancel
Save